diff -r 12c456ceeff2 -r 5253a20d2a1e emailuis/emailui/src/FreestyleEmailUiHtmlViewerContainer.cpp --- 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 #include #include - +#include // #include "CFSMailMessage.h" // #include #include - +#include #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" ); - -// +_LIT( KURLSlash, "/"); // Constants used in html content modification const TInt KMaxCharsToSearch( 200 ); _LIT8( KStartTag, ""); _LIT( KHTMLDataScheme, "data:0"); -// + +_LIT8( KHtmlLineBreak, "
" ); +_LIT8( KHtmlLineBreakCRLF, "
\xD\xA" ); +_LIT8( KHtmlLessThan, "<" ); +_LIT8( KHtmlGreaterThan, ">" ); +_LIT8( KHtmlAmpersand, "&" ); +_LIT8( KHtmlQuotation, """ ); +_LIT8( KHtmlLinkTag, "" ); +_LIT8( KHtmlLinkEndTag, "" ); +_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; } // 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 @@ // // 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") ) ): - User::LeaveIfError( targetFile.Write( aContent.Mid(i,1) ) ); +// + } + } + +// --------------------------------------------------------------------------- +// Finds and html formats hyperlinks in a document +// --------------------------------------------------------------------------- +// +// +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("
") )); - } - 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 ); - } -//
+ } @@ -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 ); + } +