--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/imstutils/imconversationview/imcvuiapp/src/cimcvapprichtextcontainer.cpp Tue Feb 02 10:12:18 2010 +0200
@@ -0,0 +1,2113 @@
+/*
+* Copyright (c) 2009 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:
+* Export help related files.
+*
+*/
+
+
+
+
+// INCLUDE FILES
+#include "cimcvapprichtextcontainer.h"
+#include "cimcvappmessagewrapper.h"
+#include "mimcvapptextview.h"
+#include "cimcvappui.h"
+#include "mimcvenginemessage.h"
+#include "cimcvappmessageextensionshandler.h"
+
+#include <AknIconUtils.h>
+#include <txtrich.h> // CRichtText
+#include <AknSettingCache.h>
+#include <aknenv.h>
+#include <aknconsts.h>
+#include <finditemengine.h>
+#include <barsread.h> // resourcereader
+#include <StringLoader.h>
+
+#include <AknsDrawUtils.h>
+#include <AknsUtils.h>
+#include <AknUtils.h>
+#include "imcvlogger.h"
+#include "cimcvapppicture.h"
+#include <imcvuiapp.mbg>
+#include "cimcvappsmileiconutility.h"
+#include <imcvuiapp.rsg>
+
+// CONSTANTS
+const TInt KIMCVHighlightColor = 244;
+const TInt KTimeStampMaxLength = 15; // max length of timestamp text
+const TInt KUnicodeRLM = 0x200F; // Right-to-Left Mark
+const TInt KUnicodeLRM = 0x200E; // Left-to-Right Mark
+//Received message maximum length is 400 character,
+//this must always be in sync with imconnectionprovider KReceiveMsgMaxLength
+const TInt KReceiveMsgMaxLength = 400;
+const TInt KMsgMaxLength = 450; //Received message maximum length is 400 character + truncation message
+_LIT( KSeparator, ": " );
+_LIT(KSpace, " ");
+
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CIMCVAppRichTextContainer::CIMCVAppRichTextContainer
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CIMCVAppRichTextContainer::CIMCVAppRichTextContainer(MIMCVAppUi* aAppUi,
+ MIMCVAppTextView* aTextView,
+ CIMCVAppMessageExtensionsHandler* aExtensionsHandler,
+ CGulIcon* aFromMe,
+ CGulIcon* aToMe,
+ MGraphicsDeviceMap* aMap,
+ TInt aServiceId,
+ TBool aScrollOver /*= ETrue*/):
+ iAppUi(aAppUi),
+ iTextView( aTextView ),
+ iItemHighlight( ETrue ),
+ iHighlightState( ENoHighlight ),
+ iExtensionsHandler( aExtensionsHandler ),
+ iScrollOver( aScrollOver ),
+ iFromMe( aFromMe ),
+ iToMe( aToMe ),
+ iMap(aMap),
+ iServiceId( aServiceId )
+ {
+ }
+
+// -----------------------------------------------------------------------------
+// CIMCVAppRichTextContainer::Initialize
+// Initializes iTextView
+// -----------------------------------------------------------------------------
+//
+void CIMCVAppRichTextContainer::Initialize( MIMCVAppUi* aAppUi,
+ MIMCVAppTextView* aTextView,
+ CIMCVAppMessageExtensionsHandler* aExtensionsHandler,
+ CGulIcon* aFromMe,
+ CGulIcon* aToMe,
+ MGraphicsDeviceMap* aMap,
+ TBool aScrollOver /*= ETrue*/ )
+ {
+ iAppUi = aAppUi;
+ iTextView = aTextView;
+ iExtensionsHandler = aExtensionsHandler;
+ iFromMe = aFromMe;
+ iToMe = aToMe;
+ iMap = aMap;
+ iScrollOver = aScrollOver;
+ }
+
+// -----------------------------------------------------------------------------
+// CIMCVAppRichTextContainer::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CIMCVAppRichTextContainer::ConstructL(const TDesC& aPrimaryKey)
+ {
+
+ iPrimaryKey = aPrimaryKey.AllocL();
+
+ iAppUi->AddLayoutChangeObserver( this );
+ iAppUi->AddResourceChangeObserver( this );
+ // setup layout
+ TAknLayoutId layoutId;
+ CAknEnv::Static()->GetCurrentLayoutId( layoutId );
+
+
+ iPrimaryFont = AknLayoutUtils::FontFromId( EAknLogicalFontPrimaryFont,
+ NULL );
+ iSecondaryFont = AknLayoutUtils::FontFromId( EAknLogicalFontPrimarySmallFont,
+ NULL );
+
+ CParaFormat paraFormat;
+ TParaFormatMask paraFormatMask;
+ paraFormat.iLanguage = CAknEnv::Static()->SettingCache().InputLanguage();
+ paraFormatMask.SetAttrib( EAttParaLanguage );
+
+ paraFormat.iFillColor = KRgbWhite;
+ paraFormatMask.SetAttrib( EAttFillColor );
+
+ paraFormat.iLeftMarginInTwips = 100;
+ paraFormat.iIndentInTwips = -100;
+ paraFormatMask.SetAttrib( EAttLeftMargin );
+ paraFormatMask.SetAttrib( EAttIndent );
+
+ TCharFormat charFormat;
+ TCharFormatMask charFormatMask;
+ charFormat.iFontSpec = iSecondaryFont->FontSpecInTwips();
+ charFormatMask.SetAttrib( EAttFontTypeface );
+ charFormatMask.SetAttrib( EAttFontHeight );
+
+ // Text color
+ TRgb defaultSkinTextColor( KRgbBlack );
+ AknsUtils::GetCachedColor( AknsUtils::SkinInstance(),
+ defaultSkinTextColor,
+ KAknsIIDQsnTextColors,
+ EAknsCIQsnTextColorsCG6 );
+ charFormat.iFontPresentation.iTextColor = defaultSkinTextColor;
+ charFormatMask.SetAttrib( EAttColor );
+
+ charFormat.iFontPresentation.iPictureAlignment =
+ TFontPresentation::EAlignTop;
+ charFormatMask.SetAttrib( EAttFontPictureAlignment );
+
+ charFormat.iFontSpec.iFontStyle.SetStrokeWeight( EStrokeWeightNormal );
+ charFormatMask.SetAttrib( EAttFontStrokeWeight );
+
+
+ iParaFormatLayer = CParaFormatLayer::NewL( ¶Format, paraFormatMask );
+ iCharFormatLayer = CCharFormatLayer::NewL( charFormat, charFormatMask );
+
+ iRichText = CRichText::NewL( iParaFormatLayer, iCharFormatLayer );
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::ConstructL() end" ));
+ }
+
+// -----------------------------------------------------------------------------
+// CIMCVAppRichTextContainer::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CIMCVAppRichTextContainer* CIMCVAppRichTextContainer::NewL( MIMCVAppUi* aAppUi,
+ MIMCVAppTextView* aTextView,
+ CIMCVAppMessageExtensionsHandler* aExtensionsHandler,
+ CGulIcon* aFromMe,
+ CGulIcon* aToMe,
+ MGraphicsDeviceMap* aMap,
+ const TDesC& aPrimaryKey,
+ TInt aServiceId,
+ TBool aScrollOver /*= ETrue*/)
+ {
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::NewL() start" ));
+ CIMCVAppRichTextContainer* self = new( ELeave ) CIMCVAppRichTextContainer(aAppUi,
+ aTextView,
+ aExtensionsHandler, aFromMe, aToMe, aMap,aServiceId,
+ aScrollOver );
+
+ CleanupStack::PushL( self );
+ self->ConstructL(aPrimaryKey);
+ CleanupStack::Pop( self );
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::NewL() end" ));
+ return self;
+ }
+
+
+// Destructor
+CIMCVAppRichTextContainer::~CIMCVAppRichTextContainer()
+ {
+ if(iPrimaryKey)
+ {
+ delete iPrimaryKey;
+ iPrimaryKey = NULL;
+ }
+ delete iParaFormatLayer;
+ delete iCharFormatLayer;
+ delete iRichText;
+ iMessages.ResetAndDestroy();
+ if(iAppUi)
+ {
+ iAppUi->RemoveLayoutChangeObserver( this );
+ iAppUi->RemoveResourceChangeObserver( this );
+ }
+ }
+
+
+// -----------------------------------------------------------------------------
+// CIMCVAppRichTextContainer::SelectedItem
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+HBufC* CIMCVAppRichTextContainer::SelectedItemL()
+ {
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::SelectedItemL() start" ));
+ if( iHighlightState == EItemSelected )
+ {
+ TCursorSelection curSel( iMessages[iSelected]->Selection() );
+
+ // calculate item highlight position
+ TCursorSelection itemSel(
+ iMessages[iSelected]->Highlights()[iSelectedItem] );
+
+ TInt messageStart( curSel.LowerPos() );
+ curSel.iAnchorPos = itemSel.iAnchorPos + messageStart;
+ curSel.iCursorPos = itemSel.iCursorPos + messageStart;
+
+ HBufC* text = HBufC::NewMaxL( curSel.Length() );
+ TPtr ptr( text->Des() );
+ iRichText->Extract( ptr, curSel.LowerPos(), curSel.Length() );
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::SelectedItemL() end" ));
+ return text;
+ }
+ else
+ {
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::SelectedItemL() end" ));
+ return KNullDesC().AllocL();
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CIMCVAppRichTextContainer::SelectedItemType
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CIMCVAppRichTextContainer::SelectedItemType()
+ {
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::SelectedItemType() start" ));
+ if( (iHighlightState == EItemSelected) && ( iMessages.Count() >0 )
+ && (iSelected >= 0 ) )
+ {
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::SelectedItemType() end" ));
+
+ return iMessages[iSelected]->HighlightTypes()[iSelectedItem];
+ }
+ else
+ {
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::SelectedItemType() end" ));
+ return KErrNotFound;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CIMCVAppRichTextContainer::RichText
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+MLayDoc* CIMCVAppRichTextContainer::TextLayout()
+ {
+ return iRichText;
+ }
+// -----------------------------------------------------------------------------
+// CIMCVAppRichTextContainer::RichText
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CIMCVAppRichTextContainer::ServiceId() const
+ {
+ return iServiceId;
+ }
+// -----------------------------------------------------------------------------
+// CIMCVAppRichTextContainer::SetItemHighlight
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CIMCVAppRichTextContainer::SetItemHighlight( TBool aItemHighlight )
+ {
+ iItemHighlight = aItemHighlight;
+ TInt richTextDocumentLength = iRichText->DocumentLength();
+ if (!richTextDocumentLength)
+ return;
+
+ if (aItemHighlight)
+ {
+ HBufC* text = HBufC::NewMaxLC( richTextDocumentLength );
+ TPtr txt( text->Des() );
+
+ iRichText->Extract( txt);
+ CFindItemEngine* findItem = CFindItemEngine::NewL( txt,
+ CFindItemEngine::TFindItemSearchCase(
+ CFindItemEngine::EFindItemSearchPhoneNumberBin |
+ CFindItemEngine::EFindItemSearchMailAddressBin |
+ CFindItemEngine::EFindItemSearchURLBin/* |
+ CFindItemEngine::EFindItemSearchScheme*/ )
+ );
+
+ CleanupStack::PushL( findItem );
+ const CArrayFixFlat<CFindItemEngine::SFoundItem>* items = findItem->ItemArray();
+ TInt count( items->Count() );
+
+ for( TInt i(0); i<count; ++i )
+ {
+ const CFindItemEngine::SFoundItem item = items->At(i);
+
+ // selection in rich text
+ TCursorSelection realSel( item.iStartPos + item.iLength, item.iStartPos );
+
+ HighLightItemL( realSel );
+ }
+
+ CleanupStack::PopAndDestroy( findItem );
+ CleanupStack::PopAndDestroy( text);
+
+ }
+ else
+ {
+ TCharFormat charFormat;
+ TCharFormatMask charFormatMask;
+ charFormatMask.SetAttrib( EAttFontUnderline );
+
+ charFormat.iFontPresentation.iUnderline = EUnderlineOff;
+
+ iRichText->ApplyCharFormatL ( charFormat, charFormatMask, 0, richTextDocumentLength);
+ }
+ }
+// -----------------------------------------------------------------------------
+// CIMCVAppRichTextContainer::MoveHighlightL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CIMCVAppRichTextContainer::MoveHighlightL( THighlightMovement aDirection )
+ {
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::MoveHighlightL() start" ));
+ TBool up( aDirection == EPrevious );
+ TInt messageCount( iMessages.Count() );
+ if( messageCount == 0 )
+ {
+ // no messages, nothing to highlight
+ //but make highlight state as EMessageBottom
+ //so that tabs can be switched when there is no conversation in text container.
+ if(iHighlightState == EMessageBottom)
+ {
+ iHighlightState = ENoHighlight;
+ }
+ else
+ {
+ iHighlightState = EMessageBottom;
+ }
+ return KErrNone;
+ }
+
+
+ TInt highlightCount( iMessages[iSelected]->Highlights().Count() );
+
+ if( !iItemHighlight )
+ {
+ // if item highlighting is not on, clear the item count
+ highlightCount = 0;
+ }
+
+ // if message is highlighted, but it doesn't fit to screen
+ // scroll it line by line
+ if( iHighlightState == EMessageTop || iHighlightState == EMessageBottom )
+ {
+ TCursorSelection& sel = iMessages[iSelected]->Selection();
+ if( up )
+ {
+ // up
+ if( !iTextView->IsVisible( sel.LowerPos() ) )
+ {
+ // we're scrolling up and top line is not shown,
+ // so scroll messages down by one line
+ iTextView->ScrollLinesL( 1 );
+ return KErrNone;
+ }
+ }
+ else if( !iTextView->IsVisible( sel.HigherPos() ) )
+ {
+ // we're scrolling down and bottom line is not shown,
+ // so scroll messages up by one line
+ iTextView->ScrollLinesL( -1 );
+ return KErrNone;
+ }
+ }
+
+ // update highlight position
+ switch( iHighlightState )
+ {
+ case ENoHighlight: // no highlight, select last or first message
+ {
+ if( up )
+ {
+ iSelected = messageCount - 1;
+
+ // Get highlight count of prev message
+ // if item highlighting is on
+ if ( iItemHighlight )
+ {
+ highlightCount = iMessages[iSelected]->Highlights().Count();
+ }
+
+ if ( highlightCount > 0 )
+ {
+ // highlight items inside last message (if any)
+ iHighlightState = EItemSelected;
+ iSelectedItem = highlightCount - 1;
+ }
+ else
+ {
+ // bottom of last message
+ iHighlightState = EMessageBottom;
+ }
+ }
+ else
+ {
+ // top of first message
+ iHighlightState = EMessageTop;
+ iSelected = 0;
+ }
+ break;
+ }
+ case EItemSelected: // highlighting items
+ {
+ if( up )
+ {
+ // up, previous item
+ --iSelectedItem;
+ if( iSelectedItem < 0 )
+ {
+ // end of highlights, focus message
+ iHighlightState = EMessageTop;
+ }
+ }
+ else
+ {
+ // down, next item
+ ++iSelectedItem;
+ if( iSelectedItem >= highlightCount )
+ {
+ // end of highlights
+ if ( iSelected < messageCount - 1 )
+ {
+ // focus next message
+ ++iSelected;
+ iHighlightState = EMessageTop;
+ }
+ else if ( iScrollOver )
+ {
+ // going down from last message,
+ // disable highlight so editor can take the focus
+ DisableHighlightL();
+ return KErrNone;
+ }
+ else
+ {
+ // Loop back to beginning
+ iSelected = 0;
+ iSelectedItem = 0;
+ iHighlightState = EMessageTop;
+ }
+
+ }
+ }
+ break;
+ }
+ case EMessageTop: // highlighting message ("top" of it)
+ {
+ if( up )
+ {
+ // up, highlighting previous message
+ if( iSelected > 0 )
+ {
+ // prev
+ --iSelected;
+
+ // get highlight count of prev message
+ // if item highlighting is on
+ if ( iItemHighlight )
+ {
+ highlightCount = iMessages[iSelected]->Highlights().Count();
+ }
+
+ if ( highlightCount > 0 )
+ {
+ // highlight items inside prev message (if any)
+ iHighlightState = EItemSelected;
+ iSelectedItem = highlightCount - 1;
+ }
+ else
+ {
+ // highlight whole prev message
+ iHighlightState = EMessageBottom;
+ }
+ }
+ else if ( iScrollOver )
+ {
+ // going up from first message,
+ // disable highlight, so editor can take the focus
+ DisableHighlightL();
+ return KErrNone;
+ }
+ else
+ {
+ // Loop to last message
+ iSelected = messageCount-1;
+ highlightCount = 0;
+
+ // Get highlight count of last message
+ // if item highlighting is on
+ if ( iItemHighlight )
+ {
+ highlightCount =
+ iMessages[iSelected]->Highlights().Count();
+ }
+
+ if ( highlightCount > 0 )
+ {
+ // Highlight items inside last message (if any)
+ iHighlightState = EItemSelected;
+ iSelectedItem = highlightCount - 1;
+ }
+ else
+ {
+ // Highlight whole last message
+ iHighlightState = EMessageBottom;
+ }
+ }
+ }
+ else
+ {
+ // down, highlight items inside this message (if any)
+ if( highlightCount > 0 )
+ {
+ iSelectedItem = 0;
+ iHighlightState = EItemSelected;
+ }
+ else if( iSelected < messageCount-1 )
+ {
+ // next
+ ++iSelected;
+ iHighlightState = EMessageTop;
+ }
+ else if( iScrollOver )
+ {
+ // going down from last message,
+ // disable highlight, so editor can take the focus
+ DisableHighlightL();
+ return KErrNone;
+ }
+ else
+ {
+ // Loop back to beginning
+ iSelected = 0;
+ iSelectedItem = 0;
+ iHighlightState = EMessageTop;
+ }
+ }
+ break;
+ }
+ case EMessageBottom: // highlighting message ("bottom" of it)
+ {
+ if( up )
+ {
+ // up, highlight items inside this message (if any)
+ if( highlightCount > 0 )
+ {
+ iSelectedItem = highlightCount-1;
+ iHighlightState = EItemSelected;
+ }
+ else if( iSelected > 0 )
+ {
+ // prev
+ --iSelected;
+
+ // get highlight count of prev message
+ // if item highlighting is on
+ if ( iItemHighlight )
+ {
+ highlightCount = iMessages[iSelected]->Highlights().Count();
+ }
+
+ if ( highlightCount > 0 )
+ {
+ // highlight items inside prev message (if any)
+ iHighlightState = EItemSelected;
+ iSelectedItem = highlightCount - 1;
+ }
+ else
+ {
+ iHighlightState = EMessageBottom;
+ }
+ }
+ else if( iScrollOver )
+ {
+ // going up from first message,
+ // disable highlight, so editor can take the focus
+ DisableHighlightL();
+ return KErrNone;
+ }
+ else
+ {
+ // Loop to last message
+ iSelected = messageCount-1;
+ highlightCount = 0;
+
+ // Get highlight count of last message
+ // if item highlighting is on
+ if ( iItemHighlight )
+ {
+ highlightCount =
+ iMessages[iSelected]->Highlights().Count();
+ }
+
+ if ( highlightCount > 0 )
+ {
+ // Highlight items inside last message (if any)
+ iHighlightState = EItemSelected;
+ iSelectedItem = highlightCount - 1;
+ }
+ else
+ {
+ // Highlight whole last message
+ iHighlightState = EMessageBottom;
+ }
+ }
+ }
+ else
+ {
+ // down, highlighting next message
+ if( iSelected < messageCount-1 )
+ {
+ // next
+ ++iSelected;
+ iHighlightState = EMessageTop;
+ }
+ else if( iScrollOver )
+ {
+ // going down from last message,
+ // disable highlight, so editor can take the focus
+ DisableHighlightL();
+ return KErrNone;
+ }
+ else
+ {
+ // Loop back to beginning
+ iSelected = 0;
+ iSelectedItem = 0;
+ iHighlightState = EMessageTop;
+ }
+ }
+ break;
+ }
+ default:
+ {
+
+ break;
+ }
+ }
+
+ // get the selection
+ TCursorSelection curSel( CurrentSelection() );
+
+ // remove colors from old highlight
+ TInt textLen( iRichText->DocumentLength() );
+ if( iPrevious.iAnchorPos < textLen &&
+ iPrevious.iCursorPos <= textLen )
+ {
+ BackColorL( iPrevious, KRgbWhite );
+ TextBackColorL( iPrevious, KRgbWhite );
+ }
+
+ // and set new one
+ if ( iHighlightState == EItemSelected )
+ {
+ MAknsSkinInstance* skin = AknsUtils::SkinInstance();
+ TRgb color;
+
+ TInt error = AknsUtils::GetCachedColor( skin,
+ color,
+ KAknsIIDQsnHighlightColors,
+ EAknsCIQsnHighlightColorsCG2 );
+
+ if ( !error )
+ {
+ // No error, use skinned background color
+ TextBackColorL( curSel, color );
+ }
+ else
+ {
+ TextBackColorL( curSel, AKN_LAF_COLOR_STATIC( KIMCVHighlightColor ) );
+ }
+ }
+ else
+ {
+ MAknsSkinInstance* skin = AknsUtils::SkinInstance();
+ TRgb color;
+
+ TInt error = AknsUtils::GetCachedColor( skin,
+ color,
+ KAknsIIDQsnHighlightColors,
+ EAknsCIQsnHighlightColorsCG2 );
+
+ if ( !error )
+ {
+ // No error, use skinned background color
+ BackColorL( curSel, color );
+ }
+ else
+ {
+ BackColorL( curSel, AKN_LAF_COLOR_STATIC( KIMCVHighlightColor ) );
+ }
+ }
+
+ // handle changed format
+ TCursorSelection changed( Union( iPrevious, curSel ) );
+
+
+ iTextView->HandleFormatChangedL( changed, ETrue );
+
+ iTextView->ScrollVisibleL( curSel, ETrue );
+
+ iPrevious = curSel;
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::MoveHighlightL() end" ));
+ return KErrNone;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CIMCVAppRichTextContainer::DisableHighlightL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CIMCVAppRichTextContainer::DisableHighlightL()
+ {
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::DisableHighlightL() start" ));
+ iHighlightState = ENoHighlight;
+
+ TCursorSelection sel( 0,0 );
+ TInt count( iMessages.Count() );
+ if( count > 0 )
+ {
+ sel = iMessages[count-1]->Selection();
+ }
+
+ // remove colors from old highlight (if any)
+ TInt textLen( iRichText->DocumentLength() );
+ if( iPrevious.iAnchorPos < textLen &&
+ iPrevious.iCursorPos <= textLen )
+ {
+ BackColorL( iPrevious, KRgbWhite );
+ TextBackColorL( iPrevious, KRgbWhite );
+ iTextView->HandleFormatChangedL( iPrevious );
+ }
+
+ // set focus to last message
+ iTextView->ScrollVisibleL( sel, EFalse );
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::DisableHighlightL() end" ));
+ }
+
+
+// -----------------------------------------------------------------------------
+// CIMCVAppRichTextContainer::Highlighted
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TBool CIMCVAppRichTextContainer::Highlighted()
+ {
+ return iHighlightState != ENoHighlight;
+ }
+
+// -----------------------------------------------------------------------------
+// CIMCVAppRichTextContainer::Highlighted
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CIMCVAppRichTextContainer::HighlightItemAtPosL( TInt aPos )
+ {
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::HighlightItemAtPosL() start" ));
+ TInt messagecount = iMessages.Count();
+ if( messagecount == 0 )
+ {
+ // no messages
+ return KErrNotFound;
+ }
+
+ // Store old values
+ TInt oldSelectedMessage = iSelected;
+ TInt oldSelectedItem = iSelectedItem;
+ THighlightState oldHighlight = iHighlightState;
+
+ // Find message in position aPos
+ TBool found = EFalse;
+ for( TInt i = 0; i < messagecount; ++i )
+ {
+ TCursorSelection sel = iMessages[ i ]->WholeSelection();
+ if( aPos >= sel.LowerPos() &&
+ aPos <= sel.HigherPos() )
+ {
+ // Found the message
+ iSelected = i;
+ iHighlightState = EMessageTop;
+ found = ETrue;
+ // stop searching
+ break;
+ }
+ }
+
+ if( !found )
+ {
+ // not found
+ return KErrNotFound;
+ }
+
+ // Check if there are items inside the message that can be highlighted.
+ if( iItemHighlight )
+ {
+ TInt hlCount = iMessages[ iSelected ]->Highlights().Count();
+ TInt relativePos =
+ aPos - iMessages[ iSelected ]->WholeSelection().LowerPos();
+
+ for( TInt i = 0; i < hlCount; ++i )
+ {
+ TCursorSelection sel = iMessages[ iSelected ]->Highlights()[ i ];
+
+ // Highlight's selection is relative to message
+ if( relativePos >= sel.LowerPos() &&
+ relativePos <= sel.HigherPos() )
+ {
+ // Found an item
+ iHighlightState = EItemSelected;
+ iSelectedItem = i;
+ // stop searching
+ break;
+ }
+ }
+ }
+
+ // Update UI only if selection has changed
+ if( iSelected != oldSelectedMessage ||
+ iSelectedItem != oldSelectedItem ||
+ oldHighlight != iHighlightState )
+ {
+ UpdateSelectionL();
+ return KErrNone;
+ }
+ // Already highlighted
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::HighlightItemAtPosL() end" ));
+ return KErrAlreadyExists;
+ }
+
+// -----------------------------------------------------------------------------
+// CIMCVAppRichTextContainer::UpdateSelection
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CIMCVAppRichTextContainer::UpdateSelectionL()
+ {
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::UpdateSelectionL() start" ));
+ // get the selection
+ TCursorSelection curSel( CurrentSelection() );
+
+ // remove colors from old highlight
+ TInt textLen( iRichText->DocumentLength() );
+ if( iPrevious.iAnchorPos < textLen &&
+ iPrevious.iCursorPos <= textLen )
+ {
+ BackColorL( iPrevious, KRgbWhite );
+ TextBackColorL( iPrevious, KRgbWhite );
+ }
+
+ // and set new one
+ if ( iHighlightState == EItemSelected )
+ {
+ MAknsSkinInstance* skin = AknsUtils::SkinInstance();
+ TRgb color;
+
+ TInt error = AknsUtils::GetCachedColor( skin,
+ color,
+ KAknsIIDQsnHighlightColors,
+ EAknsCIQsnHighlightColorsCG2 );
+
+ if ( !error )
+ {
+ // No error, use skinned background color
+ TextBackColorL( curSel, color );
+ }
+ else
+ {
+ TextBackColorL( curSel, AKN_LAF_COLOR_STATIC( KIMCVHighlightColor ) );
+ }
+ }
+ else
+ {
+ MAknsSkinInstance* skin = AknsUtils::SkinInstance();
+ TRgb color;
+
+ TInt error = AknsUtils::GetCachedColor( skin,
+ color,
+ KAknsIIDQsnHighlightColors,
+ EAknsCIQsnHighlightColorsCG2 );
+
+ if ( !error )
+ {
+ // No error, use skinned background color
+ BackColorL( curSel, color );
+ }
+ else
+ {
+ BackColorL( curSel, AKN_LAF_COLOR_STATIC( KIMCVHighlightColor ) );
+ }
+ }
+
+ // handle changed format
+ TCursorSelection changed( Union( iPrevious, curSel ) );
+
+ iTextView->HandleFormatChangedL( changed );
+ iTextView->ScrollVisibleL( curSel, ETrue );
+
+
+ iPrevious = curSel;
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::UpdateSelectionL() end" ));
+ }
+
+// -----------------------------------------------------------------------------
+// CIMCVAppRichTextContainer::InsertTimeStampL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TCursorSelection CIMCVAppRichTextContainer::InsertTimeStampL(
+ CIMCVAppMessageWrapper& aMessageWrapper )
+ {
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::InsertTimeStampL() start" ));
+ TInt start = 0;
+ TCursorSelection timeSel( start, start );
+
+
+ // format time
+ HBufC* timeStamp = HBufC::NewLC( KTimeStampMaxLength + KSpace().Length() );
+ TPtr timePtr( timeStamp->Des() );
+
+ HBufC* timeStampFormat = NULL;
+ timeStampFormat = StringLoader::LoadLC( R_QTN_TIME_USUAL_WITH_ZERO );
+
+ TTime time = aMessageWrapper.Message().TimeStamp();
+ TRAPD( err, time.FormatL( timePtr, *timeStampFormat ) );
+ if ( err == KErrOverflow )
+ {
+ // Reserved text space was not enough.
+ // Adjust the KTimeStampMaxLength!
+
+
+ // in release builds return without timestamp
+ CleanupStack::PopAndDestroy( 2, timeStamp ); // timeStamp, timeStampFormat
+ return timeSel;
+ }
+
+ // Convert numbers to local language
+ AknTextUtils::LanguageSpecificNumberConversion( timePtr );
+
+ // Set Alignment of Pm/Am from local setting
+ // This keeps the am/pm text close to the time.
+ timePtr.Append( AknLayoutUtils::LayoutMirrored() ?
+ KUnicodeRLM : KUnicodeLRM );
+ // append time to rich text
+ timePtr.Append( KSpace );
+ iRichText->InsertL( start, timePtr );
+
+ CleanupStack::PopAndDestroy( 2, timeStamp ); // timeStamp, timeStampFormat
+ timeSel.SetSelection( start, timePtr.Length() - 1 );
+
+ // bold the time
+ if ( timeSel.Length() > 0 )
+ {
+ BoldL( timeSel );
+ }
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::InsertTimeStampL() end" ));
+ return timeSel;
+ }
+
+// -----------------------------------------------------------------------------
+// CIMCVAppRichTextContainer::InsertContentL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CIMCVAppRichTextContainer::InsertContentL( CIMCVAppMessageWrapper& aMessageWrapper )
+ {
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::InsertContentL() start" ));
+ MIMCVEngineMessage& message = aMessageWrapper.Message();
+
+ MIMCVEngineMessage::TContentType type( message.ContentType() );
+ switch( type )
+ {
+ case MIMCVEngineMessage::EContentText:
+ {
+ TInt oldLen = iRichText->DocumentLength();
+
+ // Insert text
+ TPtrC msg( message.Text() );
+
+ HBufC* tempMsg = NULL;
+
+ TInt paraBreak = msg.Locate( CEditableText::EParagraphDelimiter );
+ // Replace all paragraph delimiters with line breaks
+ // to keep alingment consistent
+ if ( paraBreak != KErrNotFound )
+ {
+ tempMsg = msg.AllocLC();
+ TPtr ptr( tempMsg->Des() );
+ ptr.Zero();
+
+ ReplaceParaDelimsWithLineBreaks( msg, ptr );
+ msg.Set( ptr );
+ }
+
+ HBufC* numberConv = NULL;
+
+ // Convert numerals to local language
+ // 1) date item
+ if ( aMessageWrapper.Message().SystemMessageType() ==
+ MIMCVEngineMessage::ESystemMessageDateChange )
+ {
+ // Don't touch the original message
+ numberConv = msg.AllocLC();
+ TPtr ptr( numberConv->Des() );
+ AknTextUtils::LanguageSpecificNumberConversion( ptr );
+ msg.Set( ptr );
+ }
+
+ iRichText->InsertL( 0, msg );
+
+ TInt textEnd = msg.Length();
+
+ // Check for extensions (smileys)
+ TCursorSelection selection( 0, textEnd );
+ TInt bfrConv = iRichText->DocumentLength();
+ iExtensionsHandler->ConvertSelectionToExtensionL( *iRichText,
+ selection,
+ iServiceId );
+
+ // Move textEnd index if extensions were found
+ textEnd -= ( bfrConv - iRichText->DocumentLength() );
+
+ // Add nbs to preserve formatting
+ iRichText->InsertL( textEnd,
+ CEditableText::EZeroWidthNoBreakSpace );
+
+ // If this is system message, it should be bold
+ if( message.MessageType() == MIMCVEngineMessage::EMessageSystem )
+ {
+ TCursorSelection sel( 0, textEnd );
+ BoldL( sel );
+ // System messages need different kind of alignment
+ CParaFormat paraFormat;
+ TParaFormatMask paraFormatMask;
+ paraFormat.iLeftMarginInTwips = 0;
+ paraFormatMask.SetAttrib( EAttLeftMargin );
+ iRichText->ApplyParaFormatL( ¶Format, paraFormatMask,
+ 0, textEnd + 1 );
+ }
+ else
+ {
+ // Apply alignment for "normal" messages
+ CParaFormat paraFormat;
+ TParaFormatMask paraFormatMask;
+ paraFormat.iLeftMarginInTwips = 100;
+ paraFormatMask.SetAttrib( EAttLeftMargin );
+ iRichText->ApplyParaFormatL( ¶Format, paraFormatMask,
+ 0, textEnd + 1 );
+
+ // Remove bolding from message content
+ TCharFormat charFormat;
+ TCharFormatMask charFormatMask;
+ charFormat.iFontSpec.iFontStyle.SetStrokeWeight( EStrokeWeightNormal );
+ charFormatMask.SetAttrib( EAttFontStrokeWeight );
+ iRichText->ApplyCharFormatL( charFormat, charFormatMask,
+ 0, textEnd + 1 );
+ }
+
+ // Cleanup
+ if ( numberConv )
+ {
+ CleanupStack::PopAndDestroy( numberConv );
+ }
+ if ( tempMsg )
+ {
+ CleanupStack::PopAndDestroy( tempMsg );
+ }
+
+ return iRichText->DocumentLength() - oldLen;
+ }
+ default:
+ {
+ // Unsupported type
+
+ break;
+ }
+ }
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::InsertContentL() end" ));
+ return 0;
+ }
+
+// -----------------------------------------------------------------------------
+// CIMCVAppRichTextContainer::InsertNickL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TCursorSelection CIMCVAppRichTextContainer::InsertNickL(
+ CIMCVAppMessageWrapper& aMessageWrapper )
+ {
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::InsertNickL() start" ));
+ // insert nick
+ MIMCVEngineMessage& message = aMessageWrapper.Message();
+ TPtrC sender;
+ TPtrC recipient;
+ if ( message.MessageType() == MIMCVEngineMessage::EMessageGroup ||
+ message.MessageType() == MIMCVEngineMessage::EMessageWhisper )
+ {
+ sender.Set( message.Sender() );
+ recipient.Set( message.Recipient() );
+ }
+
+ TCursorSelection nickSel( 0,0 );
+
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::InsertNickL() end" ));
+ return nickSel;
+ }
+
+// -----------------------------------------------------------------------------
+// CIMCVAppRichTextContainer::LayoutChangedL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CIMCVAppRichTextContainer::LayoutChangedL( TInt aType)
+ {
+ #if 0
+ //if layout change.. then dont update skin text color.
+ if (aType == KAknsMessageSkinChange)
+ {
+ UpdateSkinnedTextColourL();
+ }
+ #endif
+ }
+
+// -----------------------------------------------------------------------------
+// CCARichTextContainer::ResourceChangedL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CIMCVAppRichTextContainer::ResourceChangedL()
+ {
+ // When resource changes (branding):
+ // clear content, so that old pictures don't cause any problems.
+ // we are reloaded anyway.
+ iRichText->DeleteL( 0, iRichText->DocumentLength() );
+ iTextView->HandleGlobalChangeNoRedrawL();
+ }
+// CIMCVAppRichTextContainer::AddMessageL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CIMCVAppRichTextContainer::AddMessageL( MIMCVEngineMessage& aMessage )
+ {
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::AddMessageL() start" ));
+ if( !iShowTimeStamps &&
+ aMessage.SystemMessageType() == MIMCVEngineMessage::ESystemMessageDateChange )
+ {
+ // if timestamp setting is OFF we don't show day change items
+ return;
+ }
+
+ TInt oldCount = iMessages.Count();
+
+ // create wrapper
+ CIMCVAppMessageWrapper* wrapper = CIMCVAppMessageWrapper::NewL( aMessage );
+
+ CleanupStack::PushL( wrapper );
+ iMessages.AppendL( wrapper ); // takes the ownership
+ CleanupStack::Pop( wrapper );
+
+
+ // start new paragraph
+ TInt lineStart = iRichText->DocumentLength();
+ if( lineStart != 0 )
+ {
+ iRichText->InsertL( lineStart, CEditableText::EParagraphDelimiter );
+ }
+
+ // Set Alignment from local layout
+ iRichText->InsertL( iRichText->DocumentLength(),
+ AknLayoutUtils::LayoutMirrored() ? KUnicodeRLM : KUnicodeLRM );
+
+ // add message to rich text
+ TInt startPos( iRichText->DocumentLength() );
+ TCursorSelection timeSel = AddTimeStampL( *wrapper );
+ TCursorSelection nickSel = AddNickL( *wrapper );
+ AddContentL( startPos, *wrapper );
+ TInt endPos( iRichText->DocumentLength() );
+
+ // set selection for highlight and the whole selection
+ // (so that this can be removed)
+ // append deletioncount to new messages
+ wrapper->Selection().SetSelection( endPos - 1, startPos );
+ wrapper->WholeSelection().SetSelection( endPos, lineStart );
+ wrapper->MessageSelection().SetSelection( endPos - 1, nickSel.HigherPos() );
+
+
+ // append coloring
+ TCursorSelection& sel = iColorWholeMessage ? wrapper->Selection() : nickSel;
+ TInt len( sel.Length() );
+
+
+ // Make sure the background (highlight) is not copied from
+ // previous message.
+ BackColorL( sel, KRgbWhite );
+ TextBackColorL( sel, KRgbWhite );
+
+ if( len > 0 &&
+ aMessage.MessageType() != MIMCVEngineMessage::EMessageSystem )
+ {
+ // custom colors
+ if( aMessage.MessagerType() == MIMCVEngineMessage::EMessageSent )
+ {
+ // own msg
+ if( iOwnMsgColorInUse )
+ {
+ TextColorL( sel, iOwnMsgColor );
+ }
+ }
+ else if( aMessage.MessagerType() == MIMCVEngineMessage::EMessageReceived )
+ {
+ // other msg
+ if( iMsgColorInUse )
+ {
+ TextColorL( sel, iMsgColor );
+ }
+ }
+ }
+
+#ifdef RD_30_COMPATIBILITY_MODE
+ if( lineStart == 0 )
+ {
+ // This is needed only in 3.0 backport so that the alignment
+ // character doesn't cause a virtual linebreak.
+ TRAP_IGNORE( iTextView->HandleFormatChangedL(
+ wrapper->WholeSelection() ) );
+ }
+#endif // RD_30_COMPATIBILITY_MODE
+
+ // inform of inserted rich text
+ TCursorSelection curSel( CurrentSelection() );
+ TRAPD( error, iTextView->HandleAdditionL( lineStart == 0, curSel, EFalse ) );
+ if( error != KErrNone )
+ {
+
+ // Remove failed text
+ TCursorSelection del = wrapper->WholeSelection();
+ iRichText->DeleteL( del.LowerPos(), del.Length() );
+
+ // Remove the failed wrapper and leave
+ TInt index = iMessages.Find( wrapper );
+ if( index != KErrNotFound )
+ {
+ delete wrapper;
+ iMessages.Remove( index );
+ }
+
+ // Try to handle changes once more
+ TRAPD( updateErr, iTextView->HandleGlobalChangeNoRedrawL() );
+ if( !updateErr )
+ {
+ TCursorSelection curSel( CurrentSelection() );
+ TRAP_IGNORE( iTextView->ScrollVisibleL( curSel, EFalse ) );
+ }
+ User::Leave( error );
+ }
+
+ // and scroll (unless in highlight-mode)
+ if( iHighlightState == ENoHighlight )
+ {
+ TCursorSelection curSel( CurrentSelection() );
+ iTextView->ScrollVisibleL( curSel, EFalse );
+
+ // If this is recorded chat container (iScrollOver == EFalse)
+ // and added message was first move highlight
+ // so we have focus on the topmost item.
+ if ( oldCount == 0 && !iScrollOver )
+ {
+ MoveHighlightL( ENext );
+ }
+ }
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::AddMessageL() end" ));
+ }
+
+
+
+// -----------------------------------------------------------------------------
+// CIMCVAppRichTextContainer::InsertMessageL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CIMCVAppRichTextContainer::InsertMessageL( MIMCVEngineMessage& aMessage )
+ {
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::InsertMessageL() start" ));
+ if ( !iShowTimeStamps &&
+ aMessage.SystemMessageType() == MIMCVEngineMessage::ESystemMessageDateChange )
+ {
+ // if timestamp setting is OFF we don't show day change items
+ return;
+ }
+
+ // create wrapper
+ CIMCVAppMessageWrapper* wrapper = CIMCVAppMessageWrapper::NewL( aMessage );
+
+ CleanupStack::PushL( wrapper );
+ iMessages.InsertL( wrapper, 0 ); // takes the ownership
+ CleanupStack::Pop( wrapper );
+
+
+ TInt oldLen = iRichText->DocumentLength();
+
+ // Insert paragraph break if this is not the last message
+ TInt paraBreak = 0;
+ if ( iMessages.Count() > 1 )
+ {
+ iRichText->InsertL( 0, CEditableText::EParagraphDelimiter );
+ paraBreak = 1;
+ }
+
+ // Insert message to rich text in reverse order compared to adding
+ TInt contentLen = InsertContentL( *wrapper );
+ TCursorSelection nickSel = InsertNickL( *wrapper );
+ TCursorSelection timeSel = InsertTimeStampL( *wrapper );
+
+ // Set Alignment from local layout
+ TInt dirChrLen = iRichText->DocumentLength();
+ iRichText->InsertL( 0, AknLayoutUtils::LayoutMirrored() ?
+ KUnicodeRLM : KUnicodeLRM );
+ dirChrLen = iRichText->DocumentLength() - dirChrLen;
+
+ wrapper->SetInserted( ETrue );
+
+ // Update timestamp selection
+ timeSel.iAnchorPos += dirChrLen;
+ timeSel.iCursorPos += dirChrLen;
+ // Update nick selection
+ nickSel.iAnchorPos += timeSel.HigherPos();
+ nickSel.iCursorPos += timeSel.HigherPos();
+ // Update thumb pos
+ TCursorSelection& thumbPos = wrapper->ThumbPos();
+ thumbPos.iAnchorPos += nickSel.HigherPos() + KSeparator().Length();
+ thumbPos.iCursorPos += nickSel.HigherPos() + KSeparator().Length();
+
+ TInt addedLen = iRichText->DocumentLength() - oldLen;
+
+ // parse text for highlights and store positions to messagewrapper
+ HBufC* text = HBufC::NewMaxLC( contentLen );
+ TPtr txt( text->Des() );
+ iRichText->Extract( txt,
+ nickSel.HigherPos() + KSeparator().Length() + 1, // Don't extract separator and space
+ contentLen );
+ ParseTextL( txt, nickSel.HigherPos() + KSeparator().Length() + 1,
+ nickSel.HigherPos() + KSeparator().Length() + 1, *wrapper );
+ CleanupStack::PopAndDestroy( text );
+
+ // Set selection for highlight and the whole selection
+ // so that this message can be removed
+ wrapper->Selection().SetSelection( addedLen - 1 - paraBreak, 0 );
+ wrapper->WholeSelection().SetSelection( addedLen - 1, 0 );
+ wrapper->MessageSelection().SetSelection( addedLen - 1,
+ nickSel.HigherPos() + 1 );
+
+ if ( iHighlightState != ENoHighlight )
+ {
+ BackColorL( wrapper->WholeSelection(), KRgbWhite );
+ TextBackColorL( wrapper->WholeSelection(), KRgbWhite );
+ }
+
+ // Update wrappers after this if there is any
+ if ( iMessages.Count() > 1 )
+ {
+ UpdateWrappers( 1, addedLen );
+ }
+
+ // Append coloring
+ TCursorSelection& sel = iColorWholeMessage ? wrapper->Selection() : nickSel;
+ TInt len( sel.Length() );
+
+ if ( len > 0 &&
+ aMessage.MessageType() != MIMCVEngineMessage::EMessageSystem )
+ {
+ // Custom colors
+ if ( aMessage.MessagerType() == MIMCVEngineMessage::EMessageSent )
+ {
+ // Own msg
+ if( iOwnMsgColorInUse )
+ {
+ TextColorL( sel, iOwnMsgColor );
+ }
+ }
+ else if ( aMessage.MessagerType() == MIMCVEngineMessage::EMessageReceived )
+ {
+ // Other msg
+ if( iMsgColorInUse )
+ {
+ TextColorL( sel, iMsgColor );
+ }
+ }
+ }
+
+ // Inform of inserted rich text
+ TInt error = KErrNone;
+ if ( oldLen == 0 )
+ {
+ TCursorSelection curSel( CurrentSelection() );
+ // First message inserted, format the whole text
+ TRAP( error, iTextView->HandleAdditionL( ETrue, curSel, EFalse ) );
+ }
+ else
+ {
+ TCursorSelection curSel( CurrentSelection() );
+ // There might be a faster method to handle text addition, but
+ // this works for now.
+ TRAP( error, iTextView->HandleAdditionL( ETrue, curSel, EFalse) );
+ }
+ // And scroll (unless in highlight-mode)
+ if ( iHighlightState == ENoHighlight )
+ {
+ TCursorSelection curSel( CurrentSelection() );
+ iTextView->ScrollVisibleL( curSel, EFalse );
+ }
+ else
+ {
+ // In highlight mode, message inserted -> increase selected
+ // message index and previous selection indexes
+ iSelected++;
+ iPrevious.iAnchorPos += addedLen;
+ iPrevious.iCursorPos += addedLen;
+
+ TCursorSelection curSel( CurrentSelection() );
+ iTextView->ScrollVisibleL( curSel, EFalse );
+ }
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::InsertMessageL() end" ));
+ }
+
+// -----------------------------------------------------------------------------
+// CIMCVAppRichTextContainer::UpdateWrappers
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CIMCVAppRichTextContainer::UpdateWrappers( TInt aFirstIndex, TInt aChange )
+ {
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::UpdateWrappers() start" ));
+ TInt count( iMessages.Count() );
+ for( TInt i( aFirstIndex ); i<count; ++i )
+ {
+ CIMCVAppMessageWrapper* wrapper = iMessages[i];
+ TCursorSelection& selection = wrapper->Selection();
+ TCursorSelection& wholeSelection = wrapper->WholeSelection();
+ TCursorSelection& thumbPos = wrapper->ThumbPos();
+ selection.iAnchorPos += aChange;
+ selection.iCursorPos += aChange;
+ wholeSelection.iAnchorPos += aChange;
+ wholeSelection.iCursorPos += aChange;
+ thumbPos.iAnchorPos += aChange;
+ thumbPos.iCursorPos += aChange;
+ }
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::UpdateWrappers() end" ));
+ }
+
+// -----------------------------------------------------------------------------
+// CIMCVAppRichTextContainer::Union
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TCursorSelection CIMCVAppRichTextContainer::Union( const TCursorSelection& aSel1,
+ const TCursorSelection& aSel2 )
+ {
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::Union() start" ));
+ // make union of selections
+ TCursorSelection changed;
+ changed.iAnchorPos = aSel1.LowerPos();
+ changed.iCursorPos = aSel1.HigherPos();
+
+ TInt low( aSel2.LowerPos() );
+ TInt high( aSel2.HigherPos() );
+ if( low < changed.iAnchorPos )
+ {
+ changed.iAnchorPos = low;
+ }
+ if( high > changed.iCursorPos )
+ {
+ changed.iCursorPos = high;
+ }
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::Union() end" ));
+ return changed;
+ }
+
+// -----------------------------------------------------------------------------
+// CIMCVAppRichTextContainer::CurrentSelection
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TCursorSelection CIMCVAppRichTextContainer::CurrentSelection() const
+ {
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::CurrentSelection() start" ));
+ TCursorSelection sel( 0,0 );
+ if( iHighlightState == ENoHighlight )
+ {
+ // if nothing highlighted, return last message
+ TInt count( iMessages.Count() );
+ if( count > 0 )
+ {
+ sel = iMessages[count-1]->Selection();
+ }
+ }
+ else
+ {
+ // something highlighted, start with current message
+ sel = iMessages[iSelected]->Selection();
+
+ // check if the highlighted selection is item inside message
+ if( iHighlightState == EItemSelected )
+ {
+ // calculate item highlight position
+ TCursorSelection itemSel(
+ iMessages[iSelected]->Highlights()[iSelectedItem] );
+
+ TInt messageStart( sel.LowerPos() );
+ sel.iAnchorPos = itemSel.iAnchorPos + messageStart;
+ sel.iCursorPos = itemSel.iCursorPos + messageStart;
+ }
+ }
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::CurrentSelection() end" ));
+ return sel;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CIMCVAppRichTextContainer::TextBackColorL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CIMCVAppRichTextContainer::TextBackColorL( const TCursorSelection& aSel,
+ const TRgb& aColor )
+ {
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::TextBackColorL() start" ));
+ TCharFormat charFormat;
+ TCharFormatMask charFormatMask;
+ charFormatMask.SetAttrib( EAttFontHighlightColor );
+ charFormatMask.SetAttrib( EAttFontHighlightStyle );
+
+ charFormat.iFontPresentation.iHighlightColor = aColor;
+ charFormat.iFontPresentation.iHighlightStyle = aColor == KRgbWhite ?
+ TFontPresentation::EFontHighlightNone :
+ TFontPresentation::EFontHighlightNormal;
+
+ iRichText->ApplyCharFormatL( charFormat, charFormatMask,
+ aSel.LowerPos(),
+ aSel.Length() );
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::TextBackColorL() end" ));
+ }
+
+// -----------------------------------------------------------------------------
+// CIMCVAppRichTextContainer::TextColorL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CIMCVAppRichTextContainer::TextColorL( const TCursorSelection& aSel,
+ const TRgb& aColor )
+ {
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::TextColorL() start" ));
+ TCharFormat charFormat;
+ TCharFormatMask charFormatMask;
+ charFormatMask.SetAttrib( EAttColor );
+ charFormat.iFontPresentation.iTextColor = aColor;
+
+ iRichText->ApplyCharFormatL( charFormat, charFormatMask,
+ aSel.LowerPos(),
+ aSel.Length() );
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::TextColorL() end" ));
+ }
+
+// -----------------------------------------------------------------------------
+// CIMCVAppRichTextContainer::BackColorL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CIMCVAppRichTextContainer::BackColorL( const TCursorSelection& aSel,
+ const TRgb& aColor )
+ {
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::BackColorL() start" ));
+ CParaFormat paraFormat;
+ TParaFormatMask paraFormatMask;
+ paraFormatMask.SetAttrib( EAttFillColor );
+
+ paraFormat.iFillColor = aColor;
+ iRichText->ApplyParaFormatL( ¶Format, paraFormatMask,
+ aSel.LowerPos(),
+ aSel.Length() );
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::BackColorL() end" ));
+ }
+
+// -----------------------------------------------------------------------------
+// CIMCVAppRichTextContainer::HighLightItemL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CIMCVAppRichTextContainer::HighLightItemL( const TCursorSelection& aSel )
+ {
+
+ TCharFormat charFormat;
+ TCharFormatMask charFormatMask;
+ charFormatMask.SetAttrib( EAttFontUnderline );
+
+ charFormat.iFontPresentation.iUnderline = EUnderlineOn;
+
+ iRichText->ApplyCharFormatL( charFormat, charFormatMask,
+ aSel.LowerPos(),
+ aSel.Length() );
+ }
+
+
+// -----------------------------------------------------------------------------
+// CIMCVAppRichTextContainer::GetMessageCount
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CIMCVAppRichTextContainer::GetMessageCount()
+ {
+ return iMessages.Count();
+ }
+
+// -----------------------------------------------------------------------------
+// CIMCVAppRichTextContainer::BoldL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CIMCVAppRichTextContainer::BoldL( const TCursorSelection& aSel )
+ {
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::BoldL() start" ));
+#ifdef _DEBUG
+ TInt len( iRichText->DocumentLength() );
+
+#endif //_DEBUG
+
+ TCharFormat charFormat;
+ TCharFormatMask charFormatMask;
+
+ charFormat.iFontSpec.iFontStyle.SetStrokeWeight( EStrokeWeightBold );
+ charFormatMask.SetAttrib( EAttFontStrokeWeight );
+
+ iRichText->ApplyCharFormatL( charFormat, charFormatMask,
+ aSel.LowerPos(),
+ aSel.Length() );
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::BoldL() end" ));
+ }
+
+// -----------------------------------------------------------------------------
+// CIMCVAppRichTextContainer::ParseTextL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CIMCVAppRichTextContainer::ParseTextL( const TDesC& aText, TInt aStartPos,
+ TInt aRelativePos, CIMCVAppMessageWrapper& aMessageWrapper )
+ {
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::ParseTextL() start" ));
+ CFindItemEngine* findItem = CFindItemEngine::NewL( aText,
+ CFindItemEngine::TFindItemSearchCase(
+ CFindItemEngine::EFindItemSearchPhoneNumberBin |
+ CFindItemEngine::EFindItemSearchMailAddressBin |
+ CFindItemEngine::EFindItemSearchURLBin/* |
+ CFindItemEngine::EFindItemSearchScheme*/ )
+ );
+
+ CleanupStack::PushL( findItem );
+
+ // reset array
+ RArray<TCursorSelection>& highlights = aMessageWrapper.Highlights();
+ RArray<TInt>& types = aMessageWrapper.HighlightTypes();
+ highlights.Reset();
+ types.Reset();
+
+ // get found items
+ const CArrayFixFlat<CFindItemEngine::SFoundItem>* items =
+ findItem->ItemArray();
+ TInt count( items->Count() );
+
+ for( TInt i(0); i<count; ++i )
+ {
+ const CFindItemEngine::SFoundItem item = items->At(i);
+
+ // selection in rich text
+ TCursorSelection realSel( aStartPos + item.iStartPos + item.iLength,
+ aStartPos + item.iStartPos );
+
+ // relative selection inside one message
+ TCursorSelection relativeSel( aRelativePos + item.iStartPos +
+ item.iLength,
+ aRelativePos + item.iStartPos );
+
+ highlights.AppendL( relativeSel );
+ types.AppendL( item.iItemType );
+
+ // apply highlight item formatting
+ HighLightItemL( realSel );
+ }
+
+ CleanupStack::PopAndDestroy( findItem );
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::ParseTextL() end" ));
+ }
+
+// -----------------------------------------------------------------------------
+// CIMCVAppRichTextContainer::AddNickL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TCursorSelection CIMCVAppRichTextContainer::AddNickL(
+ CIMCVAppMessageWrapper& aMessageWrapper )
+ {
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::AddNickL() start" ));
+ // insert nick
+ MIMCVEngineMessage& message = aMessageWrapper.Message();
+ TPtrC sender;
+ TPtrC recipient;
+ if( message.MessageType() == MIMCVEngineMessage::EMessageGroup ||
+ message.MessageType() == MIMCVEngineMessage::EMessageWhisper )
+ {
+ sender.Set( message.Sender() );
+ recipient.Set( message.Recipient() );
+ }
+ // need to implements todo
+ TCursorSelection nickSel( 0,0 );
+ //============================================================================
+ if( message.MessagerType() == MIMCVEngineMessage::EMessageSent &&
+ message.MessageType() == MIMCVEngineMessage::EMessagePTOP)
+ {
+ CIMCVAppPicture* pic = new( ELeave )CIMCVAppPicture( *iMap, iFromMe );
+ TPictureHeader header;
+ header.iPicture = TSwizzle<CPicture>(pic );
+ iRichText->InsertL( iRichText->DocumentLength(), header );// takes ownership
+ iRichText->InsertL( iRichText->DocumentLength(), KSeparator );
+ }
+
+ else if( message.MessageType() == MIMCVEngineMessage::EMessagePTOP &&
+ message.MessagerType() == MIMCVEngineMessage::EMessageReceived )
+ {
+ // received p2p message and we want to display icon
+ // insert "to me" icon and separator
+ CIMCVAppPicture* pic = new( ELeave )CIMCVAppPicture( *iMap,iToMe );
+ TPictureHeader header;
+ header.iPicture = TSwizzle<CPicture>( pic );
+ iRichText->CancelInsertCharFormat(); // to prevent ETEXT 31 panic
+ iRichText->InsertL( iRichText->DocumentLength(), header ); // takes ownership
+ iRichText->InsertL( iRichText->DocumentLength(), KSeparator );
+ }
+ //============================================================================
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::AddNickL() end" ));
+ return nickSel;
+ }
+
+// -----------------------------------------------------------------------------
+// CIMCVAppSmileIconUtility::LoadDefaultBitmapL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+CGulIcon* CIMCVAppRichTextContainer::LoadDefaultBitmapL( TInt aBitmapId, TInt aMaskId,
+ const TDesC& aFullPath, TBool/* aOverrideBrand */)
+ {
+
+ IM_CV_LOGS(TXT("CIMCVAppSmileIconUtility::LoadDefaultBitmapL() start") );
+ CFbsBitmap* bitmap = NULL;
+ CFbsBitmap* mask = NULL;
+
+ MAknsSkinInstance* skin = AknsUtils::SkinInstance();
+
+ TAknsItemID itemId( KAknsIIDNone );
+
+ AknsUtils::CreateIconLC( skin,
+ itemId,
+ bitmap, mask, aFullPath, aBitmapId, aMaskId );
+
+ CGulIcon* gulIcon = CGulIcon::NewL( bitmap, mask );
+ CleanupStack::Pop( 2 ); // bitmap, mask
+ IM_CV_LOGS(TXT("CIMCVAppSmileIconUtility::LoadDefaultBitmapL() end") );
+ return gulIcon;
+ }
+
+// -----------------------------------------------------------------------------
+// CIMCVAppRichTextContainer::AddTimeStampL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TCursorSelection CIMCVAppRichTextContainer::AddTimeStampL(
+ CIMCVAppMessageWrapper& aMessageWrapper )
+ {
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::AddTimeStampL() start" ));
+ TInt start = iRichText->DocumentLength();
+
+ TCursorSelection timeSel( start, start );
+
+
+ // format time
+ HBufC* timeStamp = HBufC::NewLC( KTimeStampMaxLength + KSpace().Length() );
+ TPtr timePtr( timeStamp->Des() );
+
+ HBufC* timeStampFormat = NULL;
+ timeStampFormat = StringLoader::LoadLC( R_QTN_TIME_USUAL_WITH_ZERO );
+
+ TTime time = aMessageWrapper.Message().TimeStamp();
+ TRAPD( err, time.FormatL( timePtr, *timeStampFormat ) );
+ if( err == KErrOverflow )
+ {
+ // Reserved text space was not enough.
+ // Adjust the KTimeStampMaxLength!
+ // in release builds return without timestamp
+ CleanupStack::PopAndDestroy( 2, timeStamp); // timeStamp, timeStampFormat
+ return timeSel;
+ }
+
+ // Convert numbers to local language
+ AknTextUtils::LanguageSpecificNumberConversion( timePtr );
+
+ // Set Alignment of Pm/Am from local setting
+ // This keeps the am/pm text close to the time.
+ timePtr.Append( AknLayoutUtils::LayoutMirrored() ?
+ KUnicodeRLM : KUnicodeLRM );
+
+ // append time to rich text
+ timePtr.Append( KSpace );
+ iRichText->InsertL( start, timePtr );
+
+ CleanupStack::PopAndDestroy( 2, timeStamp); // timeStamp, timeStampFormat
+ timeSel.SetSelection( start, iRichText->DocumentLength() - 1 );
+
+ // bold the time
+ if( timeSel.Length() > 0 )
+ {
+ BoldL( timeSel );
+ }
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::AddTimeStampL() end" ));
+ return timeSel;
+ }
+
+// -----------------------------------------------------------------------------
+// CIMCVAppRichTextContainer::AddContentL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CIMCVAppRichTextContainer::AddContentL( TInt aMsgStart,
+ CIMCVAppMessageWrapper& aMessageWrapper )
+ {
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::AddContentL() start" ));
+ MIMCVEngineMessage& message = aMessageWrapper.Message();
+
+ MIMCVEngineMessage::TContentType type( message.ContentType() );
+ switch( type )
+ {
+ case MIMCVEngineMessage::EContentText:
+ {
+ // insert text
+ //If received message is longer than 400 characters it will be truncated in imconnectionprovider
+ //so append truncation message to inform user that received message is truncated
+ HBufC* newmsg = HBufC::NewLC(KMsgMaxLength);
+ TPtr msg = newmsg->Des();
+ if(message.Text().Length() > KReceiveMsgMaxLength)
+ {
+ msg.Append(message.Text().Left(KReceiveMsgMaxLength));
+ HBufC* addText = StringLoader::LoadLC( R_QTN_CONVIEW_TRUNCATED );
+ msg.Append(addText->Des());
+ CleanupStack::PopAndDestroy(addText);//addText
+ }
+ else
+ {
+ msg.Append(message.Text());
+ }
+ // TPtrC msg( message.Text() );
+ HBufC* tempMsg = NULL;
+
+ TInt paraBreak = msg.Locate( CEditableText::EParagraphDelimiter );
+ // Replace all paragraph delimiters with line breaks
+ // to keep alingment consistent
+ if ( paraBreak != KErrNotFound )
+ {
+ tempMsg = msg.AllocLC();
+ TPtr ptr( tempMsg->Des() );
+ ptr.Zero();
+
+ ReplaceParaDelimsWithLineBreaks( msg, ptr );
+ msg.Set( ptr );
+ }
+
+ HBufC* numberConv = NULL;
+
+ // Convert numerals to local language
+ // 1) date item
+ if( aMessageWrapper.Message().SystemMessageType() ==
+ MIMCVEngineMessage::ESystemMessageDateChange )
+ {
+ // don't touch the original message
+ numberConv = msg.AllocLC();
+ TPtr ptr( numberConv->Des() );
+ AknTextUtils::LanguageSpecificNumberConversion( ptr );
+ msg.Set( ptr );
+ }
+
+ TInt textStart( iRichText->DocumentLength() );
+ iRichText->InsertL( textStart, msg );
+
+ CleanupStack::PopAndDestroy(newmsg);//newmsg
+ // check for extensions (smileys)
+ TCursorSelection selection( iRichText->DocumentLength(),
+ textStart );
+ iExtensionsHandler->ConvertSelectionToExtensionL( *iRichText,
+ selection ,
+ iServiceId );
+
+ TInt textEnd( iRichText->DocumentLength() );
+
+ // add nbs to preserve formatting
+ iRichText->InsertL( iRichText->DocumentLength(),
+ CEditableText::EZeroWidthNoBreakSpace );
+
+ // if this is system message, it should be bold
+ if( message.MessageType() == MIMCVEngineMessage::EMessageSystem )
+ {
+ TCursorSelection sel( textStart, textEnd );
+ BoldL( sel );
+ // System messages need different kind of alignment
+ CParaFormat paraFormat;
+ TParaFormatMask paraFormatMask;
+ paraFormat.iLeftMarginInTwips = 0;
+ paraFormatMask.SetAttrib( EAttLeftMargin );
+ iRichText->ApplyParaFormatL( ¶Format, paraFormatMask,
+ textStart, sel.Length() );
+ }
+ else
+ {
+ // Apply alignment for "normal" messages
+ CParaFormat paraFormat;
+ TParaFormatMask paraFormatMask;
+ paraFormat.iLeftMarginInTwips = 100;
+ paraFormatMask.SetAttrib( EAttLeftMargin );
+ iRichText->ApplyParaFormatL( ¶Format, paraFormatMask,
+ textStart, textEnd - textStart );
+ }
+
+ // parse text for highlights and store positions to messagewrapper
+ HBufC* text = HBufC::NewMaxLC( textEnd-textStart );
+ TPtr txt( text->Des() );
+ iRichText->Extract( txt, textStart, textEnd-textStart );
+ ParseTextL( txt, textStart, textStart-aMsgStart, aMessageWrapper );
+ CleanupStack::PopAndDestroy( text );
+
+ // Cleanup
+ if( numberConv )
+ {
+ CleanupStack::PopAndDestroy( numberConv );
+ }
+ if ( tempMsg )
+ {
+ CleanupStack::PopAndDestroy( tempMsg );
+ }
+ break;
+ }
+
+ default:
+ {
+ // unsupported type
+
+ break;
+ }
+ }
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::AddContentL() end" ));
+ }
+
+
+// -----------------------------------------------------------------------------
+// CIMCVAppRichTextContainer::UpdateSkinnedTextColourL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CIMCVAppRichTextContainer::UpdateSkinnedTextColourL()
+ {
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::UpdateSkinnedTextColourL() start" ));
+ // Get current text's color
+ TRgb defaultSkinTextColor( KRgbBlack );
+ AknsUtils::GetCachedColor( AknsUtils::SkinInstance(),
+ defaultSkinTextColor,
+ KAknsIIDQsnTextColors,
+ EAknsCIQsnTextColorsCG6 );
+
+ TCharFormat charFormat;
+ TCharFormatMask charFormatMask;
+ charFormat.iFontPresentation.iTextColor = defaultSkinTextColor;
+ charFormatMask.SetAttrib( EAttColor );
+
+ // also appended messages should have new colour
+ TInt richTextDocumentLength = iRichText->DocumentLength();
+
+ iRichText->ApplyCharFormatL ( charFormat, charFormatMask, 0, richTextDocumentLength);
+ TCursorSelection cursorSelection(0, richTextDocumentLength);
+ iTextView->HandleFormatChangedL (cursorSelection);
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::UpdateSkinnedTextColourL() end" ));
+ }
+
+// -----------------------------------------------------------------------------
+// CIMCVAppRichTextContainer::SkinColoredSelection
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TCursorSelection CIMCVAppRichTextContainer::SkinColoredSelection(
+ CIMCVAppMessageWrapper& aMessageWrapper,
+ TBool aUseDefaultColors,
+ TBool aCustomDefinedColor )
+ {
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::SkinColoredSelection() start" ));
+ // This logic determines which part of the message is colored by the theme
+ if( !aCustomDefinedColor && aUseDefaultColors )
+ {
+ return aMessageWrapper.WholeSelection();
+ }
+
+ if( !iColorWholeMessage )
+ {
+ return aMessageWrapper.MessageSelection();
+ }
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::SkinColoredSelection() end" ));
+ return TCursorSelection( 0, 0 );
+ }
+
+// -----------------------------------------------------------------------------
+// CIMCVAppRichTextContainer::ReplaceParaDelimsWithLineBreaks
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CIMCVAppRichTextContainer::ReplaceParaDelimsWithLineBreaks(
+ const TPtrC& aSource,
+ TPtr& aTarget ) const
+ {
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::ReplaceParaDelimsWithLineBreaks() start" ));
+#ifdef _DEBUG
+ TPtrC target;
+ target.Set( aTarget );
+
+#endif
+
+ TInt paraBreak = aSource.Mid( aTarget.Length() ).Locate(
+ CEditableText::EParagraphDelimiter );
+
+ if ( paraBreak == KErrNotFound )
+ {
+ // No more paragraph delimiters, append what's left
+ aTarget.Append( aSource.Mid( aTarget.Length() ) );
+ // And break away from recursion
+ return;
+ }
+
+ aTarget.Append( aSource.Mid( aTarget.Length(), paraBreak ) );
+ aTarget.Append( CEditableText::ELineBreak );
+
+#ifdef _DEBUG
+ target.Set( aTarget );
+
+#endif
+
+ ReplaceParaDelimsWithLineBreaks( aSource, aTarget );
+ IM_CV_LOGS(TXT("CIMCVAppRichTextContainer::ReplaceParaDelimsWithLineBreaks() end" ));
+ }
+
+// -----------------------------------------------------------------------------
+// CIMCVAppRichTextContainer::GetPrimaryKey
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+
+const TDesC& CIMCVAppRichTextContainer::GetPrimaryKey()
+ {
+ if( iPrimaryKey)
+ {
+ return *iPrimaryKey;
+ }
+ return KNullDesC;
+ }
+// End of File