--- a/emailuis/emailui/src/FreestyleEmailUiHtmlViewerContainer.cpp Thu Jan 07 12:38:38 2010 +0200
+++ b/emailuis/emailui/src/FreestyleEmailUiHtmlViewerContainer.cpp Mon Jan 18 20:08:26 2010 +0200
@@ -21,13 +21,13 @@
#include <coemain.h>
#include <commdbconnpref.h>
#include <bautils.h>
-
+#include <biditext.h>
//<cmail>
#include "CFSMailMessage.h"
//</cmail>
#include <brctlinterface.h>
#include <sysutil.h>
-
+#include <SchemeHandler.h>
#include "FreestyleEmailUiAppui.h"
#include "FreestyleEmailUiUtilities.h"
@@ -47,10 +47,10 @@
_LIT( KHeaderHtmlFile, "header.html" );
_LIT( KBodyHtmlFile, "body.html" );
_LIT( KMessageHtmlFile, "email.html" );
+_LIT( KMessageHtmlRTLFile, "email_rtl.html" );
_LIT( KZDrive, "z:" );
_LIT( KHtmlFlagFile, "html.flag" );
-
-// <cmail>
+_LIT( KURLSlash, "/");
// Constants used in html content modification
const TInt KMaxCharsToSearch( 200 );
_LIT8( KStartTag, "<html" );
@@ -64,7 +64,32 @@
_LIT8( KHTMLEmptyContent, "<HTML><BODY></BODY></HTML>");
_LIT( KHTMLDataScheme, "data:0");
-// </cmail>
+
+_LIT8( KHtmlLineBreak, "<br>" );
+_LIT8( KHtmlLineBreakCRLF, "<br>\xD\xA" );
+_LIT8( KHtmlLessThan, "<" );
+_LIT8( KHtmlGreaterThan, ">" );
+_LIT8( KHtmlAmpersand, "&" );
+_LIT8( KHtmlQuotation, """ );
+_LIT8( KHtmlLinkTag, "<a href=\"%S\">" );
+_LIT8( KHtmlLinkEndTag, "</a>" );
+_LIT( KURLTypeBody, "body");
+
+const TText8 KGreaterThan = 0x3e;
+const TText8 KLessThan = 0x3c;
+const TText8 KAmpersand = 0x26;
+const TText8 KQuotation = 0x22;
+const TText8 KCharacterSpace = 0x20;
+const TText8 KSOH = 0x01; // Start Of Heading
+const TText8 KCR = 0x0d; // Carriage Return
+const TText8 KLF = 0x0a; // Line Feed
+const TText8 KHT = 0x09; // Horizontal Tab
+const TReal KOverlayButtonMarginX = 0.01; // 1%
+const TReal KOverlayButtonMarginY = 0.01; // 1%
+const TReal KOverlayButtonSizeP = 0.15; // 15%
+const TReal KOverlayButtonSizeLs = 0.20; // 25%
+const TReal KOverlayButtonPosP = 0.88;
+const TReal KOverlayButtonPosLs = 0.85;
// ---------------------------------------------------------------------------
// Two-phased constructor.
@@ -115,6 +140,9 @@
delete iBrCtlInterface;
iConnection.Close();
iSocketServer.Close();
+
+ delete iOverlayControlNext;
+ delete iOverlayControlPrev;
}
// <cmail> Because of browser changes, followings must be performed before iAppUi.exit()
@@ -145,8 +173,7 @@
EnsureHTMLResourceL();
CreateWindowL();
- SetRect( iAppUi.ClientRect() );
-
+ SetRect( iView.ContainerRect() );
TUint brCtlCapabilities = TBrCtlDefs::ECapabilityClientResolveEmbeddedURL |
TBrCtlDefs::ECapabilityDisplayScrollBar |
@@ -167,9 +194,102 @@
iBrCtlInterface->SetBrowserSettingL( TBrCtlDefs::ESettingsFontSize, TBrCtlDefs::EFontSizeLevelLarger );
iEventHandler = CFreestyleMessageHeaderURLEventHandler::NewL( iAppUi, iView );
+
+ TRect nextButtonRect = OverlayButtonRect( EFalse );
+ iOverlayControlNext = COverlayControl::NewL( this, this, nextButtonRect,
+ EMbmFreestyleemailuiQgn_indi_cmail_arrow_next,
+ EMbmFreestyleemailuiQgn_indi_cmail_arrow_next_mask );
+
+ TRect prevButtonRect = OverlayButtonRect( ETrue );
+ iOverlayControlPrev = COverlayControl::NewL( this, this, prevButtonRect,
+ EMbmFreestyleemailuiQgn_indi_cmail_arrow_previous,
+ EMbmFreestyleemailuiQgn_indi_cmail_arrow_previous_mask );
+ iScrollPosition = 0;
ActivateL();
}
+void CFsEmailUiHtmlViewerContainer::MakeVisible( TBool aVisible )
+ {
+ UpdateOverlayButtons( aVisible );
+ CCoeControl::MakeVisible( aVisible );
+ }
+
+void CFsEmailUiHtmlViewerContainer::HandleOverlayPointerEventL( COverlayControl* aControl,
+ const TPointerEvent& aEvent )
+ {
+ if( aEvent.iType == TPointerEvent::EButton1Up )
+ {
+ if( aControl == iOverlayControlNext )
+ {
+ iView.HandleCommandL( EFsEmailUiCmdNextMessage );
+ }
+ else if( aControl == iOverlayControlPrev )
+ {
+ iView.HandleCommandL( EFsEmailUiCmdPreviousMessage );
+ }
+ }
+ }
+
+void CFsEmailUiHtmlViewerContainer::UpdateOverlayButtons( TBool aVisible )
+ {
+ TBool nextAvailable = EFalse;
+ TBool prevAvailable = EFalse;
+ if( iMessage )
+ {
+ TFSMailMsgId currentMsgId = iMessage->GetMessageId();
+ TFSMailMsgId tmpMsgId;
+ TFSMailMsgId tmpMsgFolderId;
+ nextAvailable = iAppUi.IsNextMsgAvailable( currentMsgId, tmpMsgId, tmpMsgFolderId );
+ prevAvailable = iAppUi.IsPreviousMsgAvailable( currentMsgId, tmpMsgId, tmpMsgFolderId );
+ }
+
+ if( iOverlayControlPrev )
+ {
+ iOverlayControlPrev->SetRect( OverlayButtonRect( ETrue ) );
+ iOverlayControlPrev->MakeVisible( aVisible && prevAvailable );
+ }
+ if( iOverlayControlNext )
+ {
+ iOverlayControlNext->SetRect( OverlayButtonRect( EFalse ) );
+ iOverlayControlNext->MakeVisible( aVisible && nextAvailable );
+ }
+ }
+
+// Get rect for button
+TRect CFsEmailUiHtmlViewerContainer::OverlayButtonRect( TBool aLeft )
+ {
+ TRect rect = Rect();
+ TSize size = rect.Size();
+
+ TBool landscape = size.iWidth > size.iHeight;
+ TInt buttonSize;
+
+ if( landscape )
+ {
+ buttonSize = size.iHeight * KOverlayButtonSizeLs;
+ }
+ else
+ {
+ buttonSize = size.iWidth * KOverlayButtonSizeP;
+ }
+
+ rect.iBr.iY = size.iHeight * (1-KOverlayButtonMarginY);
+
+ if( aLeft )
+ {
+ rect.iTl.iX = size.iWidth * KOverlayButtonMarginX;
+ rect.iBr.iX = rect.iTl.iX + buttonSize;
+ }
+ else
+ {
+ rect.iBr.iX = size.iWidth * (1 - KOverlayButtonMarginX);
+ rect.iTl.iX = rect.iBr.iX - buttonSize;
+ }
+
+ rect.iTl.iY = rect.iBr.iY - buttonSize;
+ return rect;
+ }
+
// Getter for br contro, interface
CBrCtlInterface* CFsEmailUiHtmlViewerContainer::BrowserControlIf()
{
@@ -200,11 +320,14 @@
// ---------------------------------------------------------------------------
//
void CFsEmailUiHtmlViewerContainer::LoadContentFromMailMessageL(
- CFSMailMessage* aMailMessage )
+ CFSMailMessage* aMailMessage, TBool aResetScrollPos )
{
FUNC_LOG;
ASSERT( aMailMessage );
iMessage = aMailMessage;
+ // Cancel any browser fetch operation, just in case the browser is still
+ // loading a previous message (since we are about to overwrite it).
+ CancelFetch();
TPath headerHtmlFile;
headerHtmlFile.Copy( iHtmlFolderPath );
@@ -213,7 +336,15 @@
// insert email header into email.html file
// CFreestyleMessageHeaderHTML will replace contents of email.html
// So, no need to clear the contents
- CFreestyleMessageHeaderHTML::ExportL( *iMessage, iFs, headerHtmlFile, iAppUi.ClientRect().Width() );
+ TLanguage language = User::Language();
+ TBidiText::TDirectionality direction = TBidiText::ScriptDirectionality( language );
+ if(aResetScrollPos)
+ {
+ iScrollPosition = 0;
+ }
+ CFreestyleMessageHeaderHTML::ExportL( *iMessage, iFs, headerHtmlFile, iAppUi.ClientRect().Width(),
+ iScrollPosition,
+ direction);
// Remove all previously created files from temporary HTML folder
EmptyTempHtmlFolderL();
@@ -262,16 +393,24 @@
CleanupStack::PopAndDestroy( contentBuffer );
CleanupStack::PopAndDestroy( textBodyPart );
}
-
}
// pass the emailHtmlFile to the browser for it to load
if ( bodyPartAvailable )
{
TPath emailHtmlFile;
emailHtmlFile.Copy( iHtmlFolderPath );
- emailHtmlFile.Append( KMessageHtmlFile );
+ if ( direction == TBidiText::ELeftToRight )
+ {
+ emailHtmlFile.Append( KMessageHtmlFile );
+ }
+ else
+ {
+ emailHtmlFile.Append( KMessageHtmlRTLFile );
+ }
LoadContentFromFileL( emailHtmlFile );
}
+
+ UpdateOverlayButtons( ETrue );
}
// ---------------------------------------------------------------------------
@@ -347,11 +486,30 @@
void CFsEmailUiHtmlViewerContainer::SizeChanged()
{
FUNC_LOG;
+
+ TRect rect = Rect();
if ( iBrCtlInterface )
{
- TRect rect = Rect();
iBrCtlInterface->SetRect( rect );
}
+
+ if ( iMessage )
+ {
+ // update the width in header part and reload
+ TPath headerHtmlFile;
+ headerHtmlFile.Copy( iHtmlFolderPath );
+ headerHtmlFile.Append( KHeaderHtmlFile );
+
+ TRAP_IGNORE( CFreestyleMessageHeaderHTML::ExportL( *iMessage, iFs, headerHtmlFile,
+ rect.Width(), iScrollPosition ) )
+
+ TPath emailHtmlFile;
+ emailHtmlFile.Copy( iHtmlFolderPath );
+ emailHtmlFile.Append( KMessageHtmlFile );
+ TRAP_IGNORE( LoadContentFromFileL( emailHtmlFile ) )
+ }
+
+ UpdateOverlayButtons( IsVisible() );
}
// ---------------------------------------------------------------------------
@@ -490,6 +648,8 @@
if ( iMessage )
{
LoadContentFromMailMessageL( iMessage );
+
+ UpdateOverlayButtons( ETrue );
}
}
else if ( aEvent.iProgressStatus == TFSProgress::EFSStatus_RequestCancelled ||
@@ -554,7 +714,23 @@
const TDesC& /*aCurrentUrl*/, MBrCtlLinkContent& /*aBrCtlLinkContent*/ )
{
FUNC_LOG;
- return iEventHandler->HandleEventL( aUrl );
+ if (IsMessageBodyURL(aUrl))
+ {
+ iView.StartFetchingMessageL();
+ return ETrue;
+ }
+ else
+ {
+ if ( NeedToLaunchBrowserL( aUrl ) )
+ {
+ LaunchBrowserL( aUrl );
+ return ETrue;
+ }
+ else
+ {
+ return iEventHandler->HandleEventL( aUrl );
+ }
+ }
}
// ---------------------------------------------------------------------------
@@ -987,9 +1163,11 @@
//
// <cmail>
void CFsEmailUiHtmlViewerContainer::ConvertToHTML( const TDesC8& aContent,
- const TDesC& aFileName, CFSMailMessagePart& aHtmlBodyPart )
+ const TDesC& aFileName, CFSMailMessagePart& aTextBodyPart )
{
FUNC_LOG;
+ const TInt KBodyTextChunkSizeBytes = 1024;
+
if ( SysUtil::DiskSpaceBelowCriticalLevelL( &iFs, aContent.Size(), EDriveC ) )
{
// Can not write the data, there's not enough free space on disk.
@@ -997,49 +1175,334 @@
}
else
{
+ CBufBase* bodyBuf = CBufSeg::NewL( KBodyTextChunkSizeBytes );
+ CleanupStack::PushL( bodyBuf );
+
+ bodyBuf->InsertL( 0, aContent );
+
+ TInt position( 0 );
+ TText8 previous = 0;
+ TBool EndOfString( EFalse );
+
+ while ( !EndOfString )
+ {
+ TInt startPosition = position;
+ TPtr8 segment( bodyBuf->Ptr( startPosition ) );
+ int i = 0;
+
+ while(i < segment.Length())
+ {
+ TInt currentPos = position + i;
+ TText8 ch = segment[i];
+
+ switch( ch )
+ {
+ case KSOH: // end of line for IMAP and POP
+ bodyBuf->Delete( currentPos, 1 );
+ bodyBuf->InsertL( currentPos, KHtmlLineBreakCRLF );
+ i += KHtmlLineBreakCRLF().Length();
+ segment.Set( bodyBuf->Ptr( startPosition ) );
+ break;
+ case KLF: // line feed
+ if ( previous == KCR )
+ {
+ bodyBuf->InsertL( currentPos, KHtmlLineBreak );
+ i += KHtmlLineBreak().Length();
+ segment.Set( bodyBuf->Ptr( startPosition ) );
+ }
+ else
+ {
+ i++;
+ }
+ break;
+ case KQuotation:
+ bodyBuf->Delete( currentPos, 1 );
+ bodyBuf->InsertL( currentPos, KHtmlQuotation );
+ i += KHtmlQuotation().Length();
+ segment.Set( bodyBuf->Ptr( startPosition ) );
+ break;
+ case KAmpersand:
+ bodyBuf->Delete( currentPos, 1 );
+ bodyBuf->InsertL( currentPos, KHtmlAmpersand );
+ i += KHtmlAmpersand().Length();
+ segment.Set( bodyBuf->Ptr( startPosition ) );
+ break;
+ case KGreaterThan:
+ bodyBuf->Delete( currentPos, 1 );
+ bodyBuf->InsertL( currentPos, KHtmlGreaterThan );
+ i += KHtmlGreaterThan().Length();
+ segment.Set( bodyBuf->Ptr( startPosition ) );
+ break;
+ case KLessThan:
+ bodyBuf->Delete( currentPos, 1 );
+ bodyBuf->InsertL( currentPos, KHtmlLessThan );
+ i += KHtmlLessThan().Length();
+ segment.Set( bodyBuf->Ptr( startPosition ) );
+ break;
+ default:
+ i++;
+ break;
+ }
+ previous = ch;
+ }
+ position += segment.Length();
+ if ( ( bodyBuf->Size() - position ) <= 0 )
+ {
+ EndOfString = ETrue;
+ }
+ }
+
+ CreateHyperlinksFromUrlsL( *bodyBuf );
+
RFile targetFile;
CleanupClosePushL( targetFile );
-
User::LeaveIfError( targetFile.Replace( iFs, aFileName, EFileWrite ) );
- HBufC8* charSet = GetCharacterSetL( aHtmlBodyPart );
+ HBufC8* charSet = GetCharacterSetL( aTextBodyPart );
CleanupStack::PushL( charSet );
- User::LeaveIfError( targetFile.Write( KHtmlHeader1 ) );
- User::LeaveIfError( targetFile.Write( *charSet ) );
- User::LeaveIfError( targetFile.Write( KHtmlHeader2 ) );
+ RBuf8 messageHeader;
+ TInt bufSize = KHtmlHeader1().Length() + charSet->Length() + KHtmlHeader2().Length();
+ messageHeader.CreateL( bufSize );
+ messageHeader.CleanupClosePushL();
+
+ messageHeader.Append( KHtmlHeader1 );
+ messageHeader.Append( *charSet );
+ messageHeader.Append( KHtmlHeader2 );
+
+ RFileWriteStream fileStream( targetFile );
+ fileStream.PushL();
+ fileStream.WriteL( messageHeader.Ptr(), messageHeader.Length() );
+
+ TInt bufPos( 0 );
+ TInt bufTotalSize = bodyBuf->Size();
+
+ while ( bufPos < bufTotalSize )
+ {
+ TInt segmentLength = bodyBuf->Ptr( bufPos ).Length();
+ fileStream.WriteL( bodyBuf->Ptr( bufPos ).Ptr(), segmentLength );
+ bufPos += segmentLength;
+ }
+
+ fileStream.CommitL();
+
+ CleanupStack::PopAndDestroy( &fileStream );
+ CleanupStack::PopAndDestroy( &messageHeader );
CleanupStack::PopAndDestroy( charSet );
-
+ CleanupStack::PopAndDestroy( &targetFile );
+ CleanupStack::PopAndDestroy( bodyBuf );
- // Write the original content
- for(int i=0;i<aContent.Length();i++)
- {
- if( i==aContent.Length()-1 )
- {
- aContent.Mid( i,1 ).CompareC( _L8("\x01" ) )==0 ?
- User::LeaveIfError( targetFile.Write( _L8("<br>") ) ):
- User::LeaveIfError( targetFile.Write( aContent.Mid(i,1) ) );
+// </cmail>
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// Finds and html formats hyperlinks in a document
+// ---------------------------------------------------------------------------
+//
+// <cmail>
+void CFsEmailUiHtmlViewerContainer::CreateHyperlinksFromUrlsL( CBufBase& aSource )
+ {
+ FUNC_LOG;
+ const TInt urlMaxLength = 2048;
+ _LIT8( KHttp, "http://" );
+ _LIT8( KHttps, "https://");
+ _LIT8( KWww, "www.");
+
+ TBool eos( EFalse );
+ TInt position( 0 );
+ TInt carryOverInc( 0 );
+
+ while ( !eos )
+ {
+ while ( carryOverInc >= aSource.Ptr( position ).Length() )
+ { // Skip segments of overlapping url string
+ carryOverInc -= aSource.Ptr( position ).Length();
+ position += aSource.Ptr( position ).Length();
}
- else
+
+ TPtr8 segment( aSource.Ptr( position ) );
+ TLex8 lexSegment( segment );
+ lexSegment.Inc( carryOverInc );
+ carryOverInc = 0;
+
+ while (!lexSegment.Eos())
{
- if(aContent.Mid( i,1 ).CompareC( _L8("\x01" ) )==0 ||
- aContent.Mid( i,2 ).CompareC( _L8("\x0D\x0A" ) )==0 )
- {
- User::LeaveIfError( targetFile.Write( _L8("<br>") ));
- }
- else
- {
- User::LeaveIfError( targetFile.Write( aContent.Mid(i,1) ) );
+ TPtrC8 nextToken( lexSegment.NextToken() );
+ TInt foundAt( KErrNotFound );
+
+ // Find HTTP, HTTPS, or WWW link in CBufSeg segment of size 1024 bytes.
+ if ( ( ( foundAt = nextToken.FindC( KHttp ) ) != KErrNotFound ) ||
+ ( ( foundAt = nextToken.FindC( KHttps ) ) != KErrNotFound ) ||
+ ( ( foundAt = nextToken.FindC( KWww ) ) != KErrNotFound ) )
+ {
+ if ( !lexSegment.Eos() )
+ {
+ if ( !foundAt )
+ { // Token starts with http/https/www.x
+ TPtrC8 url;
+ TInt lineBreakPos( KErrNotFound );
+ if ( ( lineBreakPos = nextToken.FindC( KHtmlLineBreak ) ) != KErrNotFound )
+ { // Token contains html line break -> remove
+ url.Set( nextToken.Left( lineBreakPos ) );
+ }
+ else
+ {
+ url.Set( nextToken );
+ }
+
+ if ( url.CompareC( KWww ) != KErrNone ) // if token=www., validate format
+ { // www.x
+ RBuf8 urlBuf;
+ urlBuf.CreateL( KHtmlLinkTag().Length() + url.Length() * 2
+ + KHtmlLinkEndTag().Length() + KHtmlLineBreak().Length() );
+ urlBuf.CleanupClosePushL();
+ // Format html link
+ urlBuf.AppendFormat( KHtmlLinkTag, &url );
+ urlBuf.Append( url );
+ urlBuf.Append( KHtmlLinkEndTag );
+ if ( lineBreakPos != KErrNotFound )
+ { // Add line break if removed earlier
+ urlBuf.Append( KHtmlLineBreak );
+ }
+ //Test
+ TInt nextTokenLength = nextToken.Length();
+ TInt segOffset = lexSegment.Offset();
+ TInt urlLength = urlBuf.Length();
+
+ //Test
+ TInt offset = lexSegment.Offset() - nextToken.Length();
+ TLexMark8 tokenMark;
+ // Move next character last token back
+ lexSegment.Inc( - nextToken.Length() );
+ lexSegment.Mark( tokenMark );
+ aSource.Delete( offset + position, nextToken.Length() );
+ aSource.InsertL( offset + position, urlBuf );
+ segment.Set( aSource.Ptr( position ) );
+ lexSegment.Assign( segment );
+ // Set next character to the position of inserted hyperlink
+ lexSegment.UnGetToMark( tokenMark );
+
+ // If Max segment length is reached, set carry over value to
+ // properly set next character in following CBufSeg segment
+ if ( ( offset + urlBuf.Length() ) >= segment.Length() )
+ {
+ carryOverInc = offset + urlBuf.Length() - segment.Length();
+ while ( !lexSegment.Eos() )
+ { // Set to segment's end
+ lexSegment.NextToken();
+ }
+ }
+ else
+ {
+ lexSegment.Inc( urlBuf.Length() );
+ }
+
+ CleanupStack::PopAndDestroy( &urlBuf );
+ }
+ }
+ }
+ else
+ // Next token is end of string, here we handle the last token of a segment
+ {
+ _LIT8( KUrlEnd, "<" );
+
+ TInt endOfUrlPos( KErrNotFound );
+ TText8 ch = segment[ segment.Length() - 1];
+ RBuf8 url;
+ url.CreateL( urlMaxLength );
+ url.CleanupClosePushL();
+
+ // Find if hyperlink ends within this segment boundaries
+ if ( ch == KSOH || ch == KCR || ch == KLF || ch == KHT || ch == KCharacterSpace )
+ {
+ endOfUrlPos = nextToken.Length() - 1;
+ }
+ else if ( ( endOfUrlPos = nextToken.Right( KHtmlLineBreak().Length() ).Find( KUrlEnd ) ) != KErrNotFound )
+ {
+ endOfUrlPos = nextToken.Length() - KHtmlLineBreak().Length() + endOfUrlPos;
+ }
+ else
+ { // Handle hyperlink spread in multiple segments
+ TInt nextPos = position;
+ TPtrC8 nextSegment( aSource.Ptr( nextPos ) );
+ TLex8 lexNextSegment( nextSegment );
+ TPtrC8 nextNextToken( nextToken );
+ TBool firstPass( ETrue );
+
+ while ( endOfUrlPos == KErrNotFound || nextPos >= aSource.Size() )
+ {
+ if ( ( url.Length() + nextNextToken.Length() ) > urlMaxLength )
+ { // URL exceeds limit of 2K, do nothing
+ break;
+ }
+
+ url.Append( nextNextToken );
+ if ( ( nextSegment.Length() == nextNextToken.Length() ) || firstPass )
+ { // Token takes up the whole segment, or first pass( first segment
+ // with last token where hyperlink does not end within segment's
+ // boundaries, move to next segment
+ nextPos += nextSegment.Length();
+ nextSegment.Set( aSource.Ptr( nextPos ) );
+ lexNextSegment.Assign( nextSegment );
+ nextNextToken.Set( lexNextSegment.NextToken() );
+ if ( firstPass )
+ {
+ firstPass = EFalse;
+ }
+ }
+ else
+ { // Last segment's token with hyperlink's end
+ if ( ( endOfUrlPos = url.Find( KHtmlLineBreak ) ) != KErrNotFound )
+ { // Remove line break
+ url.Delete( endOfUrlPos, KHtmlLineBreak().Length() );
+ endOfUrlPos = nextNextToken.Length() - KHtmlLineBreak().Length();
+ }
+ else
+ {
+ endOfUrlPos = nextNextToken.Length();
+ }
+ }
+ }
+
+ if ( endOfUrlPos != KErrNotFound )
+ { // Handle hyperlink that is within 2K limit
+ RBuf8 urlBuf;
+ urlBuf.CreateL( KHtmlLinkTag().Length() + url.Length() * 2
+ + KHtmlLinkEndTag().Length() + KHtmlLineBreak().Length() );
+ urlBuf.CleanupClosePushL();
+ // Format html link
+ urlBuf.AppendFormat( KHtmlLinkTag, &url );
+ urlBuf.Append( url );
+ urlBuf.Append( KHtmlLinkEndTag );
+ urlBuf.Append( KHtmlLineBreak );
+
+ TInt offset = lexSegment.Offset() - nextToken.Length();
+ // Remove hyperlink from the original message body
+ aSource.Delete( offset + position, url.Length() );
+ // Insert html formated hyperlink
+ aSource.InsertL( offset + position, urlBuf );
+ segment.Set( aSource.Ptr( position ) );
+
+ // Set carry on value to mark where new token should start in following segment
+ carryOverInc = endOfUrlPos;
+ position = nextPos;
+
+ CleanupStack::PopAndDestroy( &urlBuf );
+ }
+ }
+ CleanupStack::PopAndDestroy( &url );
+ }
}
- }
}
- INFO("Add end tags");
- User::LeaveIfError( targetFile.Write( KHtmlEndTags ) );
-
+ position += segment.Length();
+ if ( ( aSource.Size() - position ) <= 0 )
+ {
+ eos = ETrue;
+ }
+ }
- CleanupStack::PopAndDestroy( &targetFile );
- }
-// </cmail>
+
}
@@ -1076,6 +1539,7 @@
CleanupStack::Pop( charSet );
return charSet;
}
+
void CFsEmailUiHtmlViewerContainer::StopObserving()
{
if( iObservingDownload )
@@ -1116,22 +1580,189 @@
if ( aType == CFsEmailUiViewBase::EScreenLayoutChanged )
{
// only update header if we get a layout change from email ui
- if ( iMessage )
+ RefreshCurrentMailHeader();
+ }
+ }
+
+void CFsEmailUiHtmlViewerContainer::RefreshCurrentMailHeader()
+ {
+ if ( iMessage )
+ {
+ // Update the width in header part and reload
+ TPath headerHtmlFile;
+ headerHtmlFile.Copy( iHtmlFolderPath );
+ headerHtmlFile.Append( KHeaderHtmlFile );
+
+ TLanguage language = User::Language();
+ TBidiText::TDirectionality direction = TBidiText::ScriptDirectionality( language );
+ TRAP_IGNORE( CFreestyleMessageHeaderHTML::ExportL( *iMessage, iFs, headerHtmlFile, iAppUi.ClientRect().Width(), direction ) )
+
+ TPath emailHtmlFile;
+ emailHtmlFile.Copy( iHtmlFolderPath );
+ if ( direction == TBidiText::ELeftToRight )
{
- // update the width in header part and reload
- TPath headerHtmlFile;
- headerHtmlFile.Copy( iHtmlFolderPath );
- headerHtmlFile.Append( KHeaderHtmlFile );
-
- TRAP_IGNORE( CFreestyleMessageHeaderHTML::ExportL( *iMessage, iFs, headerHtmlFile, iAppUi.ClientRect().Width() ) )
-
- TPath emailHtmlFile;
- emailHtmlFile.Copy( iHtmlFolderPath );
emailHtmlFile.Append( KMessageHtmlFile );
-
- TRAP_IGNORE( LoadContentFromFileL( emailHtmlFile ) )
-
+ }
+ else
+ {
+ emailHtmlFile.Append( KMessageHtmlRTLFile );
+ }
+
+ //Load page synchronously if menu invisible
+ if(!iEventHandler->IsMenuVisible())
+ {
+ TRAP_IGNORE( LoadContentFromFileL( emailHtmlFile ) );
SetRect( iAppUi.ClientRect() );
}
+ //Load page asynchronously after dismissing menu
+ else
+ {
+ iEventHandler->DismissMenuAndReload();
+ }
}
}
+
+void CFsEmailUiHtmlViewerContainer::ReloadPageL()
+ {
+ TLanguage language = User::Language();
+ TBidiText::TDirectionality direction = TBidiText::ScriptDirectionality( language );
+ TPath emailHtmlFile;
+ emailHtmlFile.Copy( iHtmlFolderPath );
+ if ( direction == TBidiText::ELeftToRight )
+ {
+ emailHtmlFile.Append( KMessageHtmlFile );
+ }
+ else
+ {
+ emailHtmlFile.Append( KMessageHtmlRTLFile );
+ }
+ TRAP_IGNORE( LoadContentFromFileL( emailHtmlFile ) );
+ SetRect( iAppUi.ClientRect() );
+ }
+
+/**
+ * The body fetch link is cmail://body/fetch. Look for the URL separator
+ * and the presence of cmail and body on the url.
+ * @param aUrl
+ * return ETrue for a valid body URL
+ */
+TBool CFsEmailUiHtmlViewerContainer::IsMessageBodyURL(const TDesC& aUrl)
+ {
+ TInt index = aUrl.Find(KURLSchemeSeparator);
+ if (index == KErrNotFound)
+ {
+ return EFalse;
+ }
+ else
+ {
+ if (aUrl.Left(index).CompareF(KURLSchemeCmail) == 0)
+ {
+ TInt bodyIndex = aUrl.Find(KURLTypeBody);
+ if (bodyIndex == KErrNotFound)
+ {
+ return EFalse;
+ }
+ else
+ {
+ TPtrC16 data= aUrl.Mid(bodyIndex);
+ TInt separator = data.Find(KURLSlash);
+ if(separator == KErrNotFound)
+ {
+ return EFalse;
+ }
+ else
+ {
+ TPtrC16 temp = data.Mid(separator+1);
+ TLex lex(temp);
+ lex.Val(iScrollPosition);
+ }
+ return ETrue;
+ }
+
+ }
+ else
+ {
+ return EFalse;
+ }
+ }
+ }
+// ---------------------------------------------------------------------------
+// From MBrCtlWindowObserver
+// ---------------------------------------------------------------------------
+//
+CBrCtlInterface* CFsEmailUiHtmlViewerContainer::OpenWindowL( TDesC& /*aUrl*/, TDesC* /*aTargetName*/,
+ TBool /*aUserInitiated*/, TAny* /*aReserved*/ )
+ {
+ return iBrCtlInterface;
+ }
+
+// ---------------------------------------------------------------------------
+// From MBrCtlWindowObserver
+// ---------------------------------------------------------------------------
+//
+CBrCtlInterface* CFsEmailUiHtmlViewerContainer::FindWindowL( const TDesC& /*aTargetName*/ ) const
+ {
+ return NULL;
+ }
+
+// ---------------------------------------------------------------------------
+// From MBrCtlWindowObserver
+// ---------------------------------------------------------------------------
+//
+void CFsEmailUiHtmlViewerContainer::HandleWindowCommandL( const TDesC& /*aTargetName*/,
+ TBrCtlWindowCommand /*aCommand*/ )
+ {
+
+ }
+
+// ---------------------------------------------------------------------------
+// Check if a tap on the URL requires browser(standalone) to be launched
+// ---------------------------------------------------------------------------
+//
+TBool CFsEmailUiHtmlViewerContainer::NeedToLaunchBrowserL( const TDesC& aUrl )
+ {
+ TBool launchBrowser( ETrue );
+ // look for file:///
+ _LIT( KFileLink, "file:///");
+
+ // This might be linking to header.html or body.html frames
+ // Ignore them.
+ if ( aUrl.Left( KFileLink().Length() ).CompareF( KFileLink ) == 0 )
+ {
+ //Now there is a chance that this could be from HTML folder
+ // Replace all slash character with backslash characters
+ HBufC* embeddedUrl = aUrl.AllocLC();
+ TPtr ptr = embeddedUrl->Des();
+
+ _LIT( KBackslash, "\\" );
+ for ( TInt pos = ptr.Locate('/'); pos >= 0; pos = ptr.Locate('/') )
+ {
+ ptr.Replace( pos, 1, KBackslash );
+ }
+
+ // Check whether given url refers to file in the html folder
+ TInt pos = embeddedUrl->FindF( iHtmlFolderPath );
+ CleanupStack::PopAndDestroy( embeddedUrl );
+ pos >= 0 ? launchBrowser = EFalse : ETrue;
+ }
+ // Ignore links starting with cmail://
+ else if ( aUrl.Left( KURLSchemeCmail().Length() ).CompareF( KURLSchemeCmail ) == 0 )
+ {
+ launchBrowser = EFalse;
+ }
+
+ return launchBrowser;
+ }
+
+// ---------------------------------------------------------------------------
+// Launch the browser as a standalone app
+// ---------------------------------------------------------------------------
+//
+void CFsEmailUiHtmlViewerContainer::LaunchBrowserL( const TDesC& aUrl )
+ {
+ CSchemeHandler* handler = CSchemeHandler::NewL( aUrl );
+ CleanupStack::PushL( handler );
+ handler->HandleUrlStandaloneL();
+ CleanupStack::PopAndDestroy( handler );
+ }
+