--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emailuis/emailui/src/FreestyleEmailUiMailViewerRichText.cpp Thu Dec 17 08:39:21 2009 +0200
@@ -0,0 +1,2267 @@
+/*
+* Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: FreestyleEmailUi mail viewer rich text implementation
+* Version : %version: 47 %
+*
+*/
+
+
+// SYSTEM INCLUDES
+#include "emailtrace.h"
+#include <AknUtils.h>
+#include <freestyleemailui.mbg>
+#include <FreestyleEmailUi.rsg>
+#include <StringLoader.h>
+#include <AknBidiTextUtils.h>
+//<cmail>
+#include "fstextviewer.h"
+#include "fsrichtext.h"
+#include "CFSMailMessagePart.h"
+#include "CFSMailClient.h"
+#include "CFSMailCommon.h"
+//</cmail>
+#include <txtfrmat.h>
+// <cmail> SF
+#include <alf/alftextvisual.h>
+// </cmail>
+//<cmail> Platform layout changes
+#include <aknlayoutscalable_apps.cdl.h>
+#include <layoutmetadata.cdl.h>
+//</cmail> Platform layout changes
+
+// for fonts
+#include <AknFontAccess.h>
+#include <AknLayoutFont.h>
+
+// <cmail> separator line
+#include <w32std.h>
+#include <coecntrl.h>
+// </cmail> separator line
+
+// INTERNAL INCLUDES
+#include "FreestyleEmailUiMailViewerRichText.h"
+#include "FreestyleEmailUiAppui.h"
+#include "FreestyleEmailUiConstants.h"
+#include "FreestyleEmailUiLiterals.h"
+#include "FreestyleEmailUiFileSystemInfo.h"
+#include "FreestyleEmailUi.hrh"
+#include "FreestyleEmailUiTextureManager.h"
+#include "FreestyleEmailUiUtilities.h"
+#include "FreestyleEmailUiLayoutHandler.h"
+#include "FreestyleEmailUiMailViewerConstants.h"
+#include "ncsconstants.h" // for KSentLineDateAndTimeSeparatorText
+
+
+// CONST VALUES
+static const TInt KHotspotHighlightOn = 1;
+// Max hotspot count is a maximum number of hotspots allowed to be placed into
+// fs_generic text viewer component.
+static const TInt KMaxHotspotCount = 300;
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::NewL
+// -----------------------------------------------------------------------------
+CFSEmailUiMailViewerRichText* CFSEmailUiMailViewerRichText::NewL(
+ CFreestyleEmailUiAppUi& aAppUi )
+ {
+ FUNC_LOG;
+ CFSEmailUiMailViewerRichText* self =
+ CFSEmailUiMailViewerRichText::NewLC( aAppUi );
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::NewLC
+// -----------------------------------------------------------------------------
+CFSEmailUiMailViewerRichText* CFSEmailUiMailViewerRichText::NewLC(
+ CFreestyleEmailUiAppUi& aAppUi )
+ {
+ FUNC_LOG;
+ CFSEmailUiMailViewerRichText* self =
+ new (ELeave) CFSEmailUiMailViewerRichText( aAppUi );
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::ConstructL
+// -----------------------------------------------------------------------------
+void CFSEmailUiMailViewerRichText::ConstructL()
+ {
+ FUNC_LOG;
+
+ CEikonEnv* env = CEikonEnv::Static();
+ iViewerRichText = CFsRichText::NewL( env->SystemParaFormatLayerL(),
+ env->SystemCharFormatLayerL() );
+
+ }
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::CFSEmailUiMailViewerRichText
+// -----------------------------------------------------------------------------
+CFSEmailUiMailViewerRichText::CFSEmailUiMailViewerRichText(
+ CFreestyleEmailUiAppUi& aAppUi )
+ : iAppUi( aAppUi )
+ {
+ FUNC_LOG;
+ }
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::~CFSEmailUiMailViewerRichText
+// -----------------------------------------------------------------------------
+CFSEmailUiMailViewerRichText::~CFSEmailUiMailViewerRichText()
+ {
+ FUNC_LOG;
+ delete iViewerRichText;
+
+ iFontsArray.ResetAndDestroy();
+
+ iViewerHeadingHotSpotData.Reset();
+ iBodyTextHotSpotData.Reset();
+ }
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::SetHotspotByIndexL
+// -----------------------------------------------------------------------------
+// <cmail>
+void CFSEmailUiMailViewerRichText::SetHotspotByIndexL( TInt aIndex )
+ {
+ FUNC_LOG;
+ /*TInt headingHotspotCount = iViewerHeadingHotSpotData.Count();
+ TInt bodyHotspotCount = iBodyTextHotSpotData.Count();
+
+ if ( iTextViewer )
+ {
+ if ( aIndex < headingHotspotCount )
+ {
+ iTextViewer->FocusLineL( iViewerHeadingHotSpotData[aIndex].iHotspotLine , EFalse );
+ iTextViewer->SetCurrentHotspotByOrderL( aIndex );
+ }
+ else if ( (aIndex - headingHotspotCount) < bodyHotspotCount )
+ {
+ iTextViewer->FocusLineL( iViewerHeadingHotSpotData[headingHotspotCount - 1].iHotspotLine , ETrue );
+ iTextViewer->SetCurrentHotspotByOrderL( headingHotspotCount - 1 );
+ }
+ }*/
+ // Remove the if/elseif contents above and replace them with the commented line below, once it becomes available in fs_generic
+ iTextViewer->SetCurrentHotspotByOrderL( aIndex, ETrue );
+ }
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::CurrentHotspotIndexL
+// -----------------------------------------------------------------------------
+TInt CFSEmailUiMailViewerRichText::CurrentHotspotIndexL()
+ {
+ FUNC_LOG;
+ /*TInt hotspotIndex(0);
+
+ if ( iTextViewer )
+ {
+ TInt start(0);
+ TInt end(0);
+ TInt headingHotspotCount = iViewerHeadingHotSpotData.Count();
+ TInt bodyHotspotCount = iBodyTextHotSpotData.Count();
+ TBool foundHotspot = EFalse;
+
+ iTextViewer->GetCurrentHotspotL( start, end );
+
+ if ( headingHotspotCount > 0 )
+ {
+ TInt headingHotspotEnd = iViewerHeadingHotSpotData[ headingHotspotCount-1 ].iEnd;
+ if ( start < headingHotspotEnd )
+ {
+ for ( TInt i = 0; i < headingHotspotCount; ++i)
+ {
+ if ( iViewerHeadingHotSpotData[i].iStart == start )
+ {
+ foundHotspot = ETrue;
+ hotspotIndex = i;
+ break;
+ }
+ }
+ }
+ }
+
+ if ( !foundHotspot )
+ {
+ for ( TInt i = 0; i < bodyHotspotCount; ++i)
+ {
+ if ( iBodyTextHotSpotData[i].iStartPos + iHeaderLength == start )
+ {
+ hotspotIndex = i + headingHotspotCount;
+ break;
+ }
+ }
+ }
+ }
+
+ return hotspotIndex;*/
+
+ return iTextViewer->GetCurrentHotspotByOrder();
+ }
+// </cmail>
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::EmailStatusIconLine
+// -----------------------------------------------------------------------------
+TInt CFSEmailUiMailViewerRichText::EmailStatusIconLine()
+ {
+ FUNC_LOG;
+ return iEmailStatusIconLine;
+ }
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::FollowupIconLine
+// -----------------------------------------------------------------------------
+TInt CFSEmailUiMailViewerRichText::FollowupIconLine()
+ {
+ FUNC_LOG;
+ return iFollowupIconLine;
+ }
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::RefreshRichTextL
+// -----------------------------------------------------------------------------
+void CFSEmailUiMailViewerRichText::RefreshRichTextL( CFsTextViewer& aTextViewer,
+ CFSMailMessage& aMessage,
+ CFSMailBox& aMailBox )
+ {
+ FUNC_LOG;
+
+ Reset();
+
+ // Save new pointers
+ iTextViewer = &aTextViewer;
+ iMessage = &aMessage;
+ iMailBox = &aMailBox;
+
+ // Reconstruct the whole rich text
+ // line by line according to information found from current message
+ AppendFromLineL( *iMessage, iHeaderLineInfo );
+ AppendRecipientLinesL( *iMessage, iHeaderLineInfo, EViewerRecipientTypeTo );
+ AppendRecipientLinesL( *iMessage, iHeaderLineInfo, EViewerRecipientTypeCc );
+
+ // show bcc field only if opened from sent folder
+ TFSMailMsgId currentMessageFolderId = iMessage->GetFolderId();
+ CFSMailFolder* currentFolder = NULL;
+
+ TRAP_IGNORE( currentFolder = iAppUi.GetMailClient()->GetFolderByUidL(
+ iMessage->GetMailBoxId(), currentMessageFolderId ) );
+
+ CleanupStack::PushL( currentFolder );
+ if ( currentFolder && currentFolder->GetFolderType() == EFSSentFolder )
+ {
+ AppendRecipientLinesL( *iMessage, iHeaderLineInfo, EViewerRecipientTypeBcc );
+ }
+ CleanupStack::PopAndDestroy( currentFolder );
+
+ AppendSentLineL( *iMessage, iHeaderLineInfo );
+
+ AppendSubjectLinesL( *iMessage, iHeaderLineInfo );
+ AppendHtmlTextLineL( *iMessage, iHeaderLineInfo );
+ AppendAttachmentLinesL( *iMessage, iHeaderLineInfo );
+
+ // Append little bit of vertical space before the header area ends.
+ InsertTransparentSpacingIconL( EBottomMostSpace );
+
+ // <cmail> separator line
+ AppendSeparatorLineL();
+ // </cmail> separator line
+
+ // Add the upmost space also just before the body text.
+ InsertTransparentSpacingIconL( ETopMostSpace );
+
+ // Save the total header lenght in characters
+ iHeaderLength = iViewerRichText->DocumentLength();
+
+ // Add body text
+ AppendInitialBodytextLinesL( *iMessage );
+ }
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::Reset
+// -----------------------------------------------------------------------------
+void CFSEmailUiMailViewerRichText::Reset()
+ {
+ FUNC_LOG;
+
+ // reset all the data
+ iTextViewer = NULL;
+ iMessage = NULL;
+ iMailBox = NULL;
+
+ iViewerRichText->Reset();
+ iViewerHeadingHotSpotData.Reset();
+ iBodyTextHotSpotData.Reset();
+ iStatusLayout = NULL;
+ iStatusVisual = NULL;
+
+ iHeaderLength = 0;
+ iHeaderLineInfo.iHeaderLineCount = 0;
+ iHeaderLineInfo.iToLineCount = 0;
+ iHeaderLineInfo.iCcLineCount = 0;
+ iHeaderLineInfo.iSubjectLineCount = 0;
+
+ iAttachmentHotSpotIndex = KErrNotFound;
+ iViewHtmlHotSpotIndex = KErrNotFound;
+ }
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::RichText
+// -----------------------------------------------------------------------------
+CFsRichText& CFSEmailUiMailViewerRichText::RichText()
+ {
+ FUNC_LOG;
+ return *iViewerRichText;
+ }
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::SentTextLine
+// -----------------------------------------------------------------------------
+TInt CFSEmailUiMailViewerRichText::SentTextLine() const
+ {
+ FUNC_LOG;
+ return iSentTextLine;
+ }
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::SubjectTextLine
+// -----------------------------------------------------------------------------
+TInt CFSEmailUiMailViewerRichText::SubjectTextLine() const
+ {
+ FUNC_LOG;
+ return iSubjectTextLine;
+ }
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::AttachmentTextLine
+// -----------------------------------------------------------------------------
+TInt CFSEmailUiMailViewerRichText::AttachmentTextLine() const
+ {
+ FUNC_LOG;
+ TInt line = KErrNotFound;
+ if ( iAttachmentHotSpotIndex >= 0 &&
+ iAttachmentHotSpotIndex < iViewerHeadingHotSpotData.Count() )
+ {
+ line = iViewerHeadingHotSpotData[ iAttachmentHotSpotIndex ].iHotspotLine;
+ }
+ return line;
+ }
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::ViewHtmlTextLine
+// -----------------------------------------------------------------------------
+TInt CFSEmailUiMailViewerRichText::ViewHtmlTextLine() const
+ {
+ FUNC_LOG;
+ TInt line = KErrNotFound;
+ if ( iViewHtmlHotSpotIndex >= 0 &&
+ iViewHtmlHotSpotIndex < iViewerHeadingHotSpotData.Count() )
+ {
+ line = iViewerHeadingHotSpotData[ iViewHtmlHotSpotIndex ].iHotspotLine;
+ }
+ return line;
+ }
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::HeaderLengthInCharacters
+// -----------------------------------------------------------------------------
+TInt CFSEmailUiMailViewerRichText::HeaderLengthInCharacters() const
+ {
+ FUNC_LOG;
+ return iHeaderLength;
+ }
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::UpdateIconL
+// -----------------------------------------------------------------------------
+void CFSEmailUiMailViewerRichText::UpdateIconL( TViewerIconType aViewerIconType )
+ {
+ FUNC_LOG;
+ TInt place = 0;
+
+// <cmail> icons changed
+
+ CFbsBitmap* imageImage = NULL;
+ CFbsBitmap* mask = NULL;
+ TSize newIconSize = iAppUi.LayoutHandler()->ViewerIconSize();
+ TFileName iconFile;
+ TFsEmailUiUtility::GetFullIconFileNameL( iconFile );
+ // Load right icon according to type
+ // Email status and follow up icons have their fixed places.
+ // Spacing and indentation icons are always appended to the end of the rich text and
+ // they are always transparent.
+ switch ( aViewerIconType )
+ {
+ case EViewerEmailStatus:
+ {
+ TFSEmailUiTextures textureId = TFsEmailUiUtility::GetMsgIconTextureId( iMessage );
+ iAppUi.FsTextureManager()->ProvideBitmapL( textureId, imageImage, mask );
+ place = iEmailStatusIconPlace;
+ }
+ break;
+ case EViewerIconFollowUp:
+ {
+ AknsUtils::CreateColorIconL(
+ AknsUtils::SkinInstance(),
+ KAknsIIDNone,
+ KAknsIIDQsnIconColors,
+ EAknsCIQsnIconColorsCG7,
+ imageImage,
+ mask,
+ iconFile,
+ EMbmFreestyleemailuiQgn_indi_cmail_viewer_follow_up,
+ EMbmFreestyleemailuiQgn_indi_cmail_viewer_follow_up_mask,
+ KRgbBlack );
+ AknIconUtils::DisableCompression( imageImage );
+ AknIconUtils::DisableCompression( mask );
+ place = iFollowupIconPlace;
+ }
+ break;
+ case EViewerIconFollowUpComplete:
+ {
+ AknsUtils::CreateColorIconL(
+ AknsUtils::SkinInstance(),
+ KAknsIIDNone,
+ KAknsIIDQsnIconColors,
+ EAknsCIQsnIconColorsCG7,
+ imageImage,
+ mask,
+ iconFile,
+ EMbmFreestyleemailuiQgn_indi_cmail_viewer_follow_up_complete,
+ EMbmFreestyleemailuiQgn_indi_cmail_viewer_follow_up_complete_mask,
+ KRgbBlack );
+ AknIconUtils::DisableCompression( imageImage );
+ AknIconUtils::DisableCompression( mask );
+ place = iFollowupIconPlace;
+ }
+ break;
+ case EViewerIconFollowUpNone:
+ {
+ AknIconUtils::CreateIconL( imageImage, mask, iconFile,
+ EMbmFreestyleemailuiQgn_graf_cmail_blank,
+ EMbmFreestyleemailuiQgn_graf_cmail_blank_mask );
+ AknIconUtils::DisableCompression( imageImage );
+ AknIconUtils::DisableCompression( mask );
+ place = iFollowupIconPlace;
+ }
+ break;
+ case EViewerAttachment:
+ {
+ AknIconUtils::CreateIconL( imageImage, mask, iconFile,
+ EMbmFreestyleemailuiQgn_indi_cmail_attachment,
+ EMbmFreestyleemailuiQgn_indi_cmail_attachment_mask );
+ AknIconUtils::DisableCompression( imageImage );
+ AknIconUtils::DisableCompression( mask );
+ place = iAttachmentIconPlace;
+ // Make the attachment icon a bit smaller than other icons. Shrink only the height:
+ // when aspect ratio is preserved, the shrinked image will be centered within the standard width icon.
+ // <cmail> Platform layout change
+ //newIconSize.iHeight = newIconSize.iHeight * 3 / 4;
+ // </cmail> Platform layout change
+ }
+ break;
+ case EViewerIconIndentation:
+ {
+ AknIconUtils::CreateIconL( imageImage, mask, iconFile,
+ EMbmFreestyleemailuiQgn_graf_cmail_blank,
+ EMbmFreestyleemailuiQgn_graf_cmail_blank_mask );
+ AknIconUtils::DisableCompression( imageImage );
+ AknIconUtils::DisableCompression( mask );
+ place = iViewerRichText->DocumentLength();
+ }
+ break;
+ case EViewerIconSpacing:
+ {
+ AknIconUtils::CreateIconL( imageImage, mask, iconFile,
+ EMbmFreestyleemailuiQgn_graf_cmail_blank,
+ EMbmFreestyleemailuiQgn_graf_cmail_blank_mask );
+ AknIconUtils::DisableCompression( imageImage );
+ AknIconUtils::DisableCompression( mask );
+ place = iViewerRichText->DocumentLength();
+ // for spacing icon iCurrentSpacingIconSize need to be calculated beforehand
+ // and set properly
+ newIconSize = iCurrentSpacingIconSize;
+ }
+ break;
+ // <cmail> separator line
+ case EViewerIconSeparatorLine:
+ {
+ TRgb colorToFetch = iAppUi.LayoutHandler()->SeparatorLineColor();
+ TSize lineSize = iAppUi.LayoutHandler()->SeparatorGraphicSizeInThisResolution();
+ TInt KMyTempHigh = lineSize.iHeight;
+ // Graphic elments width is too large for these rich text classes
+ // and thus we have to calculate proper width by ourself.
+ TInt KMyTempWidth = SeparatorLineWidth();
+
+ // create a bitmap to be used off-screen
+ CFbsBitmap* offScreenBitmap = new (ELeave) CFbsBitmap();
+ User::LeaveIfError(offScreenBitmap->Create(TSize(KMyTempWidth,KMyTempHigh),
+ iAppUi.DisplayMode()));
+ CleanupStack::PushL(offScreenBitmap);
+
+ mask = new (ELeave) CFbsBitmap();
+ CleanupStack::PushL(mask);
+
+ // create an off-screen device and context
+ CGraphicsContext* bitmapContext=NULL;
+ CFbsBitmapDevice* bitmapDevice = CFbsBitmapDevice::NewL(offScreenBitmap);
+ CleanupStack::PushL(bitmapDevice);
+ User::LeaveIfError(bitmapDevice->CreateContext(bitmapContext));
+ CleanupStack::PushL(bitmapContext);
+
+ TRect rect(0,0,KMyTempWidth,KMyTempHigh);
+ bitmapContext->SetBrushColor(colorToFetch);
+ bitmapContext->SetBrushStyle(CGraphicsContext::ESolidBrush);
+ bitmapContext->SetPenColor(colorToFetch);
+ bitmapContext->DrawRect(rect);
+
+ imageImage = offScreenBitmap;
+ AknIconUtils::DisableCompression( imageImage );
+ place = iViewerRichText->DocumentLength();
+ newIconSize = TSize( KMyTempWidth,KMyTempHigh);
+ // cleanup
+ CleanupStack::PopAndDestroy(2);
+ CleanupStack::Pop(2);
+ }
+ break;
+ // </cmail> separator line
+ default:
+ {
+ User::Leave( KErrNotSupported );
+ }
+ break;
+ }
+// </cmail>
+
+ AknIconUtils::SetSize( imageImage, newIconSize, EAspectRatioPreserved );
+ AknIconUtils::SetSize( mask, newIconSize, EAspectRatioPreserved );
+
+ // Create picture object, which takes ownership of bitmaps
+ CleanupStack::PushL( imageImage );
+ CleanupStack::PushL( mask );
+ CMyPicture* picture = new ( ELeave ) CMyPicture( newIconSize, *imageImage, *mask );
+ CleanupStack::Pop( mask );
+ CleanupStack::Pop( imageImage );
+
+ CleanupStack::PushL( picture );
+
+ // remove old picture if there is one.
+ if ( place < iViewerRichText->DocumentLength() )
+ {
+ iViewerRichText->DeleteL( place, 1 );
+ }
+
+ // Insert header object to the right spot
+ TPictureHeader header;
+ header.iPicture = TSwizzle<CPicture>( picture );
+ CleanupStack::Pop( picture ); // The following call will always take the ownership of the picture pointed in the header. Not only when succesful.
+ iViewerRichText->InsertL( place, header );
+ }
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::FindCurrentHeaderHotSpotL
+// -----------------------------------------------------------------------------
+TBool CFSEmailUiMailViewerRichText::FindCurrentHeaderHotSpotL( SViewerHeadingHotSpotData& aCurrentHotSpot ) const
+ {
+ FUNC_LOG;
+ TBool foundHotSpot = EFalse;
+ TInt start(0);
+ TInt end(0);
+ if ( iTextViewer )
+ {
+ iTextViewer->GetCurrentHotspotL( start, end );
+ TInt headingHotSpotCount = iViewerHeadingHotSpotData.Count();
+ if ( headingHotSpotCount > 0 )
+ {
+ TInt headingHotspotEnd = iViewerHeadingHotSpotData[ headingHotSpotCount-1 ].iEnd;
+ if ( start < headingHotspotEnd )
+ {
+ for ( TInt i = 0 ; i < headingHotSpotCount ; i++ )
+ {
+ if ( iViewerHeadingHotSpotData[ i ].iStart == start )
+ {
+ aCurrentHotSpot = iViewerHeadingHotSpotData[ i ];
+ foundHotSpot = ETrue;
+ break;
+ }
+ }
+ }
+ }
+ }
+ return foundHotSpot;
+ }
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::FindCurrentBodyHotSpotL
+// -----------------------------------------------------------------------------
+TBool CFSEmailUiMailViewerRichText::FindCurrentBodyHotSpotL( CFindItemEngine::SFoundItem& aCurrentHotSpot ) const
+ {
+ FUNC_LOG;
+ TBool foundHotSpot = EFalse;
+ TInt start(0);
+ TInt end(0);
+ if ( iTextViewer )
+ {
+ iTextViewer->GetCurrentHotspotL( start, end );
+ for ( TInt a = 0 ; a < iBodyTextHotSpotData.Count() ; a++ )
+ {
+ if ( start == iBodyTextHotSpotData[a].iStartPos + iHeaderLength )
+ {
+ aCurrentHotSpot = iBodyTextHotSpotData[a];
+ foundHotSpot = ETrue;
+ break;
+ }
+ }
+ }
+ return foundHotSpot;
+ }
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::FindCurrentHotSpotL
+// -----------------------------------------------------------------------------
+THotspotType CFSEmailUiMailViewerRichText::FindCurrentHotSpotL(
+ SViewerHeadingHotSpotData& aHeaderHotspot,
+ CFindItemEngine::SFoundItem& aBodyHotspot ) const
+ {
+ FUNC_LOG;
+ THotspotType retVal = ENoHotspot;
+ if ( FindCurrentHeaderHotSpotL( aHeaderHotspot ) )
+ {
+ retVal = EHeaderHotspot;
+ }
+ else if ( FindCurrentBodyHotSpotL( aBodyHotspot ) )
+ {
+ retVal = EBodyHotspot;
+ }
+ return retVal;
+ }
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::GetHotspotTextLC, heading hotspots
+// -----------------------------------------------------------------------------
+HBufC* CFSEmailUiMailViewerRichText::GetHotspotTextLC(
+ const SViewerHeadingHotSpotData& aHotSpot ) const
+ {
+ FUNC_LOG;
+ TInt hotspotTextLength = aHotSpot.iEnd - aHotSpot.iStart;
+ if ( aHotSpot.iEnd == aHotSpot.iStart ) // check for special case
+ {
+ hotspotTextLength = 1;
+ }
+
+ return GetHotspotTextLC( aHotSpot.iStart, hotspotTextLength );
+ }
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::GetHotspotTextLC, body text hotspots
+// -----------------------------------------------------------------------------
+HBufC* CFSEmailUiMailViewerRichText::GetHotspotTextLC(
+ const CFindItemEngine::SFoundItem& /*aHotSpot*/ ) const
+ {
+ FUNC_LOG;
+ HBufC* hotspotText = iTextViewer->GetCurrentHotspotTextL();
+ CleanupStack::PushL( hotspotText );
+ return hotspotText;
+ }
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::GetEmailAddressLC
+// -----------------------------------------------------------------------------
+HBufC* CFSEmailUiMailViewerRichText::GetEmailAddressLC(
+ const SViewerHeadingHotSpotData& aCurrentHotSpot ) const
+ {
+ FUNC_LOG;
+ HBufC* emailAddress = NULL;
+ if( aCurrentHotSpot.iType == ETypeFromAddressDisplayName )
+ {
+ CFSMailAddress* mailAddressObject = iMessage->GetSender();
+ emailAddress = mailAddressObject->GetEmailAddress().AllocLC();
+ }
+ else if( aCurrentHotSpot.iType == ETypeToAddressDisplayName )
+ {
+ RPointerArray<CFSMailAddress>& addressArray = iMessage->GetToRecipients();
+ emailAddress = addressArray[aCurrentHotSpot.iDisplayNameArrayIndex]->GetEmailAddress().AllocLC();
+ }
+ else if( aCurrentHotSpot.iType == ETypeCcAddressDisplayName )
+ {
+ RPointerArray<CFSMailAddress>& addressArray = iMessage->GetCCRecipients();
+ emailAddress = addressArray[aCurrentHotSpot.iDisplayNameArrayIndex]->GetEmailAddress().AllocLC();
+ }
+ else if( aCurrentHotSpot.iType == ETypeBccAddressDisplayName )
+ {
+ RPointerArray<CFSMailAddress>& addressArray = iMessage->GetBCCRecipients();
+ emailAddress = addressArray[aCurrentHotSpot.iDisplayNameArrayIndex]->GetEmailAddress().AllocLC();
+ }
+ else if( aCurrentHotSpot.iType == ETypeEmailAddress )
+ {
+ emailAddress = GetHotspotTextLC( aCurrentHotSpot );
+ }
+ else
+ {
+ User::Leave( KErrNotSupported );
+ }
+ return emailAddress;
+ }
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::GetHeaderHotspotEmailAddressLC
+// -----------------------------------------------------------------------------
+HBufC* CFSEmailUiMailViewerRichText::GetHeaderHotspotEmailAddressLC(
+ const SViewerHeadingHotSpotData& aCurrentHeaderHotSpotData ) const
+ {
+ FUNC_LOG;
+ return GetEmailAddressLC( aCurrentHeaderHotSpotData );
+ }
+
+
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::AppendRecipientIndetationL
+// -----------------------------------------------------------------------------
+void CFSEmailUiMailViewerRichText::AppendRecipientIndetationL()
+ {
+ FUNC_LOG;
+ // add transparent indentation icon here, to get right indentation in pixels
+ UpdateIconL( EViewerIconIndentation );
+ }
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::AppendNewLineL
+// -----------------------------------------------------------------------------
+void CFSEmailUiMailViewerRichText::AppendNewLineL()
+ {
+ FUNC_LOG;
+ AppendFormattedTextL( KLineFeed, EViewerFontText );
+ }
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::AppendSpaceL
+// -----------------------------------------------------------------------------
+void CFSEmailUiMailViewerRichText::AppendSpaceL()
+ {
+ FUNC_LOG;
+ AppendFormattedTextL( KSpace, EViewerFontText );
+ }
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::ClipHeaderInfoToFitLC
+// -----------------------------------------------------------------------------
+//<cmail>
+HBufC* CFSEmailUiMailViewerRichText::ClipHeaderInfoToFitLC( const TDesC& aText, TBool aIsDisplayName )
+ {
+ FUNC_LOG;
+ // Clip to fit in available amouth of pixels
+ const CAknLayoutFont* textNameFont = GetCorrectFontL( EViewerFontHotspotNormal );
+ // <cmail> Platform layout change
+ TInt textWidthInPixels = HeaderIndentedTextAreaWidth( EFalse );
+ // </cmail> Platform layout change
+ // create new descriptor for the clipped text.
+ HBufC* textBuffer = aText.AllocLC();
+ // Drop out unwanted characters from display name such as <> and ""
+ if ( aIsDisplayName && textBuffer )
+ {
+ TFsEmailUiUtility::StripDisplayName( *textBuffer );
+ textWidthInPixels -= iAppUi.LayoutHandler()->ViewerIconSize().iWidth;
+ }
+ TPtr textBufferModDes = textBuffer->Des();
+ AknTextUtils::ClipToFit( textBufferModDes, *textNameFont, textWidthInPixels );
+ return textBuffer;
+ }
+//</cmail>
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::HeaderIndentedTextAreaWidth
+// -----------------------------------------------------------------------------
+TInt CFSEmailUiMailViewerRichText::HeaderIndentedTextAreaWidth( const TBool aAddExtra ) const
+ {
+ FUNC_LOG;
+ // For some reason, the ratioanally calculated text width seems to be a bit
+ // wider than the width where GenericTextViewer does line wrapping. Reserve
+ // some extra pixels to overcome this. Maybe there is some difference in
+ // the ways the text width is calculated?
+ // <cmail> Platform layout change
+ //const TInt KExtraPixels = 10;
+ TInt extraPixels( 10 );
+ if ( aAddExtra )
+ {
+ const CAknLayoutFont* newFont = NULL;
+ TRAP_IGNORE( newFont = GetCorrectFontL( EViewerFontText ) );
+ if ( newFont )
+ {
+ TOpenFontMetrics fontMetrics;
+ newFont->GetFontMetrics( fontMetrics );
+ extraPixels = fontMetrics.MaxWidth();
+ }
+ }
+ // </cmail> Platform layout change
+
+ TRect screenRect = iTextViewer->GetControl()->DisplayArea();
+
+ TInt recipientIndenInpixels = iAppUi.LayoutHandler()->ViewerIndentationIconSize().iWidth;
+ TInt scrollBarBreadth = CEikScrollBar::DefaultScrollBarBreadth();
+
+ // Calculate space left for actual text
+ TInt rightMargin = iAppUi.LayoutHandler()->ViewerRightMarginInPixels() + scrollBarBreadth;
+ TInt leftMargin = iAppUi.LayoutHandler()->ViewerLeftMarginInPixels();
+ TInt textWidthInPixels = screenRect.iBr.iX - recipientIndenInpixels - rightMargin - leftMargin - extraPixels;
+
+ return textWidthInPixels;
+ }
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::AppendFromLineL
+// -----------------------------------------------------------------------------
+void CFSEmailUiMailViewerRichText::AppendFromLineL( CFSMailMessage& aMessagePtr,
+ SMailMsgHeaderInfo& aHeaderInfo )
+ {
+ FUNC_LOG;
+
+ // Add the upmost space before the header information
+ InsertTransparentSpacingIconL( ETopMostSpace );
+
+ CFSMailAddress* fromAddress = aMessagePtr.GetSender();
+ if ( fromAddress )
+ {
+ // Append "from:" text
+ HBufC* fromHeadingText = StringLoader::LoadLC( R_FREESTYLE_EMAIL_UI_VIEWER_FROM );
+ AppendFormattedTextL( *fromHeadingText, EViewerFontTitle );
+ CleanupStack::PopAndDestroy( fromHeadingText );
+
+ // Append new line
+ AppendNewLineL();
+ aHeaderInfo.iHeaderLineCount++;
+
+ AppendRecipientIndetationL();
+
+ TDesC* displayName = &fromAddress->GetDisplayName();
+ TDesC* emailAddrs = &fromAddress->GetEmailAddress();
+ if ( displayName && displayName->Length() != 0 )
+ {
+ HBufC* clippedDisplayName = ClipHeaderInfoToFitLC( *displayName, ETrue );
+
+ // Append display name and hotspot
+ InsertHotspotTextAndFontL( *clippedDisplayName );
+
+ // Add hotspot information to rich text and hotspot data to header hotspots array
+ TInt hotSpotLength = clippedDisplayName->Length();
+ iViewerRichText->SetHotSpotL( iRichTextDocumentLength, hotSpotLength, KHotspotHighlightOn );
+ SViewerHeadingHotSpotData hsData;
+ hsData.iType = ETypeFromAddressDisplayName;
+ hsData.iStart = iRichTextDocumentLength;
+ hsData.iEnd = iRichTextDocumentLength + hotSpotLength;
+ hsData.iDisplayNameArrayIndex = 0;
+ hsData.iHotspotLine = aHeaderInfo.iHeaderLineCount;
+ iViewerHeadingHotSpotData.Append( hsData );
+
+ CleanupStack::PopAndDestroy( clippedDisplayName );
+
+ // Append new line
+ AppendNewLineL();
+ aHeaderInfo.iHeaderLineCount++;
+ }
+ else if ( emailAddrs && emailAddrs->Length() != 0 )
+ {
+ // clip emailAddress to fit in one line.
+ HBufC* clippedDisplayName = ClipHeaderInfoToFitLC( *displayName, ETrue );
+
+ // Append email address and hotspot
+ InsertHotspotTextAndFontL( *clippedDisplayName );
+ TInt hotSpotLength = clippedDisplayName->Length();
+ iViewerRichText->SetHotSpotL(iRichTextDocumentLength, hotSpotLength, KHotspotHighlightOn );
+ SViewerHeadingHotSpotData hsData;
+ hsData.iType = ETypeEmailAddress;
+ hsData.iStart = iRichTextDocumentLength;
+ hsData.iEnd = iRichTextDocumentLength + hotSpotLength;
+ hsData.iDisplayNameArrayIndex = 0;
+ hsData.iHotspotLine = aHeaderInfo.iHeaderLineCount;
+ iViewerHeadingHotSpotData.Append( hsData );
+
+ CleanupStack::PopAndDestroy( clippedDisplayName );
+
+ // Append new line
+ AppendNewLineL();
+ aHeaderInfo.iHeaderLineCount++;
+ }
+ }
+ }
+
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::AppendRecipientsL
+// -----------------------------------------------------------------------------
+void CFSEmailUiMailViewerRichText::AppendRecipientsL(
+ const RPointerArray<CFSMailAddress>& aRecipientArray, SMailMsgHeaderInfo& aHeaderInfo,
+ TViewerRecipientType aRecipientType )
+ {
+ FUNC_LOG;
+
+ TInt showAddresses(0);
+ TInt recipientCount = aRecipientArray.Count();
+ TInt maxRecipientCount = iAppUi.LayoutHandler()->ViewerMaxRecipientLineCount();
+
+ if ( recipientCount <= maxRecipientCount )
+ {
+ // All recipients fit to screen
+ showAddresses = recipientCount;
+ }
+ else
+ {
+ // Reserve space for additional recipients count
+ showAddresses = maxRecipientCount - 1;
+ }
+
+ for ( TInt i = 0; i < showAddresses; i++ )
+ {
+ iRichTextDocumentLength = iViewerRichText->DocumentLength();
+ TDesC* displayName = &( aRecipientArray[i]->GetDisplayName() );
+ TDesC* emailAddrs = &( aRecipientArray[i]->GetEmailAddress() );
+ if ( displayName && displayName->Length() != 0 )
+ {
+ AppendRecipientIndetationL();
+
+ HBufC* clippedDisplayName = ClipHeaderInfoToFitLC( *displayName, ETrue );
+
+ // Append display name and set hotspot data
+ InsertHotspotTextAndFontL( *clippedDisplayName );
+
+ iViewerRichText->SetHotSpotL( iRichTextDocumentLength, clippedDisplayName->Length(), KHotspotHighlightOn );
+ SViewerHeadingHotSpotData hsData;
+ switch ( aRecipientType )
+ {
+ case EViewerRecipientTypeCc:
+ hsData.iType = ETypeCcAddressDisplayName;
+ break;
+ case EViewerRecipientTypeBcc:
+ hsData.iType = ETypeBccAddressDisplayName;
+ break;
+ case EViewerRecipientTypeTo:
+ default:
+ hsData.iType = ETypeToAddressDisplayName;
+ break;
+ }
+ hsData.iStart = iRichTextDocumentLength;
+ hsData.iEnd = iRichTextDocumentLength + clippedDisplayName->Length();
+ hsData.iDisplayNameArrayIndex = i;
+ hsData.iHotspotLine = aHeaderInfo.iHeaderLineCount;
+ iViewerHeadingHotSpotData.Append( hsData );
+
+ CleanupStack::PopAndDestroy( clippedDisplayName );
+
+ // Append new line
+ AppendNewLineL();
+ aHeaderInfo.iHeaderLineCount++;
+ }
+ else if ( emailAddrs && emailAddrs->Length() != 0 )
+ {
+ AppendRecipientIndetationL();
+
+ // clip emailAddress to fit in one line.
+ HBufC* clippedDisplayName = ClipHeaderInfoToFitLC( *displayName, ETrue );
+
+ // Append email address name and set hotspot data
+ InsertHotspotTextAndFontL( *clippedDisplayName );
+ iViewerRichText->SetHotSpotL( iRichTextDocumentLength, clippedDisplayName->Length(), KHotspotHighlightOn );
+ SViewerHeadingHotSpotData hsData;
+ hsData.iType = ETypeEmailAddress;
+ hsData.iStart = iRichTextDocumentLength;
+ hsData.iEnd = iRichTextDocumentLength + clippedDisplayName->Length();
+ hsData.iHotspotLine = aHeaderInfo.iHeaderLineCount;
+ iViewerHeadingHotSpotData.Append( hsData );
+
+ CleanupStack::PopAndDestroy( clippedDisplayName );
+
+ // Append new line
+ AppendNewLineL();
+ aHeaderInfo.iHeaderLineCount++;
+ }
+ }
+ if ( recipientCount > showAddresses )
+ {
+ InsertTransparentSpacingIconL( EHeaderInfoSpace );
+
+ AppendRecipientIndetationL();
+
+ HBufC* nMoreRecipientsText = StringLoader::LoadLC( R_FREESTYLE_EMAIL_UI_VIEWER_N_MORE_RECIPIENTS, recipientCount );
+ // Append n more recipients address name and set hotspot data
+ InsertHotspotTextAndFontL( *nMoreRecipientsText );
+ iViewerRichText->SetHotSpotL(iRichTextDocumentLength, nMoreRecipientsText->Length(), KHotspotHighlightOn );
+ SViewerHeadingHotSpotData hsData;
+ switch ( aRecipientType )
+ {
+ case EViewerRecipientTypeCc:
+ hsData.iType = ETypeCcNMoreRecipients;
+ break;
+ case EViewerRecipientTypeBcc:
+ hsData.iType = ETypeBccNMoreRecipients;
+ break;
+ case EViewerRecipientTypeTo:
+ default:
+ hsData.iType = ETypeToNMoreRecipients;
+ break;
+ }
+ hsData.iStart = iRichTextDocumentLength;
+ hsData.iEnd = iRichTextDocumentLength+nMoreRecipientsText->Length();
+ hsData.iHotspotLine = aHeaderInfo.iHeaderLineCount;
+ iViewerHeadingHotSpotData.Append( hsData );
+ // Append new line
+ AppendNewLineL();
+ aHeaderInfo.iHeaderLineCount++;
+ CleanupStack::PopAndDestroy( nMoreRecipientsText );
+ }
+ }
+
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::AppendRecipientLinesL
+// -----------------------------------------------------------------------------
+void CFSEmailUiMailViewerRichText::AppendRecipientLinesL( CFSMailMessage& aMessagePtr,
+ SMailMsgHeaderInfo& aHeaderInfo, TViewerRecipientType aRecipientType )
+ {
+ FUNC_LOG;
+
+ RPointerArray<CFSMailAddress>* mailAddressArray = NULL;
+ HBufC* headingText = NULL;
+ switch ( aRecipientType )
+ {
+ case EViewerRecipientTypeTo:
+ {
+ mailAddressArray = &aMessagePtr.GetToRecipients(); // ownership is not transfered.
+ headingText = StringLoader::LoadLC( R_FREESTYLE_EMAIL_UI_VIEWER_TO );
+ }
+ break;
+ case EViewerRecipientTypeCc:
+ {
+ mailAddressArray = &aMessagePtr.GetCCRecipients(); // ownership is not transfered.
+ headingText = StringLoader::LoadLC( R_FREESTYLE_EMAIL_UI_VIEWER_CC );
+ }
+ break;
+ case EViewerRecipientTypeBcc:
+ {
+ mailAddressArray = &aMessagePtr.GetBCCRecipients(); // ownership is not transfered.
+ headingText = StringLoader::LoadLC( R_FREESTYLE_EMAIL_UI_VIEWER_BCC );
+ }
+ break;
+ default:
+ {
+ // nothing here.
+ }
+ break;
+ }
+
+ if ( mailAddressArray && mailAddressArray->Count() )
+ {
+ // Add vertical empty space between last recipient and new heading info text
+ InsertTransparentSpacingIconL( EHeaderInfoSpace );
+
+ AppendFormattedTextL( *headingText, EViewerFontTitle );
+
+ AppendNewLineL();
+ aHeaderInfo.iHeaderLineCount++;
+
+ // Append the recipients
+ AppendRecipientsL( *mailAddressArray, aHeaderInfo, aRecipientType );
+ }
+
+ // cleanup if heading text was created
+ if ( headingText )
+ {
+ CleanupStack::PopAndDestroy( headingText );
+ }
+
+ }
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::AppendSentLineL
+// -----------------------------------------------------------------------------
+void CFSEmailUiMailViewerRichText::AppendSentLineL( CFSMailMessage& aMessagePtr,
+ SMailMsgHeaderInfo& aHeaderInfo )
+ {
+ FUNC_LOG;
+
+ InsertTransparentSpacingIconL( EHeaderInfoSpace );
+
+ // Save "Sent ..." text line number for initial focus setting
+ iSentTextLine = aHeaderInfo.iHeaderLineCount;
+
+ HBufC* dateText = TFsEmailUiUtility::DateTextFromMsgLC( &aMessagePtr );
+ HBufC* timeText = TFsEmailUiUtility::TimeTextFromMsgLC( &aMessagePtr );
+ HBufC* sentHeadingText = StringLoader::LoadLC( R_FREESTYLE_EMAIL_UI_VIEWER_SENT );
+ HBufC* combinedSentText = sentHeadingText->ReAllocL( sentHeadingText->Length() + KSpace().Length() +
+ dateText->Length() +
+ KSentLineDateAndTimeSeparatorText().Length() +
+ timeText->Length() );
+ CleanupStack::Pop( sentHeadingText );
+ CleanupStack::PushL( combinedSentText );
+ TPtr combinedSentTextPtr = combinedSentText->Des();
+ combinedSentTextPtr.Append( KSpace );
+ combinedSentTextPtr.Append( *dateText );
+ combinedSentTextPtr.Append( KSentLineDateAndTimeSeparatorText );
+ combinedSentTextPtr.Append( *timeText );
+
+ AppendFormattedTextL( *combinedSentText, EViewerFontSent );
+
+ CleanupStack::PopAndDestroy( combinedSentText );
+ CleanupStack::PopAndDestroy( timeText );
+ CleanupStack::PopAndDestroy( dateText );
+
+ AppendNewLineL();
+ aHeaderInfo.iHeaderLineCount++;
+ }
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::AppendSubjectLinesL
+// -----------------------------------------------------------------------------
+void CFSEmailUiMailViewerRichText::AppendSubjectLinesL( CFSMailMessage& aMessagePtr,
+ SMailMsgHeaderInfo& aHeaderInfo )
+ {
+ FUNC_LOG;
+ InsertTransparentSpacingIconL( EHeaderInfoSpace );
+
+ // "Subject:" text
+ HBufC* subjectHeadingText = StringLoader::LoadLC( R_FREESTYLE_EMAIL_UI_VIEWER_SUBJECT );
+ AppendFormattedTextL( *subjectHeadingText, EViewerFontTitle );
+ CleanupStack::PopAndDestroy( subjectHeadingText );
+
+ AppendNewLineL();
+ aHeaderInfo.iHeaderLineCount++;
+
+ // Save "subject:" text line number for initial focus setting
+ iSubjectTextLine = aHeaderInfo.iHeaderLineCount;
+
+ TInt subjectLineCount = 0;
+
+ // Get the subject text to modifyable buffer because truncation may be needed.
+ // Use "no subject" text if not available.
+ HBufC* subjectBuf = TFsEmailUiUtility::CreateSubjectTextLC( &aMessagePtr );
+ TPtr subjectPtr = subjectBuf->Des();
+
+ // Wrap and clip to maximum number of lines
+ TInt subjectWidthInPixels = HeaderIndentedTextAreaWidth();
+ TInt maxSubjectLines = iAppUi.LayoutHandler()->ViewerMaxSubjectLineCount();
+ CArrayFixFlat<TPtrC>* wrappedArray = new (ELeave) CArrayFixFlat<TPtrC>( maxSubjectLines );
+ CleanupStack::PushL( wrappedArray );
+ CArrayFixFlat<TInt>* lineWidthArray = new (ELeave) CArrayFixFlat<TInt>( maxSubjectLines );
+ CleanupStack::PushL( lineWidthArray );
+ for ( TInt i = 0 ; i < maxSubjectLines ; ++i )
+ {
+ lineWidthArray->AppendL( subjectWidthInPixels );
+ }
+ //<cmail>
+ const CAknLayoutFont* subjectFont = GetCorrectFontL( EViewerFontText );
+
+ AknTextUtils::WrapToArrayAndClipL( subjectPtr, *lineWidthArray, *subjectFont, *wrappedArray );
+ //</cmail>
+ subjectLineCount = wrappedArray->Count();
+
+ TInt i = 1; // indicating current subject line, starting as 1 = first line, 2 = second line
+ for( ; i <= subjectLineCount ; i++ )
+ {
+ // Rest of the lines have no preceeding icon, just indentation
+ AppendRecipientIndetationL();
+
+ TPtrC temp = (*wrappedArray)[i-1];
+ AppendFormattedTextL( temp, EViewerFontText );
+
+ // add line break
+ AppendNewLineL();
+ aHeaderInfo.iHeaderLineCount++;
+ aHeaderInfo.iSubjectLineCount++;
+ }
+
+ CleanupStack::PopAndDestroy( lineWidthArray );
+ CleanupStack::PopAndDestroy( wrappedArray );
+ CleanupStack::PopAndDestroy( subjectBuf );
+ }
+
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::AppendMessageIconL
+// -----------------------------------------------------------------------------
+void CFSEmailUiMailViewerRichText::AppendMessageIconL()
+ {
+ FUNC_LOG;
+ // append embedded icon.
+ iEmailStatusIconPlace = iViewerRichText->DocumentLength();
+ iEmailStatusIconLine = iHeaderLineInfo.iHeaderLineCount;
+ UpdateIconL( EViewerEmailStatus );
+ }
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::AppendFollowUpIconL
+// -----------------------------------------------------------------------------
+TBool CFSEmailUiMailViewerRichText::AppendFollowUpIconL( CFSMailMessage& aMessagePtr )
+ {
+ FUNC_LOG;
+ TBool added = EFalse;
+
+ if ( TFsEmailUiUtility::IsFollowUpSupported( *iMailBox ) )
+ {
+ iFollowupIconPlace = iViewerRichText->DocumentLength();
+ iFollowupIconLine = iHeaderLineInfo.iHeaderLineCount;
+ if ( aMessagePtr.IsFlagSet( EFSMsgFlag_FollowUpComplete ) )
+ {
+ UpdateIconL( EViewerIconFollowUpComplete );
+ }
+ else if ( aMessagePtr.IsFlagSet( EFSMsgFlag_FollowUp ) )
+ {
+ UpdateIconL( EViewerIconFollowUp );
+ }
+ else
+ {
+ UpdateIconL( EViewerIconFollowUpNone );
+ }
+ added = ETrue;
+ }
+
+ return added;
+ }
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::AppendAttachmentIconL
+// -----------------------------------------------------------------------------
+void CFSEmailUiMailViewerRichText::AppendAttachmentIconL()
+ {
+ FUNC_LOG;
+ // append embedded icon.
+ iAttachmentIconPlace = iViewerRichText->DocumentLength();
+ UpdateIconL( EViewerAttachment );
+
+ InsertSpaceAfterIconL();
+ }
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::AppendAttachmentLinesL
+// Append attachement(s) line to the rich text.
+// -----------------------------------------------------------------------------
+void CFSEmailUiMailViewerRichText::AppendAttachmentLinesL( CFSMailMessage& aMessagePtr, SMailMsgHeaderInfo& aHeaderInfo )
+ {
+ FUNC_LOG;
+ if ( aMessagePtr.IsFlagSet( EFSMsgFlag_Attachments ) )
+ {
+ // get attachments and count
+ RPointerArray<CFSMailMessagePart> attachments;
+ CleanupResetAndDestroyClosePushL( attachments );
+ aMessagePtr.AttachmentListL( attachments );
+ TInt attachmentsCount = attachments.Count();
+ HBufC* attachmentText = NULL;
+ if ( attachmentsCount == 1 )
+ {
+ TDesC& attachmentName = attachments[0]->AttachmentNameL();
+ TUint attachmentSize = attachments[0]->ContentSize(); // bytes
+
+ // create size text including the unit and preceeding space character
+ HBufC* sizeWithUnit = TFsEmailUiUtility::CreateSizeDescLC( attachmentSize );
+ HBufC* sizeText = HBufC::NewL( sizeWithUnit->Length()+1 );
+ sizeText->Des().Append( ' ' );
+ sizeText->Des().Append( *sizeWithUnit );
+ CleanupStack::PopAndDestroy( sizeWithUnit );
+ CleanupStack::PushL( sizeText );
+
+ // clip attachment name to fit in one line so that size information has enough space too.
+ //<cmail>
+ const CAknLayoutFont* attachmentFont = GetCorrectFontL( EViewerFontHotspotNormal );
+
+ TInt attachmentTextWidthInPixels = HeaderIndentedTextAreaWidth();
+ TInt sizeTextInPixels = attachmentFont->TextWidthInPixels( *sizeText );
+ TInt pixelsLeftForAttachmentName = attachmentTextWidthInPixels - sizeTextInPixels;
+
+ // safe check if the size information is too wide for some reason.
+ if ( pixelsLeftForAttachmentName < 0 )
+ {
+ attachmentText = HBufC::NewL( attachmentName.Length() + sizeText->Length() );
+ attachmentText->Des().Append( attachmentName );
+ attachmentText->Des().Append( *sizeText );
+ TPtr attachmentTextBufferModDes = attachmentText->Des();
+ AknTextUtils::ClipToFit( attachmentTextBufferModDes, *attachmentFont, attachmentTextWidthInPixels );
+ }
+ else
+ { // normal case
+ HBufC* attacmentNameBuffer = attachmentName.AllocLC();
+ TPtr attachmentNameBufferModDes = attacmentNameBuffer->Des();
+ AknTextUtils::ClipToFit( attachmentNameBufferModDes, *attachmentFont, pixelsLeftForAttachmentName );
+
+ attachmentText = HBufC::NewL( attacmentNameBuffer->Length() + sizeText->Length() );
+ attachmentText->Des().Append( *attacmentNameBuffer );
+ attachmentText->Des().Append( *sizeText );
+ CleanupStack::PopAndDestroy( attacmentNameBuffer );
+ }
+ CleanupStack::PopAndDestroy( sizeText );
+ }
+ //</cmail>
+ else if ( attachmentsCount > 1 )
+ {
+ TInt totalSize = 0;
+ for( TInt i = 0; i < attachmentsCount ; i++ )
+ {
+ totalSize += attachments[i]->ContentSize();
+ }
+ HBufC* sizeText = TFsEmailUiUtility::CreateSizeDescLC( totalSize );
+ attachmentText = StringLoader::LoadL( R_FSE_VIEWER_ATTACHMENTS_TEXT_WITH_SIZE,
+ *sizeText, attachmentsCount );
+ CleanupStack::PopAndDestroy( sizeText );
+ }
+
+ // Append attachment line to rich text if there was attachments
+ if ( attachmentText )
+ {
+ CleanupStack::PushL( attachmentText );
+
+ InsertTransparentSpacingIconL( EHeaderInfoSpace );
+
+ AppendAttachmentIconL();
+
+ InsertHotspotTextAndFontL( *attachmentText );
+ iViewerRichText->SetHotSpotL( iRichTextDocumentLength, attachmentText->Length(), KHotspotHighlightOn );
+ SViewerHeadingHotSpotData hsData;
+ if ( attachmentsCount == 1 )
+ {
+ hsData.iType = ETypeAttachment;
+ }
+ else
+ {
+ hsData.iType = ETypeAttachments;
+ }
+ hsData.iStart = iRichTextDocumentLength;
+ hsData.iEnd = iRichTextDocumentLength + attachmentText->Length();
+ hsData.iHotspotLine = aHeaderInfo.iHeaderLineCount;
+ iAttachmentHotSpotIndex = iViewerHeadingHotSpotData.Count();
+ iViewerHeadingHotSpotData.Append( hsData );
+ CleanupStack::PopAndDestroy( attachmentText );
+
+ // Append new lines
+ AppendNewLineL();
+ aHeaderInfo.iHeaderLineCount++;
+ }
+ CleanupStack::PopAndDestroy( &attachments );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::AppendHtmlTextLineL
+// Appends "View as HTML" selection hotspot to the rich text if message has HTML text part
+// -----------------------------------------------------------------------------
+void CFSEmailUiMailViewerRichText::AppendHtmlTextLineL( CFSMailMessage& aMessagePtr, SMailMsgHeaderInfo& aHeaderInfo )
+ {
+ FUNC_LOG;
+
+ CFSMailMessagePart* htmlBodyPart = aMessagePtr.HtmlBodyPartL();
+ if ( htmlBodyPart )
+ {
+ CleanupStack::PushL( htmlBodyPart );
+
+ // Add just a little bit of vertical space before the next lines
+ InsertTransparentSpacingIconL( EHeaderInfoSpace );
+
+ // Indent the "View as HTML" link
+ AppendRecipientIndetationL();
+
+ HBufC* htmlLineText = StringLoader::LoadLC( R_FREESTYLE_EMAIL_UI_VIEWER_HTML );
+ HBufC* clippedHtmlLine = ClipHeaderInfoToFitLC( *htmlLineText, EFalse );
+
+ InsertHotspotTextAndFontL( *clippedHtmlLine );
+ iViewerRichText->SetHotSpotL( iRichTextDocumentLength, clippedHtmlLine->Length(), KHotspotHighlightOn );
+ SViewerHeadingHotSpotData hsData;
+ hsData.iType = ETypeHtml;
+ hsData.iStart = iRichTextDocumentLength;
+ hsData.iEnd = iRichTextDocumentLength + htmlLineText->Length();
+ hsData.iHotspotLine = iHeaderLineInfo.iHeaderLineCount;
+ iViewHtmlHotSpotIndex = iViewerHeadingHotSpotData.Count();
+ iViewerHeadingHotSpotData.Append( hsData );
+
+ CleanupStack::PopAndDestroy( clippedHtmlLine );
+ CleanupStack::PopAndDestroy( htmlLineText );
+ CleanupStack::PopAndDestroy( htmlBodyPart );
+
+ // Append one line feed plus little extra vertical space
+ AppendNewLineL();
+ aHeaderInfo.iHeaderLineCount++;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::AppendInitialBodytextLinesL
+// Append body text which is found from the message to the end of the rich text.
+// If plain text body part is not found, tries to convert body from html part
+// -----------------------------------------------------------------------------
+void CFSEmailUiMailViewerRichText::AppendInitialBodytextLinesL( CFSMailMessage& aMessagePtr )
+ {
+ FUNC_LOG;
+ CFSMailMessagePart* plainTextBodyPart = aMessagePtr.PlainTextBodyPartL();
+
+ if ( plainTextBodyPart )
+ {
+ CleanupStack::PushL( plainTextBodyPart );
+
+ TInt fetchedSize = plainTextBodyPart->FetchedContentSize();
+ if ( fetchedSize > 0 )
+ {
+ // Limit displayed plain text body size to KPlainTextLimitationInBytes
+ // currently set to 150K characters of text that should be more than enough for mobile email
+ TInt bufSize = Min( fetchedSize, KPlainTextLimitationInChars );
+ HBufC* plainTextData16 = HBufC::NewLC( bufSize );
+
+ TPtr pointer = plainTextData16->Des();
+ plainTextBodyPart->GetContentToBufferL( pointer, 0 );
+
+ // Store body length
+ iBodyLength = plainTextData16->Length();
+
+ // append everything we have now
+ AppendFormattedTextL( *plainTextData16, EViewerFontText );
+
+ // Append hotspot data for content
+ iBodyTextHotSpotData.Reset();
+ FindBodyTextHotSpotsL( *plainTextData16 );
+ CleanupStack::PopAndDestroy( plainTextData16 );
+ // Make sure that text viewer is not filled with more than max
+ // number of hotspot count
+ TInt hotspotCount = iBodyTextHotSpotData.Count();
+ if ( hotspotCount > KMaxHotspotCount )
+ {
+ hotspotCount = KMaxHotspotCount;
+ }
+ for ( TInt i=0; i < hotspotCount; i++ )
+ {
+ AddBodyHotsSpotWithTextFormatingL( iBodyTextHotSpotData[i] );
+ }
+ }
+ CleanupStack::PopAndDestroy( plainTextBodyPart );
+ }
+ else
+ {
+ CFSMailMessagePart* htmlBodyPart = aMessagePtr.HtmlBodyPartL();
+ if ( htmlBodyPart )
+ {
+ CleanupStack::PushL( htmlBodyPart );
+
+ TInt fetchedBodySize = htmlBodyPart->FetchedContentSize();
+ TInt wholeContentSize = htmlBodyPart->ContentSize();
+ if ( fetchedBodySize == wholeContentSize )
+ {
+ HBufC* htmlData = HBufC::NewLC( fetchedBodySize );
+ TPtr pointer = htmlData->Des();
+ htmlBodyPart->GetContentToBufferL( pointer, 0 );
+ HBufC* txtData = TFsEmailUiUtility::ConvertHtmlToTxtL( *htmlData );
+ CleanupStack::PopAndDestroy( htmlData );
+ CleanupStack::PushL( txtData );
+
+ // User large fixed maximum amount of characters to append.
+ // In normal cases all text is included.
+ TPtrC truncatedText = txtData->Left( KPlainTextLimitationInChars );
+ iBodyLength = truncatedText.Length();
+ AppendFormattedTextL( truncatedText, EViewerFontText );
+ // Append hotspot data for content
+ iBodyTextHotSpotData.Reset();
+ FindBodyTextHotSpotsL( truncatedText );
+ CleanupStack::PopAndDestroy( txtData );
+ // Make sure that text viewer is not filled with more than max
+ // number of hotspot count
+ TInt hotspotCount = iBodyTextHotSpotData.Count();
+ if ( hotspotCount > KMaxHotspotCount )
+ {
+ hotspotCount = KMaxHotspotCount;
+ }
+ for ( TInt i=0; i < hotspotCount; i++ )
+ {
+ AddBodyHotsSpotWithTextFormatingL( iBodyTextHotSpotData[i] );
+ }
+ }
+
+ CleanupStack::PopAndDestroy( htmlBodyPart );
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::AppendFetchedBodytextLinesL
+// Append rest of the body text replacing "Fetching more text"
+// -----------------------------------------------------------------------------
+void CFSEmailUiMailViewerRichText::AppendFetchedBodytextLinesL( CFSMailMessage& aMessagePtr )
+ {
+ FUNC_LOG;
+ TInt startBodyPoint = iBodyLength;
+ CFSMailMessagePart* plainTextBodyPart = aMessagePtr.PlainTextBodyPartL();
+ if ( plainTextBodyPart )
+ {
+ CleanupStack::PushL( plainTextBodyPart );
+ // Fetching More text is not required any more
+ SetEmptyStatusLayoutTextL();
+
+ // Limit the whole data reading to KPlainTextLimitationInChars, usually this is more than
+ // enough for mobile email client
+ TInt fetchedSize = plainTextBodyPart->FetchedContentSize();
+ TInt bufSize = Min( fetchedSize, KPlainTextLimitationInChars );
+ HBufC* plainTextData16 = HBufC::NewLC( bufSize );
+
+ // Get more fetched content to buffer
+ TPtr pointer = plainTextData16->Des();
+ plainTextBodyPart->GetContentToBufferL( pointer, 0 );
+
+ // Store body length
+ iBodyLength = plainTextData16->Length();
+
+ // Safety check required by POP protocol. Sometimes iBodyLength changes
+ // when message has been fetched. Following is added to prevent crashes related to that.
+ if ( startBodyPoint > iBodyLength )
+ {
+ startBodyPoint = iBodyLength;
+ }
+
+ // Insert rest of the body text after previously added body text
+ TPtrC restOfThePlainText = plainTextData16->Mid( startBodyPoint );
+ InsertFormattedTextL( restOfThePlainText, EViewerFontText,
+ iHeaderLength + startBodyPoint );
+
+ // Find hotspots from the added body text
+ TInt previousBodyHotspotCount = iBodyTextHotSpotData.Count();
+ FindBodyTextHotSpotsL( restOfThePlainText );
+ // Make sure that text viewer is not filled with more than max
+ // number of hotspot count
+ TInt hotspotCount = iBodyTextHotSpotData.Count();
+ if ( hotspotCount > KMaxHotspotCount )
+ {
+ hotspotCount = KMaxHotspotCount;
+ }
+ for ( TInt i = previousBodyHotspotCount; i < hotspotCount; i++ )
+ {
+ iBodyTextHotSpotData[i].iStartPos += startBodyPoint;
+ AddBodyHotsSpotWithTextFormatingL( iBodyTextHotSpotData[i] );
+ }
+
+ iTextViewer->ReloadTextL();
+ CleanupStack::PopAndDestroy( plainTextData16 );
+ CleanupStack::PopAndDestroy( plainTextBodyPart );
+ }
+
+ }
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::CreateStatusLayoutL
+// Creates status layout to display fetching more text.
+// -----------------------------------------------------------------------------
+void CFSEmailUiMailViewerRichText::CreateStatusLayoutL( TBool aSetEmptyContents /*= ETrue*/ )
+ {
+ FUNC_LOG;
+ // ensure not created twice
+ if ( !iStatusVisual && iTextViewer )
+ {
+ iStatusLayout = static_cast<CAlfAnchorLayout*>( iTextViewer->GetStatusLayout() );
+ CAlfControl* textViewerControl = iTextViewer->GetControl();
+ iStatusVisual = CAlfTextVisual::AddNewL( *textViewerControl, iStatusLayout );
+ iStatusVisual->EnableShadow( EFalse );
+ iStatusVisual->SetColor( iAppUi.LayoutHandler()->ViewerBodyTextColor() );
+
+ TAlfTimedValue statusVisualOpacity;
+ statusVisualOpacity.SetValueNow ( 1 );
+ iStatusVisual->SetOpacity( statusVisualOpacity );
+
+ // <cmail> Platform layout change
+ /*iStatusVisual->SetTextStyle( iAppUi.LayoutHandler()->FSTextStyleFromIdL( EFSFontTypeSmallBold )->Id() );*/
+ iStatusVisual->SetTextStyle( iAppUi.LayoutHandler()->FSTextStyleFromLayoutL( AknLayoutScalable_Apps::list_single_cmail_header_caption_pane_t1() ).Id() );
+ // </cmail> Platform layout change
+ iStatusVisual->SetAlign( EAlfAlignHCenter, EAlfAlignVTop );
+
+ if ( aSetEmptyContents )
+ {
+ SetEmptyStatusLayoutTextL();
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::AppendFetchingMoreTextL
+// metdod for updating the animated text while rest of the message is been fetched
+// -----------------------------------------------------------------------------
+void CFSEmailUiMailViewerRichText::AppendFetchingMoreTextL()
+ {
+ FUNC_LOG;
+ // Create status layout if it doesn't exist yet
+ CreateStatusLayoutL( EFalse );
+
+ // add fetching content text with current animation
+ HBufC* fetchingContentText = StringLoader::LoadLC( R_FREESTYLE_EMAIL_UI_VIEWER_FETCHING_CONTENT_TEXT );
+
+ // create buffer for "Fetching more text" and dots animation
+ HBufC* newDes = HBufC::NewLC( fetchingContentText->Length() + KTotalNumberOfLines + KTotalNumberOfLines);
+ TPtr des = newDes->Des();
+
+ // add KTotalNumberOfLines always at the beginning
+ for( TInt i = 0 ; i < KTotalNumberOfLines / KNumberOfLines ; i++ )
+ {
+ des.Append( KThreeLines );
+ }
+
+ // append fething text
+ des.Append( *fetchingContentText );
+
+ // add dots according to current ellipsis count
+ for( TInt i = 0 ; i < iCurrentEllipsisCount ; i++ )
+ {
+ des.Append( KThreeLines );
+ }
+
+ // ellipses count counter going through 0,1,2,3,0,1,2,3,0,... sequence
+ if( iCurrentEllipsisCount >= KTotalNumberOfLines / KNumberOfLines )
+ {
+ iCurrentEllipsisCount = 0;
+ }
+ else
+ {
+ iCurrentEllipsisCount++;
+ }
+
+ // just in case, try clipping the text if it doesn't fit in one line for some reason.
+ TRect screenRect = iTextViewer->GetControl()->DisplayArea();
+ //<cmail>
+ const CAknLayoutFont* bodyTextFont = GetCorrectFontL( EViewerFontBody );
+ TInt rightMargin = iAppUi.LayoutHandler()->ViewerRightMarginInPixels();
+ TInt leftMargin = iAppUi.LayoutHandler()->ViewerLeftMarginInPixels();
+ TInt pixelsToFit = screenRect.iBr.iX - rightMargin - leftMargin;
+ AknTextUtils::ClipToFit( des, *bodyTextFont, pixelsToFit );
+ //</cmail>
+
+ // Assign the text to status layout.
+ iStatusVisual->SetTextL( *newDes );
+ iStatusLayout->SetClipping( EFalse );
+ TSize statusSize = iStatusVisual->TextExtents();
+ iStatusLayout->SetSize( statusSize );
+ iStatusVisual->SetRect( TRect( TPoint( 0, 0 ), statusSize ) );
+ iTextViewer->UpdateStatusLayout();
+
+ CleanupStack::PopAndDestroy( newDes );
+ CleanupStack::PopAndDestroy( fetchingContentText );
+ }
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::SetEmptyStatusLayoutTextL
+// The text in status layout is updated to contain only a couple of line feeds.
+// This ensures, that the whole body can be scrolled visible also when the
+// attachment downloading popup is shown in the bottom.
+// -----------------------------------------------------------------------------
+void CFSEmailUiMailViewerRichText::SetEmptyStatusLayoutTextL()
+ {
+ FUNC_LOG;
+ _LIT( KEmptyStatusText, "\n " );
+ if ( iStatusVisual && iStatusLayout && iTextViewer )
+ {
+ iStatusVisual->SetTextL( KEmptyStatusText );
+ iStatusLayout->SetClipping( EFalse );
+ TSize statusSize = iStatusVisual->TextExtents();
+ iStatusLayout->SetSize( statusSize );
+ iStatusVisual->SetRect( TRect( TPoint( 0, 0 ), statusSize ) );
+ iTextViewer->UpdateStatusLayout();
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::SetHotspotHighlightedColorL
+// -----------------------------------------------------------------------------
+void CFSEmailUiMailViewerRichText::SetHotspotHighlightedColorL( TInt aStartIndx, TInt aLenght, TBool aHighlight )
+ {
+ FUNC_LOG;
+ TCharFormat charFormat;
+ TCharFormatMask charFormatMask;
+ if ( aHighlight )
+ {
+ charFormat.iFontPresentation.iTextColor = SkinFontColorByType( EViewerFontHotspotHighLighted );
+ }
+ else
+ {
+ charFormat.iFontPresentation.iTextColor = SkinFontColorByType( EViewerFontHotspotNormal );
+ }
+
+ charFormatMask.SetAttrib( EAttColor );
+ iViewerRichText->ApplyCharFormatL( charFormat, charFormatMask, aStartIndx, aLenght );
+ iTextViewer->ReloadTextL();
+ }
+
+// ---------------------------------------------------------------------------
+// Getter for the index of the attachment hotspot
+// ---------------------------------------------------------------------------
+TInt CFSEmailUiMailViewerRichText::AttachmentHotSpotIndex() const
+ {
+ FUNC_LOG;
+ return iAttachmentHotSpotIndex;
+ }
+
+// ---------------------------------------------------------------------------
+// Getter for the index of the View HTML hotspot
+// ---------------------------------------------------------------------------
+TInt CFSEmailUiMailViewerRichText::ViewHtmlHotSpotIndex() const
+ {
+ FUNC_LOG;
+ return iViewHtmlHotSpotIndex;
+ }
+
+// ---------------------------------------------------------------------------
+// Helper function for getting hotspot text from rich text data
+// ---------------------------------------------------------------------------
+HBufC* CFSEmailUiMailViewerRichText::GetHotspotTextLC( TInt aStartPos,
+ TInt aLength ) const
+ {
+ FUNC_LOG;
+ __ASSERT_DEBUG( aStartPos >= 0, User::Invariant() );
+ __ASSERT_DEBUG( aLength > 0, User::Invariant() );
+
+ HBufC* des = HBufC::NewLC( aLength );
+
+ // Hotspot text is retrived in a loop, because the CPlainText::Read
+ // method may return only part of the requested text
+ TInt documentLength = iViewerRichText->DocumentLength();
+ while ( aLength > 0 && aStartPos < documentLength )
+ {
+ TPtrC text = iViewerRichText->Read( aStartPos, aLength );
+ des->Des().Append( text );
+ aLength -= text.Length();
+ aStartPos += text.Length();
+ }
+
+ return des;
+ }
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::FindBodyTextHotSpotsL
+// -----------------------------------------------------------------------------
+void CFSEmailUiMailViewerRichText::FindBodyTextHotSpotsL( const TDesC& aBodyContent )
+ {
+ FUNC_LOG;
+ // Use s60 find item engine to find hotspots from the body text
+ CFindItemEngine* hotspotSearch = CFindItemEngine::NewL
+ (
+ aBodyContent,
+ // define wanted
+ (CFindItemEngine::TFindItemSearchCase)
+ (CFindItemEngine::EFindItemSearchMailAddressBin |
+ CFindItemEngine::EFindItemSearchPhoneNumberBin |
+ CFindItemEngine::EFindItemSearchURLBin |
+ CFindItemEngine::EFindItemSearchScheme )
+ );
+ CleanupStack::PushL( hotspotSearch );
+
+ // <cmail>
+ // insert found data to member variable iHotSpotData
+ const CArrayFixFlat<CFindItemEngine::SFoundItem>* itemArray = hotspotSearch->ItemArray();
+ TInt itemCount = hotspotSearch->ItemCount();
+ for ( TInt i = 0; i < itemCount; i++ )
+ {
+ CFindItemEngine::SFoundItem* foundItem = const_cast<CFindItemEngine::SFoundItem*> ( &itemArray->At( i ) );
+ TBool foundSameHotspotTwice = EFalse;
+ // Check if same hotspot is found twice. This may happen when both flags
+ // EFindItemSearchScheme and EFindItemSearchURLBin are ON for search request.
+ for ( TInt j = i + 1; j < itemCount; j++ )
+ {
+ if ( foundItem->iStartPos == itemArray->At( j ).iStartPos )
+ {
+ foundSameHotspotTwice = ETrue;
+ break;
+ }
+ }
+ if ( !foundSameHotspotTwice )
+ {
+ // At this phase hotspot is one character too early
+ // Change it to right place. If FindItemEngine implementation
+ // will change then following line must be removed.
+ //foundItem->iStartPos++;
+ iBodyTextHotSpotData.AppendL( itemArray->At( i ) );
+ }
+ }
+ // </cmail>
+
+ CleanupStack::PopAndDestroy( hotspotSearch );
+ }
+
+
+//<cmail>
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::GetCorrectFontL
+// -----------------------------------------------------------------------------
+const CAknLayoutFont* CFSEmailUiMailViewerRichText::GetCorrectFontL( TViewerFontType aFontType ) const
+ {
+ FUNC_LOG;
+ /*
+ EViewerFontTitle = 0,
+ EViewerFontText,
+ EViewerFontBody,
+ EViewerFontHotspotNormal,
+ EViewerFontHotspotHighLighted,
+ EViewerFontSent,
+ EViewerFontIndentation
+ */
+ const CAknLayoutFont* font = NULL;
+
+ switch ( aFontType )
+ {
+ case EViewerFontTitle:
+ case EViewerFontSent:
+ {
+ font = CurrentTitleFontL();
+ }
+ break;
+ case EViewerFontText:
+ case EViewerFontBody:
+ case EViewerFontHotspotNormal:
+ case EViewerFontHotspotHighLighted:
+ case EViewerFontIndentation:
+ default:
+ {
+ font = CurrentTextFontL();
+ }
+ break;
+ }
+
+ if (NULL == font)
+ User::Leave(KErrGeneral);
+
+ return font;
+
+ }
+
+/*
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::ReConstructFontArrayL
+// -----------------------------------------------------------------------------
+void CFSEmailUiMailViewerRichText::ReConstructFontArrayL()
+ {
+ FUNC_LOG;
+ iFontsArray.ResetAndDestroy();
+
+ // append title font
+ CAknLayoutFont* titleFont = CurrentTitleFontLC();
+ iFontsArray.AppendL( titleFont );
+ CleanupStack::Pop( titleFont );
+
+ // append text font
+ CAknLayoutFont* textFont = CurrentTextFontLC();
+ iFontsArray.AppendL( textFont );
+ CleanupStack::Pop( textFont );
+
+ // append body font
+ CAknLayoutFont* bodyFont = CurrentTextFontLC();
+ iFontsArray.AppendL( bodyFont );
+ CleanupStack::Pop( bodyFont );
+
+ // append not highlighted hotspot font
+ CAknLayoutFont* normalHotspotFont = CurrentTextFontLC();
+ iFontsArray.AppendL( normalHotspotFont );
+ CleanupStack::Pop( normalHotspotFont );
+
+ // append highlighted hotspot font
+ CAknLayoutFont* highLightedHotspotFont = CurrentTextFontLC();
+ iFontsArray.AppendL( highLightedHotspotFont );
+ CleanupStack::Pop( highLightedHotspotFont );
+
+ // append sent line font
+ CAknLayoutFont* sentLineFont = CurrentSentTextFontLC();
+ iFontsArray.AppendL( sentLineFont );
+ CleanupStack::Pop( sentLineFont );
+
+ // append indentation font
+ CAknLayoutFont* indentationFont = CurrentTextFontLC();
+ iFontsArray.AppendL( indentationFont );
+ CleanupStack::Pop( indentationFont );
+ }
+*/
+
+/*
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::FontFromFontArray
+// -----------------------------------------------------------------------------
+CAknLayoutFont& CFSEmailUiMailViewerRichText::FontFromFontArray( TViewerFontType aFontType ) const
+ {
+ FUNC_LOG;
+ return *iFontsArray[aFontType];
+ }
+*/
+//</cmail>
+
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::SkinFontColorByType
+// -----------------------------------------------------------------------------
+TRgb CFSEmailUiMailViewerRichText::SkinFontColorByType( TViewerFontType aFontType )
+ {
+ FUNC_LOG;
+ TRgb returnedColor;
+ switch ( aFontType )
+ {
+ case EViewerFontTitle:
+ {
+ returnedColor = iAppUi.LayoutHandler()->ViewerTitleTextColor();
+ }
+ break;
+ case EViewerFontBody:
+ {
+ returnedColor = iAppUi.LayoutHandler()->ViewerBodyTextColor();
+ }
+ break;
+ case EViewerFontHotspotNormal:
+ {
+ returnedColor = iAppUi.LayoutHandler()->ViewerNormalHotspotTextColor();
+ }
+ break;
+ case EViewerFontHotspotHighLighted:
+ {
+ returnedColor = iAppUi.LayoutHandler()->ViewerHighlightedHotspotTextColor();
+ }
+ break;
+ case EViewerFontSent:
+ {
+ // <cmail>
+ //returnedColor = iAppUi.LayoutHandler()->ViewerTitleFontHeight();
+ returnedColor = iAppUi.LayoutHandler()->ViewerTitleTextColor();
+ // </cmail>
+ }
+ break;
+ case EViewerFontText:
+ default:
+ {
+ returnedColor = iAppUi.LayoutHandler()->ViewerTextTextColor();
+ }
+ break;
+ }
+ return returnedColor;
+ }
+
+//<cmail> LAYOUT CHANGES
+
+/*
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::CurrentTitleFontLC
+// -----------------------------------------------------------------------------
+CAknLayoutFont* CFSEmailUiMailViewerRichText::CurrentTitleFontLC()
+ {
+ FUNC_LOG;
+ TAknLogicalFontId logicalFontId = iAppUi.LayoutHandler()->ViewerTitleFontAknLogicalFontId();
+ TAknFontSpecification spec( logicalFontId );
+ TInt heightInPixels = iAppUi.LayoutHandler()->ViewerTitleFontHeight();
+ spec.SetTextPaneHeight( heightInPixels );
+ CWsScreenDevice* dev = CCoeEnv::Static()->ScreenDevice();
+ CAknLayoutFont* font = AknFontAccess::CreateLayoutFontFromSpecificationL( *dev, spec );
+ CleanupStack::PushL( font );
+ return font;
+ }
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::CurrentTextFontLC
+// -----------------------------------------------------------------------------
+CAknLayoutFont* CFSEmailUiMailViewerRichText::CurrentTextFontLC()
+ {
+ FUNC_LOG;
+ TAknLogicalFontId logicalFontId = iAppUi.LayoutHandler()->ViewerTextFontAknLogicalFontId();
+ TAknFontSpecification spec( logicalFontId );
+ TInt heightInPixels = iAppUi.LayoutHandler()->ViewerTextFontHeight();
+ spec.SetTextPaneHeight( heightInPixels );
+ CWsScreenDevice* dev = CCoeEnv::Static()->ScreenDevice();
+ CAknLayoutFont* font = AknFontAccess::CreateLayoutFontFromSpecificationL( *dev, spec );
+ CleanupStack::PushL( font );
+ return font;
+ }
+*/
+
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::CurrentTitleFontL
+// -----------------------------------------------------------------------------
+const CAknLayoutFont* CFSEmailUiMailViewerRichText::CurrentTitleFontL() const
+ {
+ FUNC_LOG;
+ TRect mainPaneRect;
+ AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EMainPane, mainPaneRect);
+
+ TAknLayoutRect cmailPaneRect;
+ cmailPaneRect.LayoutRect(mainPaneRect, AknLayoutScalable_Apps::list_cmail_pane());
+
+ TAknLayoutRect labelRect;
+ labelRect.LayoutRect(cmailPaneRect.Rect(), AknLayoutScalable_Apps::list_single_cmail_header_caption_pane());
+
+ TAknLayoutText layoutText;
+ layoutText.LayoutText(labelRect.Rect(), AknLayoutScalable_Apps::list_single_cmail_header_caption_pane_t1());
+
+ const CAknLayoutFont* font = CAknLayoutFont::AsCAknLayoutFontOrNull( layoutText.Font() );
+
+ //All fonts must be loaded properly? Leave if something is failing.
+ if(NULL == font)
+ User::Leave(KErrGeneral);
+
+ return font;
+
+ }
+
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::CurrentTextFontL
+// -----------------------------------------------------------------------------
+const CAknLayoutFont* CFSEmailUiMailViewerRichText::CurrentTextFontL() const
+ {
+ FUNC_LOG;
+ TRect mainPaneRect;
+ AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EMainPane, mainPaneRect);
+
+ TAknLayoutRect cmailPaneRect;
+ cmailPaneRect.LayoutRect(mainPaneRect, AknLayoutScalable_Apps::list_cmail_pane());
+
+ //Using variety 0 -> 1 row line by default
+ TAknLayoutRect labelRect;
+ labelRect.LayoutRect(cmailPaneRect.Rect(), AknLayoutScalable_Apps::list_single_cmail_header_detail_pane( 0 ));
+
+ TAknLayoutText layoutText;
+ layoutText.LayoutText(labelRect.Rect(), AknLayoutScalable_Apps::list_single_cmail_header_detail_pane_t1( 0 ));
+
+ const CAknLayoutFont* font = CAknLayoutFont::AsCAknLayoutFontOrNull( layoutText.Font() );
+
+ //All fonts must be loaded properly? Leave if something is failing.
+ if(NULL == font)
+ User::Leave(KErrGeneral);
+
+ return font;
+
+ }
+
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::CurrentSentTextFontLC
+// -----------------------------------------------------------------------------
+const CAknLayoutFont* CFSEmailUiMailViewerRichText::CurrentSentTextFontL() const
+ {
+ return CurrentTitleFontL();
+ }
+//</cmail>
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::CurrentSpacingHeight
+// -----------------------------------------------------------------------------
+TInt CFSEmailUiMailViewerRichText::CurrentSpacingHeight( TViewerSpacingIconType aSpacingIconType ) const
+ {
+ FUNC_LOG;
+ TInt heightInPixels = 0;
+ switch( aSpacingIconType )
+ {
+ case ETopMostSpace:
+ {
+ heightInPixels = iAppUi.LayoutHandler()->ViewerTopMostSpaceHeight();
+ }
+ break;
+ case ERecipientSpace:
+ {
+ heightInPixels = iAppUi.LayoutHandler()->ViewerRecipientSpaceHeight();
+ }
+ break;
+ case EHeaderInfoSpace:
+ {
+ heightInPixels = iAppUi.LayoutHandler()->ViewerHeaderInfoSpaceHeight();
+ }
+ break;
+ case EBottomMostSpace:
+ {
+ heightInPixels = iAppUi.LayoutHandler()->ViewerBottomMostSpaceHeight();
+ }
+ break;
+ }
+ return heightInPixels;
+ }
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::InsertTransparentSpacingIconL
+// -----------------------------------------------------------------------------
+void CFSEmailUiMailViewerRichText::InsertTransparentSpacingIconL( TViewerSpacingIconType aSpacingIconType )
+ {
+ FUNC_LOG;
+ TInt currentSpace = CurrentSpacingHeight( aSpacingIconType );
+ TInt fontSide = 0;
+ switch ( aSpacingIconType )
+ {
+ case ETopMostSpace:
+ case EBottomMostSpace:
+ {
+ TInt currentTextHeight = iAppUi.LayoutHandler()->ViewerTitleFontHeight();
+ fontSide = currentSpace - currentTextHeight;
+ }
+ break;
+ case ERecipientSpace:
+ {
+ TInt currentTextHeight = iAppUi.LayoutHandler()->ViewerTextFontHeight();
+ fontSide = currentSpace - currentTextHeight;
+ }
+ break;
+ case EHeaderInfoSpace:
+ {
+ TInt currentTextHeight = iAppUi.LayoutHandler()->ViewerTitleFontHeight();
+ fontSide = currentSpace - currentTextHeight;
+ }
+ break;
+ }
+ iCurrentSpacingIconSize.SetSize( fontSide, fontSide );
+
+ UpdateIconL( EViewerIconSpacing );
+
+ // Add extra space before line ending so that we can modify the line height
+ AppendSpaceL();
+
+ AppendNewLineL();
+ iHeaderLineInfo.iHeaderLineCount++;
+
+ // to make the icon need less space.
+ TCharFormat charFormat;
+ TCharFormatMask charFormatMask;
+ charFormat.iFontSpec.iHeight = CEikonEnv::Static()->ScreenDevice()->VerticalPixelsToTwips( fontSide );
+ charFormat.iFontPresentation.iUnderline = EUnderlineOff;
+ charFormatMask.SetAttrib( EAttFontHeight );
+ charFormatMask.SetAttrib( EAttFontUnderline );
+ iViewerRichText->ApplyCharFormatL( charFormat, charFormatMask, iViewerRichText->DocumentLength() - 3, 3 );
+ }
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::InsertSpaceAfterIconL
+// -----------------------------------------------------------------------------
+void CFSEmailUiMailViewerRichText::InsertSpaceAfterIconL()
+ {
+ FUNC_LOG;
+ TInt spaceInPixels = iAppUi.LayoutHandler()->ViewerPixelsBetweenMsgStatusIconAndSubject();
+ iCurrentSpacingIconSize.SetSize( spaceInPixels, spaceInPixels );
+ UpdateIconL( EViewerIconSpacing );
+ }
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::InsertHotspotTextAndFontL
+// -----------------------------------------------------------------------------
+void CFSEmailUiMailViewerRichText::InsertHotspotTextAndFontL( const TDesC& aText )
+ {
+ FUNC_LOG;
+ AppendFormattedTextL( aText, EViewerFontHotspotNormal );
+ }
+
+// -----------------------------------------------------------------------------
+// Appends formatted text to the rich text
+// -----------------------------------------------------------------------------
+void CFSEmailUiMailViewerRichText::AppendFormattedTextL( const TDesC& aText,
+ TViewerFontType aFontType )
+ {
+ FUNC_LOG;
+ iRichTextDocumentLength = iViewerRichText->DocumentLength();
+ InsertFormattedTextL( aText, aFontType, iRichTextDocumentLength );
+ }
+
+// -----------------------------------------------------------------------------
+// Inserts formatted text to the rich text
+// -----------------------------------------------------------------------------
+void CFSEmailUiMailViewerRichText::InsertFormattedTextL( const TDesC& aText,
+ TViewerFontType aFontType, TInt aPosition )
+ {
+ FUNC_LOG;
+ ASSERT( aPosition >= 0 );
+ ASSERT( aPosition <= iViewerRichText->DocumentLength() );
+
+ // Insert text at given position
+ iViewerRichText->InsertL( aPosition, aText );
+
+ //<cmail>
+ const CAknLayoutFont* newFont = GetCorrectFontL( aFontType );
+
+ TRgb fontColor = SkinFontColorByType( aFontType );
+ TFontUnderline underline = EUnderlineOff;
+ if ( aFontType == EViewerFontHotspotNormal )
+ {
+ underline = EUnderlineOn;
+ }
+
+ ApplyFontToTextL( newFont, aPosition, aText.Length(), fontColor, underline );
+ //</cmail>
+ }
+
+//<cmail>
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::ApplyFontToTextL
+// -----------------------------------------------------------------------------
+void CFSEmailUiMailViewerRichText::ApplyFontToTextL( const CAknLayoutFont* aFont,
+ TInt aStartInx,
+ TInt aLength,
+ TRgb& aColor,
+ TFontUnderline aUnderline )
+ {
+ FUNC_LOG;
+ TCharFormat charFormat;
+ TCharFormatMask charFormatMask;
+ charFormat.iFontSpec = aFont->FontSpecInTwips();
+ // Applies antialiasing for all text in mail viewer.
+ charFormat.iFontSpec.iFontStyle.SetBitmapType( EAntiAliasedGlyphBitmap );
+ charFormat.iFontPresentation.iTextColor = aColor;
+ charFormat.iFontPresentation.iUnderline = aUnderline;
+ charFormatMask.SetAll();
+ iViewerRichText->ApplyCharFormatL( charFormat, charFormatMask, aStartInx, aLength );
+ }
+//</cmail>
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::AddBodyHotsSpotWithTextFormatingL
+// -----------------------------------------------------------------------------
+void CFSEmailUiMailViewerRichText::AddBodyHotsSpotWithTextFormatingL( const CFindItemEngine::SFoundItem& aBodyHotSpotData )
+ {
+ FUNC_LOG;
+ iViewerRichText->SetHotSpotL( aBodyHotSpotData.iStartPos + iHeaderLength,
+ aBodyHotSpotData.iLength, KHotspotHighlightOn );
+
+ // add underlining and right color the the hotspots
+ //<cmail>
+ const CAknLayoutFont* newFont = GetCorrectFontL( EViewerFontText );
+ TRgb fontColor = SkinFontColorByType( EViewerFontHotspotNormal );
+
+ TFontUnderline underline = EUnderlineOn;
+ ApplyFontToTextL( newFont, aBodyHotSpotData.iStartPos + iHeaderLength,
+ aBodyHotSpotData.iLength, fontColor, underline );
+ //</cmail>
+
+ }
+
+// <cmail> separator line
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::AppendSeparatorLineL
+// Append attachement(s) line to the rich text.
+// -----------------------------------------------------------------------------
+void CFSEmailUiMailViewerRichText::AppendSeparatorLineL()
+ {
+ FUNC_LOG;
+ UpdateIconL( EViewerIconSeparatorLine );
+ }
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMailViewerRichText::SeparatorLineWidth
+// -----------------------------------------------------------------------------
+TInt CFSEmailUiMailViewerRichText::SeparatorLineWidth() const
+ {
+ FUNC_LOG;
+ // For some reason, the ratioanally calculated text width seems to be a bit
+ // wider than the width where GenericTextViewer does line wrapping. Reserve
+ // some extra pixels to overcome this. Maybe there is some difference in
+ // the ways the text width is calculated?
+ const TInt KExtraPixels( 10 );
+
+ TRect screenRect = iTextViewer->GetControl()->DisplayArea();
+ TInt scrollBarBreadth = CEikScrollBar::DefaultScrollBarBreadth();
+
+ // Calculate space left for actual text
+ TInt rightMargin = iAppUi.LayoutHandler()->ViewerRightMarginInPixels() + scrollBarBreadth;
+ TInt leftMargin = iAppUi.LayoutHandler()->ViewerLeftMarginInPixels();
+ TInt widthInPixels = screenRect.iBr.iX - rightMargin - leftMargin - KExtraPixels;
+
+ return widthInPixels;
+ }
+
+// </cmail> separator line
+
+// End of the file
+