--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/messagingappbase/smilengine/xhtml/src/xhtmlparser.cpp Thu Dec 17 08:44:11 2009 +0200
@@ -0,0 +1,1775 @@
+/*
+* 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: Provides CXhtmlParser class methods.
+*
+*/
+
+
+
+#include <coemain.h>
+#include <gulfont.h>
+#include <eikenv.h>
+#include <txtfrmat.h>
+#include <txtetext.h>
+#include <frmconst.h>
+#include <e32math.h>
+#include <gdi.h>
+#include <AknUtils.h>
+#include <fontids.hrh>
+#include <gmxmldocument.h>
+#include <gmxmlnode.h>
+#include <gmxmlelement.h>
+#include <gmxmltext.h>
+#include <smilliterals.h>
+
+#include "Xhtmldef.h"
+#include "xhtmlentityconverter.h"
+#include "xhtmlfontspecs.h"
+#include "xhtmlstack.h"
+#include "xhtmlstackmanager.h"
+#include "xhtmlhyperlink.h"
+#include "xhtmlparser.h"
+#include "xhtmlparserlogging.h"
+
+const TInt KNoListContext = 0;
+const TInt KUnorderedListContext = 1;
+const TInt KOrderedListContext = 2;
+const TInt KNoStylePosition = -1;
+
+const TInt KListBullet = 0x2022;
+const TInt KListBullet2 = 0x25E6;
+const TInt KPlainBullet = 0x2d; // '-'
+const TInt KPlainBullet2 = 0x2a; // '*'
+const TInt KColon = 0x3a; // ':'
+const TInt KSemicolon = 0x3b; // ';'
+
+const TInt KBlackColorCode = 0x000000;
+const TInt KWhiteColorCode = 0xffffff;
+const TInt KBlueColorCode = 0xff0000;
+const TInt KLimeColorCode = 0x00ff00;
+const TInt KRedColorCode = 0x0000ff;
+
+const TInt KDefaultIndentWidth = 4; // 4 spaces
+const TInt KDefaultMaxListLevels = 5;
+
+_LIT( KWhiteSpace, " " );
+_LIT( KHrSeparator, "__________" );
+_LIT16(KListNumberFormat, "%d. ");
+_LIT( KNullString, "" );
+
+const TInt KHyperLinkArrayGranularity = 16;
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
+const TText KZeroWidthSpace = 0x200B;
+#endif
+
+// ---------------------------------------------------------
+// CXhtmlParser::NewL
+// ---------------------------------------------------------
+//
+EXPORT_C CXhtmlParser* CXhtmlParser::NewL( MXhtmlParserObserver* aParserObserver )
+ {
+ CXhtmlParser* self = new( ELeave ) CXhtmlParser( aParserObserver );
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop( self );
+ return self;
+ };
+
+// ---------------------------------------------------------
+// CXhtmlParser::~CXhtmlParser
+// ---------------------------------------------------------
+//
+CXhtmlParser::~CXhtmlParser()
+ {
+ if( iCurrentCharLayer )
+ {
+ iCurrentCharLayer->Reset();
+ delete iCurrentCharLayer;
+ }
+
+ delete iXmlParser;
+ delete iXhtmlFontSpecs;
+ delete iHyperLinkAddress;
+ delete iStackManager;
+ delete iXmlDocument;
+
+ if ( iHyperLinkArray )
+ {
+ iHyperLinkArray->ResetAndDestroy();
+ delete iHyperLinkArray;
+ }
+ }
+
+// ---------------------------------------------------------
+// CXhtmlParser::CreateDomL
+// ---------------------------------------------------------
+//
+EXPORT_C void CXhtmlParser::CreateDomL( RFs &aRFs, const TDesC& aFileToParse )
+ {
+ XHTMLLOG_WRITE( "CXhtmlParser::CreateDomL in" );
+ User::LeaveIfError( iXmlParser->ParseFile( aRFs, aFileToParse ) );
+ XHTMLLOG_WRITE( "CXhtmlParser::CreateDomL out" );
+ }
+
+// ---------------------------------------------------------
+// CXhtmlParser::CreateDomL
+// ---------------------------------------------------------
+//
+EXPORT_C void CXhtmlParser::CreateDomL( RFile& aFileHandleToParse )
+ {
+ XHTMLLOG_WRITE( "CXhtmlParser::CreateDomL in" );
+ User::LeaveIfError( iXmlParser->ParseFile( aFileHandleToParse ) );
+ XHTMLLOG_WRITE( "CXhtmlParser::CreateDomL out" );
+ }
+
+// ---------------------------------------------------------
+// CXhtmlParser::ParseL
+// ---------------------------------------------------------
+//
+EXPORT_C void CXhtmlParser::ParseL( CRichText& aRichText )
+ {
+ XHTMLLOG_WRITE( "CXhtmlParser::ParseL in" );
+ iRichText = &aRichText;
+
+ ResetValues();
+ ParseDomL( iXmlDocument);
+ XHTMLLOG_WRITE( "CXhtmlParser::ParseL out" );
+ }
+
+// ---------------------------------------------------------
+// CXhtmlParser::Cancel
+// ---------------------------------------------------------
+//
+EXPORT_C void CXhtmlParser::Cancel()
+ {
+ iXmlParser->Cancel();
+ }
+
+// ---------------------------------------------------------
+// CXhtmlParser::SetFonts
+// ---------------------------------------------------------
+//
+EXPORT_C void CXhtmlParser::SetFonts( const CFont* aBigFont,
+ const CFont* aDefaultFont,
+ const CFont* aSmallFont,
+ const CFont* aCourierFont )
+ {
+ iXhtmlFontSpecs->SetFonts( aBigFont, aDefaultFont, aSmallFont, aCourierFont );
+ }
+
+// ---------------------------------------------------------
+// CXhtmlParser::SetDefaultTextColor
+// ---------------------------------------------------------
+//
+EXPORT_C void CXhtmlParser::SetDefaultTextColor( TRgb aColor )
+ {
+ iTextColor = aColor;
+ }
+
+// ---------------------------------------------------------
+// CXhtmlParser::SetMode
+//
+// ---------------------------------------------------------
+//
+EXPORT_C void CXhtmlParser::SetMode( TBool aPlainText, TBool aShowUrls )
+ {
+ iPlainText = aPlainText;
+ iShowUrls = aShowUrls;
+ }
+
+// ---------------------------------------------------------
+// CXhtmlParser::HyperLink
+// ---------------------------------------------------------
+//
+EXPORT_C TInt CXhtmlParser::HyperLink( TInt aIndex,
+ TInt& aStartPos, TInt& aEndPos,
+ TPtrC& aAddress )
+ {
+ if ( aIndex >= iHyperLinkArray->Count() )
+ {
+ return KErrArgument;
+ }
+
+ CXhtmlHyperLink* hpLink = (*iHyperLinkArray)[aIndex];
+ aStartPos = hpLink->StartPosition();
+ aEndPos = hpLink->EndPosition();
+
+ if ( hpLink->Address() )
+ {
+ TPtr tmpPtr = hpLink->Address()->Des();
+ aAddress.Set( tmpPtr );
+ }
+ else
+ {
+ aAddress.Set(KNullString);
+ }
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------
+// CXhtmlParser::HyperLinkCount
+// ---------------------------------------------------------
+//
+EXPORT_C TInt CXhtmlParser::HyperLinkCount()
+ {
+ if ( iHyperLinkArray )
+ {
+ return iHyperLinkArray->Count();
+ }
+ return 0;
+ }
+
+// ---------------------------------------------------------
+// CXhtmlParser::ParseFileCompleteL
+// ---------------------------------------------------------
+//
+void CXhtmlParser::ParseFileCompleteL()
+ {
+ XHTMLLOG_WRITE( "CXhtmlParser::ParseFileCompleteL in" );
+ delete iXmlDocument;
+ iXmlDocument = iXmlParser->DetachXMLDoc();
+
+ TRAPD( error, iObserver->ParseCompleteL() );
+
+ if ( error )
+ {
+ iObserver->ParseError( error );
+ }
+ XHTMLLOG_WRITE( "CXhtmlParser::ParseFileCompleteL out" );
+ }
+
+// ---------------------------------------------------------
+// CXhtmlParser::CXhtmlParser
+// ---------------------------------------------------------
+//
+CXhtmlParser::CXhtmlParser( MXhtmlParserObserver* aParserObserver ) :
+ iParsingAllowed( EFalse ),
+ iPlainText( EFalse ),
+ iShowUrls( EFalse ),
+ iPreformatted( 0 ),
+ iAlignment( CParaFormat::ELeftAlign ),
+ iStylePos( KNoStylePosition ),
+ iNewParagraph( EFalse ),
+ iNewLines( 0 ),
+ iForcedNewLines( 0 ),
+ iSkipWhiteSpaces( ETrue ),
+ iAlignmentChanged( EFalse ),
+ iImageFound( EFalse ),
+ iFirstTextLineAdded( EFalse ),
+ iCurrentListContext( KNoListContext ),
+ iDefListLevel( 0 ),
+ iBlockQuoteLevel( 0 ),
+ iHyperLinkPos( 0 ),
+ iTextColor( KBlackColorCode ),
+ iObserver( aParserObserver ),
+ iIndentWidth( KDefaultIndentWidth ),
+ iMaxListLevels( KDefaultMaxListLevels )
+ {
+ }
+
+// ---------------------------------------------------------
+// CXhtmlParser::ConstructL
+// ---------------------------------------------------------
+//
+void CXhtmlParser::ConstructL()
+ {
+ iStackManager = CXhtmlStackManager::NewL();
+ iXmlParser = CMDXMLParser::NewL( this );
+
+// This enables the correction of the following bug:
+//
+// ID: TPHU-72BFLV
+// Title: MMS Viewer: Whitespace characters are consumed in XHTML text
+//
+// Partial correction to the bug is implemented in Symbian XML parser code.
+// This call sets XML parser to mode where all whitespaces are forwarded to
+// XHTML parser inside DOM document. So, actual whitespace handling is
+// implemented inside XHTML parser.
+
+ iXmlParser->SetWhiteSpaceHandlingMode( ETrue );
+
+ CXhtmlEntityConverter* converter =
+ new ( ELeave ) CXhtmlEntityConverter();
+
+ //Ownership transferred to XML parser
+ iXmlParser->SetEntityConverter( converter );
+
+ iXhtmlFontSpecs = new ( ELeave ) CXhtmlFontSpecs();
+ iHyperLinkArray = new ( ELeave ) CArrayPtrFlat<CXhtmlHyperLink>( KHyperLinkArrayGranularity );
+ }
+
+// ---------------------------------------------------------
+// CXhtmlParser::ParseDomL
+// ---------------------------------------------------------
+//
+void CXhtmlParser::ParseDomL( CMDXMLDocument* aXmlDocument )
+ {
+ XHTMLLOG_WRITE( "CXhtmlParser::ParseDomL in" );
+ TCharFormat charFormat;
+ TCharFormatMask charFormatMask;
+
+ charFormat.iFontSpec = iXhtmlFontSpecs->DefaultFont()->FontSpecInTwips();
+ charFormat.iFontPresentation.iTextColor = iTextColor;
+
+ charFormatMask.SetAttrib( EAttColor );
+ charFormatMask.SetAttrib( EAttFontTypeface );
+ charFormatMask.SetAttrib( EAttFontPosture );
+ charFormatMask.SetAttrib( EAttFontHeight );
+ charFormatMask.SetAttrib( EAttFontStrokeWeight );
+
+ // delete old CharFormatLayer
+
+ if( iCurrentCharLayer )
+ {
+ iCurrentCharLayer->Reset();
+ delete iCurrentCharLayer;
+ iCurrentCharLayer = NULL;
+ }
+
+ // create new CharFormatLayer based on GlobalCharFormatLayer and
+ // custom font/color
+
+ CCharFormatLayer* charFormatLayer = CCharFormatLayer::NewL( charFormat,
+ charFormatMask );
+
+ charFormatLayer->SetBase( iRichText->GlobalCharFormatLayer() );
+ iCurrentCharLayer = charFormatLayer;
+
+ CMDXMLNode* node = aXmlDocument->DocumentElement();
+
+ while( node )
+ {
+ OpenNodeL( node );
+
+ if( node->FirstChild() )
+ {
+ node = node->FirstChild();
+ }
+ else if( node->NextSibling() )
+ {
+ CloseNodeL( node );
+ node = node->NextSibling();
+ }
+ else
+ {
+ while( node )
+ {
+ CloseNodeL( node );
+
+ if( node->NextSibling() )
+ {
+ node = node->NextSibling();
+ break;
+ }
+ node = node->ParentNode();
+ }
+ }
+ }
+ XHTMLLOG_WRITE( "CXhtmlParser::ParseDomL out" );
+ }
+
+// ---------------------------------------------------------
+// CXhtmlParser::OpenNodeL
+// ---------------------------------------------------------
+//
+void CXhtmlParser::OpenNodeL( CMDXMLNode* aNode )
+ {
+ switch( aNode->NodeType() )
+ {
+ case CMDXMLNode::EElementNode:
+ {
+ CMDXMLElement* element = static_cast<CMDXMLElement*>( aNode );
+
+
+ // PrepareForBeginElementL does some operations needed before possible
+ // attributes are handled.
+ //
+ // In practice PrepareForBeginElementL adds a new style to stylestack
+ // If there is no attributes within this tag, this style is not used although
+ // it is on the stack
+
+ PrepareForBeginElementL( element->NodeName() );
+
+ // handle possible attributes related to begin tag
+
+ for( TInt i = 0; i<element->NumAttributes(); ++i )
+ {
+ TPtrC name;
+ TPtrC value;
+
+ if ( element->AttributeDetails( i, name, value ) == KErrNone )
+ {
+ AttributeValueL( name, value );
+ }
+ }
+
+ // Handles actual begin tag. If it doesn't cause changes to
+ // style or paragraphs, doesn't do anything
+
+ BeginElementL( element->NodeName() );
+ break;
+ }
+
+ case CMDXMLNode::ETextNode:
+ {
+ CMDXMLText* txt = static_cast<CMDXMLText*>( aNode );
+
+ // Adds actual text to CRichText object.
+ // Style and paragraph format are added later when
+ // end tags are handled
+
+ ContentL( txt->Data() );
+ break;
+ }
+
+ case CMDXMLNode::ECDATASectionNode:
+ {
+ // CDATA section skipped
+ break;
+ }
+
+ case CMDXMLNode::ECommentNode:
+ {
+ // comment skipped
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+ }
+
+// ---------------------------------------------------------
+// CXhtmlParser::CloseNode
+// ---------------------------------------------------------
+//
+void CXhtmlParser::CloseNodeL( CMDXMLNode* aNode )
+ {
+ if( aNode->NodeType()==CMDXMLNode::EElementNode )
+ {
+ EndElementL( aNode->NodeName() );
+ }
+ }
+
+// ---------------------------------------------------------
+// CXhtmlParser::PrepareForBeginElementL
+// ---------------------------------------------------------
+//
+void CXhtmlParser::PrepareForBeginElementL( const TDesC& aName )
+ {
+ iAlignmentChanged = EFalse;
+ iImageFound = EFalse;
+
+ if ( !aName.CompareF( KATag ) )
+ {
+ BeginHyperLink( iRichText->DocumentLength() );
+ }
+ else if ( !aName.CompareF( KImgTag ) )
+ {
+ iImageFound = ETrue;
+ }
+
+ BeginStyleL();
+ }
+
+// ---------------------------------------------------------
+// CXhtmlParser::BeginElementL
+// ---------------------------------------------------------
+//
+void CXhtmlParser::BeginElementL( const TDesC& aName )
+ {
+ iImageFound = EFalse;
+
+ // If default alignment changed within this tag, begin new paragraph with new alignment.
+ // Add information about changed alignment. This info is used later
+ // to end paragraph
+
+ if ( iAlignmentChanged )
+ {
+ iStackManager->StyleStack()->Top()->iAlignmentChanged = ETrue;
+ iAlignmentChanged = EFalse;
+
+ BeginParagraphL( iAlignment );
+ }
+
+ if( !aName.CompareF( KHtmlTag ) )
+ {
+ }
+ else if( !aName.CompareF( KHrTag ) )
+ {
+ BeginParagraphL( CParaFormat::ECenterAlign );
+ // default alignment is center
+
+ BeginStyleL();
+
+ TCharFormat charFormat;
+ TCharFormatMask charFormatMask;
+
+ charFormat.iFontSpec = iXhtmlFontSpecs->DefaultFont()->FontSpecInTwips();
+
+ charFormatMask.SetAttrib( EAttFontHeight );
+ charFormatMask.SetAttrib( EAttFontTypeface );
+ charFormatMask.SetAttrib( EAttFontPosture );
+ charFormatMask.SetAttrib( EAttFontStrokeWeight );
+
+ ChangeCurrentStyleL(charFormat, charFormatMask);
+ InsertTextL( KHrSeparator);
+ }
+ else if (!aName.CompareF( KDdTag ) )
+ {
+ BeginParagraphL( iAlignment );
+ iDefListLevel++;
+ }
+ else if (!aName.CompareF( KDtTag ) )
+ {
+ InsertLineBreak();
+ }
+ else if (!aName.CompareF( KDlTag ) )
+ {
+ InsertLineBreak();
+ BeginParagraphL( iAlignment );
+ }
+ else if( !aName.CompareF( KBodyTag ) )
+ {
+ BeginStyleL();
+ iParsingAllowed = ETrue;
+ }
+ else if( !aName.CompareF( KAbbrTag ) )
+ {
+ }
+ else if( !aName.CompareF( KAcronymTag ) )
+ {
+ }
+ else if( !aName.CompareF( KSpanTag ) )
+ {
+ }
+ else if( !aName.CompareF( KDivTag ) )
+ {
+ BeginParagraphL( iAlignment );
+ }
+ else if( !aName.CompareF( KBrTag ) )
+ {
+ InsertForcedLineBreak();
+ }
+ else if( !aName.CompareF( KPTag ) )
+ {
+ InsertLineBreak();
+ BeginParagraphL( iAlignment );
+ }
+ else if( !aName.CompareF( KSmallTag ) || !aName.CompareF( KBigTag ) )
+ {
+ TCharFormat charFormat;
+ TCharFormatMask charFormatMask;
+
+ charFormatMask.SetAttrib( EAttFontTypeface );
+ charFormatMask.SetAttrib( EAttFontPosture );
+ charFormatMask.SetAttrib( EAttFontHeight );
+ charFormatMask.SetAttrib( EAttFontStrokeWeight );
+
+ if ( !aName.CompareF( KSmallTag ) )
+ {
+ charFormat.iFontSpec = iXhtmlFontSpecs->SmallFont()->FontSpecInTwips();
+ }
+ else
+ {
+ charFormat.iFontSpec = iXhtmlFontSpecs->BigFont()->FontSpecInTwips();
+ }
+ BeginStyleL();
+ ChangeCurrentStyleL(charFormat, charFormatMask);
+ }
+
+ else if( !aName.CompareF( KFontTag ) )
+ {
+ }
+ else if( !aName.CompareF( KBTag ) || !aName.CompareF( KStrongTag ) )
+ {
+ TCharFormat charFormat;
+ TCharFormatMask charFormatMask;
+ charFormatMask.SetAttrib( EAttFontStrokeWeight );
+ charFormat.iFontSpec.iFontStyle.SetStrokeWeight( EStrokeWeightBold );
+
+ BeginStyleL();
+ ChangeCurrentStyleL(charFormat, charFormatMask);
+ }
+ else if( !aName.CompareF( KITag ) || !aName.CompareF( KEmTag ) ||
+ !aName.CompareF( KCiteTag ) || !aName.CompareF( KDfnTag ) ||
+ !aName.CompareF( KVarTag ) )
+ {
+ TCharFormat charFormat;
+ TCharFormatMask charFormatMask;
+
+ charFormatMask.SetAttrib( EAttFontPosture );
+ charFormat.iFontSpec.iFontStyle.SetPosture( EPostureItalic );
+
+ BeginStyleL();
+ ChangeCurrentStyleL( charFormat, charFormatMask);
+ }
+ else if( !aName.CompareF( KAddressTag ) )
+ {
+ TCharFormat charFormat;
+ TCharFormatMask charFormatMask;
+
+ charFormatMask.SetAttrib( EAttFontPosture );
+ charFormat.iFontSpec.iFontStyle.SetPosture( EPostureItalic );
+
+ BeginStyleL();
+ ChangeCurrentStyleL(charFormat, charFormatMask);
+
+ InsertLineBreak();
+ }
+ else if( !aName.CompareF( KKbdTag ) || !aName.CompareF( KCodeTag ) ||
+ !aName.CompareF( KSampTag ) )
+ {
+ TCharFormat charFormat;
+ TCharFormatMask charFormatMask;
+
+ charFormatMask.SetAttrib( EAttFontTypeface );
+ charFormatMask.SetAttrib( EAttFontPosture );
+ charFormatMask.SetAttrib( EAttFontHeight );
+ charFormatMask.SetAttrib( EAttFontStrokeWeight );
+
+ charFormat.iFontSpec = iXhtmlFontSpecs->CourierFont()->FontSpecInTwips();
+
+ BeginStyleL();
+ ChangeCurrentStyleL( charFormat, charFormatMask );
+ }
+ else if( !aName.CompareF( KBlockquoteTag ) )
+ {
+ InsertLineBreak();
+ BeginParagraphL( iAlignment );
+
+ iBlockQuoteLevel++;
+ }
+ else if( !aName.CompareF( KPreTag ) )
+ {
+ if ( iPreformatted == 0 )
+ {
+ InsertLineBreak();
+ InsertLineBreak();
+ }
+ iPreformatted++;
+ }
+ else if( !aName.CompareF( KQTag ) )
+ {
+ }
+ else if ( !aName.CompareF( KH1Tag ) || !aName.CompareF( KH2Tag ) ||
+ !aName.CompareF( KH3Tag )|| !aName.CompareF( KH4Tag ) ||
+ !aName.CompareF( KH5Tag )|| !aName.CompareF( KH6Tag ) )
+ {
+ InsertLineBreak();
+ BeginParagraphL( iAlignment );
+ BeginStyleL();
+
+ TCharFormat charFormat;
+ TCharFormatMask charFormatMask;
+
+ charFormatMask.SetAttrib( EAttFontTypeface );
+ charFormatMask.SetAttrib( EAttFontPosture );
+ charFormatMask.SetAttrib( EAttFontHeight );
+ charFormatMask.SetAttrib( EAttFontStrokeWeight );
+
+ if ( !aName.CompareF( KH1Tag ) )
+ {
+ charFormat.iFontSpec = iXhtmlFontSpecs->H1Font()->FontSpecInTwips();
+ }
+ else if ( !aName.CompareF( KH2Tag ) )
+ {
+ charFormat.iFontSpec = iXhtmlFontSpecs->H2Font()->FontSpecInTwips();
+ }
+ else if ( !aName.CompareF( KH3Tag ) )
+ {
+ charFormat.iFontSpec = iXhtmlFontSpecs->H3Font()->FontSpecInTwips();
+ }
+ else if ( !aName.CompareF( KH4Tag ) )
+ {
+ charFormat.iFontSpec = iXhtmlFontSpecs->H4Font()->FontSpecInTwips();
+ }
+ else if ( !aName.CompareF( KH5Tag ) )
+ {
+ charFormat.iFontSpec = iXhtmlFontSpecs->H5Font()->FontSpecInTwips();
+ }
+ else
+ {
+ charFormat.iFontSpec = iXhtmlFontSpecs->H6Font()->FontSpecInTwips();
+ }
+
+ charFormat.iFontSpec.iFontStyle.SetStrokeWeight( EStrokeWeightBold );
+ ChangeCurrentStyleL(charFormat, charFormatMask);
+ }
+ else if( !aName.CompareF( KUlTag ) )
+ {
+ BeginListL( KUnorderedListContext );
+ }
+ else if( !aName.CompareF( KOlTag ) )
+ {
+ BeginListL( KOrderedListContext );
+ }
+ else if ( !aName.CompareF( KLiTag ) )
+ {
+ BeginListItemL();
+ BeginStyleL();
+ }
+ }
+
+// ---------------------------------------------------------
+// CXhtmlParser::EndElementL
+// ---------------------------------------------------------
+//
+void CXhtmlParser::EndElementL( const TDesC& aName )
+ {
+ if ( !aName.CompareF( KHtmlTag ) )
+ {
+ ApplyStyleL();
+
+ // last line break to the end of the document
+ iRichText->InsertL( iRichText->DocumentLength(),
+ CRichText::ELineBreak );
+ }
+ else if ( !aName.CompareF( KBodyTag ) )
+ {
+ EndStyleL();
+ iParsingAllowed = EFalse;
+ }
+ else if ( !aName.CompareF( KATag ) )
+ {
+ EndHyperLinkL( iRichText->DocumentLength() );
+ }
+ else if ( !aName.CompareF( KDdTag ) )
+ {
+ EndParagraphL();
+ iDefListLevel--;
+ }
+ else if ( !aName.CompareF( KDtTag ) )
+ {
+ }
+ else if ( !aName.CompareF( KDlTag ) )
+ {
+ InsertLineBreak();
+ EndParagraphL();
+ }
+ else if( !aName.CompareF( KSmallTag ) || !aName.CompareF( KBigTag ) )
+ {
+ EndStyleL();
+ }
+ else if ( !aName.CompareF( KBTag ) || !aName.CompareF( KStrongTag ) )
+ {
+ EndStyleL();
+ }
+ else if ( !aName.CompareF( KITag ) || !aName.CompareF( KEmTag ) ||
+ !aName.CompareF( KCiteTag ) || !aName.CompareF( KDfnTag ) ||
+ !aName.CompareF( KVarTag ) )
+ {
+ EndStyleL();
+ }
+ else if ( !aName.CompareF( KAddressTag ) )
+ {
+ InsertLineBreak();
+ EndStyleL();
+ }
+ else if ( !aName.CompareF( KKbdTag ) || !aName.CompareF( KCodeTag ) ||
+ !aName.CompareF( KSampTag ) )
+ {
+ EndStyleL();
+ }
+ else if ( !aName.CompareF( KBlockquoteTag ) )
+ {
+ InsertLineBreak();
+ EndParagraphL();
+ iBlockQuoteLevel--;
+ }
+ else if ( !aName.CompareF( KPreTag ) )
+ {
+ if ( iPreformatted > 0 )
+ {
+ iPreformatted--;
+
+ if ( iPreformatted == 0 )
+ {
+ InsertLineBreak();
+ InsertLineBreak();
+ }
+ }
+ }
+ else if ( !aName.CompareF( KPTag ) )
+ {
+ InsertLineBreak();
+ EndParagraphL();
+ }
+ else if ( !aName.CompareF( KDivTag ) )
+ {
+ EndParagraphL();
+ }
+ else if ( !aName.CompareF( KQTag ) )
+ {
+ }
+ else if ( !aName.CompareF( KH1Tag ) || !aName.CompareF( KH2Tag ) ||
+ !aName.CompareF( KH3Tag )|| !aName.CompareF( KH4Tag ) ||
+ !aName.CompareF( KH5Tag )|| !aName.CompareF( KH6Tag ) )
+ {
+ EndStyleL();
+ InsertLineBreak();
+ EndParagraphL();
+ }
+ else if ( !aName.CompareF( KLiTag ) )
+ {
+ EndStyleL();
+ }
+ else if ( !aName.CompareF( KUlTag ) || !aName.CompareF( KOlTag ) )
+ {
+ EndListL();
+ }
+ else if( !aName.CompareF( KHrTag ) )
+ {
+ EndStyleL();
+ InsertLineBreak();
+ EndParagraphL();
+ }
+ else if( !aName.CompareF( KBrTag ) )
+ {
+ }
+
+ // if alignment was changed and a new paragraph added, end this paragraph
+
+ if ( iStackManager->StyleStack()->Top() && iStackManager->StyleStack()->Top()->iAlignmentChanged )
+ {
+ EndParagraphL();
+ }
+ EndStyleL(); // BeginStyleL has been called in PrepareForBeginElementL
+ }
+
+// ---------------------------------------------------------
+// CXhtmlParser::BeginStyleL
+// ---------------------------------------------------------
+//
+void CXhtmlParser::BeginStyleL()
+ {
+ if ( iStackManager->StyleStack()->Top() )
+ {
+ if ( iStylePos == KNoStylePosition )
+ {
+ iStylePos = iStackManager->StyleStack()->Top()->iStyleStart;
+ }
+ }
+ TXhtmlStyleInfo* style = new( ELeave )
+ TXhtmlStyleInfo( iRichText->DocumentLength(), iAlignment );
+
+ iStackManager->StyleStack()->PushL( style );
+ }
+
+// ---------------------------------------------------------
+// CXhtmlParser::EndStyleL
+// ---------------------------------------------------------
+//
+void CXhtmlParser::EndStyleL()
+ {
+ if ( iStackManager->StyleStack()->Top() )
+ {
+ if ( iStylePos == KNoStylePosition )
+ {
+ iStylePos = iStackManager->StyleStack()->Top()->iStyleStart;
+ }
+ if ( iStackManager->StyleStack()->Top()->iStyleChanged )
+ {
+ ApplyStyleL();
+ iStylePos = KNoStylePosition;
+ iCurrentCharLayer = CleanCharLayer();
+ }
+ iAlignment = iStackManager->StyleStack()->Top()->iPrevAlign;
+ }
+
+ iStackManager->StyleStack()->Pop();
+
+ if ( iStackManager->StyleStack()->Top() )
+ {
+ iStackManager->StyleStack()->Top()->iStyleStart = iRichText->DocumentLength();
+ }
+ }
+
+// ---------------------------------------------------------
+// CXhtmlParser::ChangeCurrentStyleL
+// ---------------------------------------------------------
+//
+void CXhtmlParser::ChangeCurrentStyleL(TCharFormat charFormat,
+ TCharFormatMask charFormatMask)
+ {
+ ApplyStyleL();
+ iStylePos = KNoStylePosition;
+
+ if ( iStackManager->StyleStack()->Top() )
+ {
+ iStackManager->StyleStack()->Top()->iStyleChanged = ETrue;
+ }
+
+ CCharFormatLayer* cfl =
+ CCharFormatLayer::NewL( charFormat, charFormatMask );
+ cfl->SetBase( iCurrentCharLayer );
+ iCurrentCharLayer = cfl;
+ }
+
+// ---------------------------------------------------------
+// CXhtmlParser::ApplyStyle
+// ---------------------------------------------------------
+//
+void CXhtmlParser::ApplyStyleL()
+ {
+ if ( iStylePos != KNoStylePosition && ( iRichText->DocumentLength() - iStylePos > 0 ) )
+ {
+ TCharFormat charFormat;
+ TCharFormatMask charFormatMask;
+
+ iCurrentCharLayer->SenseEffective( charFormat );
+ charFormatMask.SetAll();
+
+ if ( !iPlainText )
+ {
+ iRichText->ApplyCharFormatL( charFormat, charFormatMask,
+ iStylePos, iRichText->DocumentLength() - iStylePos );
+ }
+
+ }
+ }
+
+// ---------------------------------------------------------
+// CXhtmlParser::BeginParagraphL
+// ---------------------------------------------------------
+//
+void CXhtmlParser::BeginParagraphL( CParaFormat::TAlignment aAlignment )
+ {
+ if ( iStackManager->ParaStack()->Top() )
+ {
+ ApplyParagraphL( iStackManager->ParaStack()->Top()->iParaStart,
+ iStackManager->ParaStack()->Top()->iAlignment );
+ }
+ if ( iFirstTextLineAdded )
+ {
+ AppendParagraphL( iPlainText );
+ }
+ else
+ {
+ iNewParagraph = ETrue;
+ }
+ TXhtmlParaInfo* info = new( ELeave ) TXhtmlParaInfo( iRichText->DocumentLength(), aAlignment );
+ iStackManager->ParaStack()->PushL( info );
+ }
+
+// ---------------------------------------------------------
+// CXhtmlParser::EndParagraphL
+// ---------------------------------------------------------
+//
+void CXhtmlParser::EndParagraphL()
+ {
+ if (iStackManager->ParaStack()->Top())
+ {
+ ApplyParagraphL( iStackManager->ParaStack()->Top()->iParaStart,
+ iStackManager->ParaStack()->Top()->iAlignment );
+
+ if ( iFirstTextLineAdded )
+ {
+ AppendParagraphL( iPlainText );
+ }
+ else
+ {
+ iNewParagraph = ETrue;
+ }
+ }
+
+ iStackManager->ParaStack()->Pop();
+
+ if ( iStackManager->ParaStack()->Top() )
+ {
+ iStackManager->ParaStack()->Top()->iParaStart = iRichText->DocumentLength();
+ }
+ }
+
+// ---------------------------------------------------------
+// CXhtmlParser::ApplyParagraphL
+// ---------------------------------------------------------
+//
+void CXhtmlParser::ApplyParagraphL( TInt aParaStart,
+ CParaFormat::TAlignment aAlignment )
+ {
+ TInt docLength = iRichText->DocumentLength();
+ TInt paraLength = docLength - aParaStart;
+
+ if ( paraLength > 0 )
+ {
+ CParaFormat* paraFormat = CParaFormat::NewL();
+ CleanupStack::PushL( paraFormat );
+ TParaFormatMask paraFormatMask = TParaFormatMask();
+
+ if ( aAlignment != CParaFormat::EUnspecifiedAlign )
+ {
+ paraFormatMask.SetAttrib( EAttAlignment );
+ paraFormat->iHorizontalAlignment = aAlignment;
+ }
+
+ CGraphicsDevice* screenDevice = CCoeEnv::Static()->ScreenDevice();
+
+ TInt indentWidthInTwips = iIndentWidth * screenDevice->HorizontalPixelsToTwips(
+ iXhtmlFontSpecs->DefaultFont()->CharWidthInPixels( TChar(' ') ) );
+
+ // check limits
+
+ TInt leftLevel =
+ ( ( iStackManager->ListStack()->Count() + iDefListLevel + iBlockQuoteLevel ) < iMaxListLevels )
+ ? ( iStackManager->ListStack()->Count() + iDefListLevel + iBlockQuoteLevel ) : iMaxListLevels;
+
+ TInt rightLevel = ( iBlockQuoteLevel < iMaxListLevels ) ? iBlockQuoteLevel : iMaxListLevels;
+
+ // set indents
+
+ paraFormat->iLeftMarginInTwips = leftLevel * indentWidthInTwips;
+ paraFormat->iRightMarginInTwips = rightLevel * indentWidthInTwips;
+
+ paraFormatMask.SetAttrib( EAttLeftMargin );
+ paraFormatMask.SetAttrib( EAttRightMargin );
+
+ if (!iPlainText)
+ {
+ iRichText->ApplyParaFormatL( paraFormat, paraFormatMask, aParaStart,
+ paraLength );
+
+ }
+ CleanupStack::PopAndDestroy( paraFormat );
+ }
+ }
+
+// ---------------------------------------------------------
+// CXhtmlParser::BeginListL
+// ---------------------------------------------------------
+//
+void CXhtmlParser::BeginListL(TInt aListContext)
+ {
+ if ( iStackManager->ListStack()->Count() == 0 && iDefListLevel == 0)
+ {
+ InsertLineBreak();
+ }
+ BeginParagraphL( iAlignment );
+
+ TXhtmlListInfo* info = new( ELeave ) TXhtmlListInfo( iCurrentListContext );
+ iStackManager->ListStack()->PushL( info );
+
+ iCurrentListContext = aListContext;
+ }
+
+// ---------------------------------------------------------
+// CXhtmlParser::EndList
+// ---------------------------------------------------------
+//
+void CXhtmlParser::EndListL()
+ {
+ if ( ( iStackManager->ListStack()->Count() + iDefListLevel ) <= 1 )
+ {
+ InsertLineBreak();
+ }
+ EndParagraphL();
+
+ if (iStackManager->ListStack()->Top())
+ {
+ iCurrentListContext = iStackManager->ListStack()->Top()->iListContext;
+ }
+ iStackManager->ListStack()->Pop();
+ }
+
+// ---------------------------------------------------------
+// CXhtmlParser::BeginListItemL
+// ---------------------------------------------------------
+//
+void CXhtmlParser::BeginListItemL()
+ {
+ TXhtmlListInfo *info = iStackManager->ListStack()->Top();
+ if ( !info )
+ {
+ return;
+ }
+
+ if ( ( info->iListIndex > 0 ) && ( iNewLines == 0 ) && ( iForcedNewLines == 0 ) )
+ {
+ iRichText->InsertL( iRichText->DocumentLength(),
+ CRichText::EParagraphDelimiter );
+ }
+
+ info->iListIndex++;
+
+ if ( iCurrentListContext == KOrderedListContext )
+ {
+ TBuf16<16> prefix;
+ prefix.Format( KListNumberFormat, info->iListIndex );
+
+ HBufC* tmpString = prefix.AllocLC();
+
+ TPtrC result;
+ DoNumberConversion( tmpString, result );
+
+ InsertTextL( result );
+ CleanupStack::PopAndDestroy( tmpString );
+ }
+ else
+ {
+ if ( iPlainText )
+ {
+ TInt bullet = ( iStackManager->ListStack()->Count() % 2 ) ? KPlainBullet : KPlainBullet2 ;
+ InsertCharacterL( TChar( bullet ) );
+ }
+ else
+ {
+ TInt bullet = ( iStackManager->ListStack()->Count() % 2 ) ? KListBullet : KListBullet2 ;
+ InsertCharacterL( TChar( bullet) );
+ }
+ }
+ }
+
+// ---------------------------------------------------------
+// CXhtmlParser::BeginHyperLinkL
+// ---------------------------------------------------------
+//
+void CXhtmlParser::BeginHyperLink( TInt aBeginPosition )
+ {
+ XHTMLLOG_WRITE( "BeginHyperLinkL" );
+
+ delete iHyperLinkAddress;
+ iHyperLinkAddress = NULL;
+
+ iHyperLinkPos = aBeginPosition;
+ }
+
+// ---------------------------------------------------------
+// CXhtmlParser::EndHyperLinkL
+// ---------------------------------------------------------
+//
+void CXhtmlParser::EndHyperLinkL( TInt aEndPosition )
+ {
+ XHTMLLOG_WRITE( "EndHyperLinkL");
+
+ if ( iHyperLinkAddress )
+ {
+ CXhtmlHyperLink* hpLink = new (ELeave) CXhtmlHyperLink( iHyperLinkPos,
+ aEndPosition - 1 );
+
+ TPtrC addrPtr = iHyperLinkAddress->Des();
+ hpLink->SetAddressL(addrPtr);
+
+ delete iHyperLinkAddress;
+ iHyperLinkAddress = NULL;
+
+ iHyperLinkArray->InsertL( iHyperLinkArray->Count(), hpLink );
+
+ if ( iShowUrls )
+ {
+ InsertCharacterL( TChar(' ') );
+ InsertCharacterL( TChar('(') );
+ InsertTextL( hpLink->Address()->Des() );
+ InsertCharacterL( TChar(')') );
+ }
+ }
+ }
+
+// ---------------------------------------------------------
+// CXhtmlParser::ContentL
+// ---------------------------------------------------------
+//
+void CXhtmlParser::ContentL( const TDesC& aData )
+ {
+ if ( !iParsingAllowed )
+ {
+ return;
+ }
+
+ HBufC16* buffer = aData.Alloc();
+ CleanupStack::PushL( buffer );
+
+ TPtr16 bufferPtr = buffer->Des();
+
+ if( iPreformatted > 0 )
+ {
+ // XHTML parsing, pre tag specified (preformatted text)
+
+ TInt offset = 0;
+ TInt poffset = 0;
+
+ TChar LF( 0x0A );
+ TChar CR( 0x0D );
+
+ if( bufferPtr.Locate( LF ) > 0 || bufferPtr.Locate( CR ) > 0 )
+ {
+ while( offset < bufferPtr.Length() )
+ {
+ TPtrC16 theRest = bufferPtr.Mid( offset );
+
+ poffset = theRest.Locate( CR );
+
+ if( poffset != KErrNotFound )
+ {
+ TPtrC16 first = theRest.Mid( 0, poffset );
+ InsertTextL( first );
+
+ iRichText->InsertL( iRichText->DocumentLength(),
+ CRichText::ELineBreak );
+
+ offset = offset + poffset + 1;
+
+ // if next character is LF, add offset by one
+
+ if ( theRest.Locate( LF ) == poffset + 1)
+ {
+ offset++;
+ }
+ }
+ else
+ {
+ poffset = theRest.Locate( LF );
+
+ if( poffset != KErrNotFound )
+ {
+ TPtrC16 first = theRest.Mid( 0, poffset );
+ InsertTextL( first );
+
+ iRichText->InsertL( iRichText->DocumentLength(),
+ CRichText::ELineBreak );
+
+ offset = offset + poffset + 1;
+ }
+ else
+ {
+ InsertTextL( theRest );
+ break;
+ }
+ }
+ } // while
+ }
+ else
+ {
+ // no newline(s) found, insert text as such
+ InsertTextL( bufferPtr );
+ }
+ }
+ else
+ {
+ // XHTML parsing, pre tag not specified (extra whitespaces removed)
+ CollapseWhiteSpaces( bufferPtr );
+
+ if (bufferPtr.Length() > 0)
+ {
+ InsertTextL( bufferPtr );
+ }
+ }
+ CleanupStack::PopAndDestroy( buffer );
+ }
+
+// ---------------------------------------------------------
+// CXhtmlParser::CollapseWhiteSpaces
+//
+// Function processes the whole text and converts any
+// found sequence of white spaces into single space.
+// ---------------------------------------------------------
+//
+void CXhtmlParser::CollapseWhiteSpaces( TDes& aData )
+ {
+ TInt whiteSpaces( 0 );
+ TInt currentPos( 0 );
+
+ while( currentPos < aData.Length() )
+ {
+ if( aData[currentPos] == CEditableText::ESpace ||
+ aData[currentPos] == KZeroWidthSpace ||
+ ( aData[currentPos] >= 0x0009 && aData[currentPos] <= 0x000d ) )
+ {
+ whiteSpaces++;
+ }
+ else if( whiteSpaces > 0 )
+ {
+ currentPos = currentPos - whiteSpaces;
+
+ if (iSkipWhiteSpaces)
+ {
+ aData.Delete( currentPos, whiteSpaces );
+ iSkipWhiteSpaces = EFalse;
+ }
+ else
+ {
+ aData.Replace( currentPos, whiteSpaces, KWhiteSpace );
+ }
+ whiteSpaces = 0;
+ }
+ else
+ {
+ // no whitespaces at the beginning
+ iSkipWhiteSpaces = EFalse;
+ }
+ currentPos++;
+ }
+
+ if( whiteSpaces > 0 )
+ {
+ if (iSkipWhiteSpaces)
+ {
+ aData.Delete( currentPos - whiteSpaces, whiteSpaces );
+ }
+ else
+ {
+ aData.Replace( currentPos - whiteSpaces, whiteSpaces, KWhiteSpace );
+ }
+ }
+ }
+
+// ---------------------------------------------------------
+// CXhtmlParser::AttributeValueL
+// ---------------------------------------------------------
+//
+void CXhtmlParser::AttributeValueL( const TDesC& aName, const TDesC& aValue )
+ {
+ CParaFormat::TAlignment alignment = iAlignment;
+
+ if( !aName.CompareF( KHrefAttr ) )
+ {
+ SetReferenceL( aValue );
+ }
+ if( !aName.CompareF( KStyleAttr ) )
+ {
+ TRgb colorValue = 0;
+ TBool colorAttr = EFalse;
+ TBool underlineAttr = EFalse;
+
+ TInt offset = 0;
+ TInt poffset = 0;
+
+ HBufC16* buffer = aValue.AllocLC();
+
+ TPtr16 bufferPtr = buffer->Des();
+
+ RemoveAllSpace( bufferPtr );
+
+ TPtrC nameStyle;
+ TPtrC valueStyle;
+ TBool transparent = EFalse;
+
+ while( offset < bufferPtr.Length() )
+ {
+ TPtrC16 theRest = bufferPtr.Mid( offset );
+ poffset = theRest.Locate( TChar( KSemicolon ) );
+
+ if( poffset != KErrNotFound )
+ {
+ TPtrC16 first = theRest.Mid( 0, poffset );
+ SplitAttribute( first, nameStyle, valueStyle );
+ offset = offset + poffset + 1;
+ }
+ else
+ {
+ SplitAttribute( theRest, nameStyle, valueStyle );
+ offset = bufferPtr.Length();
+ }
+
+ if( !nameStyle.CompareF( KColorAttr ) )
+ {
+ colorValue = ParseColor( valueStyle, transparent );
+ colorAttr = ETrue;
+ }
+
+ if ( !nameStyle.CompareF( KTextDecorationAttr ) &&
+ !valueStyle.CompareF( KUnderlineAttr ) )
+ {
+ underlineAttr = ETrue;
+ }
+
+ if( !nameStyle.CompareF( KTextAlignAttr ) )
+ {
+ //left
+ if ( !valueStyle.CompareF( KLeftAttr ) )
+ {
+ //set the align-value and use it in the paragraph-tag if set
+ iAlignment = CParaFormat::ELeftAlign;
+ }
+ //center
+ else if( !valueStyle.CompareF( KCenterAttr ) )
+ {
+ iAlignment = CParaFormat::ECenterAlign;
+ }
+
+ //right
+ else if( !valueStyle.CompareF( KRightAttr ) )
+ {
+ iAlignment = CParaFormat::ERightAlign;
+ }
+
+ //justified
+ else if( !valueStyle.CompareF( KJustifyAttr ) )
+ {
+ iAlignment = CParaFormat::EJustifiedAlign;
+ }
+ }
+ }
+
+ CleanupStack::PopAndDestroy( buffer );
+
+ TCharFormat charFormat;
+ TCharFormatMask charFormatMask;
+
+ if( colorAttr )
+ {
+ charFormatMask.SetAttrib( EAttColor );
+ charFormat.iFontPresentation.iTextColor = colorValue;
+ }
+ if ( underlineAttr )
+ {
+ charFormatMask.SetAttrib( EAttFontUnderline );
+ charFormat.iFontPresentation.iUnderline = EUnderlineOn;
+ }
+ ChangeCurrentStyleL(charFormat, charFormatMask);
+ }
+
+ if( !aName.CompareF( KColorAttr ) )
+ {
+ TBool transparent = EFalse;
+ TRgb color = ParseColor( aValue, transparent );
+
+ TCharFormat charFormat;
+ TCharFormatMask charFormatMask;
+
+ charFormatMask.SetAttrib( EAttColor );
+ charFormat.iFontPresentation.iTextColor = color;
+ ChangeCurrentStyleL(charFormat, charFormatMask);
+ }
+ else if( !aName.CompareF( KAltAttr ) )
+ {
+ if( aValue.Length() > 0 && iImageFound)
+ {
+ InsertTextL( aValue );
+ }
+ }
+ if ( alignment != iAlignment )
+ {
+ iAlignmentChanged = ETrue;
+ }
+ }
+
+// ---------------------------------------------------------
+// CXhtmlParser::SetReferenceL()
+// ---------------------------------------------------------
+//
+void CXhtmlParser::SetReferenceL( const TDesC& aUrl )
+ {
+ delete iHyperLinkAddress;
+ iHyperLinkAddress = NULL;
+
+ iHyperLinkAddress = HBufC::NewL( aUrl.Length() );
+ TPtr ptr = iHyperLinkAddress->Des();
+ ptr = aUrl;
+ }
+
+// ---------------------------------------------------------
+// CXhtmlParser::RemoveAllSpace
+// ---------------------------------------------------------
+//
+void CXhtmlParser::RemoveAllSpace( TDes& aString )
+ {
+ const TChar KSpace = TChar( ' ' );
+ for( TInt offset = aString.Locate( KSpace ); offset != KErrNotFound;
+ offset = aString.Locate( KSpace ) )
+ {
+ aString.Delete( offset, 1 );
+ }
+ }
+
+// ---------------------------------------------------------
+// CXhtmlParser::SplitAttribute
+// ---------------------------------------------------------
+//
+void CXhtmlParser::SplitAttribute( TPtrC& aString, TPtrC& aAttributeName,
+ TPtrC& aAttributeValue )
+ {
+ TInt offset = 0;
+ TInt poffset = 0;
+ TInt start = 0;
+
+ if( aString.Locate( TChar( KColon ) ) > 0 )
+ {
+ while( offset < aString.Length() )
+ {
+ TPtrC16 theRest = aString.Mid( offset );
+ poffset = theRest.Locate( TChar ( KColon ) );
+
+ if( poffset != KErrNotFound )
+ {
+ aAttributeName.Set( theRest.Mid( start, poffset ) );
+ aAttributeValue.Set( theRest.Mid( poffset + 1 ) );
+ return;
+ }
+ }
+ }
+ }
+
+// ---------------------------------------------------------
+// CXhtmlParser::ParseColor
+// ---------------------------------------------------------
+//
+TRgb CXhtmlParser::ParseColor( const TDesC& aString, TBool& aTransparent )
+ {
+ aTransparent = ETrue;
+ TRgb res = 0;
+ if ( aString.Length()>1 )
+ {
+ TUint32 val = 0;
+ if( aString[0] == '#' )
+ {
+ TLex lexer ( aString.Mid( 1 ) );
+ if( lexer.Val( val, EHex, KWhiteColorCode )==KErrNone )
+ {
+ res = TRgb ((val&KBlueColorCode)>>16,
+ (val&KLimeColorCode)>>8, (val&KRedColorCode));
+ aTransparent = EFalse;
+ }
+ }
+ else if ( aString == KTransparentVal )
+ {
+ aTransparent = ETrue;
+ }
+ else
+ {
+ for( TInt n = 0; KColorNames[n]; n++ )
+ {
+
+ if ( !aString.CompareF( TPtrC(KColorNames[n]) ) )
+ {
+ res = KColorValues[n];
+
+ aTransparent = EFalse;
+ break;
+ }
+ }
+ }
+ }
+ return res;
+ }
+
+// ---------------------------------------------------------
+// CXhtmlParser::CdataL
+// ---------------------------------------------------------
+//
+void CXhtmlParser::CdataL( const TDesC& aData )
+ {
+ if ( iParsingAllowed )
+ {
+ InsertTextL( aData );
+ }
+ }
+
+// ---------------------------------------------------------
+// CXhtmlParser::CleanCharLayer
+// ---------------------------------------------------------
+//
+CCharFormatLayer* CXhtmlParser::CleanCharLayer()
+ {
+ CCharFormatLayer* cfl = iCurrentCharLayer;
+ const CCharFormatLayer* layer = static_cast<const CCharFormatLayer*>( cfl->SenseBase() );
+ iCurrentCharLayer = const_cast<CCharFormatLayer*>( layer );
+
+ cfl->Reset();
+ delete cfl;
+ return iCurrentCharLayer;
+ }
+
+// ---------------------------------------------------------
+// Convert between arabic-indic digits and european digits based on existing language setting.
+// So it'll convert any digit from the string
+// to use either european digits or arabic-indic digits based on current settings.
+// @param aFieldString: Data buffer used in conversion.
+// @param aFieldData: Return converted data in this parameter.
+// ---------------------------------------------------------
+//
+void CXhtmlParser::DoNumberConversion( HBufC* aFieldString, TPtrC& aFieldData ) const
+ {
+ if( aFieldString )
+ {
+ TPtr tmpPtr = aFieldString->Des();
+ if ( tmpPtr.Length() > 0 )
+ {
+ AknTextUtils::DisplayTextLanguageSpecificNumberConversion( tmpPtr );
+ }
+ aFieldData.Set( tmpPtr );
+ }
+ else
+ {
+ aFieldData.Set(KNullString);
+ }
+ }
+
+// ---------------------------------------------------------
+// CXhtmlParser::ResetValuesL
+// ---------------------------------------------------------
+//
+void CXhtmlParser::ResetValues()
+ {
+ iParsingAllowed = EFalse;
+ iPreformatted = 0;
+ iAlignment = CParaFormat::ELeftAlign;
+ iStylePos = KNoStylePosition;
+ iNewParagraph = EFalse;
+ iNewLines = 0;
+ iForcedNewLines = 0;
+ iSkipWhiteSpaces = ETrue;
+ iAlignmentChanged = EFalse;
+ iImageFound = EFalse;
+ iFirstTextLineAdded = EFalse;
+ iCurrentListContext = KNoListContext;
+ iDefListLevel = 0;
+ iBlockQuoteLevel = 0;
+ iHyperLinkPos = 0;
+ iHyperLinkArray->ResetAndDestroy();
+ }
+
+// ---------------------------------------------------------
+// CXhtmlParser::InsertTextL
+// ---------------------------------------------------------
+//
+void CXhtmlParser::InsertTextL( const TDesC& aText )
+ {
+#ifdef USE_LOGGER
+ XHTMLLOG_WRITE( "InsertTextL" );
+ HBufC* buf = HBufC::NewL( aText.Length() +4 );
+ buf->Des().Append(_L("["));
+ buf->Des().Append(aText);
+ buf->Des().Append(_L("]"));
+ XHTMLLOG_WRITEF( _L("%S"), buf );
+ delete buf;
+#endif
+
+ TInt maxLines = ( iNewLines > iForcedNewLines ) ? iNewLines : iForcedNewLines;
+
+ if ( !iFirstTextLineAdded )
+ {
+ maxLines = iForcedNewLines;
+ }
+
+ if ( iNewParagraph )
+ {
+ maxLines--;
+ }
+
+ for ( TInt i = 0; i < maxLines; i++ )
+ {
+ iRichText->InsertL( iRichText->DocumentLength(),
+ CRichText::ELineBreak );
+ }
+ iRichText->InsertL( iRichText->DocumentLength(), aText );
+
+ iNewParagraph = EFalse;
+ iNewLines = 0;
+ iForcedNewLines = 0;
+
+ iFirstTextLineAdded = ETrue;
+ }
+
+// ---------------------------------------------------------
+// CXhtmlParser::InsertCharacterL
+// ---------------------------------------------------------
+//
+void CXhtmlParser::InsertCharacterL( const TChar aText )
+ {
+#ifdef USE_LOGGER
+ XHTMLLOG_WRITE( "InsertCharacterL" );
+
+ TBuf<2048> b;
+ b.Append(_L("["));
+ b.Append(aText);
+ b.Append(_L("]"));
+ XHTMLLOG_WRITEF( b );
+#endif
+
+ TInt maxLines = ( iNewLines > iForcedNewLines ) ? iNewLines : iForcedNewLines;
+
+ if ( !iFirstTextLineAdded )
+ {
+ maxLines = iForcedNewLines;
+ }
+
+ if ( iNewParagraph )
+ {
+ maxLines--;
+ }
+
+ for ( TInt i = 0; i < maxLines; i++ )
+ {
+ iRichText->InsertL( iRichText->DocumentLength(),
+ CRichText::ELineBreak );
+ }
+ iRichText->InsertL( iRichText->DocumentLength(), aText );
+
+ iNewParagraph = EFalse;
+ iNewLines = 0;
+ iForcedNewLines = 0;
+
+ iFirstTextLineAdded = ETrue;
+ }
+
+// ---------------------------------------------------------
+// CXhtmlParser::AppendParagraphL
+// ---------------------------------------------------------
+//
+void CXhtmlParser::AppendParagraphL( TBool aPlainText )
+ {
+ XHTMLLOG_WRITE( "AppendParagraphL" );
+
+ iSkipWhiteSpaces = ETrue;
+
+ if ( !iNewParagraph )
+ {
+
+ if ( aPlainText )
+ {
+ iRichText->InsertL( iRichText->DocumentLength(),
+ CRichText::ELineBreak );
+ }
+ else
+ {
+ iRichText->AppendParagraphL();
+ }
+
+ iNewParagraph = ETrue;
+
+ if ( iNewLines < 2 )
+ {
+ iNewLines++;
+ }
+ }
+ }
+
+// ---------------------------------------------------------
+// CXhtmlParser::InsertLineBreakL
+// ---------------------------------------------------------
+//
+void CXhtmlParser::InsertLineBreak()
+ {
+ XHTMLLOG_WRITE( "InsertLineBreakL" );
+
+ iSkipWhiteSpaces = ETrue;
+ if ( iNewLines < 2 )
+ {
+ iNewLines++;
+ }
+ }
+
+// ---------------------------------------------------------
+// CXhtmlParser::InsertForcedLineBreakL
+// ---------------------------------------------------------
+//
+void CXhtmlParser::InsertForcedLineBreak()
+ {
+ XHTMLLOG_WRITE( "InsertForcedLineBreakL" );
+
+ iSkipWhiteSpaces = ETrue;
+ iForcedNewLines++;
+ }