mobilemessaging/postcard/postcardsrc/PostcardAppUi.cpp
changeset 0 72b543305e3a
child 2 0bf1d54f37d9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mobilemessaging/postcard/postcardsrc/PostcardAppUi.cpp	Thu Dec 17 08:44:11 2009 +0200
@@ -0,0 +1,2800 @@
+/*
+* Copyright (c) 2005 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  PostcardAppUi implementation
+*
+*/
+
+
+
+// ========== INCLUDE FILES ================================
+
+#include <e32std.h>
+#include <w32std.h>
+
+#include <eikapp.h>                 // CEikApplication
+#include <eikdialg.h>               // CEikDialog
+#include <eikenv.h>                 // Eikon Enviroment
+#include <eikmenub.h>               // CEikMenuBar
+#include <eikmenup.h>               // CEikMenuPane
+#include <bamdesca.h>               // MDesCArray
+#include <bautils.h>                // NearestLanguageFile
+
+#include <bldvariant.hrh>
+#include <centralrepository.h>
+#include <data_caging_path_literals.hrh>
+#include <ErrorUI.h>
+#include <featmgr.h>
+#include <StringLoader.h>
+
+#include <aknenv.h>
+#include <aknconsts.h>
+#include <AknGlobalMsgQuery.h>      // Global Msg Query
+#include <AknIndicatorContainer.h>
+#include <akninputblock.h>          // CAknInputBlock
+#include <aknnavi.h>                // CAknNavigationControlContainer
+#include <aknnotewrappers.h>
+#include <akntitle.h>
+#include <AknWaitDialog.h>
+
+#include <avkon.hrh>
+#include <avkon.mbg>
+
+#include <AknsConstants.h>
+#include <AknsUtils.h>
+
+#include <fbs.h>
+#include <gulicon.h>
+#include <txtetext.h>
+
+#include <hlplch.h>                 // For HlpLauncher 
+#include <csxhelp/postcard.hlp.hrh>
+
+#include <cntfield.h>
+#include <cntfldst.h>
+#include <cntitem.h>				// for ContactItem
+
+#include <mtmdef.h>                 // TMsvPartList
+#include <mtmuibas.h>               // MTM UI
+#include <msvapi.h>
+#include <msvstd.hrh>               // KUidMsvMessageEntryValue
+
+#include <cmsvattachment.h>
+#include <mmsvattachmentmanager.h>
+#include <mmsvattachmentmanagersync.h>
+
+#include <msgoperationwait.h>           // for CMsgOperationWait
+#include <MtmExtendedCapabilities.hrh>  // for KMtmUiFunctionMessageInfo
+#include <MuiuMsvUiServiceUtilities.h>  // for Diskspace check
+#include <muiumsvuiserviceutilitiesinternal.h>  // for Offline mode check
+
+#include <MsgEditorAppUi.rsg>
+#include <MsgEditorAppUiExtension.h>// for iMsgEditorAppUiExtension (zoom)
+#include <MsgEditorCommon.h>
+
+
+#include <mmsclient.h>
+#include <mmsmsventry.h>
+
+#include <messaginginternalcrkeys.h>
+#include <messagingvariant.hrh>     // postcard feature (variation) bits
+#include <MsgMediaResolver.h>
+#include <MsgMedia.hrh>             // TMmsMediaType
+#include <MsgImageInfo.h>
+#include <MsgMimeTypes.h>
+
+#include <Postcard.rsg>             // resource identifiers
+#include <postcard.mbg>             // icons
+#include "Postcard.hrh"             // for EPostcardCmds
+#include "PostcardAddressForm.h"    // for editing recipient address
+#include "PostcardAppUi.h"          // class header
+#include "PostcardCenRep.h"
+#include "PostcardController.h"     // Controller class
+#include "PostcardLaf.h"
+#include "PostcardOperationInsertImage.h" // for inserting images
+#include "PostcardOperationOpen.h"	// for opening the application
+#include "PostcardOperationSave.h"	// for saving or sending the postcard
+#include "PostcardPointerObserver.h"// MPocaPointerEventObserver
+#include "PostcardPrivateCRKeys.h"  // cenrep keys
+#include "PostcardQueryWaiter.h"    // for PostcardQueryWaiter
+#include "PostcardTextDialog.h"		// for editing greeting text
+#include "PostcardUtils.h"
+
+// ========== EXTERNAL DATA STRUCTURES =====================
+
+// ========== EXTERNAL FUNCTION PROTOTYPES =================
+
+// ========== CONSTANTS ====================================
+
+const TInt KPostcardMaxSendConfirmationLength = 320;
+const TInt KPostcardMaxMiniatureCharsPerLine = 100;
+const TInt KPostcardLegacyWidth = 208; // the width of legacy display
+const TInt KPostcardQvgaWidth = 320; // the width of legacy display
+const TInt KPostcardMaxAddressFocusLines = 5; // max number of address focus lines
+
+// ========== MACROS =======================================
+
+// ========== LOCAL CONSTANTS AND MACROS ===================
+
+// ========== MODULE DATA STRUCTURES =======================
+
+// ========== LOCAL FUNCTION PROTOTYPES ====================
+
+// ========== LOCAL FUNCTIONS ==============================
+
+// ========== MEMBER FUNCTIONS =============================
+
+// ---------------------------------------------------------
+// CPostcardAppUi::CPostcardAppUi
+// ---------------------------------------------------------
+CPostcardAppUi::CPostcardAppUi()
+    {
+    }
+
+// ---------------------------------------------------------
+// CPostcardAppUi::ConstructL
+// ---------------------------------------------------------
+void CPostcardAppUi::ConstructL()
+    {
+    CMsgEditorAppUi::ConstructL();
+    
+    // We don't have any app ui if launched from idle
+    if ( iEikonEnv->EikAppUi() )
+        {
+        iAbsorber = CAknInputBlock::NewLC();
+        CleanupStack::Pop( iAbsorber );
+        }
+
+    // Create central repository interface
+    iCenRep = CPostcardCenRep::NewL();
+
+    // initialize feature manager to check supported features
+    FeatureManager::InitializeLibL();
+    if ( FeatureManager::FeatureSupported( KFeatureIdCamera ) )
+        {
+        iPocaFlags |= EPostcardCamcorder;
+        }
+    if( FeatureManager::FeatureSupported( KFeatureIdHelp ) )
+        {
+        iPocaFlags |= EPostcardHelp;
+        }
+    if( FeatureManager::FeatureSupported( KFeatureIdOfflineMode ) )
+        {
+        iPocaFlags |= EPostcardFeatureOffline;
+        }
+    FeatureManager::UnInitializeLib( );
+
+    // In case the postcard application is installed somewhere else than "Z" drive
+    // we find out the right drive for postcard resource file
+    TParse parseDrive;
+    parseDrive.Set( Application( )->AppFullName( ), NULL, NULL );
+    TPtrC drive = parseDrive.Drive( );
+
+    TParse parse;
+    parse.Set( KPostcardResourceFile, &KDC_APP_RESOURCE_DIR, NULL );
+    TFileName fileName( parse.FullName() );
+    fileName.Insert( 0, drive );
+    BaflUtils::NearestLanguageFile( iCoeEnv->FsSession(), fileName );
+    iResourceFile = iEikonEnv->AddResourceFileL( fileName );
+    parse.Set( KMsgEditorAppUiResourceFile, &KDC_RESOURCE_FILES_DIR, NULL );
+    fileName.Zero( );
+    fileName.Append( parse.FullName() );
+    BaflUtils::NearestLanguageFile( iCoeEnv->FsSession(), fileName );
+	iBaseResourceFile = iEikonEnv->AddResourceFileL( fileName );
+	
+    iNaviPane = static_cast<CAknNavigationControlContainer*>
+        ( StatusPane()->ControlL( TUid::Uid( EEikStatusPaneUidNavi ) ) );
+    
+    iTitlePane = static_cast<CAknTitlePane*>
+        ( StatusPane()->ControlL( TUid::Uid( EEikStatusPaneUidTitle ) ) );
+    
+	if( !iEikonEnv->StartedAsServerApp( ) )
+		{
+	    Document().PrepareToLaunchL( this );
+		}
+
+    iIdle = CPeriodic::NewL( EPriorityNormal - 1 );
+    }
+
+// ---------------------------------------------------------
+// CPostcardAppUi::~CPostcardAppUi
+// ---------------------------------------------------------
+CPostcardAppUi::~CPostcardAppUi()
+    {
+    // remove resource file from CONE-maintained resource file list.
+    if ( iResourceFile )
+        {
+        iEikonEnv->DeleteResourceFile( iResourceFile );
+        }
+    if ( iBaseResourceFile )
+        {
+        iEikonEnv->DeleteResourceFile( iBaseResourceFile );
+        }
+
+    delete iController;
+
+	delete iGreeting;
+	delete iContact;
+
+	delete iImageInfo;
+	
+	delete iIdle;
+
+    delete iAppIcon;
+    
+	if( iMessageQuery )
+		{
+        iMessageQuery->CancelMsgQuery();
+        delete iMessageQuery;
+        iMessageQuery = NULL;		
+		}
+
+    delete iSendText;
+
+    delete iCenRep;
+    }
+
+// ---------------------------------------------------------
+// LaunchViewL
+// ---------------------------------------------------------
+void CPostcardAppUi::LaunchViewL()
+    {
+    // First show wait note and start the launch process
+    ShowWaitNoteL( R_POSTCARD_WAIT_OPENING, EFalse );
+
+    const TMsvEntry& entry = Document( ).Entry( );
+    if ( entry.iType.iUid != KUidMsvMessageEntryValue )
+        {
+        User::Leave( KErrGeneral );
+        }
+
+    TRAPD( error, Document( ).Mtm( ).LoadMessageL( ) );
+    if ( error )
+        {
+        User::Leave( error );
+        }
+    Document( ).SetMessageType( );
+
+  	if ( !entry.ReadOnly() ) // editor
+    	{
+   	   	// End key should not close application in editor
+	   	CMsgEditorAppUi::SetCloseWithEndKey( EFalse );
+    	}
+
+    if( entry.ReadOnly() && !iNaviDecorator )
+        {
+        CreateViewerNaviPaneL( Document().Entry().iDate, EMsgEditorMsgPriorityNormal, ETrue );    
+        iNaviPane->PushL( *iNaviDecorator );  // <- This has nothing to do with cleanup-stack!    
+        }
+
+    delete iAbsorber;
+    iAbsorber = NULL;
+
+    iController = CPostcardController::NewL( Document()
+#ifdef RD_SCALABLE_UI_V2
+        , *this
+#endif
+        );
+
+    CreateAndSetTitleIconL();
+    
+    RefreshFocusLinesL( );
+
+    iOperation = CPostcardOperationOpen::NewL(
+        *this,
+        Document(),
+        *this,
+        FsSession() );
+    iOperation->Start( EFalse );
+    }
+
+
+// ---------------------------------------------------------
+// CanSaveMessageL
+// ---------------------------------------------------------
+TBool CPostcardAppUi::CanSaveMessageL( TInt aAmount )
+    {
+    return !( MsvUiServiceUtilities::DiskSpaceBelowCriticalLevelL( 
+        Document().Session(), 
+        aAmount ) );
+    }
+
+// ---------------------------------------------------------
+// DoMsgSaveExitL - called from options menu
+// ---------------------------------------------------------
+void CPostcardAppUi::DoMsgSaveExitL()
+    {
+    if( iMsgType == EPostcardSent )
+        { // Msg is a sent one so just close the application
+        Exit();
+        return;
+        }
+        
+    if ( CAknEnv::AppWithShutterRunning() )
+        {
+        iPocaFlags |= EPostcardRunAppShutterAtExit;
+        }
+
+    if ( IsMessageEmpty() ) 
+        {
+        if ( Document().Mtm().Entry().Entry().Visible() )
+            {
+            ShowInformationNoteL( R_POSTCARD_MESSAGE_DELETED, ETrue );
+            }
+        DeleteCurrentEntryL();
+        }
+    else if ( Document( ).Modified( ) && CanSaveMessageL() )
+        {
+        if ( IsForeground() )
+            {
+            TInt resId = R_POSTCARD_SAVING_NEW;
+            if( iMsgType == EPostcardDraft )
+                { // We are saving an old postcard
+                resId = R_POSTCARD_SAVING;
+                }
+
+            iPocaFlags |= EPostcardClosing;
+            DoSaveL();
+            ShowWaitNoteL( resId, EFalse );
+            }
+        else
+            {
+            TRAP_IGNORE( DoSaveL() );
+            }
+        BeginActiveWait();
+        if ( iPocaFlags & EPostcardRunAppShutterAtExit )
+            {
+            RunAppShutter();
+            }
+        }
+    }
+
+// ---------------------------------------------------------
+// CompleteLaunchViewL
+// ---------------------------------------------------------
+void CPostcardAppUi::CompleteLaunchViewL( )
+    {
+    iController->ActivateL( );
+	RemoveWaitNote( );
+	
+	iMsgType = Document( ).MessageType( );
+    if( iMsgType == EPostcardSent )
+        {
+	    iController->SetFocused( EPostcardImage );
+        }
+    else
+        {
+	    iController->SetFocused( EPostcardRecipient );
+            
+        // If postcard editor is opened then disable the dialer 
+        iAvkonAppUi->SetKeyEventFlags( 
+              CAknAppUiBase::EDisableSendKeyShort | 
+              CAknAppUiBase::EDisableSendKeyLong );	
+        }
+    SetMiddleSoftkeyL(); // set msk for this view
+    if( iMsgType == EPostcardSendAs )
+        {
+        CheckLengthsL(  );
+        }
+    else if( iMsgType == EPostcardForward )
+        {
+        DoEditAddressL( );
+        }
+    iController->DrawDeferred( );
+    iPocaFlags |= EPostcardLaunchSuccessful;
+    }
+
+// ---------------------------------------------------------
+// CPostcardAppUi::HandleKeyEventL
+// ---------------------------------------------------------
+TKeyResponse CPostcardAppUi::HandleKeyEventL(
+    const TKeyEvent& aKeyEvent, TEventCode aType )
+    {
+    
+    if ( !Document( ).IsLaunched( ) )
+        { // still launching
+        return EKeyWasConsumed;
+        }
+
+	if( aType != EEventKey )
+		{
+		return EKeyWasNotConsumed;
+		}
+
+    switch ( aKeyEvent.iCode )
+        {
+        case EKeyOK:
+        case EKeyEnter:         //Enter Key
+            {
+            // Selection key: Show context menus
+            DoSelectionKeyL();
+            return EKeyWasConsumed;
+            }
+
+        case EKeyYes:
+            {
+            // In view mode there's no function in Yes key
+            if( iMsgType != EPostcardSent )
+                {
+                if( !ContactHasData( *iContact ) )
+                    { // If there's no contact data -> open edit address dialog
+                    DoEditAddressL( );
+                    }
+                else
+                    { // Else start sending process
+                    DoSendL( );                
+                    }
+                }
+            return EKeyWasConsumed;
+            }
+        case EKeyBackspace:
+        case EKeyDelete:
+            {
+            // Either delete image or the whole postcard entry
+            DoBackspaceL( );
+            return EKeyWasConsumed;
+            }
+        default:
+            break;
+        }
+    switch ( aKeyEvent.iScanCode )
+        {
+        case EStdKeyLeftArrow:  // FALLTHROUGH
+        case EStdKeyRightArrow:
+            if( iMsgType == EPostcardSent && iController->Focused( ) == EPostcardImage )
+                {
+                return NavigateBetweenMessagesL(
+                    aKeyEvent.iScanCode == EStdKeyRightArrow ?
+                    ETrue : EFalse );
+                }
+		    //lint -fallthrough
+        case EStdKeyUpArrow:    // FALLTHROUGH
+        case EStdKeyDownArrow:  // FALLTHROUGH
+            {
+            if( !( iPocaFlags & EPostcardGreetingActive ) && 
+            	!( iPocaFlags & EPostcardRecipientActive ) )
+            	{
+	            iController->Move( aKeyEvent.iScanCode );
+	            SetMiddleSoftkeyL(); // set msk for this view
+	            
+                if ( iMsgType == EPostcardSent )
+                    {
+                    // In viewer
+                    if ( iController->Focused() != EPostcardImage )
+                        {
+                        // Viewer does not have navigation arrows in text side
+                        iNaviPane->Pop( iNaviDecorator );
+                        }
+                    else
+                        {
+                        iNaviPane->PushL( *iNaviDecorator );
+                        }
+                    }
+            	}
+                
+            return EKeyWasConsumed;
+            }
+        default:
+        	{
+	        if( iMsgType != EPostcardSent && iController->Focused( ) == EPostcardText )
+	            {
+	            if( !( iPocaFlags & EPostcardGreetingActive ) )
+	            	{
+	            	if( aKeyEvent.iCode >= 35 && aKeyEvent.iCode <= 255 )
+	            	    {
+    		            DoEditGreetingL( aKeyEvent );            		            	    
+	            	    }
+	            	}
+	            }
+	        else if( iMsgType != EPostcardSent && iController->Focused( ) == EPostcardRecipient )
+	            {
+	            if( !( iPocaFlags & EPostcardRecipientActive ) )
+	            	{
+	            	if( aKeyEvent.iCode >= 35 && aKeyEvent.iCode <= 255 )
+	            	    {
+    		            DoEditAddressL( aKeyEvent );
+	            	    }
+	            	}
+	            }
+            break;
+        	}
+        }
+    return EKeyWasNotConsumed;
+    }
+
+// ---------------------------------------------------------
+// HandleCommandL
+// ---------------------------------------------------------
+void CPostcardAppUi::HandleCommandL( TInt aCommand )
+    {
+    if ( aCommand != EEikCmdExit &&
+         !Document().IsLaunched() )
+        {
+        return;
+        }
+    switch (aCommand)
+        {
+        case EPostcardCmdSend:
+            DoSendL( );
+            break;
+        case EPostcardCmdEditAddress:
+            DoEditAddressL( );
+            break;
+        case EPostcardCmdEditGreeting:
+            DoEditGreetingL( );
+            break;
+        case EPostcardCmdInsertFromGallery:
+            DoInsertImageL( MsgAttachmentUtils::EImage );
+            break;
+        case EPostcardCmdInsertFromCamera:
+            DoInsertImageL( MsgAttachmentUtils::ENewImage );
+            break;
+        case EPostcardCmdReplaceFromGallery:
+            DoInsertImageL( MsgAttachmentUtils::EImage );
+            break;
+        case EPostcardCmdReplaceFromCamera:
+            DoInsertImageL( MsgAttachmentUtils::ENewImage );
+            break;
+        case EPostcardCmdDelete:
+            DoBackspaceL( );
+            break;
+        case EPostcardCmdMessageInfo:
+            DoUpdateEntryAndShowMessageInfoL( );
+            break;
+        case EPostcardCmdForward:
+            DoForwardMessageL( );
+            break;
+        case EAknSoftkeyClose:
+        	DoBackSaveL( );
+        	break;
+        case EAknSoftkeyEdit: // falltrough
+        case EAknSoftkeyOpen:
+        	DoSelectionKeyL( );
+        	break;
+        case EAknCmdHelp:
+            {            
+            if( iMsgType == EPostcardSent )
+                {
+                LaunchHelpL( KMMS_POSTCARD_HLP_MAIN_VIEW() );
+                }
+            else
+                {
+                LaunchHelpL( KMMS_POSTCARD_HLP_MAIN_EDIT() );                
+                }
+            break;
+            }
+        case EAknCmdExit:
+        case EEikCmdExit:
+            RemoveWaitNote();
+            ExitAndSaveL();
+            break;
+        default:
+            break;
+        }
+    return;
+    }
+
+// ---------------------------------------------------------
+// DynInitMenuPaneL
+// ---------------------------------------------------------
+void CPostcardAppUi::DynInitMenuPaneL( TInt aMenuId, CEikMenuPane* aMenuPane )
+    {
+    switch ( aMenuId )
+        {
+        case R_POSTCARD_MAIN_OPTIONS:
+            DynInitMainMenuL( aMenuPane );
+            break;
+
+        case R_POSTCARD_INSERT_SUBMENU:
+        case R_POSTCARD_REPLACE_SUBMENU:
+            DynInitInsertSubMenuL( aMenuPane );
+            break;
+
+        case R_POSTCARD_CONTEXT_OPTIONS:
+            DynInitContextMenuL( aMenuPane );
+            break;
+        
+        default:
+            break;
+        }
+    }
+
+// ---------------------------------------------------------
+// DynInitMainMenuL
+// ---------------------------------------------------------
+void CPostcardAppUi::DynInitMainMenuL( CEikMenuPane* aMenuPane )
+    {
+    aMenuPane->SetItemDimmed( EPostcardCmdSend, 
+        IsMainMenuOptionInvisible( EPostcardCmdSend ));
+    aMenuPane->SetItemDimmed( EPostcardCmdEditAddress, 
+        IsMainMenuOptionInvisible( EPostcardCmdEditAddress ));
+    aMenuPane->SetItemDimmed( EPostcardCmdEditGreeting, 
+        IsMainMenuOptionInvisible( EPostcardCmdEditGreeting ));
+    aMenuPane->SetItemDimmed( EPostcardCmdInsertSubmenu, 
+        IsMainMenuOptionInvisible( EPostcardCmdInsertSubmenu ));
+    aMenuPane->SetItemDimmed( EPostcardCmdReplaceSubmenu, 
+        IsMainMenuOptionInvisible( EPostcardCmdReplaceSubmenu ));
+    aMenuPane->SetItemDimmed( EPostcardCmdInsertFromGallery, 
+        IsMainMenuOptionInvisible( EPostcardCmdInsertFromGallery ));
+    aMenuPane->SetItemDimmed( EPostcardCmdReplaceFromGallery, 
+        IsMainMenuOptionInvisible( EPostcardCmdReplaceFromGallery ));
+    aMenuPane->SetItemDimmed( EPostcardCmdForward, 
+        IsMainMenuOptionInvisible( EPostcardCmdForward ));
+    aMenuPane->SetItemDimmed( EPostcardCmdDelete, 
+        IsMainMenuOptionInvisible( EPostcardCmdDelete ));
+    aMenuPane->SetItemDimmed( EPostcardCmdMessageInfo, 
+        IsMainMenuOptionInvisible( EPostcardCmdMessageInfo ));
+    aMenuPane->SetItemDimmed( EAknCmdHelp, 
+        IsMainMenuOptionInvisible( EAknCmdHelp ));
+    aMenuPane->SetItemDimmed( EAknCmdExit, 
+        IsMainMenuOptionInvisible( EAknCmdExit ));
+    }
+
+// ---------------------------------------------------------
+// DynInitInsertSubMenuL
+// ---------------------------------------------------------
+void CPostcardAppUi::DynInitInsertSubMenuL( CEikMenuPane* aMenuPane )
+    {
+    // If insert/replace submenu is visible -> from Gallery is always visible!
+    if ( !iImage )
+        {
+        aMenuPane->SetItemDimmed( EPostcardCmdInsertFromCamera, 
+                IsMainMenuOptionInvisible( EPostcardCmdInsertFromCamera ));
+        }
+    else
+        {
+        aMenuPane->SetItemDimmed( EPostcardCmdReplaceFromCamera, 
+                IsMainMenuOptionInvisible( EPostcardCmdReplaceFromCamera ));
+        }
+    
+    }
+
+// ---------------------------------------------------------
+// DynInitContextMenuL
+// ---------------------------------------------------------
+void CPostcardAppUi::DynInitContextMenuL( CEikMenuPane* aMenuPane )
+    {
+    aMenuPane->SetItemDimmed( EPostcardCmdInsertSubmenu, 
+        IsMainMenuOptionInvisible( EPostcardCmdInsertSubmenu ));
+    aMenuPane->SetItemDimmed( EPostcardCmdReplaceSubmenu, 
+        IsMainMenuOptionInvisible( EPostcardCmdReplaceSubmenu ));
+    aMenuPane->SetItemDimmed( EPostcardCmdInsertFromGallery, 
+        IsMainMenuOptionInvisible( EPostcardCmdInsertFromGallery ));
+    aMenuPane->SetItemDimmed( EPostcardCmdReplaceFromGallery, 
+        IsMainMenuOptionInvisible( EPostcardCmdReplaceFromGallery ));
+    }
+
+// ---------------------------------------------------------
+// IsMainMenuOptionInvisible
+// ---------------------------------------------------------
+TBool CPostcardAppUi::IsMainMenuOptionInvisible( TInt aMenuItem )
+    {
+    TBool retVal( ETrue ); // Everything first invisible
+    TPostcardPart focused = iController->Focused( );
+
+    switch ( aMenuItem )
+        {
+        case EPostcardCmdSend:
+            if( iMsgType != EPostcardSent )
+                {
+                if( ContactHasData( *iContact ) )
+                    {
+                    // If there's contact data -> show "Send"
+                    retVal = EFalse;                
+                    }
+                }
+            break;
+        case EPostcardCmdEditAddress:
+            if( iMsgType != EPostcardSent && focused != EPostcardImage )
+                {
+                retVal = EFalse;
+                }
+            break;
+        case EPostcardCmdEditGreeting:
+            if( iMsgType != EPostcardSent && focused != EPostcardImage )
+                {
+                retVal = EFalse;
+                }
+            break;
+        case EPostcardCmdInsertSubmenu:
+            if( iMsgType != EPostcardSent && !iImage )
+                {
+                if( iPocaFlags & EPostcardCamcorder )
+                	{
+	                retVal = EFalse;            		
+                	}
+                }
+            break;
+        case EPostcardCmdReplaceSubmenu:
+            if( iMsgType != EPostcardSent && iImage )
+                {
+                if( iPocaFlags & EPostcardCamcorder )
+                	{
+	                retVal = EFalse;            		
+                	}
+                }
+            break;
+        case EPostcardCmdInsertFromGallery:
+            if( iMsgType != EPostcardSent && !iImage )
+                {
+                if( !(iPocaFlags & EPostcardCamcorder ) )
+                	{
+	                retVal = EFalse;            		
+                	}
+                }
+            break;
+        case EPostcardCmdReplaceFromGallery:
+            if( iMsgType != EPostcardSent && iImage )
+                {
+                if( !(iPocaFlags & EPostcardCamcorder ) )
+                	{
+	                retVal = EFalse;            		
+                	}
+                }
+            break;
+        case EPostcardCmdInsertFromCamera:
+            if( iMsgType != EPostcardSent )
+                {
+                if( iPocaFlags & EPostcardCamcorder )
+                	{
+	                retVal = EFalse;            		
+                	}
+                }
+            break;
+        case EPostcardCmdReplaceFromCamera:
+            if( iMsgType != EPostcardSent && iImage )
+                {
+                if( iPocaFlags & EPostcardCamcorder )
+                    {
+                    retVal = EFalse;                    
+                    }
+                }
+            break;
+        case EPostcardCmdForward:
+            if( iMsgType == EPostcardSent )
+                {
+                retVal = EFalse;
+                }
+            break;
+        case EPostcardCmdDelete:
+            if( iMsgType == EPostcardSent )
+                {
+                retVal = EFalse;
+                }
+            break;
+        case EPostcardCmdMessageInfo:
+            retVal = EFalse;
+            break;
+        case EAknCmdHelp:
+			if( iPocaFlags & EPostcardHelp )
+				{
+				retVal = EFalse;				
+				}
+			break;
+        case EAknCmdExit:
+            retVal = EFalse;
+            break;
+        default:
+            ;
+        }
+    return retVal;
+    }
+
+// ---------------------------------------------------------
+// DoSendL
+// ---------------------------------------------------------
+void CPostcardAppUi::DoSendL()
+    {
+	// Let's first check all the fields are present
+	if( !iImage )
+		{
+		ShowInformationNoteL( R_POSTCARD_SEND_INSERT_IMAGE, EFalse );
+	    iController->SetFocused( EPostcardImage );
+	    SetMiddleSoftkeyL();
+	    iController->DrawDeferred( );    
+		return;
+		}
+
+    // Check that mandatory address fields are present
+    TInt mandatories = MandatoryAddressFields();
+    CContactItemFieldSet& fields = iContact->CardFields();
+    TBool allFilled = ETrue;
+    TInt i = EPostcardAddressName;
+    for( ; mandatories && allFilled ; i++, mandatories >>= 1 )
+        {
+        if( mandatories & 1 )
+            {
+            const CContactItemField* field = TPostcardUtils::FieldOrNull( fields,
+                TPostcardUtils::ContactItemNameFromId( i ) );
+            allFilled = ( field && field->TextStorage()->IsFull() );
+            }
+        }
+    // If not all filled, open the edit address dialog with the right field
+    if( !allFilled )
+        {
+        DoEditAddressL( TKeyEvent(), i - 1 );
+		return;
+        }
+
+    // Address is ok, let's still check the lengths..
+	if( !CheckLengthsL( ) )
+		{
+		return;
+		}
+	
+	// Here we are ready to send -> now let's ask the confirmation
+    if( iMessageQuery )
+        {
+        iMessageQuery->CancelMsgQuery();
+        delete iMessageQuery;
+        iMessageQuery = NULL;
+        }
+
+   
+    iMessageQuery = CAknGlobalMsgQuery::NewL();
+
+    HBufC* addressString = CreateAddressStringForSendConfirmLC();
+
+    delete iSendText; iSendText = NULL;
+    iSendText = StringLoader::LoadL( R_POSTCARD_RECIPIENT_PROMPT_TEXT,
+        *addressString );
+    CleanupStack::PopAndDestroy( addressString ); // addressString
+
+    CPostcardQueryWaiter* queryWaiter = new (ELeave) CPostcardQueryWaiter( this );
+    CleanupStack::PushL( queryWaiter );
+
+    iMessageQuery->ShowMsgQueryL( 
+            queryWaiter->iStatus,
+            *iSendText,
+            R_AVKON_SOFTKEYS_SEND_CANCEL__SEND,
+            KNullDesC(),
+            KAvkonBitmapFile,
+            EMbmAvkonQgn_note_query,
+            EMbmAvkonQgn_note_query_mask );
+
+    queryWaiter->SetActiveD(); // Will be deleted when the query is dismissed.
+    CleanupStack::Pop( queryWaiter ); // queryWaiter
+
+    // The rest of the sending process is done in QueryWaiterCallback !!
+    }
+
+// ---------------------------------------------------------
+// DoSaveL
+// ---------------------------------------------------------
+void CPostcardAppUi::DoSaveL( )
+    {
+    if ( iOperation && iOperation->IsActive() )
+        {
+        // Save operation already in progress, don't start another
+        return;
+        }
+    
+    delete iOperation;
+    iOperation = NULL;
+    
+    iOperation = CPostcardOperationSave::NewL(
+        *this,
+        Document(),
+        *this,
+        FsSession( ),
+        *iContact,
+        *iGreeting
+        );
+        
+    iOperation->Start( EFalse );    // EFalse means no sending
+    
+    iAbsorber = CAknInputBlock::NewLC();
+    CleanupStack::Pop( iAbsorber );
+    }
+
+// ---------------------------------------------------------
+// DoBackSaveL
+// ---------------------------------------------------------
+void CPostcardAppUi::DoBackSaveL()
+    {
+    if( iMsgType == EPostcardSent )
+        {
+        // Msg is a sent one so just close the application
+        Exit( EAknSoftkeyClose );
+        return;
+        }
+        
+    if ( IsMessageEmpty() ) 
+        {
+        if ( Document().Mtm().Entry().Entry().Visible() )
+            {
+            ShowInformationNoteL( R_POSTCARD_MESSAGE_DELETED, ETrue );
+            }
+        DeleteAndExitL();
+        }
+    else
+        {
+        TInt closeVal = ShowCloseQueryL( );
+        if ( closeVal == EPostcardCloseCancel )
+            {
+            // User cancels the query
+            return;
+            }
+        else if ( closeVal == EPostcardCloseDelete )
+            {
+            DeleteAndExitL();
+            }
+        else
+            {
+            // Save message
+            if ( Document( ).Modified( ) )
+                {
+                if ( CanSaveMessageL() ) 
+                    {
+                    TInt resId = R_POSTCARD_SAVING_NEW;
+                    if( iMsgType == EPostcardDraft )
+                        {
+                        // We are saving an old postcard
+                        resId = R_POSTCARD_SAVING;
+                        }
+                        
+                    iPocaFlags |= EPostcardClosing;
+                    DoSaveL( );
+                    ShowWaitNoteL( resId, ETrue );
+                    BeginActiveWait();
+                    }
+                else
+                    {
+                    if ( ShowConfirmationQueryL( R_POSTCARD_NO_SPACE_TO_SAVE ) )
+                        {
+                        // Exit without saving.
+                        Exit( EAknSoftkeyClose );
+                        }
+                    //else nothing.
+                    }
+                }
+            else
+                {
+                // No changes -> just close.
+                Exit( EAknSoftkeyClose );
+                }
+            }
+        }        
+    }
+
+// ---------------------------------------------------------
+// IsMessageEmpty
+// ---------------------------------------------------------
+TBool CPostcardAppUi::IsMessageEmpty( )
+    {
+    if( !iImage && iGreetingLength == 0 &&
+        ( !iContact || !ContactHasData( *iContact ) ) )
+        {
+        return ETrue;
+        }
+    return EFalse;
+    }
+
+// ---------------------------------------------------------
+// DoUpdateEntryAndShowMessageInfoL
+// ---------------------------------------------------------
+void CPostcardAppUi::DoUpdateEntryAndShowMessageInfoL( )
+    {
+    // First update the TMsvEntry
+    if( iMsgType != EPostcardSent )
+        { 
+        // We are dealing with unsent message -> save recipient/text for now
+        TMmsMsvEntry tEntry = static_cast<TMmsMsvEntry>( Document().Entry() );
+
+        tEntry.iDate.UniversalTime();
+
+        // Let's find name field
+        _LIT( KEmptyName, "");
+        TPtrC namePtr( KEmptyName );
+        CContactItemFieldSet& fieldSet =  iContact->CardFields();
+        for( TInt i = 0; i<fieldSet.Count(); i++ )
+            {
+            if( !fieldSet[i].Label().Compare( TPostcardUtils::ContactItemNameFromId( EPostcardAddressName ) ) )
+                {
+                namePtr.Set( fieldSet[i].TextStorage()->Text() );
+                break;
+                }
+            }
+        tEntry.iDetails.Set( namePtr ) ;
+        // Let's set the subject
+        tEntry.iDescription.Set(
+            iGreeting->Read( 0, Min( iGreetingLength, 20 ) ) );
+        
+    	tEntry.iBioType = KUidMsgSubTypeMmsPostcard.iUid;
+        
+        Document().CurrentEntry().ChangeL( tEntry );
+        }
+    // And now call message info
+    DoShowMessageInfoL();
+    }
+
+// ---------------------------------------------------------
+// DoShowMessageInfoL
+// ---------------------------------------------------------
+void CPostcardAppUi::DoShowMessageInfoL()
+    {
+    // Selection is not really used, just given as a parameter
+    CMsvEntrySelection* selection = new ( ELeave ) CMsvEntrySelection;
+    CleanupStack::PushL( selection );
+    TBuf8<1> param;
+    param.Zero();
+
+    CMsvSingleOpWatcher* watch = CMsvSingleOpWatcher::NewLC( Document() );
+    
+    CMsvOperation* op = Document().MtmUi().InvokeAsyncFunctionL(
+        KMtmUiFunctionMessageInfo,
+        *selection,
+        watch->iStatus,
+        param );
+    CleanupStack::Pop( watch ); // watch
+    Document().AddSingleOperationL( op, watch );
+
+    CleanupStack::PopAndDestroy( selection ); // selection
+    }
+
+// ---------------------------------------------------------
+// DoBackspaceL
+// ---------------------------------------------------------
+void CPostcardAppUi::DoBackspaceL( )
+    {
+    if( iMsgType == EPostcardSent )
+        {
+        if( ShowConfirmationQueryL( R_POSTCARD_DELETE_MESSAGE ) )
+            {
+            DeleteAndExitL( );
+            }
+        }
+    else 
+        {
+        if( iController->Focused( ) == EPostcardImage && iImage )
+            {
+            if( ShowConfirmationQueryL( R_POSTCARD_REMOVE_IMAGE ) )
+            	{
+				// Lets go thru the attas to find the right atta
+        		CMsvStore* editStore = Document( ).Mtm( ).Entry( ).EditStoreL( );
+				MMsvAttachmentManager* manager = &( editStore->AttachmentManagerL( ) );
+			    TInt count = manager->AttachmentCount( );
+    			CMsvAttachment* atta = NULL;
+    			TInt a = 0;
+			    for( ; a < count; a++)
+        			{
+			        atta = manager->GetAttachmentInfoL( a );
+        			CleanupStack::PushL( atta );
+        			if( Document( ).IsImage( atta->MimeType( ) ) )
+        				{
+						CleanupStack::PopAndDestroy( atta );
+        				break;
+        				}
+					CleanupStack::PopAndDestroy( atta );
+        			}
+        		if( a > -1 && a < count )
+        			{
+        			// and delete atta if found
+					editStore->AttachmentManagerExtensionsL( ).RemoveAttachmentL( a );    				
+        			}
+		    	editStore->CommitL( );
+			    delete editStore;
+                // Lets nullify the icon in Controller
+    	        iController->SetBitmap( EPostcardImage, NULL );
+	            iImage = NULL;
+	            // And draw the UI again
+        		iController->DrawDeferred( );
+            	}
+            }
+        }
+    }
+
+// ---------------------------------------------------------
+// DoForwardMessageL
+// ---------------------------------------------------------
+void CPostcardAppUi::DoForwardMessageL( )
+    {
+    TMsvPartList parts =
+        KMsvMessagePartBody |
+        KMsvMessagePartDescription |
+        KMsvMessagePartAttachments;
+
+    CBaseMtmUi& mtmUi = Document().MtmUi();
+
+    CMsgOperationWait* wait =
+        CMsgOperationWait::NewLC( EActivePriorityWsEvents + 10 );
+
+    mtmUi.SetPreferences( mtmUi.Preferences() | EMtmUiFlagEditorPreferEmbedded );
+    CMsvOperation* oper = mtmUi.ForwardL( KMsvDraftEntryIdValue, parts, wait->iStatus );
+    CleanupStack::PushL( oper );
+
+    wait->Start();
+
+    CleanupStack::PopAndDestroy( 2 );  // wait, oper
+    }
+
+// ---------------------------------------------------------
+// DoEditAddressL
+// ---------------------------------------------------------
+void CPostcardAppUi::DoEditAddressL( TKeyEvent aKeyEvent /*=TKeyEvent()*/,
+                               				TInt aFirstFocused /*=-1*/)
+    { 
+	CPostcardAddressForm* form = NULL;
+	TInt ret = 0;
+    iController->SetFocused( EPostcardRecipient );
+    form = CPostcardAddressForm::NewL( *this, Document(), *iContact, ret,
+        aFirstFocused, aKeyEvent );
+    form->SetMopParent( iController );
+    iPocaFlags |= EPostcardRecipientActive;
+
+    // Form might leave with KLeaveExit from CPostcardContact, 
+    // so we need to trap it and take proper actions. If it leaves,
+    // it means that Messaging is closed from FSW and there has been
+    // an active AIW to phonebook.
+    TRAPD( err, form->ExecLD() );
+
+	iPocaFlags &= ~EPostcardRecipientActive;
+    if ( err )
+        {
+        // form must be deleted here, since for some reason its destructor is
+        // not called, if leave oocurs in ExecLD.
+        delete form;
+        form = NULL;
+        User::Leave( err );
+        }
+
+    if( ret == EPostcardDialogExit )
+        {
+        // If exit -> we need to save if possible
+        iPocaFlags |= EPostcardExitCalledFromDialog;
+        if ( Document( ).Modified( ) )
+            {
+            if ( CanSaveMessageL() )
+                {
+                TInt resId = R_POSTCARD_SAVING;
+                ShowWaitNoteL( resId, ETrue );
+                DoSaveL( );
+                }
+            else
+                {
+                // No space -> exit without saving.
+                Exit( EEikCmdExit );
+                }
+            }
+        else
+            {
+            Exit( EEikCmdExit );         
+            }
+        }
+    else if( iMsgType == EPostcardSent )
+        {
+        if( ret == EPostcardDialogForward )
+            {
+            DoForwardMessageL( );
+            return;
+            }           
+        iController->DrawDeferred( );
+        }
+	else
+		{
+		Document( ).SetChanged( EPostcardRecipient );
+        iController->DrawDeferred( );
+		if( ret == EPostcardDialogSend )
+		    {
+            DoSendL( );		    
+		    }
+		}
+    }
+
+// ---------------------------------------------------------
+// DoEditGreetingL
+// ---------------------------------------------------------
+void CPostcardAppUi::DoEditGreetingL( TKeyEvent aKeyEvent )
+    { 
+    CPostcardTextDialog* dialog = NULL;
+    TInt ret = 0;
+    iController->SetFocused( EPostcardText );
+    dialog = CPostcardTextDialog::NewL(*this, Document(), *iGreeting, 
+        ret, aKeyEvent );
+    dialog->SetMopParent( iController );
+    iPocaFlags |= EPostcardGreetingActive;
+    TRAP_IGNORE( dialog->ExecLD() );
+
+	iPocaFlags &= ~EPostcardGreetingActive;
+
+    if( ret == EPostcardDialogExit )
+        {
+        // If exit -> we need to save if possible
+        iPocaFlags |= EPostcardExitCalledFromDialog;
+        if ( Document( ).Modified( ) )
+            {
+            if ( CanSaveMessageL() )
+                {
+                TInt resId = R_POSTCARD_SAVING;
+                ShowWaitNoteL( resId, ETrue );
+                DoSaveL( );
+                }
+            else
+                {
+                // No space -> exit without saving.
+                Exit( EEikCmdExit );                
+                }
+            }
+        else
+            {
+            Exit( EEikCmdExit );         
+            }
+        }
+    else if( iMsgType == EPostcardSent )
+        {
+        if( ret == EPostcardDialogForward )
+            {
+            DoForwardMessageL( );
+            return;
+            }           
+        iController->DrawDeferred( );
+        }
+	else
+		{
+		Document( ).SetChanged( EPostcardText );
+        iController->DrawDeferred( );
+		if( ret == EPostcardDialogSend )
+		    {
+		    // Send chosen in greeting dialog
+            if( ContactHasData( *iContact ) )
+                {
+                // If there's contact data -> start sending
+                DoSendL( );
+                }
+            else
+                {
+                // If no contact data -> open address dialog
+                DoEditAddressL( );                
+                }
+		    }
+		}
+    }
+
+// ---------------------------------------------------------
+// DoInsertImageL
+// ---------------------------------------------------------
+void CPostcardAppUi::DoInsertImageL( MsgAttachmentUtils::TMsgAttachmentFetchType aFetchType )
+    {
+    iController->SetFocused( EPostcardImage );
+    SetMiddleSoftkeyL(); // set msk for the view
+    if ( FetchFileL( aFetchType ) )
+        {
+        // The file is selected and iImageInfo created
+
+	    ShowWaitNoteL( R_POSTCARD_WAIT_INSERTING, EFalse );
+
+        iOperation = CPostcardOperationInsertImage::NewL(
+            *this,
+            Document(),
+            *this,
+            iImageInfo,
+            FsSession() );
+        iImageInfo = NULL; // ownership moves
+        iOperation->Start( EFalse );
+        
+        iAbsorber = CAknInputBlock::NewLC();
+        CleanupStack::Pop( iAbsorber );
+        }
+
+    iController->DrawDeferred( );
+    }
+
+// ---------------------------------------------------------
+// FetchFileL
+// ---------------------------------------------------------
+TBool CPostcardAppUi::FetchFileL( MsgAttachmentUtils::TMsgAttachmentFetchType aFetchType )
+    {
+    CDesCArrayFlat* dummy = new ( ELeave ) CDesCArrayFlat( 1 );
+    CleanupStack::PushL( dummy );
+    TFileName fileName;
+    TBool fetchOK = MsgAttachmentUtils::FetchFileL(
+        aFetchType,
+        fileName,
+        *dummy,
+        ETrue,
+        EFalse,
+        this );
+
+    CleanupStack::PopAndDestroy( dummy );
+
+    switch ( aFetchType )
+        {
+        case MsgAttachmentUtils::ENewImage:
+        case MsgAttachmentUtils::ENewAudio:
+        case MsgAttachmentUtils::ENewVideo:            
+            {
+            if ( fetchOK )
+                {
+                // Something was fetched
+                fetchOK = CreateMediaInfoForInsertL( fileName )
+                    ? ETrue
+                    : EFalse;
+                }
+            }
+            break;
+        case MsgAttachmentUtils::EImage:
+        case MsgAttachmentUtils::EAudio:
+        case MsgAttachmentUtils::EVideo:
+        default:
+            // CreateMediaInfoForInsertL is called in VeritySelectionL
+            break;
+        }
+    return fetchOK;
+    }
+
+
+// ---------------------------------------------------------
+// VerifySelectionL
+// ---------------------------------------------------------
+TBool CPostcardAppUi::VerifySelectionL( const MDesCArray* aSelectedFiles )
+    {
+    CAknInputBlock* blocker = CAknInputBlock::NewLC();
+
+    TBool ret = EFalse;
+    if ( aSelectedFiles->MdcaCount() == 1 )
+        {
+        TPtrC ptr = aSelectedFiles->MdcaPoint( 0 );
+        if ( CreateMediaInfoForInsertL( ptr ) )
+            {
+            ret = ETrue;
+            }
+        }
+        
+    CleanupStack::PopAndDestroy( blocker );  // Input blocker
+    return ret;
+    }
+
+// ---------------------------------------------------------
+// CreateMediaInfoForInsertL
+// ---------------------------------------------------------
+TBool CPostcardAppUi::CreateMediaInfoForInsertL( const TDesC& aFileName )
+    {
+    if( iImageInfo )
+    	{
+    	delete iImageInfo;
+    	iImageInfo = NULL;
+    	}
+
+    RFile fileHandle = Document().MediaResolver()->FileHandleL( aFileName );
+    CleanupClosePushL( fileHandle );
+	iImageInfo = static_cast<CMsgImageInfo*>( Document().MediaResolver()->CreateMediaInfoL( fileHandle ) );
+	Document().MediaResolver()->ParseInfoDetailsL( iImageInfo, fileHandle );
+	CleanupStack::PopAndDestroy( &fileHandle );
+
+    TInt errResId = 0;
+
+    if ( !CanSaveMessageL( iImageInfo->FileSize() ) )
+        {
+        User::Leave( KErrDiskFull );
+        }
+
+    // Supported type check
+    if( iImageInfo->Protection( ) )
+        {
+        errResId = R_POSTCARD_CANNOT_SEND_PROTECTED;        
+        }
+    else if ( iImageInfo->Corrupt() )
+        {
+        // Corrupt is set to only supported media types
+        errResId = R_POSTCARD_OBJECT_CORRUPTED;
+        }
+    else if( !Document( ).IsImage( iImageInfo->MimeType( ) ) )
+    	{
+        errResId = R_POSTCARD_FORMAT_NOT_SUPPORTED;    		
+    	}
+    // DRM check
+    else if ( iImageInfo->MediaType() != EMsgMediaImage )
+        {
+        // Keep this after DRM check!
+        errResId = R_POSTCARD_FORMAT_NOT_SUPPORTED;
+        }
+    else if ( iImageInfo->IsAnimation( ) )
+        {
+        errResId = R_POSTCARD_FORMAT_NOT_SUPPORTED;
+        }
+
+    if ( errResId != 0 )
+        {
+        delete iImageInfo;
+        iImageInfo = NULL;
+        ShowInformationNoteL( errResId, EFalse );
+        return EFalse;
+        }
+    return ETrue;
+
+    }
+
+// ---------------------------------------------------------
+// DoSelectionKeyL
+// ---------------------------------------------------------
+void CPostcardAppUi::DoSelectionKeyL()
+    {
+	if( iMsgType != EPostcardSent )
+		{
+		// We are in editor mode
+		TPostcardPart focused = iController->Focused( );
+		switch ( focused )
+        	{
+        	case EPostcardImage:
+        		{
+		        MenuBar( )->SetMenuTitleResourceId( R_POSTCARD_CONTEXT_MENUBAR );
+		        MenuBar()->SetMenuType(CEikMenuBar::EMenuContext);
+		        // if display fails set old menu back
+		        TRAPD( err, MenuBar( )->TryDisplayMenuBarL( ) ); 
+		        MenuBar( )->SetMenuTitleResourceId( R_POSTCARD_MAIN_MENUBAR );
+		        MenuBar()->SetMenuType(CEikMenuBar::EMenuOptions);
+		        User::LeaveIfError( err );
+        		break;
+        		}
+    		case EPostcardRecipient:
+    			{
+    			DoEditAddressL( );
+    			break;
+    			}
+    		case EPostcardText:
+    			{
+    			DoEditGreetingL( );
+    			break;
+    			}
+    		default:
+    			break;
+	        }
+		}
+	else
+		{
+		// We are in viewer mode
+		TPostcardPart focused = iController->Focused( );
+		switch ( focused )
+        	{
+        	case EPostcardImage:
+        		{
+        		break;
+        		}
+    		case EPostcardRecipient:
+    			{
+    			DoEditAddressL( );
+    			break;
+    			}
+    		case EPostcardText:
+    			{
+    			DoEditGreetingL( );
+    			break;
+    			}
+    		default:
+    			break;
+	        }			
+		}
+    return;
+    }
+    
+// ---------------------------------------------------------
+// LaunchHelpL
+// ---------------------------------------------------------
+void CPostcardAppUi::LaunchHelpL( const TDesC& aContext )
+    {
+    CArrayFix<TCoeHelpContext>* 
+        helpContext = new(ELeave) CArrayFixFlat<TCoeHelpContext>( 1 );
+    TCoeHelpContext context( TUid::Uid(0x10207247), aContext );
+    helpContext->AppendL( context );
+    HlpLauncher::LaunchHelpApplicationL( iEikonEnv->WsSession( ), helpContext );    
+    }
+
+// ---------------------------------------------------------
+// FsSession
+// ---------------------------------------------------------
+RFs& CPostcardAppUi::FsSession() const
+    {
+    return ( iCoeEnv->FsSession() );
+    }
+
+#ifdef RD_SCALABLE_UI_V2
+// ---------------------------------------------------------
+// CPostcardAppUi::PocaPointerEvent
+// ---------------------------------------------------------
+void CPostcardAppUi::PocaPointerEventL( TPocaPointerEvent aEvent,
+    TPocaPointerEventType aEventType )
+    {
+    if ( AknLayoutUtils::PenEnabled() )
+        {
+        // Handle pointer (pen) events to areas in main pane
+        switch( aEvent )
+            {
+            case EPocaPointerEventUpIcon:
+            case EPocaPointerEventDownIcon:
+                iController->MoveVertically( aEvent == EPocaPointerEventUpIcon ? ETrue : EFalse );
+                
+                if ( iMsgType == EPostcardSent )
+                    {
+                    // In viewer
+                    if ( iController->Focused() != EPostcardImage )
+                        {
+                        // Viewer does not have navigation arrows in text side
+                        iNaviPane->Pop( iNaviDecorator );
+                        }
+                    else
+                        {
+                        iNaviPane->PushL( *iNaviDecorator );
+                        }
+                    }
+                break;
+                
+            case EPocaPointerEventGreeting:
+                if( iController->Focused() == EPostcardText )
+                    {
+                    DoSelectionKeyL();
+                    }
+                else
+                    {
+                    iController->MoveHorizontally(
+                        aEvent == EPocaPointerEventAddress ? ETrue : EFalse );
+                    }
+                break;
+            case EPocaPointerEventAddress:
+                if( iController->Focused() == EPostcardRecipient )
+                    {
+                    DoSelectionKeyL();
+                    }
+                else
+                    {
+                    iController->MoveHorizontally(
+                        aEvent == EPocaPointerEventAddress ? ETrue : EFalse );
+                    }
+               break;
+            case EPocaPointerEventFrontBg: // front picture area
+                DoSelectionKeyL();
+                break;
+            default:
+                ;
+            }
+        SetMiddleSoftkeyL(); // set msk for the view
+        }
+    else
+        {
+        // Suppress warnings
+        aEvent = aEvent;
+        aEventType = aEventType;
+        }
+    }
+
+#endif // RD_SCALABLE_UI_V2
+
+// ---------------------------------------------------------
+// CPostcardAppUi::MenuBar
+// Returns application menubar.
+// ---------------------------------------------------------
+CEikMenuBar* CPostcardAppUi::MenuBar() const
+    {
+    return iEikonEnv->AppUiFactory()->MenuBar();
+    }
+
+// ---------------------------------------------------------
+// CPostcardAppUi::HandleResourceChangeL
+// ---------------------------------------------------------
+void CPostcardAppUi::HandleResourceChangeL(TInt aType)
+    {
+    CMsgEditorAppUi::HandleResourceChangeL(aType);
+	if ( aType == KEikDynamicLayoutVariantSwitch )
+        {
+        // The layout is changing -> reread coordinates
+        if ( iController )
+    	   	{
+        	iController->RefreshCoordinates( );
+        	}
+    	if ( iGreetingLength )
+    		{
+    		CreateGreetingBitmapL( );
+    		}
+        if ( ContactHasData( ) )
+            {
+            RefreshRecipientBitmapL( );
+            }
+        RefreshFocusLinesL( );
+        if ( iController )
+            {
+            iController->DrawDeferred( );
+            }
+        
+        SetTitleIconL();
+        }
+    else if ( aType == KAknsMessageSkinChange )
+        {
+        CreateAndSetTitleIconL();
+        // The skin is changing -> recreate icons and refresh coordinates
+        if( iController )
+            {
+            iController->ReLoadIconsL( );
+            }
+        }
+    }
+
+// ---------------------------------------------------------
+// CPostcardAppUi::ShowCloseQueryL
+// ---------------------------------------------------------
+TInt CPostcardAppUi::ShowCloseQueryL()
+    {
+    TInt selectedIndex( 0 );
+    CAknListQueryDialog* dlg = new ( ELeave ) CAknListQueryDialog( &selectedIndex );
+    dlg->PrepareLC( R_POSTCARD_CLOSE_QUERY );
+    if ( dlg->RunLD() )
+        {
+        return ( selectedIndex == 0 )
+            ? EPostcardCloseSave
+            : EPostcardCloseDelete;
+        }
+    else
+        {
+        return EPostcardCloseCancel;
+        }
+    }
+
+// ---------------------------------------------------------
+// CPostcardAppUi::ExitAndSaveL
+// ---------------------------------------------------------
+void CPostcardAppUi::ExitAndSaveL()
+    {
+    if ( iPocaFlags & EPostcardClosing )
+        {
+        Exit( EAknSoftkeyClose );
+        return;
+        }
+    
+    if ( CAknEnv::AppWithShutterRunning() )
+        {
+        iPocaFlags |= EPostcardRunAppShutterAtExit;
+        }
+
+    if ( iPocaFlags & EPostcardLaunchSuccessful &&
+         Document().MediaAvailable() )
+        {
+        DoMsgSaveExitL();
+        }
+    
+    Exit();
+    }
+
+// ---------------------------------------------------------
+// CPostcardAppUi::PostcardOperationEvent
+// ---------------------------------------------------------
+void CPostcardAppUi::PostcardOperationEvent(
+            TPostcardOperationType aOperation,
+            TPostcardOperationEvent aEvent )
+    {
+    // If a large image is inserted, it may take enough time for a screen
+    // backlight to go off. It wouldn't reactivate unless inactivity timer
+    // is reseted (or user presses a key).
+    User::ResetInactivityTime();
+
+    delete iAbsorber;
+    iAbsorber = NULL;
+
+    if( aOperation == EPostcardOperationOpen )
+        { 
+        if( aEvent == EPostcardOperationError )
+            {
+            RemoveWaitNote( );
+            TInt error = iOperation->GetError( );
+            if( error == R_POSTCARD_FORMAT_NOT_SUPPORTED ||
+                error == R_POSTCARD_MULTIPLE_FILES ||
+                error == R_POSTCARD_CANNOT_SEND_PROTECTED ||
+                error == R_POSTCARD_PROCESS_NOT_SUCCESSFUL ||
+                error == R_POSTCARD_OBJECT_CORRUPTED )
+                {
+                TRAP_IGNORE( ShowInformationNoteL( error, EFalse ) );
+                }
+            iOperation->Cancel( );
+            delete iOperation;
+            iOperation = NULL;
+            TRAP_IGNORE( iController->ActivateL( ) ); // This is called to give infonote more time
+            DoDelayedExit( 0 );
+            }
+        else
+            {
+            // Delete opening operation. CompleteLaunchViewL() may start
+            // a save operation.
+            delete iOperation;
+            iOperation = NULL;
+            // Change state only if opening an existing message. State for a changed
+            // item is changed when it is really edited. This prevents saving of empty
+            // messages to drafts.
+            if ( Document().MessageType() != EPostcardNew &&
+                 Document().MessageType() != EPostcardSent )
+                {
+                if ( iImage )
+                    {
+                    Document().SetChanged( EPostcardImage );
+                    }
+                if ( iGreeting )
+                    {
+                    Document().SetChanged( EPostcardText );                
+                    }
+                if ( iContact )
+                    {
+                    Document().SetChanged( EPostcardRecipient );
+                    }
+                }
+
+            TRAP_IGNORE( CompleteLaunchViewL( ) );
+            }        
+        }
+    else if( aOperation == EPostcardOperationSave )
+        {
+        if( iOperation->GetError( ) )
+        	{
+        	TRAP_IGNORE( ShowGlobalInformationNoteL( iOperation->GetError( ), EFalse ) );
+        	}
+        delete iOperation;
+        iOperation = NULL;
+
+        RemoveWaitNote();
+        if( aEvent == EPostcardOperationError )
+            {
+            Exit( EAknSoftkeyClose );
+            }
+        else
+            {
+            DoDelayedExit( 0 );
+            }
+        EndActiveWait();
+        }
+    else
+    	{
+    	// Insert image operation
+    	TInt error = iOperation->GetError( );
+        if( error )
+        	{
+        	if( error == R_POSTCARD_FORMAT_NOT_SUPPORTED ||
+                error == R_POSTCARD_PROCESS_NOT_SUCCESSFUL )
+        		{
+	        	TRAP_IGNORE( ShowInformationNoteL( error, EFalse ) );
+        		}
+        	}
+    	delete iOperation;
+    	iOperation = NULL;
+    	delete iImageInfo;
+    	iImageInfo = NULL;
+    	RemoveWaitNote( );
+	    iController->DrawDeferred( );	
+	    Document( ).SetChanged( EPostcardImage );
+    	}
+    }
+
+// ---------------------------------------------------------
+// DoDelayedExit
+// ---------------------------------------------------------
+void CPostcardAppUi::DoDelayedExit( TInt aDelayTime )
+    {
+    if ( !iIdle )
+        {
+        
+        }
+    iIdle->Cancel();
+    iIdle->Start( aDelayTime,
+                  aDelayTime, 
+                  TCallBack( DelayedExit, this ));
+    }
+
+// ---------------------------------------------------------
+// DelayedExit
+// ---------------------------------------------------------
+TInt CPostcardAppUi::DelayedExit( TAny* aThis )
+    {
+    CPostcardAppUi* editor = static_cast<CPostcardAppUi*>( aThis );
+    editor->DoExternalExit();
+	CAknEnv::RunAppShutter( );
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------
+// DoExternalExit
+// ---------------------------------------------------------
+void CPostcardAppUi::DoExternalExit()
+    {
+    RemoveWaitNote( );
+    if( iOperation )
+        {
+        delete iOperation;
+        iOperation = NULL;
+        }
+    
+    if( iPocaFlags & EPostcardExitCalledFromDialog )
+        {
+        Exit( EAknCmdExit );
+        }
+    else
+        {
+        Exit( EAknSoftkeyClose );
+        }
+    }
+
+// ---------------------------------------------------------
+// CPostcardAppUi::SetImageL
+// ---------------------------------------------------------
+void CPostcardAppUi::SetImage( CGulIcon* aIcon )
+    {
+    iImage = aIcon;
+    iController->SetBitmap( EPostcardImage, aIcon );
+    }
+
+// ---------------------------------------------------------
+// CPostcardAppUi::SetTextL
+// ---------------------------------------------------------
+void CPostcardAppUi::SetTextL( CPlainText& aPlainText )
+    {
+	delete iGreeting;
+	iGreeting = &aPlainText;
+	iGreetingLength = iGreeting->DocumentLength();
+	if( iGreetingLength )
+		{
+		CreateGreetingBitmapL( );
+		}
+	else
+		{
+		iController->RemoveBitmap( EPostcardText );		
+		}
+    }
+
+// ---------------------------------------------------------
+// CPostcardAppUi::MaxTextLength
+// ---------------------------------------------------------
+TInt CPostcardAppUi::MaxTextLength( TInt aControlId )
+    {
+    const TInt KFirstControlId = EPostcardTextEditor;
+    __ASSERT_DEBUG( aControlId >= KFirstControlId &&
+        aControlId <= EPostcardAddressCountry, Panic( EPostcardPanicCoding ) );
+
+    // Keys has to be in the same order in the table as control IDs in
+    // TPostcardControls
+    static const TUint32 keys[ENumPostcardControls] = 
+        {
+        KPocaKeyMaxGreetingLength, KPocaKeyMaxNameLength,
+        KPocaKeyMaxInfoLength, KPocaKeyMaxStreetLength,
+        KPocaKeyMaxZipLength, KPocaKeyMaxCityLength,
+        KPocaKeyMaxStateLength, KPocaKeyMaxCountryLength
+        };
+    return iCenRep->Get( keys[ aControlId - KFirstControlId ] );
+    }
+
+// ---------------------------------------------------------
+// CPostcardAppUi::CenRep
+// ---------------------------------------------------------
+const CPostcardCenRep& CPostcardAppUi::CenRep()
+    {
+    return *iCenRep;
+    }
+
+// ---------------------------------------------------------
+// CPostcardAppUi::SetRecipientL
+// ---------------------------------------------------------
+void CPostcardAppUi::SetRecipientL( CContactCard& aRecipient )
+    {
+    delete iContact;
+    iContact = &aRecipient;
+
+    if( !ContactHasData( aRecipient ) )
+        {
+        iController->RemoveBitmap( EPostcardRecipient );
+        return;			
+        }
+
+    RefreshRecipientBitmapL( );
+    }
+
+// ---------------------------------------------------------
+// CPostcardAppUi::RefreshRecipientBitmapL
+// ---------------------------------------------------------
+void CPostcardAppUi::RefreshRecipientBitmapL( )
+    {
+    // Get the contact set
+    CContactItemFieldSet& set = iContact->CardFields( );
+	
+    CDesCArrayFlat* strings = new (ELeave) CDesCArrayFlat( CPostcardAddressForm::ENumAddrFields );
+    CleanupStack::PushL( strings );
+
+    CArrayFixFlat<TInt>* indexes =
+        new ( ELeave ) CArrayFixFlat<TInt>(CPostcardAddressForm::ENumAddrFields);
+    CleanupStack::PushL( indexes );
+    for( TInt a=0; a<CPostcardAddressForm::ENumAddrFields; a++ )
+        {
+        indexes->AppendL(-1);
+        }
+
+    // Lets first find the indexes of different fields from the ContactItemFieldSet
+	for( TInt i = 0; i<set.Count( ); i++ )
+		{
+		CContactItemField& field = set[i];
+    	for( TInt a = EPostcardAddressName; a <= EPostcardAddressCountry; a++ )
+    		{
+    		if( !field.Label( ).Compare( TPostcardUtils::ContactItemNameFromId( a ) ) )
+    		    { // Label found so store the index of ContactItemField
+    	        indexes->Delete( a-EPostcardAddressName ); // remove -1
+    	        indexes->InsertL( a-EPostcardAddressName, i ); // add right one
+    			continue;
+    		    }
+    		}
+		}			
+	// Lets put them into right order
+	for( TInt a = EPostcardAddressName; a<=EPostcardAddressCountry; a++ )
+		{
+		TInt id = indexes->At( a - EPostcardAddressName );
+		if( id != -1 )
+			{
+			CContactItemField& field = set[ id ];
+    		if( field.TextStorage( )->Text( ).Length( ) > 0 )
+	    		{
+            	strings->AppendL( field.TextStorage()->Text() );
+	    		}
+			}
+		}
+    CleanupStack::PopAndDestroy( indexes );
+    // And create a transparent bitmap of the address strings
+	CGulIcon* icon = CreateTransparentIconL( *strings );
+	iController->SetBitmap( EPostcardRecipient, icon );
+
+	CleanupStack::PopAndDestroy( strings );
+    }
+
+// ---------------------------------------------------------
+// CreateGreetingBitmapL
+// ---------------------------------------------------------
+void CPostcardAppUi::CreateGreetingBitmapL( )
+	{
+    TPtrC16 text( iGreeting->Read( 0, iGreetingLength ) );
+    
+    CGulIcon* icon = CreateTransparentIconL( text );
+   	iController->SetBitmap( EPostcardText, icon );
+	}
+
+// ---------------------------------------------------------
+// CreateTransparentIconL
+// ---------------------------------------------------------
+CGulIcon* CPostcardAppUi::CreateTransparentIconL( const TDesC& aText )	
+	{
+	TSize iconSize = PostcardLaf::GreetingText( ).Size( );
+
+	// The bitmap
+	CFbsBitmap* bitmap = CreateEmptyBitmapLC( iconSize ); // pushes to stack
+
+	// The mask bitmap
+	CFbsBitmap* bitmapMask = new (ELeave) CFbsBitmap( );
+	CleanupStack::PushL( bitmapMask );
+	bitmapMask->Create( iconSize, EGray2 );
+	
+	CFbsBitmapDevice* deviceMask = CFbsBitmapDevice::NewL( bitmapMask );
+	CleanupStack::PushL( deviceMask );
+	
+	CBitmapContext* contextMask = NULL;
+	deviceMask->CreateBitmapContext( contextMask );	
+	CleanupStack::PushL( contextMask );
+
+    contextMask->SetPenStyle(CGraphicsContext::ENullPen);
+    contextMask->SetBrushStyle(CGraphicsContext::ESolidBrush);
+    contextMask->SetBrushColor( KRgbBlack );
+    contextMask->DrawRect(TRect(TPoint(0,0), iconSize));
+
+    contextMask->SetPenStyle(CGraphicsContext::ESolidPen);
+    contextMask->SetBrushStyle(CGraphicsContext::ENullBrush);
+    contextMask->SetPenColor(KRgbWhite);
+
+	CFont* font = NULL;
+    CParaFormat paraFormat;
+    TParaFormatMask paraFormatMask;
+	TCharFormat charFormat;
+	TCharFormatMask charFormatMask;
+
+	PostcardLaf::MiniatureFont( charFormat, charFormatMask, paraFormat, paraFormatMask  );
+
+	deviceMask->GetNearestFontToDesignHeightInTwips( font, charFormat.iFontSpec );
+	
+	contextMask->UseFont( font );
+
+   	TInt top = PostcardLaf::BaselineTop( );
+   	TInt delta = PostcardLaf::BaselineDelta( );
+    TInt leftMargin = PostcardLaf::LeftMargin( );
+    HBufC* buf = HBufC::NewLC( KPostcardMaxMiniatureCharsPerLine );
+    TPtr strPtr = buf->Des( );
+
+	TBool linesLeft = ETrue;
+	TInt lineIndex = 0;
+	TInt charTotalIndex = 0;
+    TBool mirrored = AknLayoutUtils::LayoutMirrored();
+    TInt lineWidth = iconSize.iWidth - leftMargin; // We use the same margin on right side, too
+    const TInt greetingLineCount = PostcardLaf::GreetingFocusLineCount();
+
+    // Insert lines until there is something to add or
+    // maximum amount of greeting focus lines is reached.
+    // This prevents drawing of text without a focus line,
+    // which can happen for the last row of the greeting text.
+	while( linesLeft && lineIndex < greetingLineCount )
+		{
+		strPtr.Zero( );
+    	TPtrC origPtr = aText.Mid( charTotalIndex ); 
+    	TInt index = 0;
+    	while( index < origPtr.Length( ) 
+    	    && font->TextWidthInPixels( origPtr.Mid( 0, index ) ) + leftMargin < lineWidth )
+    		{
+    		index++;
+    		charTotalIndex++;
+            TChar ch = origPtr[index-1];
+            if( ch == 0x2029 ) // If enter, break from the while
+                {
+                charTotalIndex++; // increase now as it will be decreased next
+                break;
+                }
+    		}
+    	if( index < origPtr.Length( ) - 1 )
+    	    { // This is the last character in the text so lets still include that
+    	    index--;
+    	    charTotalIndex--;
+    	    }
+    	if( index > 0 )
+    		{ // There's actually something to draw on this line
+    		strPtr.Append( origPtr.Mid( 0, index ) );
+    		if( strPtr[index-1] == 0x2029 )
+    		    { // Remove the last character if it's CR
+                strPtr.Delete( index-1, 1 );
+                index--;
+                charTotalIndex--;
+    		    }
+
+            if( index == 0 )
+                { // There are probably many empty lines so thats why we got here.. just increase line
+			    lineIndex++;
+    		    }
+    		else
+    		    { // Now we can draw it
+        		TInt deltaX = leftMargin;
+        		if( mirrored )
+        		    {
+        		    deltaX = iconSize.iWidth - leftMargin - font->TextWidthInPixels( strPtr );
+        		    }
+        		TPoint point = TPoint( deltaX, top + ( lineIndex * delta ) );
+        		lineIndex++; // lets change the line
+        		if( mirrored )
+        		    {
+        		    CGraphicsContext::TDrawTextExtendedParam params;
+        		    params.iParRightToLeft = ETrue; // change the direction of text
+            		contextMask->DrawTextExtended( strPtr, point, params );
+        		    }
+        		else
+        		    {
+            		contextMask->DrawText( strPtr, point );
+        		    }
+    		    }    
+    		if( index >= origPtr.Length( ) )
+    			{
+    			linesLeft = EFalse;
+    			}
+    		}
+		else  // Nothing left -> return
+			{
+			if( origPtr.Length( ) == 0)
+			    { // Nothing left -> return
+    			linesLeft = EFalse;	
+			    }
+			else
+			    { // Just an empty line -> increase line counter
+			    lineIndex++;
+			    }
+			}
+		}
+
+	CleanupStack::PopAndDestroy( 3, deviceMask );   // deviceMask, contextMask, buf
+	
+    CGulIcon* icon = CGulIcon::NewL( bitmap, bitmapMask );
+
+    // Ownership moves, so just pop.
+    CleanupStack::Pop( 2, bitmap ); // bitmapMask and bitmap
+
+	return icon;
+	}
+
+// ---------------------------------------------------------
+// CreateTransparentIconL
+// ---------------------------------------------------------
+CGulIcon* CPostcardAppUi::CreateTransparentIconL( const MDesCArray& aStrings )
+	{
+	TSize iconSize = PostcardLaf::Address( ).Size( );
+
+	CFbsBitmap* bitmap = CreateEmptyBitmapLC( iconSize ); // pushes to stack
+	
+	CFbsBitmap* bitmapMask = new (ELeave) CFbsBitmap( );
+	CleanupStack::PushL( bitmapMask );
+	bitmapMask->Create( iconSize, EGray2 );
+	
+	CFbsBitmapDevice* deviceMask = CFbsBitmapDevice::NewL( bitmapMask );
+	CleanupStack::PushL( deviceMask );
+	
+	CBitmapContext* contextMask = NULL;
+	deviceMask->CreateBitmapContext( contextMask );	
+	CleanupStack::PushL( contextMask );
+
+    contextMask->SetPenStyle(CGraphicsContext::ENullPen);
+    contextMask->SetBrushStyle(CGraphicsContext::ESolidBrush);
+    contextMask->SetBrushColor( KRgbBlack );
+    contextMask->DrawRect(TRect(TPoint(0,0), iconSize));
+
+    contextMask->SetPenStyle(CGraphicsContext::ESolidPen);
+    contextMask->SetBrushStyle(CGraphicsContext::ENullBrush);
+    contextMask->SetPenColor(KRgbWhite);
+
+	CFont* font = NULL;
+    CParaFormat paraFormat;
+    TParaFormatMask paraFormatMask;
+	TCharFormat charFormat;
+	TCharFormatMask charFormatMask;
+
+	PostcardLaf::MiniatureFont( charFormat, charFormatMask, paraFormat, paraFormatMask  );
+
+	deviceMask->GetNearestFontToDesignHeightInTwips( font, charFormat.iFontSpec );
+	
+	contextMask->UseFont( font );
+
+   	TInt top = PostcardLaf::BaselineTop( );
+   	TInt delta = PostcardLaf::BaselineDelta( );
+    TInt leftMargin = PostcardLaf::LeftMargin( );
+    HBufC* buf = HBufC::NewLC( KPostcardMaxMiniatureCharsPerLine );
+    TPtr strPtr = buf->Des( );
+    TBool mirrored = AknLayoutUtils::LayoutMirrored();
+    TInt ellipsisWidth = font->CharWidthInPixels( CEditableText::EEllipsis );
+    TInt lineWidth = iconSize.iWidth - leftMargin - ellipsisWidth; // We use the same margin on right side, too
+    TInt lines = aStrings.MdcaCount() > KPostcardMaxAddressFocusLines ? 
+        KPostcardMaxAddressFocusLines : 
+        aStrings.MdcaCount();
+    // Following characters are converted to spaces, before showing them on text side.
+    TBuf<1> replaceChars;
+    replaceChars.Zero();
+    replaceChars.Append( CEditableText::EParagraphDelimiter );
+    
+    for( TInt a = 0; a < lines; a++ )
+    	{
+    	strPtr.Zero( );
+    	TPtrC origPtr = aStrings.MdcaPoint( a );
+    	if( origPtr.Length( ) < 1 )
+    		{ // There's no text so skip this..
+    		continue;
+    		}
+    	TInt index = 0;
+    	while( index < origPtr.Length( ) && font->TextWidthInPixels( origPtr.Mid( 0, index ) ) + leftMargin < ( lineWidth ) )
+    		{
+    		index++;
+    		}
+    	strPtr.Append( origPtr.Mid( 0, index ) );
+    	if( index < origPtr.Length( ) )
+    		{
+    		strPtr.Append( CEditableText::EEllipsis );
+    		index++;
+    		}
+    	TInt deltaX = leftMargin;
+    	if( mirrored )
+    	    {
+            deltaX = iconSize.iWidth - font->TextWidthInPixels( strPtr ) - leftMargin;
+    	    }
+    	TPoint point = TPoint( deltaX, top + ( a * delta ) );
+        
+        // Convert all line changes to spaces
+    	AknTextUtils::ReplaceCharacters(
+            strPtr,
+            replaceChars,
+            CEditableText::ESpace );
+    	
+		if( mirrored )
+		    {
+		    CGraphicsContext::TDrawTextExtendedParam params;
+		    params.iParRightToLeft = ETrue; // change the direction of text
+    		contextMask->DrawTextExtended( strPtr, point, params );
+		    }
+		else
+		    {
+        	contextMask->DrawText( strPtr, point );
+		    }
+    	}
+	
+	CleanupStack::PopAndDestroy( 3, deviceMask );   // deviceMask, contextMask, buf
+	
+    CGulIcon* icon = CGulIcon::NewL( bitmap, bitmapMask );
+
+    // Ownership moves, so just pop.
+    CleanupStack::Pop( 2, bitmap ); // bitmapMask and bitmap
+
+	return icon;
+
+	}
+
+// ---------------------------------------------------------
+// RefreshFocusLinesL
+// ---------------------------------------------------------
+void CPostcardAppUi::RefreshFocusLinesL( )
+    {
+    // Lets refresh the location of lines in greeting and recipients rects
+    if( !iController )
+        {
+        // If there's no controller -> just return
+        return; 
+        }
+        
+	CFbsBitmap* dummyBmp = new (ELeave) CFbsBitmap( );
+	CleanupStack::PushL( dummyBmp );
+	dummyBmp->Create( TSize( 1, 1), EGray2 );
+	
+	CFbsBitmapDevice* dummyDevice = CFbsBitmapDevice::NewL( dummyBmp );
+	CleanupStack::PushL( dummyDevice );
+
+	CFont* font = NULL;
+    CParaFormat paraFormat;
+    TParaFormatMask paraFormatMask;
+	TCharFormat charFormat;
+	TCharFormatMask charFormatMask;
+
+	PostcardLaf::MiniatureFont( charFormat, charFormatMask, paraFormat, paraFormatMask  );
+
+	dummyDevice->GetNearestFontToDesignHeightInTwips( font, charFormat.iFontSpec );
+
+    TInt descent = font->DescentInPixels( );
+    
+    CleanupStack::PopAndDestroy( 2, dummyBmp ); // dummyBmp, dummyDevice
+    
+ 	TInt delta = PostcardLaf::BaselineDelta( );
+	TInt top = PostcardLaf::BaselineTop( );
+    TInt leftMargin = PostcardLaf::LeftMargin( );
+    TInt extraHeight = MsgEditorCommons::ScreenWidth( )>KPostcardLegacyWidth?1:0;
+    if( MsgEditorCommons::ScreenWidth( ) > KPostcardQvgaWidth )
+        {
+        extraHeight++;
+        }
+    
+    TInt rectLoop = EPostcardFocusAreaGreeting;
+    for ( rectLoop = 0; rectLoop < EPostcardFocusAreaLast; rectLoop++ )
+        {
+        TRect focusRect = rectLoop == EPostcardFocusAreaGreeting ? 
+            PostcardLaf::GreetingText() :
+            PostcardLaf::Address(); // Indicates the are where focus lines are drawn
+
+    	// Indicates number of focus lines to draw. There is always 5 focus line in address side.
+    	// Focus line count in greeting text side depends on the used layout.
+        TInt rectLineCount = rectLoop == EPostcardFocusAreaGreeting ? 
+            PostcardLaf::GreetingFocusLineCount() : 
+            KPostcardMaxAddressFocusLines;
+        CArrayPtrFlat<TRect>* lineRects = new (ELeave) CArrayPtrFlat<TRect>( rectLineCount );
+        CleanupStack::PushL( lineRects );
+
+        TRect* rect = NULL;
+        for (TInt i = 0; i < rectLineCount; i++)
+            {
+            rect = new (ELeave) TRect;
+            CleanupStack::PushL( rect );
+            lineRects->InsertL( i, rect );
+            CleanupStack::Pop( rect ); // rect -> just pop as it will be in lineRects
+            }
+
+        TInt maxHeight = focusRect.Height( );
+        TInt lineNumber = 1;
+        
+        while( ETrue )
+            {
+            TInt y = focusRect.iTl.iY + top + ( lineNumber - 1 ) * delta + descent;
+            
+            lineRects->At( lineNumber - 1 )->SetRect( 
+                                focusRect.iTl.iX + leftMargin,
+                                y,
+                                focusRect.iBr.iX - leftMargin,
+                                y + extraHeight );
+            if( lineNumber >= rectLineCount || top + lineNumber * delta > maxHeight )
+                {
+                break;
+                }
+            lineNumber++;
+            } 
+        // ownership moves to controller
+        CleanupStack::Pop( lineRects );
+
+        if( rectLoop == 0 )
+            {
+            iController->SetGreetingLines( *lineRects );
+            }
+        else
+            {
+            iController->SetRecipientLines( *lineRects );
+            }
+        }
+    }
+
+// ---------------------------------------------------------
+// CreateEmptyBitmapLC
+// ---------------------------------------------------------
+CFbsBitmap* CPostcardAppUi::CreateEmptyBitmapLC( const TSize& aSize )
+	{
+	CFbsBitmap* bitmap = new (ELeave) CFbsBitmap( );
+	CleanupStack::PushL( bitmap );
+	bitmap->Create( aSize, EGray2 );
+	
+	CFbsBitmapDevice* device = CFbsBitmapDevice::NewL( bitmap );
+	CleanupStack::PushL( device );
+	
+	CBitmapContext* context = NULL;
+	device->CreateBitmapContext( context );	
+	CleanupStack::PushL( context );
+
+    context->SetPenStyle( CGraphicsContext::ENullPen );
+    context->SetBrushStyle( CGraphicsContext::ESolidBrush );
+    context->SetBrushColor( KRgbRed );
+    context->DrawRect( TRect( TPoint( 0, 0 ), aSize ) );
+
+    CleanupStack::PopAndDestroy( 2, device );   // context, device
+
+	return bitmap;
+	}
+
+
+// ---------------------------------------------------------
+// ShowGlobalInformationNoteL
+// ---------------------------------------------------------
+void CPostcardAppUi::ShowGlobalInformationNoteL( TInt aResourceId, TBool aWaiting )
+    {
+    CErrorUI* errorUi = CErrorUI::NewLC(*iCoeEnv);
+    aWaiting ? errorUi->ShowGlobalErrorQueryL( aResourceId ) :
+               errorUi->ShowGlobalErrorNoteL( aResourceId );
+    CleanupStack::PopAndDestroy( errorUi );
+    }
+
+// ---------------------------------------------------------
+// ShowInformationNoteL
+// ---------------------------------------------------------
+void CPostcardAppUi::ShowInformationNoteL( TInt aResourceId, TBool aWaiting )
+    {
+    HBufC* prompt = StringLoader::LoadLC( aResourceId, iCoeEnv );
+    ShowInformationNoteL( *prompt, aWaiting );
+    CleanupStack::PopAndDestroy( prompt );
+    }
+
+// ---------------------------------------------------------
+// ShowInformationNoteL
+// ---------------------------------------------------------
+void CPostcardAppUi::ShowInformationNoteL( const TDesC& aText, TBool aWaiting )
+    {
+    CAknInformationNote* note = new ( ELeave )
+        CAknInformationNote( aWaiting );
+    note->ExecuteLD( aText );
+    }
+
+// ---------------------------------------------------------
+// ShowConfirmationQueryL
+// ---------------------------------------------------------
+TInt CPostcardAppUi::ShowConfirmationQueryL( TInt aResourceId, TBool aOnlyOK/*=EFalse*/ ) const
+    {
+    HBufC* prompt = StringLoader::LoadLC( aResourceId, iCoeEnv );
+    TInt retVal = ShowConfirmationQueryL( *prompt, aOnlyOK );
+    CleanupStack::PopAndDestroy( prompt );
+    return retVal;
+    }
+
+// ---------------------------------------------------------
+// ShowConfirmationQueryL
+// ---------------------------------------------------------
+TInt CPostcardAppUi::ShowConfirmationQueryL( const TDesC& aText, TBool aOnlyOK/*=EFalse*/ ) const
+    {
+    TInt dialogType=aOnlyOK?R_POSTCARD_CONFIRMABLE_QUERY:R_POSTCARD_CONFIRMATION_QUERY;
+    CAknQueryDialog* dlg = CAknQueryDialog::NewL();
+    TInt retVal = dlg->ExecuteLD( dialogType, aText );
+    return retVal;    
+    }
+
+// ---------------------------------------------------------
+// ShowWaitNoteL
+// ---------------------------------------------------------
+TBool CPostcardAppUi::ShowWaitNoteL( TInt aResourceId, TBool aNoTimeout )
+    {
+    TInt waitNoteResource = R_POSTCARD_WAIT_NOTE;
+
+    HBufC* string = StringLoader::LoadLC( aResourceId, iCoeEnv );
+    
+    iWaitDialog = new( ELeave )CAknWaitDialog(
+        reinterpret_cast<CEikDialog**>( &iWaitDialog ), aNoTimeout ); // ETrue means no delay in showing the note.
+    iWaitDialog->PrepareLC( waitNoteResource );
+    iWaitDialog->SetTextL( *string );
+    TInt success = iWaitDialog->RunLD();
+    CleanupStack::PopAndDestroy( string );
+    return success;
+    }
+
+// ---------------------------------------------------------
+// RemoveWaitNote
+// ---------------------------------------------------------
+void CPostcardAppUi::RemoveWaitNote()
+    {
+    delete iWaitDialog;
+    iWaitDialog = NULL;
+    }
+
+// ---------------------------------------------------------
+// Document
+// ---------------------------------------------------------
+CPostcardDocument& CPostcardAppUi::Document()
+    {
+    CMsgEditorDocument& doc = static_cast <CMsgEditorDocument&> ( *CEikAppUi::Document() );
+    return static_cast <CPostcardDocument&> ( doc );
+    }
+
+// ---------------------------------------------------------
+// ContactHasData
+// ---------------------------------------------------------
+TBool CPostcardAppUi::ContactHasData( const CContactCard& aContact )
+	{
+	CContactItemFieldSet& fields = aContact.CardFields( );
+	for( TInt i = 0; i < fields.Count( ); i++ )
+		{
+		CContactItemField& field = fields[i];
+		if( field.TextStorage( )->Text( ).Length( ) > 0 )
+			{
+			return ETrue;
+			}
+		}
+	return EFalse;	
+	}
+
+// ---------------------------------------------------------
+// ContactHasData
+// ---------------------------------------------------------
+TBool CPostcardAppUi::ContactHasData( )
+    {
+    // Call the overriden function with iContact
+    if(!iContact)
+    return EFalse;
+    return ContactHasData( *iContact );    
+    }
+
+
+// ---------------------------------------------------------
+// MandatoryAddressFields
+// ---------------------------------------------------------
+TInt CPostcardAppUi::MandatoryAddressFields( )
+	{
+    return iCenRep->Get( KPocaKeyMandatoryFields );
+	}
+
+// ---------------------------------------------------------
+// ReadFromResourceLC
+// ---------------------------------------------------------
+HBufC* CPostcardAppUi::ReadFromResourceLC( TInt& aResourceId )
+	{
+    return StringLoader::LoadLC( aResourceId, iCoeEnv );	
+	}
+
+// ---------------------------------------------------------
+// NavigateBetweenMessagesL
+// ---------------------------------------------------------
+TKeyResponse CPostcardAppUi::NavigateBetweenMessagesL( TBool aNextMessage )
+	{
+    if( IsNextMessageAvailableL( aNextMessage ) )
+        {
+        NextMessageL( aNextMessage );
+        }
+    return EKeyWasConsumed;
+    }
+
+// ---------------------------------------------------------
+// CheckLengthsL
+// ---------------------------------------------------------
+TBool CPostcardAppUi::CheckLengthsL( )
+	{
+    if( iGreetingLength > MaxTextLength( EPostcardTextEditor ) )
+        {
+        DoEditGreetingL();
+        return EFalse;    	    
+        }
+
+	if( !ContactHasData( *iContact ) )
+		{
+		// No contact -> no need to show anything..
+    	return ETrue;
+		}
+
+    // Get length of address fields into a table. Table is initialized to
+    // zero because contact may be missing some address fields. Lengths are
+    // first fetched into a table and checked after that in order to do the
+    // check in correct order. If a some fields are too long they are presented
+    // to user in correct order for fixing.
+    TInt lengths[CPostcardAddressForm::ENumAddrFields];
+    Mem::FillZ( lengths, sizeof( lengths ) );
+    CContactItemFieldSet& set = iContact->CardFields();
+    for( TInt i = 0; i < set.Count(); i++ )
+        {
+        CContactItemField& field = set[i];
+        CContactTextField* textField = set[i].TextStorage();
+        if (textField)
+            {
+            TInt id = TPostcardUtils::IdFromContactItemName( field.Label() );
+            __ASSERT_DEBUG( id >= EPostcardAddressName &&
+                id <= EPostcardAddressCountry, Panic( EPostcardPanicCoding ) );
+            lengths[id - EPostcardAddressName] = textField->Text().Length();
+            }
+        }
+    // Check length of fields
+    for( TInt i = EPostcardAddressName; i <= EPostcardAddressCountry; i++ )
+        {
+        if (lengths[i - EPostcardAddressName] > MaxTextLength(i))
+            {
+            // A field is too long, open the address dialog..
+            DoEditAddressL( TKeyEvent(), i );
+            return EFalse;
+            }
+        }
+    return ETrue;
+	}
+
+// ---------------------------------------------------------
+// CreateAddressStringForSendConfirmLC
+// ---------------------------------------------------------
+HBufC* CPostcardAppUi::CreateAddressStringForSendConfirmLC()
+    {
+    HBufC* buf = HBufC::NewLC( KPostcardMaxSendConfirmationLength );
+    TPtr bufPtr = buf->Des();
+
+    _LIT( KNewline, "\n" );
+    CContactItemFieldSet& set = iContact->CardFields( );
+    for(TInt i = EPostcardAddressName; i <= EPostcardAddressCountry; i++ )
+        {
+        const CContactItemField* field = TPostcardUtils::FieldOrNull( set,
+            TPostcardUtils::ContactItemNameFromId( i ) );
+        if ( field )
+            {
+            TPtrC text = field->TextStorage()->Text();
+            TInt len = text.Length();
+            if( len && len < ( bufPtr.MaxLength() - bufPtr.Length() ) )
+                {
+                bufPtr.Append( text );
+                bufPtr.Append( KNewline );
+                }
+            }
+        }
+
+    // Remove the last "\n" in case there's question mark in the end of the loc string
+    bufPtr.Delete( bufPtr.Length() - 1, 1 );
+    return buf;
+	}
+
+// ---------------------------------------------------------
+// QueryWaiterCallback
+// ---------------------------------------------------------
+void CPostcardAppUi::QueryWaiterCallbackL( TInt aResult )
+	{
+	if( aResult == EAknSoftkeySend )
+		{
+		// Proceed if send query result is send
+		
+		// Displaying extra charge query is optional
+        aResult = EAknSoftkeyOk;
+		if( iCenRep->FeatureBits() & KPostcardFeatureIdExtraChargeNotification)
+		    {
+            CAknQueryDialog* dlg = CAknQueryDialog::NewL();
+            aResult = dlg->ExecuteLD( R_POSTCARD_EXTRA_CHARGE_QUERY );
+            }
+        if( aResult == EAknSoftkeyOk )
+            {
+            // OK, start sending
+            
+            TInt resourceId = R_POSTCARD_SENDING_POSTCARD;
+            if( IsPhoneOfflineL() )
+                {
+                resourceId = R_POSTCARD_SAVED_OUTBOX;
+                }            
+            
+            ShowWaitNoteL( resourceId, ETrue );
+            iOperation = CPostcardOperationSave::NewL(
+                *this,
+                Document(),
+                *this,
+                FsSession(),
+                *iContact,
+                *iGreeting
+    	        );
+            iOperation->Start( ETrue );
+            
+            iAbsorber = CAknInputBlock::NewLC();
+            CleanupStack::Pop( iAbsorber );
+            iPocaFlags |= EPostcardClosing;
+            }
+		}
+
+	if( iMessageQuery )
+		{
+        iMessageQuery->CancelMsgQuery();
+        delete iMessageQuery;
+        iMessageQuery = NULL;		
+		}
+
+    delete iSendText;
+    iSendText = NULL;
+	}
+
+// ---------------------------------------------------------
+// QueryWaiterCallbackError
+// ---------------------------------------------------------
+void CPostcardAppUi::QueryWaiterCallbackError()
+    {
+    // Cleanup after QueryWaiterCallbackL() leaves
+
+	if( iMessageQuery )
+		{
+        iMessageQuery->CancelMsgQuery();
+        delete iMessageQuery;
+        iMessageQuery = NULL;		
+		}
+
+    delete iSendText;
+    iSendText = NULL;
+
+    RemoveWaitNote();
+
+    delete iOperation;
+    iOperation = NULL;
+    }
+
+// ---------------------------------------------------------
+// SetMiddleSoftkeyL
+// ---------------------------------------------------------
+void CPostcardAppUi::SetMiddleSoftkeyL()
+    {
+    TInt resourceId;
+    if ( iController->Frontpage() )
+        {
+        // Frontside is focused
+        if ( iMsgType == EPostcardSent )
+            {
+            resourceId = R_POSTCARD_MSK_BUTTON_EMPTY;
+            }
+        else
+            {
+            resourceId = R_POSTCARD_MSK_BUTTON_OPTIONS;
+            MenuBar()->SetContextMenuTitleResourceId(
+                R_POSTCARD_CONTEXT_MENUBAR );
+            }
+        }
+    else
+        {
+        // Backside is focused
+        resourceId = iMsgType == EPostcardSent ?
+            R_POSTCARD_MSK_BUTTON_OPEN : R_POSTCARD_MSK_BUTTON_EDIT;
+        }
+    if ( resourceId != iMskResource )
+        {
+        const TInt KMskPosition = 3;
+        CEikButtonGroupContainer *cba = Cba();
+        cba->SetCommandL( KMskPosition, resourceId );
+        cba->DrawDeferred();
+        iMskResource = resourceId;
+        }
+    }
+
+// ---------------------------------------------------------
+// GetZoomLevelL
+// ---------------------------------------------------------
+void CPostcardAppUi::GetZoomLevelL( TInt& aZoomLevel )
+    {
+    TInt err = iMsgEditorAppUiExtension->iSettingCachePlugin.GetValue( KAknLocalZoomLayoutSwitch, 
+                                                            aZoomLevel );
+                
+    if ( err != KErrNone )
+        {
+        User::Leave( err );
+        }
+    }
+
+// ---------------------------------------------------------
+// HandleLocalZoomChangeL
+// ---------------------------------------------------------
+//
+void CPostcardAppUi::HandleLocalZoomChangeL( TMsgCommonCommands aNewZoom )
+    {
+    // Forward to base, which sets new zoom level to cenrep.
+    CMsgEditorAppUi::HandleLocalZoomChangeL( aNewZoom );
+    }
+
+// ---------------------------------------------------------
+// CPostcardAppUi::BeginActiveWait
+// ---------------------------------------------------------
+//
+void CPostcardAppUi::BeginActiveWait()
+    {
+    if ( iWait.IsStarted() )
+        {
+        return;
+        }
+    iWait.Start();
+    }
+
+// ---------------------------------------------------------
+// CPostcardAppUi::EndActiveWait
+// ---------------------------------------------------------
+//
+void CPostcardAppUi::EndActiveWait()
+    {
+    if ( iWait.IsStarted() )
+        {
+        iWait.AsyncStop();
+        }
+    }
+
+// ---------------------------------------------------------
+// CPostcardAppUi::SetTitleIconL
+// ---------------------------------------------------------
+//
+void CPostcardAppUi::SetTitleIconL()
+    {
+    SetTitleIconSizeL( iAppIcon->Bitmap() );
+    
+    // Create duplicates of the icon to be used
+    CFbsBitmap* bitmap = new( ELeave ) CFbsBitmap();
+    CleanupStack::PushL( bitmap );
+    
+    CFbsBitmap* bitmapMask = new( ELeave ) CFbsBitmap();
+    CleanupStack::PushL( bitmapMask );
+    
+    User::LeaveIfError( bitmap->Duplicate( iAppIcon->Bitmap()->Handle() ) );
+    User::LeaveIfError( bitmapMask->Duplicate( iAppIcon->Mask()->Handle() ) );
+
+    iTitlePane->SetSmallPicture( bitmap, bitmapMask, ETrue );
+    iTitlePane->DrawNow();
+    
+    CleanupStack::Pop( bitmapMask );
+    CleanupStack::Pop( bitmap );
+    }
+
+// ---------------------------------------------------------
+// CPostcardAppUi::CreateAndSetTitleIconL
+// ---------------------------------------------------------
+//
+void CPostcardAppUi::CreateAndSetTitleIconL()
+    {
+    if ( iAppIcon )
+        {
+        delete iAppIcon;
+        iAppIcon = NULL;
+        }
+    
+    TParse parseDrive;
+    parseDrive.Set( Document().AppFullName( ), NULL, NULL );
+    TPtrC drive = parseDrive.Drive( );
+    
+    TParse fileParse;
+    fileParse.Set( KPostcardMifFile, &KDC_APP_BITMAP_DIR, NULL );
+    
+    TFileName fileName( fileParse.FullName( ) );
+    fileName.Insert( 0, drive );
+    
+    iAppIcon = AknsUtils::CreateGulIconL( 
+        AknsUtils::SkinInstance(), 
+        KAknsIIDQgnPropMcePostcardTitle,
+        fileParse.FullName(),
+        EMbmPostcardQgn_prop_mce_postcard_title,
+        EMbmPostcardQgn_prop_mce_postcard_title_mask );
+    
+    SetTitleIconL();
+    }
+
+// ---------------------------------------------------------
+// CPostcardAppUi::IsPhoneOfflineL
+// ---------------------------------------------------------
+//
+TBool CPostcardAppUi::IsPhoneOfflineL() const
+    {
+    if ( iPocaFlags & EPostcardFeatureOffline )
+        {    
+        return MsvUiServiceUtilitiesInternal::IsPhoneOfflineL();
+        }
+    else
+        {
+        return EFalse;
+        }       
+    }
+
+//  End of File