diff -r b13141f05c3d -r b5fbb9b25d57 emailuis/emailui/src/FreestyleEmailUiHtmlViewerContainer.cpp --- a/emailuis/emailui/src/FreestyleEmailUiHtmlViewerContainer.cpp Tue Apr 27 16:20:14 2010 +0300 +++ b/emailuis/emailui/src/FreestyleEmailUiHtmlViewerContainer.cpp Tue May 11 15:57:15 2010 +0300 @@ -26,6 +26,7 @@ #include #include #include +#include // #include "cfsmailmessage.h" @@ -79,9 +80,6 @@ _LIT( KHtmlGreaterThan, ">" ); _LIT( KHtmlAmpersand, "&" ); _LIT( KHtmlQuotation, """ ); -// _LIT( KHtmlLinkTag, "" ); -// _LIT( KHtmlLinkTagWWW, "" ); -// _LIT( KHtmlLinkEndTag, "" ); _LIT( KURLTypeBody, "body"); _LIT( KURLDisplayImages, "cmail://displayImages/" ); @@ -93,13 +91,10 @@ const TText KLessThan = 0x3c; const TText KAmpersand = 0x26; const TText KQuotation = 0x22; -// const TText KCharacterSpace = 0x20; const TText KSOH = 0x01; // Start Of Heading -// const TText KCR = 0x0d; // Carriage Return const TText KLF = 0x0a; // Line Feed -// const TText KHT = 0x09; // Horizontal Tab const TText KUnicodeNewLineCharacter = 0x2028; -const TText KUnicodeParagraphCharacter = 0x2029; +const TText KUnicodeParagraphCharacter = 0x2029; const TReal KOverlayButtonMarginX = 0.01; // 1% const TReal KOverlayButtonMarginY = 0.01; // 1% const TReal KOverlayButtonSizeP = 0.15; // 15% @@ -109,6 +104,12 @@ const TInt KStatusIndicatorHeight = 50; const TInt KStatusIndicatorXMargin = 50; +// CONSTANTS +// Zoom levels available on the UI +const TInt KZoomLevels[] = { 75, 100, 125, 150 }; +const TInt KZoomLevelCount = sizeof( KZoomLevels ) / sizeof( TInt ); +const TInt KZoomLevelIndex100 = 100; // 100 in array KZoomLevels + // CEUiHtmlViewerSettingsKeyListener // --------------------------------------------------------------------------- @@ -290,7 +291,8 @@ iAppUi( aAppUi ), iView( aView ), iFs( iCoeEnv->FsSession() ), - iFirstTime( ETrue ) + iFirstTime( ETrue ), + iZoomLevel( KZoomLevelIndex100 ) { FUNC_LOG; } @@ -340,6 +342,140 @@ ResetContent(); } +void CFsEmailUiHtmlViewerContainer::ZoomInL() + { + SetZoomLevelL( ZoomLevelL() + 1 ); + } + +void CFsEmailUiHtmlViewerContainer::ZoomOutL() + { + SetZoomLevelL( ZoomLevelL() - 1 ); + } + +TInt CFsEmailUiHtmlViewerContainer::ZoomLevelL() const + { + FUNC_LOG; + TInt zoomLevelIdx = iBrCtlInterface->BrowserSettingL( + TBrCtlDefs::ESettingsCurrentZoomLevelIndex ); + + // Behaviour of zooming in Browser Control Interface is different in version 7.1 + // than in previous versions and we need to support both. In older versions there + // are 4 preset zoom levels while version 7.1 can zoom to any percent. + RArray* zoomLevels = iBrCtlInterface->ZoomLevels(); + + if ( !zoomLevels || !zoomLevels->Count() || ( *zoomLevels )[0] != KZoomLevels[0] ) + { + // new browser: + // BrowserControlIf gives zoom level percentage insted of index to array + TBool found = EFalse; + + for ( TInt i = 0 ; i < KZoomLevelCount && !found ; ++i ) + { + if ( zoomLevelIdx == KZoomLevels[i] ) + { + zoomLevelIdx = i; + found = ETrue; + } + } + + if ( !found ) + { + zoomLevelIdx = KErrNotFound; + } + } + return zoomLevelIdx; + } + +void CFsEmailUiHtmlViewerContainer::SetZoomLevelL( const TInt aZoomLevel ) + { + FUNC_LOG; + TInt newValue = KMinTInt; + + // Behaviour of zooming in Browser Control Interface is different in version 7.1 + // than in previous versions and we need to support both. In older versions there + // are 4 preset zoom levels while version 7.1 can zoom to any percent. + RArray* zoomLevels = iBrCtlInterface->ZoomLevels(); + + if ( !zoomLevels || !zoomLevels->Count() || ( *zoomLevels )[0] != KZoomLevels[0] ) + { + // new browser: + // BrowserControlIf takes zoom level percentage insted of index to array + if ( aZoomLevel >= 0 && aZoomLevel < KZoomLevelCount ) + { + newValue = KZoomLevels[aZoomLevel]; + } + } + else + { + // old browser + newValue = aZoomLevel; + } + + iZoomLevel = ( newValue > KMinTInt ) ? newValue : aZoomLevel; + iBrCtlInterface->SetBrowserSettingL( + TBrCtlDefs::ESettingsCurrentZoomLevelIndex, iZoomLevel ); + } + +TInt CFsEmailUiHtmlViewerContainer::DoZoom( TAny* aPtr ) + { + TRAPD( error, reinterpret_cast( aPtr )->DoZoomL() ); + return error; + } + +void CFsEmailUiHtmlViewerContainer::DoZoomL() + { + iBrCtlInterface->SetBrowserSettingL( + TBrCtlDefs::ESettingsCurrentZoomLevelIndex, iZoomLevel ); + } + +TInt CFsEmailUiHtmlViewerContainer::MaxZoomLevel() const + { + return KZoomLevelCount; + } + + +void CFsEmailUiHtmlViewerContainer::CreateBrowserControlInterfaceL() + { + FUNC_LOG; + + if ( iBrCtlInterface ) + { + delete iBrCtlInterface; + iBrCtlInterface = NULL; + } + + TUint brCtlCapabilities = TBrCtlDefs::ECapabilityClientResolveEmbeddedURL | + TBrCtlDefs::ECapabilityDisplayScrollBar | + TBrCtlDefs::ECapabilityClientNotifyURL | + TBrCtlDefs::ECapabilityLoadHttpFw | + TBrCtlDefs::ECapabilityCursorNavigation | + TBrCtlDefs::ECapabilityPinchZoom | + TBrCtlDefs::ECapabilityFitToScreen; + + // Set browsercontrol to whole screen + TRect rect( TPoint(), Size() ); + + iBrCtlInterface = CreateBrowserControlL( + this, // aParent + rect, // aRect + brCtlCapabilities, // aBrCtlCapabilities + TBrCtlDefs::ECommandIdBase, // aCommandIdBase + NULL, // aBrCtlSoftkeysObserver + this, // aBrCtlLinkResolver + this, // aBrCtlSpecialLoadObserver + NULL, // aBrCtlLayoutObserver + NULL, // aBrCtlDialogsProvider + this, // aBrCtlWindowObserver + NULL // aBrCtlDownloadObserver + ); + + iBrCtlInterface->SetBrowserSettingL( TBrCtlDefs::ESettingsEmbedded, ETrue ); + iBrCtlInterface->SetBrowserSettingL( TBrCtlDefs::ESettingsAutoLoadImages, iViewerSettings->AutoLoadImages() ); + iBrCtlInterface->SetBrowserSettingL( TBrCtlDefs::ESettingsPageOverview, EFalse ); + iBrCtlInterface->SetBrowserSettingL( TBrCtlDefs::ESettingsTextWrapEnabled, ETrue ); + iBrCtlInterface->SetBrowserSettingL( TBrCtlDefs::ESettingsFontSize, TBrCtlDefs::EFontSizeLevelLarger ); + } + void CFsEmailUiHtmlViewerContainer::ConstructL() { FUNC_LOG; @@ -351,45 +487,23 @@ BaflUtils::EnsurePathExistsL( iFs, iTempHtmlFolderPath ); SetHTMLResourceFlagFullName(); EnsureHTMLResourceL(); - + CreateWindowL(); - SetRect( iView.ContainerRect() ); - - TUint brCtlCapabilities = TBrCtlDefs::ECapabilityClientResolveEmbeddedURL | - TBrCtlDefs::ECapabilityDisplayScrollBar | - TBrCtlDefs::ECapabilityClientNotifyURL | - TBrCtlDefs::ECapabilityLoadHttpFw | - TBrCtlDefs::ECapabilityCursorNavigation | - TBrCtlDefs::ECapabilityPinchZoom; + +#if defined( BRDO_MULTITOUCH_ENABLED_FF ) && !defined ( __WINSCW__ ) + //Enable advance pointer info for multi-touch. + Window().EnableAdvancedPointers(); +#endif - // Set browsercontrol to whole screen - TRect rect( TPoint(), Size() ); - - iBrCtlInterface = CreateBrowserControlL( - this, // aParent - rect, // aRect - brCtlCapabilities, // aBrCtlCapabilities - TBrCtlDefs::ECommandIdBase, // aCommandIdBase - NULL, // aBrCtlSoftkeysObserver - this, // aBrCtlLinkResolver - this, // aBrCtlSpecialLoadObserver - NULL, // aBrCtlLayoutObserver - NULL, // aBrCtlDialogsProvider - this, // aBrCtlWindowObserver - NULL // aBrCtlDownloadObserver - ); + + SetRect( iView.ContainerRect() ); + CreateBrowserControlInterfaceL(); - iBrCtlInterface->SetBrowserSettingL( TBrCtlDefs::ESettingsEmbedded, ETrue ); - iBrCtlInterface->SetBrowserSettingL( TBrCtlDefs::ESettingsAutoLoadImages, iViewerSettings->AutoLoadImages() ); - iBrCtlInterface->SetBrowserSettingL( TBrCtlDefs::ESettingsPageOverview, EFalse ); - iBrCtlInterface->SetBrowserSettingL( TBrCtlDefs::ESettingsTextWrapEnabled, ETrue ); - 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, + iOverlayControlNext = COverlayControl::NewL( this, this, nextButtonRect, + EMbmFreestyleemailuiQgn_indi_cmail_arrow_next, EMbmFreestyleemailuiQgn_indi_cmail_arrow_next_mask ); TRect prevButtonRect = OverlayButtonRect( ETrue ); @@ -411,7 +525,7 @@ CCoeControl::MakeVisible( aVisible ); } -void CFsEmailUiHtmlViewerContainer::HandleOverlayPointerEventL( COverlayControl* aControl, +void CFsEmailUiHtmlViewerContainer::HandleOverlayPointerEventL( COverlayControl* aControl, const TPointerEvent& aEvent ) { if( aEvent.iType == TPointerEvent::EButton1Up ) @@ -439,7 +553,7 @@ nextAvailable = iAppUi.IsNextMsgAvailable( currentMsgId, tmpMsgId, tmpMsgFolderId ); prevAvailable = iAppUi.IsPreviousMsgAvailable( currentMsgId, tmpMsgId, tmpMsgFolderId ); } - + if( iOverlayControlPrev ) { iOverlayControlPrev->SetRect( OverlayButtonRect( ETrue ) ); @@ -457,7 +571,7 @@ { TRect rect = Rect(); TSize size = rect.Size(); - + TBool landscape = size.iWidth > size.iHeight; TInt buttonSize; @@ -471,7 +585,7 @@ } rect.iBr.iY = size.iHeight * (1-KOverlayButtonMarginY); - + if( aLeft ) { rect.iTl.iX = size.iWidth * KOverlayButtonMarginX; @@ -482,7 +596,7 @@ rect.iBr.iX = size.iWidth * (1 - KOverlayButtonMarginX); rect.iTl.iX = rect.iBr.iX - buttonSize; } - + rect.iTl.iY = rect.iBr.iY - buttonSize; return rect; } @@ -525,23 +639,23 @@ // 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 ); headerHtmlFile.Append( KHeaderHtmlFile ); - + // insert email header into email.html file // CFreestyleMessageHeaderHTML will replace contents of email.html // So, no need to clear the contents if(aResetScrollPos) { - iScrollPosition = 0; + iScrollPosition = 0; } const TInt visibleWidth(iAppUi.ClientRect().Width()); CFreestyleMessageHeaderHTML::ExportL( *iMessage, iFs, headerHtmlFile, visibleWidth, iScrollPosition, iViewerSettings->AutoLoadImages() || iAppUi.DisplayImagesCache().Contains(*iMessage), iHeaderExpanded ); - + // Remove all previously created files from temporary HTML folder EmptyTempHtmlFolderL(); @@ -562,8 +676,11 @@ { emailHtmlFile.Append( KMessageHtmlRTLFile ); } + + CreateBrowserControlInterfaceL(); + LoadContentFromFileL( emailHtmlFile ); - + UpdateOverlayButtons( ETrue ); } @@ -576,12 +693,12 @@ FUNC_LOG; if ( iBrCtlInterface ) { - TRAP_IGNORE( + TRAP_IGNORE( iBrCtlInterface->HandleCommandL( ( TInt )TBrCtlDefs::ECommandIdBase + ( TInt )TBrCtlDefs::ECommandFreeMemory ) ); if (aDisconnect) { - TRAP_IGNORE( + TRAP_IGNORE( iBrCtlInterface->HandleCommandL( ( TInt )TBrCtlDefs::ECommandIdBase + ( TInt )TBrCtlDefs::ECommandDisconnect ) ); } @@ -640,7 +757,7 @@ { return 4; } - else + else { return 3; } @@ -677,9 +794,9 @@ { iBrCtlInterface->SetRect( rect ); } - + UpdateOverlayButtons( IsVisible() ); - + if ( iStatusIndicator ) { TRect rect = CalcAttachmentStatusRect(); @@ -695,7 +812,7 @@ const TKeyEvent& aKeyEvent, TEventCode aType ) { FUNC_LOG; - + TKeyResponse retVal = EKeyWasNotConsumed; // Handle keyboard shortcuts already on key down event as all keys @@ -713,9 +830,19 @@ } } - else if ( iBrCtlInterface && retVal == EKeyWasNotConsumed ) + if ( iBrCtlInterface && retVal == EKeyWasNotConsumed ) { - retVal = iBrCtlInterface->OfferKeyEventL( aKeyEvent, aType ); + TKeyEvent event = aKeyEvent; + if ( iBrCtlInterface->FocusedElementType() == TBrCtlDefs::EElementButton + && ( aKeyEvent.iScanCode == EStdKeyNkpEnter + || aKeyEvent.iScanCode == EStdKeyEnter ) ) + { + // Enter key events are converted to selection key event in + // order to get browser to handle them in similar way. + event.iScanCode = EStdKeyDevice3; + event.iCode = aKeyEvent.iCode ? EKeyDevice3 : 0; + } + retVal = iBrCtlInterface->OfferKeyEventL( event, aType ); } iView.SetMskL(); @@ -806,7 +933,7 @@ { iAppUi.DownloadInfoMediator()->StopObserving( this ); } - + if ( iMessage && linkContent ) { CFSMailMessagePart* part = iMessage->ChildPartL( aPart.iMessagePartId ); @@ -820,10 +947,10 @@ CleanupStack::PopAndDestroy( &contentFile ); CleanupStack::PopAndDestroy( part ); } - + if ( iMessage ) { - LoadContentFromMailMessageL( iMessage, EFalse ); + LoadContentFromMailMessageL( iMessage, EFalse ); UpdateOverlayButtons( ETrue ); } } @@ -907,7 +1034,7 @@ else { return iEventHandler->HandleEventL( aUrl ); - } + } } } @@ -954,7 +1081,7 @@ // void CFsEmailUiHtmlViewerContainer::SetTempHtmlFolderPath() { - FUNC_LOG; + FUNC_LOG; iTempHtmlFolderPath.Copy( iHtmlFolderPath ); iTempHtmlFolderPath.Append( KTempHtmlPath ); } @@ -991,7 +1118,7 @@ RFile htmlFile = aHtmlBodyPart.GetContentFileL(); CleanupClosePushL( htmlFile ); - + // Read content from given source file HBufC8* content = ReadContentFromFileLC( htmlFile ); @@ -1014,14 +1141,14 @@ TFileName targetFileName; targetFileName.Copy( iTempHtmlFolderPath ); targetFileName.Append( aHtmlFileName ); - + HBufC* content = HBufC::NewLC( aTextBodyPart.FetchedContentSize() ); TPtr contentPtr( content->Des() ); - + aTextBodyPart.GetContentToBufferL( contentPtr, 0 ); - + ConvertToHTML( *content, targetFileName, aTextBodyPart ); - + CleanupStack::PopAndDestroy( content ); } @@ -1050,11 +1177,11 @@ const TDesC& aFileName, CFSMailMessagePart& aHtmlBodyPart ) { FUNC_LOG; - + RBuf8 buffer; buffer.CreateL( aContent ); buffer.CleanupClosePushL(); - + if ( SysUtil::DiskSpaceBelowCriticalLevelL( &iFs, buffer.Size(), EDriveC ) ) { // Can not write the data, there's not enough free space on disk. @@ -1064,12 +1191,12 @@ { RFile targetFile; CleanupClosePushL( targetFile ); - + User::LeaveIfError( targetFile.Replace( iFs, aFileName, EFileWrite ) ); // Try to find initial html tag (both '' tag anywhere in // the begining of file (KMaxCharsToSearch) AND there is charset // parameter available @@ -1084,34 +1211,34 @@ { HBufC8* charSet = GetCharacterSetL( aHtmlBodyPart ); CleanupStack::PushL( charSet ); - + User::LeaveIfError( targetFile.Write( KHtmlHeader1 ) ); User::LeaveIfError( targetFile.Write( *charSet ) ); User::LeaveIfError( targetFile.Write( KHtmlHeader2 ) ); CleanupStack::PopAndDestroy( charSet ); } - else + else { // Charset tag not found in html body - + if ( buffer.Left( KMaxCharsToSearch ).FindF( KCharsetTag8 ) == KErrNotFound ) { TInt startPos(0); if ( ( startPos = buffer.Left( KMaxCharsToSearch ).FindF( KHeadTag ) ) != KErrNotFound ) - { - + { + HBufC8* charSet = GetCharacterSetL( aHtmlBodyPart ); CleanupStack::PushL( charSet ); - + HBufC8* metaBuffer = HBufC8::NewLC( charSet->Des().Length() + KHtmlHeader3().Length() ); TPtr8 metaHeader( metaBuffer->Des() ); - metaHeader.AppendFormat( KHtmlHeader3, charSet ); - TInt maxLength = buffer.Length() + metaHeader.Length(); + metaHeader.AppendFormat( KHtmlHeader3, charSet ); + TInt maxLength = buffer.Length() + metaHeader.Length(); buffer.ReAllocL( maxLength ); - + startPos += KHeadTag().Length(); buffer.Insert( startPos, metaHeader ); - + CleanupStack::PopAndDestroy( metaBuffer ); CleanupStack::PopAndDestroy( charSet ); } @@ -1244,14 +1371,14 @@ partData.iMailBoxId = iMessage->GetMailBoxId(); partData.iFolderId = iMessage->GetFolderId(); partData.iMessageId = iMessage->GetMessageId(); - + partData.iMessagePartId = aAttachment.GetPartId(); if ( iAppUi.DownloadInfoMediator() && iAppUi.DownloadInfoMediator()->IsDownloadableL( partData ) ) { ASSERT( iLinkContents.Count() == iMessageParts.Count() ); - + // Append message part details and embedded link content interface // to corresponding arrays so that the content can be returned // when the download is completed. @@ -1260,7 +1387,7 @@ { iLinkContents.Remove( iLinkContents.Count() - 1 ); } - + ASSERT( iLinkContents.Count() == iMessageParts.Count() ); if(!iView.GetAsyncFetchStatus()) { @@ -1277,7 +1404,7 @@ { FUNC_LOG; iHtmlResourceFlagPath.Copy( iHtmlFolderPath ); - iHtmlResourceFlagPath.Append( KHtmlFlagFile ); + iHtmlResourceFlagPath.Append( KHtmlFlagFile ); } void CFsEmailUiHtmlViewerContainer::EnableHTMLResourceFlagL() @@ -1306,11 +1433,11 @@ htmlFolderPathInZ.Append( privatePath ); htmlFolderPathInZ.Append( KHtmlPath ); - + CDir* dirList; TPath listSpec; listSpec.Copy( htmlFolderPathInZ ); - + listSpec.Append( _L("*.*") ); User::LeaveIfError( iFs.GetDir( listSpec, KEntryAttMaskSupported, ESortByName, dirList ) ); CleanupStack::PushL( dirList ); @@ -1319,28 +1446,28 @@ TPath sourceFileFullName; sourceFileFullName.Copy( htmlFolderPathInZ ); sourceFileFullName.Append( (*dirList)[i].iName ); - + TBool isFolder( EFalse ); BaflUtils::IsFolder( iFs, sourceFileFullName, isFolder); if ( isFolder ) { - break; + break; } - + TPath targetFileFullName; targetFileFullName.Copy( iHtmlFolderPath ); targetFileFullName.Append( (*dirList)[i].iName ); - BaflUtils::DeleteFile( iFs, targetFileFullName ); - + BaflUtils::DeleteFile( iFs, targetFileFullName ); + BaflUtils::CopyFile( iFs, sourceFileFullName, targetFileFullName); - } + } CleanupStack::PopAndDestroy( dirList ); } void CFsEmailUiHtmlViewerContainer::EnsureHTMLResourceL() { FUNC_LOG; - + if ( !HTMLResourceFlagEnabled() ) { CopyHTMLResourceL(); @@ -1352,203 +1479,24 @@ // Writes buffer content to given file after adding tags // --------------------------------------------------------------------------- // -// void CFsEmailUiHtmlViewerContainer::ConvertToHTML( const TDesC& aContent, const TDesC& aFileName, CFSMailMessagePart& /*aTextBodyPart*/ ) { FUNC_LOG; - const TInt KBodyTextChunkSize = 2048; - + if ( SysUtil::DiskSpaceBelowCriticalLevelL( &iFs, aContent.Size(), EDriveC ) ) - { - // Can not write the data, there's not enough free space on disk. - User::Leave( KErrDiskFull ); - } - else { - RBuf bodyBuf; - bodyBuf.CreateL( aContent.Size() + KBodyTextChunkSize ); - bodyBuf.CleanupClosePushL(); - bodyBuf.Insert( 0, aContent); - TInt maxlength = bodyBuf.MaxSize(); - - TInt position( 0 ); - TBool EndOfString( EFalse ); - - while ( !EndOfString ) - { - TInt startPosition = position; - TPtr segment( bodyBuf.MidTPtr( startPosition ) ); - TInt i = 0; - - while(i < segment.Length()) - { - TInt currentPos = position + i; - TText ch = segment[i]; - - switch( ch ) - { - case KSOH: // end of line for IMAP and POP - bodyBuf.Delete( currentPos, 1 ); - maxlength = maxlength + KHtmlLineBreakCRLF().Length(); - bodyBuf.ReAlloc( maxlength ); - bodyBuf.Insert( currentPos, KHtmlLineBreakCRLF ); - i += KHtmlLineBreakCRLF().Length(); - segment.Set( bodyBuf.MidTPtr( startPosition ) ); - break; - case KLF: // line feed - case KUnicodeNewLineCharacter: - case KUnicodeParagraphCharacter: - maxlength = maxlength + KHtmlLineBreak().Length(); - bodyBuf.ReAlloc( maxlength ); - bodyBuf.Insert( currentPos, KHtmlLineBreak ); - i += KHtmlLineBreak().Length() + 1; - segment.Set( bodyBuf.MidTPtr( startPosition ) ); - break; - case KQuotation: - bodyBuf.Delete( currentPos, 1 ); - maxlength = maxlength + KHtmlQuotation().Length(); - bodyBuf.ReAlloc( maxlength ); - bodyBuf.Insert( currentPos, KHtmlQuotation ); - i += KHtmlQuotation().Length(); - segment.Set( bodyBuf.MidTPtr( startPosition ) ); - break; - case KAmpersand: - bodyBuf.Delete( currentPos, 1 ); - maxlength = maxlength + KHtmlAmpersand().Length(); - bodyBuf.ReAlloc( maxlength ); - bodyBuf.Insert( currentPos, KHtmlAmpersand ); - i += KHtmlAmpersand().Length(); - segment.Set( bodyBuf.MidTPtr( startPosition ) ); - break; - case KGreaterThan: - bodyBuf.Delete( currentPos, 1 ); - maxlength = maxlength + KHtmlGreaterThan().Length(); - bodyBuf.ReAlloc( maxlength ); - bodyBuf.Insert( currentPos, KHtmlGreaterThan ); - i += KHtmlGreaterThan().Length(); - segment.Set( bodyBuf.MidTPtr( startPosition ) ); - break; - case KLessThan: - bodyBuf.Delete( currentPos, 1 ); - maxlength = maxlength + KHtmlLessThan().Length(); - bodyBuf.ReAlloc( maxlength ); - bodyBuf.Insert( currentPos, KHtmlLessThan ); - i += KHtmlLessThan().Length(); - segment.Set( bodyBuf.MidTPtr( startPosition ) ); - break; - default: - i++; - break; - } - } - position += segment.Length(); - if ( ( bodyBuf.Length() - position ) <= 0 ) - { - EndOfString = ETrue; - } - } - - CreateHyperlinksFromUrlsL( bodyBuf ); + // Can not write the data, there's not enough free space on disk. + User::Leave( KErrDiskFull ); + } + + RBuf htmlText; + CleanupClosePushL( htmlText ); - HBufC8* content8 = CnvUtfConverter::ConvertFromUnicodeToUtf8L( bodyBuf ); - CleanupStack::PushL( content8 ); - - RFile targetFile; - CleanupClosePushL( targetFile ); - User::LeaveIfError( targetFile.Replace( iFs, aFileName, EFileWrite ) ); - - RBuf8 messageHeader; - _LIT( KCharsetUtf8, "UTF-8" ); - TInt bufSize = KHtmlHeader1().Length() + KCharsetUtf8().Length() + KHtmlHeader2().Length(); - messageHeader.CreateL( bufSize ); - messageHeader.CleanupClosePushL(); + PlainTextToHtmlConverter::PlainTextToHtmlL( aContent, htmlText ); + WriteToFileL( aFileName, htmlText ); - messageHeader.Append( KHtmlHeader1 ); - messageHeader.Append( KCharsetUtf8 ); - messageHeader.Append( KHtmlHeader2 ); - - RFileWriteStream fileStream( targetFile ); - fileStream.PushL(); - fileStream.WriteL( messageHeader.Ptr(), messageHeader.Length() ); - - TInt bufPos( 0 ); - TInt bufTotalSize = content8->Size(); - - while ( bufPos < bufTotalSize ) - { - TInt segmentLength = content8->Mid( bufPos ).Length(); - fileStream.WriteL( content8->Mid( bufPos ).Ptr(), segmentLength ); - bufPos += segmentLength; - } - - fileStream.CommitL(); - - CleanupStack::PopAndDestroy( &fileStream ); - CleanupStack::PopAndDestroy( &messageHeader ); - CleanupStack::PopAndDestroy( &targetFile ); - CleanupStack::PopAndDestroy( content8 ); - CleanupStack::PopAndDestroy( &bodyBuf ); // calls bodyBuf.Close(); - -// - } - } - -// --------------------------------------------------------------------------- -// Finds and html formats hyperlinks in a document -// --------------------------------------------------------------------------- -// -// -void CFsEmailUiHtmlViewerContainer::CreateHyperlinksFromUrlsL( RBuf& aSource ) - { - FUNC_LOG; - const TInt searhCases( CFindItemEngine::EFindItemSearchURLBin ); - CFindItemEngine* itemEngine = CFindItemEngine::NewL( aSource, CFindItemEngine::TFindItemSearchCase( searhCases ) ); - CleanupStack::PushL ( itemEngine ); - if ( itemEngine->ItemCount() > 0 ) - { - _LIT( KSchemeDelimiter, "://" ); - _LIT( KUrlFormat, "%S" ); - _LIT( KUrlFormatWithHttp, "%S" ); - - const TInt sourceLength( aSource.Length() ); - // Allocate enough space for the final result - aSource.ReAllocL( sourceLength + TotalLengthOfItems( *itemEngine ) + KUrlFormatWithHttp().Length() * itemEngine->ItemCount() ); - aSource.SetMax(); - // Organize buffer so that original data is in the back of the aSource - aSource.RightTPtr( sourceLength ).Copy( aSource.Left( sourceLength ) ); - // Set source to new original data's position - const TPtrC source( aSource.RightTPtr( sourceLength ) ); - // Set target to aSource's beginning - TPtr target( aSource.MidTPtr( 0 ) ); - // Reset length, we now have an empty buffer to fill - target.SetLength( 0 ); - - TInt currentSourcePosition( 0 ); - CFindItemEngine::SFoundItem item; - for ( TBool available( itemEngine->Item( item ) ); available; available = itemEngine->NextItem( item ) ) - { - target.Append( source.Mid( currentSourcePosition, item.iStartPos - currentSourcePosition ) ); - const TPtrC url( source.Mid( item.iStartPos, item.iLength ) ); - TPtrC format( KUrlFormat() ); - if ( url.FindF( KSchemeDelimiter() ) == KErrNotFound ) - { - format.Set( KUrlFormatWithHttp() ); - } - HBufC* formatBuffer = HBufC::NewLC( format.Length() + url.Length() * 2 ); - formatBuffer->Des().Format( format, &url, &url ); - target.Append( *formatBuffer ); - CleanupStack::PopAndDestroy(); // formatBuffer - currentSourcePosition = item.iStartPos + item.iLength; - } - // Append characters that are left in buffer - if ( currentSourcePosition < sourceLength ) - { - target.Append( source.Mid( currentSourcePosition, sourceLength - currentSourcePosition ) ); - } - aSource.SetLength( target.Length() ); - } - CleanupStack::PopAndDestroy(); // itemEngine + CleanupStack::PopAndDestroy( &htmlText ); } @@ -1573,15 +1521,15 @@ HBufC8* CFsEmailUiHtmlViewerContainer::GetCharacterSetL( CFSMailMessagePart& aHtmlBodyPart ) { FUNC_LOG; - + CDesCArray& contentTypeArray( aHtmlBodyPart.ContentTypeParameters() ); - HBufC8* charSet = KNullDesC8().AllocLC(); - + HBufC8* charSet = KNullDesC8().AllocLC(); + for ( TInt i = 0; i < contentTypeArray.Count(); i++ ) { TPtrC contentEntry( contentTypeArray.MdcaPoint( i ) ); if ( ( contentEntry.FindF( KCharsetTag ) != KErrNotFound ) && - contentTypeArray.Count() >= ( i+1) ) + contentTypeArray.Count() >= ( i+1) ) { TPtrC value( contentTypeArray.MdcaPoint( i+1 ) ); if ( value.Length() ) @@ -1595,7 +1543,7 @@ } i++; } - + CleanupStack::Pop( charSet ); return charSet; } @@ -1617,8 +1565,8 @@ FUNC_LOG; if ( iBrCtlInterface ) { - TRAP_IGNORE( iBrCtlInterface->HandleCommandL( (TInt)TBrCtlDefs::ECommandCancelFetch + (TInt)TBrCtlDefs::ECommandIdBase )); - } + TRAP_IGNORE( iBrCtlInterface->HandleCommandL( (TInt)TBrCtlDefs::ECommandCancelFetch + (TInt)TBrCtlDefs::ECommandIdBase )); + } } void CFsEmailUiHtmlViewerContainer::ClearCacheAndLoadEmptyContent() @@ -1626,11 +1574,11 @@ FUNC_LOG; if ( iBrCtlInterface ) { - iBrCtlInterface->ClearCache(); + iBrCtlInterface->ClearCache(); TUid uid; uid.iUid = KCharacterSetIdentifierUtf8; TRAP_IGNORE( iBrCtlInterface->LoadDataL(KHTMLDataScheme, KHTMLEmptyContent, _L8("text/html"), uid) ); - } + } } void CFsEmailUiHtmlViewerContainer::HandleResourceChange( TInt aType ) @@ -1651,20 +1599,20 @@ TPath headerHtmlFile; headerHtmlFile.Copy( iHtmlFolderPath ); headerHtmlFile.Append( KHeaderHtmlFile ); - + TRAP_IGNORE( CFreestyleMessageHeaderHTML::ExportL( *iMessage, iFs, headerHtmlFile, iAppUi.ClientRect().Width(), iScrollPosition, iViewerSettings->AutoLoadImages() || iAppUi.DisplayImagesCache().Contains(*iMessage), iHeaderExpanded ) ) - - + + if(!iEventHandler->IsMenuVisible()) { TRAP_IGNORE( ReloadPageL() ); } else { - //Load page asynchronously after dismissing menu + //Load page asynchronously after dismissing menu //this is outdated call because it cancels Action menu which is no longer used in 9.2 // iEventHandler->DismissMenuAndReload(); } @@ -1677,8 +1625,8 @@ ( TInt )TBrCtlDefs::ECommandReload ) ); } -void CFsEmailUiHtmlViewerContainer::ShowAttachmentDownloadStatusL( - TFSProgress::TFSProgressStatus aProgressStatus, +void CFsEmailUiHtmlViewerContainer::ShowAttachmentDownloadStatusL( + TFSProgress::TFSProgressStatus aProgressStatus, const TAttachmentData& aAttachmentData ) { TBool freshDraw = EFalse; @@ -1699,18 +1647,18 @@ TRect rect = CalcAttachmentStatusRect(); iStatusIndicator = CFreestyleEmailUiAknStatusIndicator::NewL( rect, this ); freshDraw = ETrue; - } - - if ( !iStatusIndicator->IsVisible() - || ( aAttachmentData.downloadProgress == KNone ) + } + + if ( !iStatusIndicator->IsVisible() + || ( aAttachmentData.downloadProgress == KNone ) || ( aProgressStatus == TFSProgress::EFSStatus_RequestCancelled ) ) { freshDraw = ETrue; } - + TInt duration = KStatusIndicatorDefaultDuration; - if ( ( aAttachmentData.downloadProgress == TFSProgress::EFSStatus_RequestComplete ) - || ( aProgressStatus == TFSProgress::EFSStatus_RequestCancelled ) + if ( ( aAttachmentData.downloadProgress == TFSProgress::EFSStatus_RequestComplete ) + || ( aProgressStatus == TFSProgress::EFSStatus_RequestCancelled ) || ( aAttachmentData.downloadProgress == KComplete ) ) { duration = KStatusIndicatorAutomaticHidingDuration; @@ -1728,22 +1676,22 @@ CArrayFix* intArray = new (ELeave) CArrayFixFlat( 1 ); CleanupStack::PushL( intArray ); intArray->AppendL( aAttachmentData.downloadProgress ); - + statusText = StringLoader::LoadL( R_FSE_VIEWER_ATTACHMENTS_LIST_DOWNLOAD, - *descArray, + *descArray, *intArray ); CleanupStack::PopAndDestroy( intArray ); CleanupStack::PopAndDestroy( descArray ); CleanupStack::PushL( statusText ); } break; - + case TFSProgress::EFSStatus_RequestCancelled: { statusText = aAttachmentData.fileName.AllocLC(); } break; - + default: statusText = KNullDesC().AllocLC(); break; @@ -1778,7 +1726,7 @@ } } } - + CleanupStack::Pop( statusText ); } @@ -1824,7 +1772,7 @@ TRect rect = Rect(); TPoint topLeft = rect.iTl; TPoint bottomRight = rect.iBr; - + TPoint statusTopLeft( topLeft.iX + KStatusIndicatorXMargin, bottomRight.iY - KStatusIndicatorHeight + 1 ); TPoint statusBottomRight( bottomRight.iX - KStatusIndicatorXMargin, bottomRight.iY ); return TRect( statusTopLeft, statusBottomRight ); @@ -1832,13 +1780,13 @@ void CFsEmailUiHtmlViewerContainer::TouchFeedback() { - iTouchFeedBack->InstantFeedback(this, ETouchFeedbackBasic); + iTouchFeedBack->InstantFeedback(this, ETouchFeedbackBasic); } /** * 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 + * @param aUrl * return ETrue for a valid body URL */ TBool CFsEmailUiHtmlViewerContainer::IsMessageBodyURLL(const TDesC& aUrl) @@ -1875,11 +1823,11 @@ { TouchFeedback(); iHeaderExpanded = ETrue; - return ETrue; + return ETrue; } else if (aUrl.Left(index).CompareF(KURLSchemeCmail) == 0) { - TInt bodyIndex = aUrl.Find(KURLTypeBody); + TInt bodyIndex = aUrl.Find(KURLTypeBody); if (bodyIndex == KErrNotFound) { return EFalse; @@ -1896,24 +1844,24 @@ { TPtrC16 temp = data.Mid(separator+1); TLex lex(temp); - lex.Val(iScrollPosition); + lex.Val(iScrollPosition); } return ETrue; } - + } else { return EFalse; } } - } + } // --------------------------------------------------------------------------- // From MBrCtlWindowObserver // --------------------------------------------------------------------------- // -CBrCtlInterface* CFsEmailUiHtmlViewerContainer::OpenWindowL( TDesC& /*aUrl*/, TDesC* /*aTargetName*/, +CBrCtlInterface* CFsEmailUiHtmlViewerContainer::OpenWindowL( TDesC& /*aUrl*/, TDesC* /*aTargetName*/, TBool /*aUserInitiated*/, TAny* /*aReserved*/ ) { return iBrCtlInterface; @@ -1932,10 +1880,10 @@ // From MBrCtlWindowObserver // --------------------------------------------------------------------------- // -void CFsEmailUiHtmlViewerContainer::HandleWindowCommandL( const TDesC& /*aTargetName*/, +void CFsEmailUiHtmlViewerContainer::HandleWindowCommandL( const TDesC& /*aTargetName*/, TBrCtlWindowCommand /*aCommand*/ ) { - + } // --------------------------------------------------------------------------- @@ -1948,7 +1896,7 @@ // look for file:/// _LIT( KFileLink, "file:///"); _LIT( KUrlLink, "http"); - + // This might be linking to header.html or body.html frames // Ignore them. if ( aUrl.Left( KFileLink().Length() ).CompareF( KFileLink ) == 0 ) @@ -1957,7 +1905,7 @@ // 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('/') ) { @@ -1967,14 +1915,14 @@ // Check whether given url refers to file in the html folder TInt pos = embeddedUrl->FindF( iHtmlFolderPath ); CleanupStack::PopAndDestroy( embeddedUrl ); - pos >= 0 ? launchBrowser = EFalse : ETrue; + pos >= 0 ? launchBrowser = EFalse : ETrue; } // Ignore links starting with cmail:// else if ( aUrl.Left( KURLSchemeCmail().Length() ).CompareF( KURLSchemeCmail ) == 0 ) { launchBrowser = EFalse; } - // THAA-82BEAZ - show popup first + // THAA-82BEAZ - show popup first else if ( aUrl.Left(KUrlLink().Length() ).CompareF( KUrlLink ) == 0 ) { launchBrowser = EFalse; @@ -1998,7 +1946,7 @@ void CFsEmailUiHtmlViewerContainer::PrepareBodyHtmlL( const TDesC& aFileName ) { - + if( iMessage ) { CFSMailMessagePart* htmlBodyPart = iMessage->HtmlBodyPartL(); @@ -2013,7 +1961,7 @@ else { CFSMailMessagePart* textBodyPart = iMessage->PlainTextBodyPartL(); - + if ( textBodyPart ) { CleanupStack::PushL( textBodyPart ); @@ -2065,3 +2013,178 @@ UpdateOverlayButtons( IsVisible() ); } + +void CFsEmailUiHtmlViewerContainer::WriteToFileL(const TDesC& aFileName, RBuf& aHtmlText) + { + _LIT( KCharsetUtf8, "UTF-8" ); + + HBufC8* content8 = CnvUtfConverter::ConvertFromUnicodeToUtf8L( aHtmlText ); + CleanupStack::PushL( content8 ); + + RFile targetFile; + CleanupClosePushL( targetFile ); + User::LeaveIfError( targetFile.Replace( iFs, aFileName, EFileWrite ) ); + + RBuf8 messageHeader; + TInt bufSize = KHtmlHeader1().Length() + KCharsetUtf8().Length() + KHtmlHeader2().Length(); + messageHeader.CreateL( bufSize ); + messageHeader.CleanupClosePushL(); + + messageHeader.Append( KHtmlHeader1 ); + messageHeader.Append( KCharsetUtf8 ); + messageHeader.Append( KHtmlHeader2 ); + + RFileWriteStream fileStream( targetFile ); + fileStream.PushL(); + fileStream.WriteL( messageHeader.Ptr(), messageHeader.Length() ); + + TInt bufPos( 0 ); + TInt bufTotalSize = content8->Size(); + + while ( bufPos < bufTotalSize ) + { + TInt segmentLength = content8->Mid( bufPos ).Length(); + fileStream.WriteL( content8->Mid( bufPos ).Ptr(), segmentLength ); + bufPos += segmentLength; + } + + fileStream.CommitL(); + + CleanupStack::PopAndDestroy( &fileStream ); + CleanupStack::PopAndDestroy( &messageHeader ); + CleanupStack::PopAndDestroy( &targetFile ); + CleanupStack::PopAndDestroy( content8 ); + } + + + +/****************************************************************************** + * class PlainTextToHtmlConverter + ******************************************************************************/ + + + +// ----------------------------------------------------------------------------- +// PlainTextToHtmlConverter::PlainTextToHtmlL +// +// ----------------------------------------------------------------------------- +// +void PlainTextToHtmlConverter::PlainTextToHtmlL(const TDesC& aPlainText, RBuf& aHtmlText) + { + const TInt KAllocSize = 1024; + + aHtmlText.Close(); + aHtmlText.Create( aPlainText.Length() + KAllocSize ); + + const TInt searhCases( CFindItemEngine::EFindItemSearchURLBin ); + CFindItemEngine* itemEngine = CFindItemEngine::NewL( aPlainText, CFindItemEngine::TFindItemSearchCase( searhCases ) ); + CleanupStack::PushL ( itemEngine ); + + TInt currentPos = 0; + CFindItemEngine::SFoundItem item; + for ( TBool available(itemEngine->Item(item)); available; available=itemEngine->NextItem(item) ) + { + if ( item.iStartPos < currentPos ) + { + break; + } + + TPtrC textPtr = aPlainText.Mid( currentPos, item.iStartPos-currentPos ); + ConvertTextL( textPtr, aHtmlText ); + + TPtrC urlPtr = aPlainText.Mid( item.iStartPos, item.iLength ); + ConvertUrlL( urlPtr, aHtmlText); + + currentPos = item.iStartPos + item.iLength; + } + + TInt len = aPlainText.Length(); + if ( currentPos < len ) + { + TPtrC textPtr = aPlainText.Mid( currentPos ); + ConvertTextL( textPtr, aHtmlText ); + } + + CleanupStack::PopAndDestroy( itemEngine ); + } + + +// ----------------------------------------------------------------------------- +// PlainTextToHtmlConverter::ConvertTextL +// +// ----------------------------------------------------------------------------- +// +void PlainTextToHtmlConverter::ConvertTextL(const TDesC& aSource, RBuf& aTarget) + { + const TInt KAllocSize = 1024; + const TInt KEntitySize = 32; + + TInt count = aSource.Length(); + for ( TInt i=0; i= aTarget.MaxLength() ) + { + aTarget.ReAllocL( aTarget.MaxLength() + KAllocSize ); + } + + TText ch = aSource[i]; + switch( ch ) + { + case KSOH: // end of line for IMAP and POP + aTarget.Append( KHtmlLineBreakCRLF ); + break; + case KLF: // line feed + case KUnicodeNewLineCharacter: + case KUnicodeParagraphCharacter: + aTarget.Append(KHtmlLineBreak); + break; + case KQuotation: + aTarget.Append( KHtmlQuotation ); + break; + case KAmpersand: + aTarget.Append( KHtmlAmpersand ); + break; + case KGreaterThan: + aTarget.Append( KHtmlGreaterThan ); + break; + case KLessThan: + aTarget.Append( KHtmlLessThan ); + break; + default: + aTarget.Append( ch ); + break; + } + } + } + + +// ----------------------------------------------------------------------------- +// PlainTextToHtmlConverter::ConvertUrlL +// +// ----------------------------------------------------------------------------- +// +void PlainTextToHtmlConverter::ConvertUrlL(const TDesC& aSource, RBuf& aTarget) + { + _LIT( KSchemeDelimiter, "://" ); + _LIT( KUrlFormat, "%S" ); + _LIT( KUrlFormatWithHttp, "%S" ); + + TPtrC format( KUrlFormat() ); + if ( aSource.FindF( KSchemeDelimiter() ) == KErrNotFound ) + { + format.Set( KUrlFormatWithHttp() ); + } + + HBufC* formatBuffer = HBufC::NewLC( format.Length() + aSource.Length() * 2 ); + formatBuffer->Des().Format( format, &aSource, &aSource ); + + TInt len = formatBuffer->Des().Length(); + if ( aTarget.Length() + len >= aTarget.MaxLength() ) + { + aTarget.ReAllocL( aTarget.MaxLength() + len ); + } + + aTarget.Append( *formatBuffer ); + + CleanupStack::PopAndDestroy( formatBuffer ); + }