emailuis/emailui/src/FreestyleEmailUiMailViewerRichText.cpp
changeset 0 8466d47a6819
child 1 12c456ceeff2
--- /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
+