wvuing/wvuiave/AppSrc/CCAConversationsContainer.cpp
changeset 0 094583676ce7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wvuing/wvuiave/AppSrc/CCAConversationsContainer.cpp	Thu Dec 17 08:41:52 2009 +0200
@@ -0,0 +1,2056 @@
+/*
+* Copyright (c) 2006 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:  Container class for conversations view
+*
+*/
+
+#include    <AknSettingCache.h>
+
+#include    "CAPresenceManager.h"
+#include    "MCAPresence.h"
+#include    "ccafetchwaiter.h"
+#include    "ccasyncchecker.h"
+#include    "ImpsCSPAllErrors.h"
+
+// INCLUDE FILES
+#include	"CCAConversationsContainer.h"
+#include    "MCAViewSwitcher.h"
+#include    "CCAMessageEditor.h"
+#include    "ChatDefinitions.h"
+#include    "ChatDebugPrint.h"
+#include    "CCAAppUi.h"
+#include    "CCAContactEditor.h"
+#include    "CCAStatusPaneHandler.h"
+#include    "MCABlockingPC.h"
+#include    "IMDialogUtils.h"
+#include    "MCARecipientObserver.h"
+#include    "CAExternalinterface.h"
+#include    "IMNoteMapper.h"
+#include    "CCABlockingUI.h"
+#include	"chatngclient.hrh"
+#include	"CCAApp.h"
+#include	"CCAVariantFactory.h"
+#include	"MCASkinVariant.h"
+#include    "CCAUISessionManager.h"
+#include    "CCAMessageExtensionsHandler.h"
+#include    "CCAChatViewControl.h"
+#include    "IMDialogUtils.h"
+
+#include	"TCAChatListBoxLayout.h"
+#include    "IMUtils.h"
+#include    "CAUtils.h"
+#include    "ccawaitnote.h"
+#include    "chatdebugassert.h"
+#include    "CCAPCUtils.h"
+
+#include    "MCAMessageErrorInformer.h"
+#include    "MCAMessageUtils.h"
+#include    "MCAMessageCreator.h"
+#include    "MCAMessageContainerInfo.h"
+#include    "MCAMessageUtils.h"
+#include    "MCAContentProcessor.h"
+#include    "MCASettingsPC.h"
+#include    "MCAConversationMessage.h"
+#include	"MCALayoutInfo.h"
+
+
+#include    "imnginternalcrkeys.h"
+#include    "imprivatecrkeys.h"
+#include    "imvariant.hrh"
+#include    "CCAAppSettingsSAPExt.h"
+
+
+#include	"MCAUiLoginCmdCB.h"
+#include	"MCAConversationPC.h"
+#include	"CCAEditIndicator.h"
+#include	"MCAProcessManager.h"
+#include	"CCAUiMessageUtils.h"
+#include    "MCALoginPC.h"
+#include "MCALoginRefreshObserverPC.h"
+
+#include    <finditemengine.h>
+#include    <apgcli.h>
+#include    <S32FILE.H>
+#include	<npdapi.h>
+#include    <chatNG.mbg>
+#include    <chatNG.rsg>
+#include    <aknnotedialog.h>
+#include    <StringLoader.h>
+#include	<csxhelp/imng.hlp.hrh>
+#include	<impserrors.h>
+#include 	<txtrich.h>
+#include    <gulicon.h>
+#include    <AknLayout.cdl.h> //cdl 
+#include    <AppLayout.cdl.h> //cdl 
+#include    <AknsUtils.h>
+#include    <AknLayoutScalable_Apps.cdl.h>
+#include    <aknnotewrappers.h>
+#include    <AknFepGlobalEnums.h> // for EAknFepSoftkeySpell
+#include    <barsread.h>
+
+#include	"CATouchUtils.h"
+
+// The Settings have been moved to Cenrep (also retained in the Resource file),
+// so the enums for keys and central repository header is added here
+#include 	"VariantKeys.h"
+#ifdef RD_MULTIPLE_DRIVE
+#include <centralrepository.h>
+#include <IMPSServiceSettingsUINGInternalCRKeys.h>
+#include <E32std.h>
+#include <EIKAPP.H>
+#include <eikappui.h>
+#include <eikenv.h>
+#include <eikbtgpc.h>
+#include <CAknMemorySelectionDialogMultiDrive.h>
+//CONSTANTS
+const TInt KErrNotSaved = -999;
+#endif
+
+// CONSTANTS
+// Maximum amount of lines in the editor
+const TInt KChatConvEditorMaxLines = 2;
+
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+
+// -----------------------------------------------------------------------------
+// CCAConversationsContainer::NewL
+// Symbian constructor can leave.
+// -----------------------------------------------------------------------------
+//
+CCAConversationsContainer* CCAConversationsContainer::NewL(
+    const TRect& aRect,
+    MCAViewSwitcher& aViewSwitcher,
+    MCAConversationPC* aCCAConversationManagerPC,
+    MCARecipientObserver& aRecipientObserver,
+    MObjectProvider* aParent,
+    CCAMessageExtensionsHandler& aMessageHandler,
+    MCATitleUpdater& aTitleUpdater,
+    MCAEditorContentStorage& aEditorContentStorage,
+    CEikButtonGroupContainer* aCba,
+    TBool aActivateFromTabSwitch,
+    TInt& aTabId )
+    {
+    CCAConversationsContainer* self = new ( ELeave ) CCAConversationsContainer(
+        aViewSwitcher, aCCAConversationManagerPC, aRecipientObserver,
+        aMessageHandler, aTitleUpdater, aEditorContentStorage, aCba, aTabId );
+
+    CleanupStack::PushL( self );
+    self->ConstructL( aRect, aParent, aActivateFromTabSwitch );
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CCAConversationsContainer::CCAConversationsContainer
+// Default constructor must not leave
+// -----------------------------------------------------------------------------
+//
+CCAConversationsContainer::CCAConversationsContainer(
+    MCAViewSwitcher& aViewSwitcher,
+    MCAConversationPC* aCCAConversationManagerPC,
+    MCARecipientObserver& aRecipientObserver,
+    CCAMessageExtensionsHandler& aMessageHandler,
+    MCATitleUpdater& aTitleUpdater,
+    MCAEditorContentStorage& aEditorContentStorage,
+    CEikButtonGroupContainer* aCba,
+    TInt& aTabId )
+
+        : iViewSwitcher( aViewSwitcher ),
+        iRecipientObserver( aRecipientObserver ),
+        iIsChangeToOnlineAskedOnce( EFalse ),
+        iMessageExtensionsHandler( aMessageHandler ),
+        iTitleUpdater( aTitleUpdater ),
+        iEditorContentStorage( aEditorContentStorage ),
+        iCba( aCba ),
+        iConversationPC( aCCAConversationManagerPC ),
+        iTabId( aTabId )
+    {
+    }
+
+// -----------------------------------------------------------------------------
+// CCAConversationsContainer::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CCAConversationsContainer::ConstructL( const TRect& aRect,
+                                            MObjectProvider* aParent,
+                                            TBool aActivateFromTabSwitch )
+    {
+    // for getting mbm path from CCAAppUi
+    iAppUi = static_cast<CCAAppUi*>( CEikonEnv::Static()->AppUi() );
+    iAppUi->AddLayoutChangeObserver( this );
+
+    // This must be done first.
+    SetMopParent( aParent );
+
+    CreateWindowL();
+    CCAApp* app = static_cast<CCAApp*>(
+                      CEikonEnv::Static()->EikAppUi()->Application() );
+    iSkinVar = app->VariantFactory()->SkinVariantL();
+
+    AknEditUtils::SAknEditorParameters editorParams;
+    editorParams.iCursorYesNo = ETrue;
+    editorParams.iAllowedToMoveInsertionPoint = ETrue;
+    editorParams.iCharacterCase = EAknEditorTextCase;
+    editorParams.iEditingSpace = IMUtils::MaxMsgLength();
+    editorParams.iEditingWindow = KChatConvEditorMaxLines;
+    editorParams.iJustification = EAknEditorAlignBidi;
+    editorParams.iOverflowYesNo = EFalse;
+
+    iEditor = new ( ELeave ) CCAMessageEditor( iMessageExtensionsHandler );
+    iEditor->SetMopParent( this );
+    AknEditUtils::ConstructEditingL( iEditor, editorParams );
+    iEditor->SetContainerWindowL( *this );
+    iEditor->SetAllowPictures( ETrue );
+
+    iEditor->SetEdwinSizeObserver( this );
+    iEditor->SetMessageEditorObserver( this );
+
+    LoadBitmapsL();
+
+    MCAMsgAddedToRichTxtCtrlObserver* observer = NULL;
+
+    if ( aActivateFromTabSwitch && !iAppUi->FocusFlag() )
+        {
+        observer = this;
+        }
+
+    iChatView = CCAChatViewControl::NewL( aRect, *this,
+                                          *iConversationPC,
+                                          *iAppUi->GetProcessManager().GetSettingsInterface(),
+                                          iMessageExtensionsHandler,
+                                          iFromMe,
+                                          iToMe,
+                                          iUnsupported,
+                                          iCorrupted,
+                                          ETrue,
+                                          observer );
+
+    iChatView->SetObserver( this );
+
+    iAppUi->LayoutInfo()->SetLayoutID( TChatListBoxLayout::EWithEditor );
+    iAppUi->LayoutInfo()->SetEditorVisibility( ETrue );
+
+    iEditor->SetupSkinContextL();
+    iEditor->SetCursorPosL( 0, EFalse );
+
+    if ( !aActivateFromTabSwitch )
+        {
+        iEditor->SetFocus( ETrue );
+        iAppUi->SetFocusFlag( ETrue );
+        iChatView->SetFocus( EFalse );
+        }
+    else
+        {
+        iEditor->SetFocus( EFalse );
+        iChatView->SetFocus( ETrue );
+        }
+
+    iEditor->SetObserver( this );
+
+    iBlockingUI = CCABlockingUI::NewL( iAppUi->GetProcessManager().GetBlockingInterface() );
+
+    iSendkeyInMsgList = ( IMUtils::CRKeyL( KCRUidIMVariation, KIMVariationKey )
+                          & EIMFeatSendkeyInMsgList );
+
+    SetRect( aRect );
+
+    ActivateL();
+    TBool tempFlag = aActivateFromTabSwitch;
+    if ( iAppUi->FocusFlag() && aActivateFromTabSwitch )
+        {
+        tempFlag = EFalse;
+        }
+
+    ResetAfterSendL( tempFlag );
+
+    CHAT_DP( D_CHAT_LIT( "CursorPos(): %d" ), iEditor->CursorPos() );
+    CHAT_DP( D_CHAT_LIT( "TextLength(): %d" ), iEditor->TextLength() );
+
+    // Observe tap events
+    iChatView->SetTapObserver( this, EMessageList );
+    iEditor->SetTapObserver( this, EMessageEditor );
+
+    iEditIndicator = CCAEditIndicator::NewL( *iEditor ) ;
+    ifocusFlag = EFalse;
+    }
+
+// Destructor
+CCAConversationsContainer::~CCAConversationsContainer()
+    {
+
+    delete iFromMe;
+    delete iToMe;
+    delete iUnsupported;
+    delete iCorrupted;
+    delete iChatView;
+
+    delete iEditIndicator;
+    delete iEditor;
+    delete iBlockingUI;
+    if ( iAppUi )
+        {
+        if ( !iAppUi->IsUnderDestruction() )
+            {
+            iAppUi->LayoutInfo()->SetEditorVisibility( EFalse );
+            iAppUi->RemoveLayoutChangeObserver( this );
+
+            }
+        }
+    }
+
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::IsObjectSelected
+// ---------------------------------------------------------
+//
+TBool CCAConversationsContainer::IsObjectSelected( TBool& aIsOpenable , TBool& aSavePossible )
+    {
+    MCAConversationMessage* msg = iChatView->SelectedMessage();
+    if ( !msg )
+        {
+        // Nothing selected
+        return EFalse;
+        }
+
+    TBool object = EFalse;
+
+    if ( msg->ContentType() == TEnumsPC::EContentPicture ||
+         msg->ContentType() == TEnumsPC::EContentOther )
+        {
+        // We have object
+        object = ETrue;
+        }
+
+
+    switch ( msg->ContentProcessState() )
+        {
+        case TEnumsPC::EContentNotSupported:
+        case TEnumsPC::EContentCorrupted:
+        case TEnumsPC::EContentNotSupportedDrm:
+            {
+            // Not supported or corrupted, can't open
+            aIsOpenable = EFalse;
+            break;
+            }
+        case TEnumsPC::EThumbnailReady:
+        default:
+            {
+            if ( msg->ContentData().Length() == 0 )
+                {
+                // No content, don't allow opening
+                aIsOpenable = EFalse;
+                }
+            else
+                {
+                // Allow opening
+                aIsOpenable = ETrue;
+
+                //fix - refer Ui Spec Approved Version 1.0
+                //(Instant Messaging NG 001 151006.pdf)
+                //Section 10.2.10 Pg 131 -
+                //"In case user has saved the image already or sent it
+                //by himself, this option(save) is not available."
+                aSavePossible = ( ( msg->MessagerType() == TEnumsPC::EMessageSent )
+                                  || ( msg->IsImageSaved() ) )
+                                ? EFalse : ETrue ;
+                }
+            }
+        }
+
+    return object;
+    }
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::SelectedMessage
+// ---------------------------------------------------------
+//
+MCAConversationMessage* CCAConversationsContainer::SelectedMessage()
+    {
+    return iChatView->SelectedMessage();
+    }
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::FetchMessages
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::FetchMessages( TBool aFetch )
+    {
+    iChatView->FetchMessages( aFetch );
+    }
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::SelectedItem()
+// ---------------------------------------------------------
+//
+HBufC* CCAConversationsContainer::SelectedItemL()
+    {
+    return iChatView->SelectedItemL();
+    }
+
+// -----------------------------------------------------------------------------
+// CCAConversationsContainer::SelectedItemType
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CCAConversationsContainer::SelectedItemType()
+    {
+    return iChatView->SelectedItemType();
+    }
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::IsStopped()
+// This method checks if scroll mode is on or off
+// ---------------------------------------------------------
+//
+TBool CCAConversationsContainer::IsStopped() const
+    {
+    return iChatView->Highlighted();
+    }
+
+// -----------------------------------------------------------------------------
+// CCAConversationsContainer::SetItemHighlightL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CCAConversationsContainer::SetItemHighlightL( TBool aHighlight )
+    {
+    iChatView->SetHighlight( aHighlight );
+    iItemHighlight = aHighlight;
+    }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::StartScrollingL()
+// This method is called when scrolling is started again
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::StartScrollingL( TBool aActivateFromTabSwitch/*=EFalse*/ )
+    {
+    // disable highlight and set focus to editor
+    if ( iChatView->Highlighted() )
+        {
+        iChatView->DisableHighlightL();
+        }
+    if ( !aActivateFromTabSwitch )
+        {
+        iEditor->SetFocus( ETrue, EDrawNow );
+        iChatView->SetFocus( EFalse, EDrawNow );
+        }
+    else
+        {
+        iEditor->SetFocus( EFalse, EDrawNow );
+        iChatView->SetFocus( ETrue, EDrawNow );
+        }
+
+    iEditor->DrawDeferred();
+    UpdateCbaL();
+    }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::StopScrollingL()
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::StopScrollingL()
+    {
+    // unfocus editor (highlighting is enabled
+    // automatically in OfferKeyEvent of ChatView)
+    iEditor->SetFocus( EFalse, EDrawNow );
+    iChatView->SetFocus( ETrue, EDrawNow );
+    iEditor->DrawDeferred();
+    // Set editor cursor pos to end of text
+    iEditor->SetCursorPosL( iEditor->TextLength(), EFalse );
+    UpdateCbaL();
+    }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::UpdateCbaL()
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::UpdateCbaL()
+    {
+    TInt cbaRes( R_CHAT_SOFTKEYS_OPTIONS_CONTINUE__EMPTY );
+    if ( !iCba )
+        {
+        return;
+        }
+
+    if ( !iChatView->GetMessageCount() )
+        {
+        //if the message list is empty
+        if ( !iEditor->IsFocused() )
+            {
+            //if editor is not in focus then the rightSK must be "continue"
+            iCba->SetCommandSetL( cbaRes );
+            iCba->DrawNow();
+            return;
+            }
+        }
+
+    if ( iChatView->Highlighted() )
+        {
+        // focus on chatview
+        TBool ignore;
+        HBufC* item = iChatView->SelectedItemL();
+        CleanupStack::PushL( item );
+        TBool dummyArgument( EFalse );
+        if ( IsObjectSelected( ignore, dummyArgument ) )
+            {
+            // openable object selected
+            cbaRes = R_CHAT_SOFTKEYS_OPTIONS_CONTINUE__OPEN;
+            }
+        else if ( item && item->Length() > 0 )
+            {
+            // automatic find item selected
+            cbaRes = R_CHAT_SOFTKEYS_OPTIONS_CONTINUE__CONTEXTOPTIONS;
+            }
+        CleanupStack::PopAndDestroy( item );
+        }
+    else
+        {
+        // focus on editor
+        cbaRes = iEditor->TextLength() > 0 ?
+                 R_CHAT_SOFTKEYS_OPTIONS_BACK__SEND :
+                 R_CHAT_SOFTKEYS_OPTIONS_BACK__EMPTY;
+        }
+
+    // Check that there is not "Spell" in the left button
+    // ControlOrNull() is needed for 3.0 backport.
+    if ( !( iCba->ControlOrNull( EAknFepSoftkeySpell ) &&
+            iCba->IsCommandVisible( EAknFepSoftkeySpell ) ) )
+        {
+        iCba->SetCommandSetL( cbaRes );
+        iCba->DrawNow();
+        }
+    }
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::Editor()
+// This method returns pointer to CEikGlobalTextEditor
+// ---------------------------------------------------------
+//
+CCAMessageEditor& CCAConversationsContainer::Editor() const
+    {
+    return *iEditor;
+    }
+
+TBool CCAConversationsContainer::Sending() const
+    {
+    return iSending;
+    }
+
+void CCAConversationsContainer::ResetSending()
+    {
+    iSending = EFalse;
+    }
+
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::CheckBlockedL
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::CheckBlockedL()
+    {
+
+    MCABlockingPC* blockinInterface = iAppUi->GetProcessManager().GetBlockingInterface();
+
+    TPtrC wvid( iConversationPC->GetReadInterfaceId() );
+
+    // Check if target id is blocked
+    if ( blockinInterface->IsContactBlocked( wvid, ETrue ) )
+        {
+        iAppUi->ShowWaitDialogL( R_CHAT_BLOCK_REMOVING );
+        TInt errorCode = KErrNone;
+        TRAPD( err, errorCode = blockinInterface->SetTemporaryGrantL(
+                                    wvid, ETrue ) );
+        iAppUi->DismissWaitDialogL( err );
+        if ( errorCode == KErrNone )
+            {
+            IMDialogUtils::DisplayNoteDialogL( R_CHATCLIENT_CNOTE_UNBLOCK );
+            }
+        else
+            {
+            IMNoteMapper::ShowNoteL( errorCode );
+            }
+        }
+    }
+
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::SendMessageL()
+// This method handles message sending to engine
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::SendMessageL()
+    {
+    if ( iAppUi->UISessionManager().IsLoggedIn() )
+        {
+        TInt textLength( iEditor->TextLength() );
+        if ( textLength == 0 )
+            {
+            return;
+            }
+
+        // Check status, and change status to "online" if it's "away"
+        MCAPresence::TPresenceStatus curStatus =
+            CAPresenceManager::InstanceL()->StatusL();
+
+        TBool statusChangeNeeded =
+            ( curStatus == MCAPresence::EAway ||
+              curStatus == MCAPresence::EBusy );
+
+        if ( statusChangeNeeded &&
+             IMUtils::IntResourceValueL(
+                 RSC_CHAT_VARIATION_AUTOMATIC_STATUS_CHANGE ) )
+            {
+            CCAWaitNote* note = CCAWaitNote::ShowWaitNoteLC(
+                                    R_QTN_CHAT_CHANGE_STATUS_CHANGING );
+
+            TInt error = CAPresenceManager::InstanceL()->ChangeStatusL(
+                             MCAPresence::EOnline, KNullDesC );
+
+            CleanupStack::PopAndDestroy(); // waitnote
+
+            if ( error == KErrNone )
+                {
+                // Change status pane icon
+                iAppUi->UISessionManager().SetStatusPaneIconsL();
+                // show information note
+                IMDialogUtils::DisplayInformationNoteL(
+                    R_CHAT_STATUS_CHANGED_AUTOMATIC );
+                }
+            else
+                {
+                // change status failed
+                IMDialogUtils::DisplayErrorNoteL(
+                    R_QTN_CHAT_CHANGE_STATUS_FAILED );
+                }
+            }
+
+        CheckReplyL();
+
+        HBufC* msgBuf = iMessageExtensionsHandler.ProcessMessageLC( *iEditor );
+        TPtr msgPtr( msgBuf->Des() );
+
+        // Check message if there is other than empty chars
+        TInt len( msgPtr.Length() );
+        TBool contaisOnlyEmptyChars( ETrue );
+
+        for ( TInt i( 0 ); ( i < len ) && contaisOnlyEmptyChars; ++i )
+            {
+            TPtrC c = msgPtr.Mid( i, 1 );  // next character
+            TInt position = ( KEmptyCharacters() ).FindC( c );
+
+            if ( position == KErrNotFound )
+                {
+                // c not found from empty characters --> c is not empty char
+                contaisOnlyEmptyChars = EFalse;
+                }
+            }
+
+        if ( contaisOnlyEmptyChars )
+            {
+            // message contains only empty character
+            // don't send message and setting focus back to editor window
+            iEditor->SetFocus( ETrue );
+            iChatView->SetFocus( EFalse );
+            CleanupStack::PopAndDestroy( msgBuf );
+            return;
+            }
+
+
+        // Check grant list
+        CheckBlockedL();
+
+        iConversationPC->SendMessageL( msgBuf->Des() );
+
+        TInt editorFlags = ( iEditor->AknEdwinFlags() | EAknEditorFlagNoEditIndicators );
+        iEditor->SetAknEditorFlags( editorFlags );
+
+        ResetAfterSendL();
+        CleanupStack::PopAndDestroy( msgBuf ); // msgBuf
+        }
+    else
+        {
+        // Not logged in
+        // 1. Start login procedure
+        // 2. Wait for contact list fetching to complete
+        //    before proceeding with sending (unless bgfetch is enabled)
+        if ( !iLogingFlag )
+            {
+            iLogingFlag = ETrue;
+            MCALoginPC *loginPC = iAppUi->GetProcessManager().GetLogInInterface();
+            loginPC->AddObserver( this );
+
+            TBool isloggedIn = iAppUi->UISessionManager().LoginL( MCAUiLoginCmdCB::EQueryLogin );
+
+            if ( isloggedIn )
+                {
+                iWvId.Copy( iConversationPC->GetReadInterfaceId().Left(
+                                iWvId.MaxLength() ) );
+                iSending = ETrue; // set the sending flag, so we don't get deleted
+                // Login
+                }
+            else
+                { // Login failed, return
+                ResetSending();
+                loginPC->RemoveObserver();
+                }
+            iLogingFlag = EFalse;
+            }
+        }
+    }
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::AddToFriendsL()
+// Adds to friend
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::AddToFriendsL()
+    {
+
+    CCAStatusPaneHandler& statusPane = *iViewSwitcher.CAStatusPane();
+
+    HBufC* titleText = statusPane.Title()->AllocLC();
+
+    // creating a new contact
+    TBool contactSaved( EFalse );
+
+    CCAContactEditor* contactEditor =
+        CCAContactEditor::NewL( -1, contactSaved );
+    TPtrC wvid( iConversationPC->GetReadInterfaceId() );
+
+    contactEditor->EditContactLD( TEnumsPC::EAddToContact, KNullDesC, wvid, KNullDesC );
+
+    statusPane.SetTitleL( *titleText );
+    CleanupStack::PopAndDestroy( titleText );
+
+    iTitleUpdater.UpdateTitleL();
+
+    statusPane.RestoreNaviPane();
+
+    }
+
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::BlockUserL()
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::BlockUserL()
+    {
+    TPtrC wvid( iConversationPC->GetReadInterfaceId() );
+
+    iBlockingUI->BlockUserL( wvid );
+    }
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::IsBlocked()
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TBool CCAConversationsContainer::IsBlocked() const
+    {
+    TPtrC wvid( iConversationPC->GetReadInterfaceId() );
+    return iAppUi->GetProcessManager().GetBlockingInterface()->IsContactBlocked( wvid );
+    }
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::BlockUserWVIdL()
+// ---------------------------------------------------------
+void CCAConversationsContainer::BlockUserWVIdL()
+    {
+    iBlockingUI->DisplayBlockTextQueryL();
+    }
+// ---------------------------------------------------------
+// CCAConversationsContainer::UnBlockL()
+// ---------------------------------------------------------
+void CCAConversationsContainer::UnBlockL()
+    {
+    iBlockingUI->DisplayUnblockListQueryL();
+    }
+// ---------------------------------------------------------
+// CCAConversationsContainer::DisplayBlockedListL()
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::DisplayBlockedListL()
+    {
+    iBlockingUI->DisplayBlockedListL();
+    }
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::ApplicationUserSentThis()
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TBool CCAConversationsContainer::ApplicationUserSentThis() const
+    {
+    TBool ret( EFalse );
+    MCAConversationMessage* message = iChatView->SelectedMessage();
+    if ( message )
+        {
+        ret = ( message->MessagerType() == TEnumsPC::EMessageSent );
+        }
+    return ret;
+    }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::SetLoggingOnL()
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::RecordChatL()
+    {
+    TBool isMemorySelected = ETrue;
+#ifdef RD_MULTIPLE_DRIVE // show note	
+    isMemorySelected = ShowMemorySelectionDialogL();
+#endif
+    // if the location has not been set, don't do record
+    if ( !isMemorySelected )
+    	{
+    	return;
+    	}
+    
+    HBufC* logFileName = HBufC::NewLC( KMaxLogFileName );
+    TPtr logFileNamePtr( logFileName->Des() );
+
+    iConversationPC->GetLogFileName( logFileNamePtr ) ;
+
+    TInt result( IMDialogUtils::DisplayTextQueryDialogL( logFileNamePtr,
+                                                         RSC_CHATNG_LOGDIALOG_PROMPT, R_CHATCLIENT_LOG_NAME_QUERY,
+                                                         ETrue // T9
+                                                       ) );
+
+    if ( result == EAknSoftkeyOk || result == EAknSoftkeyDone )
+        {
+        //CR ID : 10139730 Show warning when saving a chat
+        ShowRecordSavingWarningL() ;
+#ifdef RD_MULTIPLE_DRIVE // show note
+        TInt error = KErrNone;
+        TRAP( error , iConversationPC->RecordChatL( *logFileName ) );
+
+        if ( error != KErrNotSaved && error != KErrDiskFull )
+#else
+        iConversationPC->RecordChatL( *logFileName );
+#endif
+            {
+            IMDialogUtils::DisplayConfirmationNoteL( R_QTN_CHAT_SAVING_SAVED );
+            }
+#ifdef RD_MULTIPLE_DRIVE
+        else if ( error == KErrDiskFull )
+            {
+            TBuf< KMaxPath > defaultDrive;
+
+            CRepository* cenrep = CRepository::NewL( KWVSettingsCenRepUid );
+
+            TInt err = cenrep->Get( KIMPSCRIMDefaultMemoryDrive, defaultDrive );
+
+            delete cenrep;
+            cenrep = NULL;
+
+            if ( err != KErrNone )
+                {
+                User::Leave( err );
+                }
+            TInt driveNo = 0;
+            err = RFs::CharToDrive( defaultDrive[0], driveNo );
+            if ( err != KErrNone )
+                {
+                User::Leave( err );
+                }
+            TDriveNumber driveNumber = TDriveNumber( driveNo );
+
+            RFs& fs = CCoeEnv::Static()->FsSession();
+
+            TDriveInfo driveInfo;
+            err = fs.Drive( driveInfo, driveNumber );
+            if ( err != KErrNone )
+                {
+                User::Leave( err );
+                }
+            if ( driveInfo.iDriveAtt & KDriveAttRemovable )
+                {
+                HBufC* prompt = iEikonEnv->AllocReadResourceLC( R_CHAT_MEMLO_MMC_NOT_ENOUGH_MEMORY );
+                IMDialogUtils::DisplayErrorNoteL( *prompt, ETrue );
+                CleanupStack::PopAndDestroy( prompt );
+                }
+            else
+                {
+                HBufC* prompt = iEikonEnv->AllocReadResourceLC( R_CHAT_MEMLO_NOT_ENOUGH_MEMORY );
+                IMDialogUtils::DisplayErrorNoteL( *prompt, ETrue );
+                CleanupStack::PopAndDestroy( prompt );
+                }
+
+            }
+#endif
+        }
+    CleanupStack::PopAndDestroy( logFileName );
+    }
+
+
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::ExtensionFits()
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TBool CCAConversationsContainer::ExtensionFits( TInt aLength )
+    {
+    TBool retVal( ETrue );
+    if ( iEditor->MaxLength() - iEditor->TextLength() < aLength )
+        {
+        retVal = EFalse;
+        }
+    return retVal;
+    }
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::ResetAfterSendL()
+// Resets arrays, lines and nick length after send
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::ResetAfterSendL( TBool aActivateFromTabSwitch/*=EFalse*/  )
+    {
+    iEditor->ResetL();
+    iEditor->SetTextLimit( IMUtils::MaxMsgLength() );
+    iEditor->SetAknEditorCurrentCase( EAknEditorTextCase );
+    StartScrollingL( aActivateFromTabSwitch );  // Call to update CBA
+    }
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::DisplayInfoNoteL()
+// Displays info note for corresponding resource id
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::DisplayInfoNoteL( const TInt aResourceId )
+    {
+    CAknNoteDialog* infoNote = new ( ELeave ) CAknNoteDialog( CAknNoteDialog::
+                                                              EConfirmationTone, CAknNoteDialog::EShortTimeout );
+
+    infoNote->ExecuteLD( aResourceId );
+    }
+
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::LayoutChangedL
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::LayoutChangedL( TInt aType )
+    {
+    LoadBitmapsL();
+    TRect mainPaneRect;
+    AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EMainPane, mainPaneRect );
+    SetRect( mainPaneRect );
+
+    // Update skin context of editor
+    if ( iEditor )
+        {
+        iEditor->SetupSkinContextL( ETrue );
+        }
+
+    CCoeControl::HandleResourceChange( aType );
+    }
+
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::HandleEdwinSizeEventL( CEikEdwin* aEdwin,
+//			TEdwinSizeEvent aEventType, TSize aDesirableEdwinSize )
+// This method is called when editor is extended to two lines
+// ---------------------------------------------------------
+//
+TBool CCAConversationsContainer::HandleEdwinSizeEventL( CEikEdwin* /*aEdwin*/,
+                                                        TEdwinSizeEvent aEventType, TSize /*aDesirableEdwinSize*/ )
+    {
+    if ( aEventType == EEventSizeChanging )
+        {
+        SizeChanged();
+
+        DrawNow();
+        return ETrue;
+        }
+    return EFalse;
+    }
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::HandleTapEventL()
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::HandleTapEventL( TTapEvent aEvent,
+                                                 TUint aControlId )
+    {
+    // Handle the tap events which occur in our child controls:
+    // Message list and Message editor.
+    switch ( aControlId )
+        {
+        case EMessageList:
+            {
+            // Focused message was double tapped
+            if ( aEvent == MCATapEventObserver::EDoubleTap )
+                {
+                // Activate tapped item
+                TBool ignore;
+                TBool dummyArgument;
+                if ( IsObjectSelected( ignore , dummyArgument ) )
+                    {
+                    iAppUi->ProcessCommandL( EChatClientOpenObject );
+                    }
+
+                }
+            // Message or item was tapped
+            else if ( aEvent == MCATapEventObserver::ESingleTap )
+                {
+                // Find objects activate with single tap
+                iRecipientObserver.ShowPopUpMenuL();
+                }
+            break;
+            }
+        case EMessageEditor:
+            {
+            // Nothing to do here ATM.
+            // Focus transition is handled in HandleControlEventL
+            break;
+            }
+        default:
+            {
+            // There is an unhandled object or the object returned wrong
+            // controlId. Check the implementation
+            __CHAT_ASSERT_DEBUG( EFalse );
+            break;
+            }
+        }
+    }
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::HandleControlEventL
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::HandleControlEventL( CCoeControl* aControl,
+                                                     TCoeEvent aEventType )
+    {
+    if ( EEventRequestFocus == aEventType )
+        {
+        if ( aControl == ( CCoeControl* )iEditor )
+            {
+            // Focus to editor
+            StartScrollingL();
+            iAppUi->SetFocusFlag( ETrue );
+            }
+        else // aControl == iChatView
+            {
+            // Focus to messagelist
+            StopScrollingL();
+            iAppUi->SetFocusFlag( EFalse );
+            }
+        }
+
+    if ( CATouchUtils::PenEnabled() )
+        {
+
+        if ( EEventStateChanged == aEventType )
+            {
+            if ( aControl == ( CCoeControl* )iEditor )
+                {
+                // Update MSK - When using virtual keyboard
+                // on touch enabled devices, one is bound to receive
+                // EEventStateChanged. Hence handle the same
+                UpdateCbaL();
+                }
+            }
+
+        }
+
+    }
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::SizeChanged()
+// Called by framework when the view size is changed
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::SizeChanged()
+    {
+    TInt lines( iEditor->NumberOfLines() );
+
+    if ( lines > 2 ) // ignore events for more than 2 lines
+        {
+        lines = 2;
+        }
+    lines--;	// convert to index
+
+    TAknLayoutRect rp;
+    if ( lines == 1 )
+        {
+        rp.LayoutRect( Rect(), AknLayoutScalable_Apps::im_reading_pane(
+                           TChatListBoxLayout::EWithEditor2Lines ) );
+        }
+    else
+        {
+        rp.LayoutRect( Rect(), AknLayoutScalable_Apps::im_reading_pane(
+                           TChatListBoxLayout::EWithEditor ) );
+        }
+
+    // Set icon sizes, do this before setting the rect for
+    // chat view to prevent icon sizes from changing after chat
+    // view rect is set.
+    ResizeIcons( TextRect() );
+
+    // set rect for chat view
+    iChatView->SetRect( rp.Rect() );
+
+    // and editor
+    TAknLayoutRect wpl;
+    wpl.LayoutRect( Rect(), AknLayoutScalable_Apps::im_writing_pane( 1 - lines ) );
+
+    TAknWindowLineLayout myWPLayout( AknLayoutScalable_Apps::im_writing_pane( 1 - lines ) );
+
+    iOutLine.LayoutRect( iAppUi->LayoutInfo()->MainPaneRect(), myWPLayout );
+
+    iVertLine.LayoutRect( wpl.Rect(),
+                          iAppUi->LayoutInfo()->IM_writing_field_elements_Line_1( lines ) );
+
+    iHoriline.LayoutRect( wpl.Rect(),
+                          iAppUi->LayoutInfo()->IM_writing_field_elements_Line_2() );
+
+    TAknMultiLineTextLayout mlwpt =
+        iAppUi->LayoutInfo()->Multiline_IM_writing_pane_texts_Line_1( lines + 1 );
+
+    AknLayoutUtils::LayoutEdwin( iEditor, wpl.Rect(), mlwpt, EAknsCIQsnTextColorsCG25 );
+    
+	FocusChanged( EDrawNow );
+
+    DrawNow();
+    }
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::CountComponentControls() const
+// ---------------------------------------------------------
+//
+TInt CCAConversationsContainer::CountComponentControls() const
+    {
+    // We have 2 controls
+    return 2;
+    }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::ComponentControl(TInt aIndex) const
+// ---------------------------------------------------------
+//
+CCoeControl* CCAConversationsContainer::ComponentControl( TInt aIndex ) const
+    {
+    //returns control with aIndex
+    switch ( aIndex )
+        {
+        case 0:
+            {
+            return iChatView;
+            }
+        case 1:
+            {
+            return iEditor;
+            }
+        default:
+            {
+            return NULL;
+            }
+        }
+    }
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::Draw(const TRect& aRect) const
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::Draw( const TRect& aRect ) const
+    {
+    CWindowGc& gc = SystemGc();
+
+    // Draw skinned background
+    iSkinVar->ClearChatListBoxBackGround(
+        gc, aRect,
+        iSkinVar->MainPaneBackgroundContext() );
+
+    TRect editorRect( iEditor->Rect() );
+    TRect outlineRect( iOutLine.Rect() );
+    TRect parent( Rect() );
+
+    TBool skinnedDraw = iSkinVar->DrawSkinnedEditor(
+                            this, gc, parent, editorRect, outlineRect );
+
+    if ( ! skinnedDraw )
+        {
+        DrawUtils::ClearBetweenRects( gc, Rect(), iEditor->Rect() );
+
+        iOutLine.DrawOutLineRect( gc );
+        iHoriline.DrawRect( gc );
+        iVertLine.DrawRect( gc );
+        }
+
+    }
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::OfferKeyEventL( const TKeyEvent& aKeyEvent,
+//												  TEventCode aType )
+// Handles keyevents
+// ---------------------------------------------------------
+//
+TKeyResponse CCAConversationsContainer::OfferKeyEventL(
+    const TKeyEvent& aKeyEvent,
+    TEventCode aType )
+    {
+    CHAT_DP( D_CHAT_LIT( "CCAConversationsContainer::OfferKeyEventL key %d" ),
+             aKeyEvent.iCode );
+    
+    if ( aKeyEvent.iScanCode == EStdKeyYes && aType != EEventKey )
+        {
+        return EKeyWasConsumed;
+        }
+    
+    if ( ( IsStopped() || !iEditor->IsFocused() ) )
+        {
+        if ( aKeyEvent.iScanCode >= '0' && aKeyEvent.iScanCode <= '9' )
+            {
+            // stop the automatic scrolling and start manual
+            // if user presses any of the number keys (0-9)
+            StartScrollingL();
+            // Key event gets passed to editor after this
+            }
+        }
+
+    if ( aType == EEventKeyDown )
+        {
+        if ( ( aKeyEvent.iScanCode == KHashKey ) &&
+             ( iEditor->TextLength() == 0 ) )
+            {
+
+            if ( !iEditIndicator->IsIndicatorActive() )
+                {
+                iEditIndicator->StartTimer();
+                }
+
+            }
+        }
+    switch ( aKeyEvent.iCode )
+        {
+            // flowthrough
+        case EKeyEnter:
+        case EKeyOK:
+        case EKeyPhoneSend:
+            {
+            if ( iEditor->IsFocused() )
+                {
+                // trapping error so that focus can be returned to editor
+                TRAPD( err, SendMessageL() );
+                if ( err )
+                    {
+                    CActiveScheduler::Current()->Error( err );
+                    }
+                iEditor->SetFocus( ETrue );
+                iChatView->SetFocus( EFalse );
+                }
+            else if ( aKeyEvent.iCode == EKeyEnter || aKeyEvent.iCode == EKeyOK
+                      && iChatView->Highlighted() )
+                {
+                TBool ignore;
+                TBool dummyArgument;
+                if ( IsObjectSelected( ignore , dummyArgument ) )
+                    {
+                    iAppUi->ProcessCommandL( EChatClientOpenObject );
+                    }
+                else
+                    {
+                    iRecipientObserver.ShowPopUpMenuL();
+                    }
+                }
+            else if ( iSendkeyInMsgList )
+                {
+                if ( aKeyEvent.iCode == EKeyPhoneSend
+                     && iChatView->Highlighted()
+                     && iChatView->SelectedItemType()
+                     == CFindItemEngine::EFindItemSearchPhoneNumberBin )
+                    {
+                    // Phone number highlighted, send key pressed -> call
+                    iAppUi->ProcessCommandL( EChatClientCall );
+                    }
+                }
+            return EKeyWasConsumed;
+            }
+
+        case EKeyBackspace:
+            {
+            // if bitmap is selected, it is deleted "normally" in
+            // iEditor's OfferKeyEvent
+            if ( iEditor->SelectionLength() > 0 )
+                {
+                break;
+                }
+
+            TInt cursorPos( iEditor->CursorPos() );
+            if ( cursorPos > 0 ) // at least one char in editor
+                {
+                TPtrC ptr = iEditor->RichText()->Read( ( cursorPos - 1 ), 1 );
+                // if a char to be "backspaced" is a picture
+                if ( ptr[ 0 ] == CEditableText::EPictureCharacter )
+                    {
+                    iMessageExtensionsHandler.DeleteExtensionL( *iEditor,
+                                                                EMessageExtensionSmiley, cursorPos - 1 );
+                    return EKeyWasConsumed;
+                    }
+                }
+
+            if ( cursorPos < 2 )
+                {
+                cursorPos = 2;
+                }
+
+            CHAT_DP( D_CHAT_LIT( "CursorPos(): %d" ), cursorPos );
+            break;
+            }
+
+        // flowthrough
+        case EKeyLeftArrow:
+        case EKeyRightArrow:
+            {
+            if ( !iEditor->IsFocused() )
+                {
+                //return EKeyWasConsumed;
+                TKeyResponse res = iAppUi->OfferTabEventL( aKeyEvent, aType );
+                if ( ifocusFlag )
+                    {
+                    StartScrollingL();
+                    ifocusFlag = EFalse;
+                    }
+                else
+                    {
+                    iAppUi->SetFocusFlag( EFalse );
+                    }
+                return res;
+                }
+            break;
+            }
+
+        case EKeyDownArrow: // flowthrough
+        case EKeyUpArrow:
+            {
+            if ( iEditor->IsFocused() )
+                {
+                // editor is focused, try to offer the key
+                if ( iEditor->OfferKeyEventL( aKeyEvent, aType )
+                     == EKeyWasConsumed )
+                    {
+                    // editor took it
+                    return EKeyWasConsumed;
+                    }
+                }
+            TInt inputLang = iAvkonEnv->SettingCache().InputLanguage();   // when the editor is empty and language has candidate pane
+            if ( !iChatView->GetMessageCount() && ( ( inputLang == ELangPrcChinese )// focus should move to messagelistpane, helps in tab swithching.
+                                                    || ( inputLang == ELangHongKongChinese )
+                                                    || ( inputLang == ELangTaiwanChinese )
+                                                    || ( inputLang == ELangJapanese ) ) )
+                {
+                //when message list is empty
+                if ( iEditor->IsFocused() )
+                    {
+                    //if editor in focus, then remove the focus from
+                    // editor and move the focus to message list
+                    StopScrollingL();
+                    iAppUi->SetFocusFlag( EFalse );
+                    }
+                else
+                    {
+                    //if editor not in focus, then remove the focus from
+                    //msg list and move the focus to editor
+                    StartScrollingL();
+                    iAppUi->SetFocusFlag( ETrue );
+                    }
+
+
+                return EKeyWasConsumed;
+                }
+            // offer the key to our chat control
+            TKeyResponse res = static_cast<CCoeControl*>( iChatView )
+                               ->OfferKeyEventL( aKeyEvent, aType );
+
+            if ( iChatView->Highlighted() )
+                {
+                // change the cba
+                StopScrollingL();
+                iAppUi->SetFocusFlag( EFalse );
+                }
+            else
+                {
+                // change the cba
+                StartScrollingL();
+                iAppUi->SetFocusFlag( ETrue );
+                }
+            return res;
+            }
+
+        default:
+            {
+            break;
+            }
+        }
+
+
+    if ( iEditor->IsFocused() )
+        {
+        TKeyResponse res = iEditor->OfferKeyEventL( aKeyEvent, aType );
+
+        // Update CBA only when there is not a shift held down
+        if ( !( aKeyEvent.iModifiers & EModifierShift ) )
+            {
+            UpdateCbaL();
+            }
+        TInt inputLang = iAvkonEnv->SettingCache().InputLanguage();         // when the language has candidate
+        if ( ( inputLang != ELangPrcChinese ) && ( inputLang != ELangHongKongChinese )//pane  then switching between tabs shouldnot
+             && ( inputLang != ELangTaiwanChinese ) && ( inputLang != ELangJapanese ) ) // happen,when editor is empty.
+            {
+
+            if ( res == EKeyWasNotConsumed && iEditor->TextLength() == 0
+                 && aType == EEventKeyDown
+                 && ( aKeyEvent.iScanCode == EStdKeyLeftArrow
+                      ||  aKeyEvent.iScanCode == EStdKeyRightArrow )
+               )
+                {
+                StopScrollingL();
+                ifocusFlag = ETrue;
+                iAppUi->SetFocusFlag( ETrue );
+                }
+            }
+        return res;
+        }
+
+    return EKeyWasNotConsumed;
+    }
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::GetHelpContext
+// This function is called when Help application is launched
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::GetHelpContext(
+    TCoeHelpContext& aContext ) const
+    {
+    aContext.iMajor = KUidChatClient;
+    aContext.iContext = KIMNG_HLP_CONVERSATIONS ;
+    }
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::FocusChanged
+// This function is called when focus has been changed
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::FocusChanged(TDrawNow aDrawNow)
+	{
+	if ( iEditor && iAppUi->FocusFlag() )
+		{
+		iEditor->SetFocus( IsFocused() );
+		}
+	
+	CCoeControl::FocusChanged( aDrawNow );
+	}
+
+// logic:
+// 1. no groups/groups not supported --> hide "to group"
+// 2. no contacts --> hide "to contact"
+// 3. 1 and 2 --> hide forward menu completely
+// 4. contacts, but no online contacts, show All contacts are Offline
+// 5. skip always the current contact we're conversing with
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::FwdContactVisible
+// ---------------------------------------------------------
+//
+TBool CCAConversationsContainer::FwdContactVisible()
+    {
+    // contacts
+    TInt numContacts( iConversationPC->ContactCount() );
+    TBool showFwdToContact = numContacts > 0;
+
+    // but check if the only contact is OTHER than the contact
+    // we are having a conversation with
+    if ( numContacts == 1 )
+        {
+        TPtrC wvid( iConversationPC->GetReadInterfaceId() );
+        if ( iConversationPC->FindAnyContact( wvid ) )
+            {
+            // found it, skip the current contact
+            // in list hiding logic
+            showFwdToContact = numContacts == 1 ? EFalse : ETrue;
+            }
+        }
+
+    CHAT_DP( D_CHAT_LIT( "CCAConversationsContainer::FwdContactVisible\
+                           - contacts %d, show %d" ),
+             numContacts, showFwdToContact );
+
+    return showFwdToContact;
+    }
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::FwdGroupVisible
+// ---------------------------------------------------------
+//
+TBool CCAConversationsContainer::FwdGroupVisible()
+    {
+    // groups
+    TBool groupsSupported = iAppUi->UISessionManager().IsSupported(
+                                CCAUISessionManager::EGroup );
+    TInt numGroups( 0 );
+
+    numGroups = iConversationPC->GroupCount( ETrue ) ;
+
+    // we have to have groups supported and visible to show the forward-menu
+    TBool showFwdToGroup = groupsSupported && ( numGroups > 0 );
+
+    CHAT_DP( D_CHAT_LIT( "CCAConversationsContainer::\
+                          FwdGroupVisible - fwd show group: %d" ),
+             ( TInt ) showFwdToGroup );
+
+    return showFwdToGroup;
+    }
+
+
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::CheckReplyL
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::CheckReplyL()
+    {
+
+    TPtrC wvid;
+    TBool contactInlist = ETrue;
+
+    iConversationPC->CheckReply( wvid, contactInlist );
+    if ( !contactInlist )
+        {
+        //To Remove wv and domain part from "WV User Id"
+        //if RSC_CHAT_VARIATION_HIDE_WV flag is enabled
+        HBufC* text = StringLoader::LoadLC( R_QTN_CHAT_FRIEND_ADD_UNKNOWN,
+                                            CCAPCUtils::DisplayId( wvid ) );
+        TInt ret = IMDialogUtils::DisplayYesNoConfirmationDialogL( *text );
+        CleanupStack::PopAndDestroy( text );
+        if ( ret == EAknSoftkeyOk || ret == EAknSoftkeyYes )
+            {
+            // Launch add contact.
+            AddToFriendsL();
+            }
+        }
+    }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::ResizeIcons
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::ResizeIcons( TRect aParentRect )
+    {
+    TSize size( aParentRect.Height(), aParentRect.Height() );
+    AknIconUtils::SetSize( iFromMe->Bitmap(), size );
+    AknIconUtils::SetSize( iToMe->Bitmap(), size );
+
+    iMessageExtensionsHandler.SizeChanged( size );
+    }
+
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::HandleMessageEditorEventL
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::HandleMessageEditorEventL( TEditorEvent aEvent )
+    {
+    switch ( aEvent )
+        {
+        case EEditorContentCleared:
+            {
+            // Call StartScrollingL to update CBA if needed
+            StartScrollingL();
+            break;
+            }
+
+
+        case EEditorFirstContentAdded:
+            {
+            // Call StartScrollingL to update CBA if needed
+            if ( !iEditor->IsFocused() )
+                {
+                StartScrollingL();
+                }
+            break;
+            }
+        default:
+            {
+            break;
+            }
+        }
+    }
+
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::LoadBitmapsL
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::LoadBitmapsL()
+    {
+    //Removed the ownership of iConnUI from this file and made it a reference
+    //APPUI owns this connection UI instance and shares the same with this component.
+    // get user-defined colors from SAP settings
+    CCAAppSettingsSAPExt* SAPExtension = CCAAppSettingsSAPExt::NewLC( iAppUi->ConnectionUI() );
+    TInt ownCol( SAPExtension->IntValueL( KIMOwnMessageColourKey ) );
+    TInt otherCol( SAPExtension->IntValueL( KIMOthersMessageColourKey ) );
+    CleanupStack::PopAndDestroy( SAPExtension );
+
+    // These are pointers, because it has to be given as a pointer parameter
+    // to skin variant when loading icons
+    TRgb* ownRgbCol = NULL;
+    TRgb* otherRgbCol = NULL;
+
+    // check if custom color is defined for incoming messages arrow
+    TBool useCustomOtherMsgColor = EFalse;
+    if ( otherCol != KErrNotFound )
+        {
+        otherRgbCol = new ( ELeave ) TRgb( otherCol );
+        CleanupStack::PushL( otherRgbCol );
+        useCustomOtherMsgColor = ETrue;
+        }
+
+    // check if custom color is defined for outgoing messages arrow
+    TBool useCustomOwnMsgColor = EFalse;
+    if ( ownCol != KErrNotFound )
+        {
+        ownRgbCol = new ( ELeave ) TRgb( ownCol );
+        CleanupStack::PushL( ownRgbCol );
+        useCustomOwnMsgColor = ETrue;
+        }
+
+    // check resource colours
+    // The color settings is fetched directly from the REsource file, and its not part of Cenrep, that is the reason for using IntResourceValueFromRssL
+    TBool defaultColors = IMUtils::IntResourceValueFromRssL(
+                              RSC_CHAT_DEFAULT_MESSAGE_COLORS );
+
+    if ( !useCustomOwnMsgColor && !defaultColors )
+        {
+        // user-defined color not defined and resource colour in use
+        TResourceReader reader;
+        CCoeEnv::Static()->CreateResourceReaderLC( reader,
+                                                   RSC_CHAT_MESSAGE_COLOR );
+        TUint8 red( reader.ReadUint8() );
+        TUint8 green( reader.ReadUint8() );
+        TUint8 blue( reader.ReadUint8() );
+
+        CleanupStack::PopAndDestroy(); // reader
+
+        if ( !ownRgbCol )
+            {
+            ownRgbCol = new ( ELeave ) TRgb( red, green, blue );
+            CleanupStack::PushL( ownRgbCol );
+            }
+        else
+            {
+            *ownRgbCol = TRgb( red, green, blue );
+            }
+
+        useCustomOwnMsgColor = ETrue;
+        }
+
+    if ( !useCustomOtherMsgColor && !defaultColors )
+        {
+        // user-defined color not defined and resource colour in use
+        TResourceReader reader;
+        CCoeEnv::Static()->CreateResourceReaderLC( reader,
+                                                   RSC_CHAT_OWN_MESSAGE_COLOR );
+        TUint8 red( reader.ReadUint8() );
+        TUint8 green( reader.ReadUint8() );
+        TUint8 blue( reader.ReadUint8() );
+
+        CleanupStack::PopAndDestroy(); // reader
+
+        if ( !otherRgbCol )
+            {
+            otherRgbCol = new ( ELeave ) TRgb( red, green, blue );
+            CleanupStack::PushL( otherRgbCol );
+            }
+        else
+            {
+            *otherRgbCol = TRgb( red, green, blue );
+            }
+
+        useCustomOwnMsgColor = ETrue;
+        }
+
+    TBool overrideBrand( AknLayoutUtils::LayoutMirrored() );
+
+    CGulIcon* temp;
+
+    // if custom colors are defined, use them
+    if ( useCustomOwnMsgColor )
+        {
+        temp = iSkinVar->LoadBitmapL( EMbmChatngQgn_prop_im_from,
+                                      EMbmChatngQgn_prop_im_from_mask,
+                                      iAppUi->MbmFullPath(),
+                                      overrideBrand, ownRgbCol );
+        }
+    else
+        {
+        temp = iSkinVar->LoadBitmapL( EMbmChatngQgn_prop_im_from,
+                                      EMbmChatngQgn_prop_im_from_mask,
+                                      iAppUi->MbmFullPath() );
+        }
+
+    CleanupStack::PushL( temp );
+    IMUtils::UpdateIcon( iFromMe, temp );
+    //iconTemp is removed from CleanupStack and does not have valid value
+
+    //it can be safely reused
+    // if custom colors are defined, use them
+    if ( useCustomOtherMsgColor )
+        {
+        temp = iSkinVar->LoadBitmapL( EMbmChatngQgn_prop_im_tome,
+                                      EMbmChatngQgn_prop_im_tome_mask,
+                                      iAppUi->MbmFullPath(),
+                                      overrideBrand, otherRgbCol );
+        }
+    else
+        {
+        temp = iSkinVar->LoadBitmapL( EMbmChatngQgn_prop_im_tome,
+                                      EMbmChatngQgn_prop_im_tome_mask,
+                                      iAppUi->MbmFullPath() );
+        }
+
+    CleanupStack::PushL( temp );
+    IMUtils::UpdateIcon( iToMe, temp );
+    //iconTemp is removed from CleanupStack and does not have valid value
+
+
+    //it can be safely reused
+    temp = iSkinVar->LoadBitmapL( EMbmChatngQgn_prop_image_corrupted,
+                                  EMbmChatngQgn_prop_image_corrupted_mask,
+                                  iAppUi->MbmFullPath() );
+    CleanupStack::PushL( temp );
+    IMUtils::UpdateIcon( iCorrupted, temp );
+    //iconTemp is removed from CleanupStack and does not have valid value
+
+    //it can be safely reused
+    temp = iSkinVar->LoadBitmapL( EMbmChatngQgn_prop_unknown,
+                                  EMbmChatngQgn_prop_unknown_mask,
+                                  iAppUi->MbmFullPath() );
+    CleanupStack::PushL( temp );
+    IMUtils::UpdateIcon( iUnsupported, temp );
+    //iconTemp is removed from CleanupStack and does not have valid value
+
+    if ( useCustomOwnMsgColor )
+        {
+        CleanupStack::PopAndDestroy(); // ownRgbCol
+        }
+
+    if ( useCustomOtherMsgColor )
+        {
+        CleanupStack::PopAndDestroy(); // otherRgbCol
+        }
+
+    }
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::RefreshEditorL
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::RefreshEditorL()
+    {
+    iEditor->RefreshEditorL();
+    }
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::IsItemHighlight
+// ---------------------------------------------------------
+//
+TBool CCAConversationsContainer::IsItemHighlight() const
+    {
+    return iItemHighlight;
+    }
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::TextRect
+// ---------------------------------------------------------
+//
+const TRect CCAConversationsContainer::TextRect() const
+    {
+    TInt lines( iEditor->NumberOfLines() );
+
+    if ( lines > 2 ) // ignore events for more than 2 lines
+        {
+        lines = 2;
+        }
+    lines--;	// convert to index
+
+    TAknLayoutRect rp;
+    if ( lines == 1 )
+        {
+        rp.LayoutRect( Rect(), AknLayoutScalable_Apps::im_reading_pane( 0
+                                                                        /*TChatListBoxLayout::EWithEditor2Lines*/ ) );
+        }
+    else
+        {
+        rp.LayoutRect( Rect(), AknLayoutScalable_Apps::im_reading_pane( 1
+                                                                        /*TChatListBoxLayout::EWithEditor*/ ) );
+        }
+
+    TAknLayoutText text;
+    text.LayoutText( rp.Rect(),
+                     AknLayoutScalable_Apps::im_reading_pane_t1( 1 ).LayoutLine() );
+
+    return text.TextRect();
+    }
+
+
+//added for multitab support
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::SwitchViewL
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::SwitchViewL( )
+    {
+    delete iChatView;
+    //iChatView is assigned NULL as NewL may leave
+    iChatView = NULL;
+
+    //when user navigate among tab.
+    MCAMsgAddedToRichTxtCtrlObserver* observer = NULL;
+
+    if ( !iAppUi->FocusFlag() )
+        {
+        observer = this;
+        }
+
+    iChatView = CCAChatViewControl::NewL( Rect(), *this,
+                                          *iConversationPC,
+                                          *iAppUi->GetProcessManager().GetSettingsInterface(),
+                                          iMessageExtensionsHandler,
+                                          iFromMe,
+                                          iToMe,
+                                          iUnsupported,
+                                          iCorrupted,
+                                          ETrue,
+                                          observer );
+
+    iChatView->SetObserver( this );
+
+    UpdateCbaL();
+
+    SizeChanged();
+
+    // Observe tap events
+    iChatView->SetTapObserver( this, EMessageList );
+
+    iAppUi->LayoutInfo()->SetLayoutID( TChatListBoxLayout::EWithEditor );
+    iAppUi->LayoutInfo()->SetEditorVisibility( ETrue );
+
+    if ( iAppUi->FocusFlag() )
+        {
+        StartScrollingL();
+        }
+    }
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::HandleLoginRefreshCompleteL
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::HandleLoginRefreshCompleteL( )
+    {
+    // Check if chat is deleted, happens when user
+    // selected to login to different server.
+    // Use case:
+    // - user was logged in to server 1
+    // - user had on going conversation with another user in server 1
+    // - user logged out from server 1
+    // - user opens the conversation and tries to send a message to the another user
+    // - user selects server 2 to login
+    // ==> all open conversations are deleted during login procedure
+    if ( iChatView->IsDeleted() )
+        {
+        iConversationPC->SetActiveConversationL( iWvId );
+
+        HBufC* msgBuf = iMessageExtensionsHandler.ProcessMessageLC( *iEditor );
+        iEditorContentStorage.StoreContent( msgBuf ); // Ownership changed
+        CleanupStack::Pop( msgBuf );
+
+        iTabId = iAppUi->CAStatusPane()->ResetAndShowCurrentTabL( TEnumsPC::EConversationItem,
+                                                                  iWvId ) ;
+        ResetSending();
+
+        SwitchViewL();
+
+        SendMessageL();
+
+        }
+    else
+        {
+        // Contacts are now available, update titlebar
+        iTitleUpdater.UpdateTitleL();
+        // Proceed with message sending
+        SendMessageL();
+        ResetSending();
+        }
+    MCALoginPC *loginPC = iAppUi->GetProcessManager().GetLogInInterface();
+    loginPC->RemoveObserver();
+    }
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::ShowRecordSavingWarningL()
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::ShowRecordSavingWarningL() const
+    {
+    if ( IMUtils::IntResourceValueL( RSC_CHAT_VARIATION_RECORD_WARNING ) )
+        {
+        HBufC* warningText = CCoeEnv::Static()->AllocReadResourceLC(
+                                 R_CHAT_RECORD_WARNING );
+
+        HBufC* warningHeading = CCoeEnv::Static()->AllocReadResourceLC(
+                                    R_CHAT_RECORD_WARNING_HEADING );
+
+        IMDialogUtils::DisplayMessageQueryDialogL(
+            R_CHATCLIENT_MESSAGE_QUERY_DIALOG,
+            *warningText,
+            *warningHeading
+        );
+
+        CleanupStack::PopAndDestroy( 2, warningText );
+        }
+
+    }
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::HandleMessageAddedL
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::HandleMessageAddedL( const TInt aMessageCount )
+    {
+    //called by tabswitch. hence set the foxus to the last message
+    if ( iConversationPC->MessageCount() == aMessageCount )
+        {
+        iChatView->MoveHighlightL( CCARichTextContainer::EPrevious );
+
+        iChatView->UnRegisterRichTxtCtrlObserver();
+
+        UpdateCbaL();
+        }
+
+    }
+
+#ifdef RD_MULTIPLE_DRIVE
+// -----------------------------------------------------------------------------
+// CCAConversationsContainer::ShowMemorySelectionDialogL
+// New actual filename for new history file.
+// -----------------------------------------------------------------------------
+//
+TBool CCAConversationsContainer::ShowMemorySelectionDialogL()
+    {
+    CHAT_DP_TXT( "CCALoggerManager::ShowMemorySelectionDialogL" );
+
+    ///////// read settings from cenrep ///////////////
+
+    TBuf< KMaxPath > defaultDrive;
+    TBuf< KMaxPath > pathTempWithoutDrive;
+    TBuf< KMaxPath > driveAndPath;
+
+    CRepository* cenrep = NULL;
+    TRAPD( err, cenrep = CRepository::NewL( KWVSettingsCenRepUid ) );
+
+    if ( err == KErrNone )
+        {
+        // creation of cenrep OK
+        CleanupStack::PushL( cenrep );
+        err = cenrep->Get( KIMPSCRIMDefaultMemoryDrive, defaultDrive );
+        if ( err != KErrNone )
+            {
+            CleanupStack::PopAndDestroy( cenrep );
+            cenrep = NULL;
+            User::Leave( err );
+            }
+        // end of reading from cenrep
+
+        TInt driveNo = 0;
+        err = RFs::CharToDrive( defaultDrive[0], driveNo );
+        TDriveNumber driveNumber = TDriveNumber( driveNo );
+
+        // Check drive's media status
+        TBool isDriveOk = iAppUi->GetDriveStatusL( driveNumber );
+        if ( !isDriveOk )
+            {
+
+            // prompt the user to save into a different drive.......
+            CAknMemorySelectionDialogMultiDrive* dlg = CAknMemorySelectionDialogMultiDrive::NewL(
+                                                           ECFDDialogTypeSave,
+                                                           EFalse );
+
+            HBufC* rootBuffer = HBufC::NewLC( KMaxPath );
+            TPtr rootBufferPtr ( rootBuffer->Des() );
+
+            HBufC* defaultFolderBuffer = HBufC::NewLC( KMaxPath );
+            TPtr defaultFolderBufferPtr ( defaultFolderBuffer->Des() );
+
+            CleanupStack::PushL( dlg );
+            TBool ret( dlg->ExecuteL( driveNumber, &rootBufferPtr, &defaultFolderBufferPtr ) );
+            CleanupStack::PopAndDestroy( dlg );
+
+            CleanupStack::PopAndDestroy( defaultFolderBuffer );
+
+            if ( ret )
+                {
+                // update the centrep sheet also..as user changed the default folder...
+                cenrep->Set( KIMPSCRIMDefaultMemoryDrive, rootBufferPtr.Left( 3 ) );
+                driveAndPath.Append( rootBufferPtr.Left( 2 ) ); // append the drive root here with user selected drive...
+                CleanupStack::PopAndDestroy( rootBuffer );
+                CleanupStack::PopAndDestroy( cenrep );
+                cenrep = NULL;
+                }
+            else
+                {
+                CleanupStack::PopAndDestroy( rootBuffer );
+                CleanupStack::PopAndDestroy( cenrep );
+                cenrep = NULL;
+                }
+    		
+    		// use selected memory
+    		return ret;
+            }
+        else
+
+            {
+
+            CleanupStack::PopAndDestroy( cenrep );
+
+            cenrep = NULL;
+
+            // use the default memory
+            return ETrue;
+            }
+	
+        }// end of cenrep error
+
+    // cenrep create error
+    return EFalse;
+    }
+
+#endif
+
+//  End of File