41868 and 45994: Call parser to determine inline vs. block. r=harishd
git-svn-id: svn://10.0.0.236/trunk@77414 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
@@ -50,20 +50,15 @@
|
||||
static NS_DEFINE_CID(kSaveAsCharsetCID, NS_SAVEASCHARSET_CID);
|
||||
static NS_DEFINE_CID(kEntityConverterCID, NS_ENTITYCONVERTER_CID);
|
||||
|
||||
static NS_DEFINE_IID(kCParserIID, NS_IPARSER_IID);
|
||||
static NS_DEFINE_IID(kCParserCID, NS_PARSER_IID);
|
||||
|
||||
static char* gHeaderComment = "<!-- This page was created by the Gecko output system. -->";
|
||||
static char* gDocTypeHeader = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">";
|
||||
const int gTabSize=2;
|
||||
|
||||
static const nsString gMozDirty = NS_ConvertToString("_moz_dirty");
|
||||
|
||||
static PRBool IsInline(eHTMLTags aTag);
|
||||
static PRBool IsBlockLevel(eHTMLTags aTag);
|
||||
static PRInt32 BreakBeforeOpen(eHTMLTags aTag);
|
||||
static PRInt32 BreakAfterOpen(eHTMLTags aTag);
|
||||
static PRInt32 BreakBeforeClose(eHTMLTags aTag);
|
||||
static PRInt32 BreakAfterClose(eHTMLTags aTag);
|
||||
static PRBool IndentChildren(eHTMLTags aTag);
|
||||
|
||||
/**
|
||||
* This method gets called as part of our COM-like interfaces.
|
||||
* Its purpose is to create an interface to parser object
|
||||
@@ -115,6 +110,7 @@ nsHTMLContentSinkStream::nsHTMLContentSinkStream()
|
||||
mLowerCaseTags = PR_TRUE;
|
||||
memset(mHTMLTagStack,0,sizeof(mHTMLTagStack));
|
||||
memset(mDirtyStack,0,sizeof(mDirtyStack));
|
||||
mDTD = 0;
|
||||
mHTMLStackPos = 0;
|
||||
mColPos = 0;
|
||||
mIndent = 0;
|
||||
@@ -166,8 +162,10 @@ nsHTMLContentSinkStream::Initialize(nsIOutputStream* aOutStream,
|
||||
|
||||
nsHTMLContentSinkStream::~nsHTMLContentSinkStream()
|
||||
{
|
||||
if (mBuffer)
|
||||
nsMemory::Free(mBuffer);
|
||||
NS_IF_RELEASE(mDTD);
|
||||
|
||||
if (mBuffer)
|
||||
nsMemory::Free(mBuffer);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1111,6 +1109,159 @@ nsHTMLContentSinkStream::CloseContainer(const nsIParserNode& aNode){
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find out from the parser whether a node is a block node.
|
||||
*/
|
||||
PRBool nsHTMLContentSinkStream::IsBlockLevel(eHTMLTags aTag)
|
||||
{
|
||||
if (!mDTD)
|
||||
{
|
||||
nsCOMPtr<nsIParser> parser;
|
||||
nsresult rv = nsComponentManager::CreateInstance(kCParserCID,
|
||||
nsnull,
|
||||
kCParserIID,
|
||||
(void **)&parser);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (!parser) return NS_ERROR_FAILURE;
|
||||
|
||||
nsAutoString htmlmime (NS_LITERAL_STRING("text/html"));
|
||||
rv = parser->CreateCompatibleDTD(&mDTD, 0, eViewNormal,
|
||||
&htmlmime, eDTDMode_transitional);
|
||||
/* XXX Note: We output linebreaks for blocks.
|
||||
I.e. we output linebreaks for "unknown" inline tags.
|
||||
I just hunted such a bug for <q>, same for <ins>, <col> etc..
|
||||
Better fallback to inline. /BenB */
|
||||
if (NS_FAILED(rv) || !mDTD)
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
// Now we can get the inline status from the DTD:
|
||||
return mDTD->IsBlockElement(aTag, eHTMLTag_unknown);
|
||||
}
|
||||
|
||||
/**
|
||||
* **** Pretty Printing Methods ******
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Desired line break state before the open tag.
|
||||
*/
|
||||
PRBool nsHTMLContentSinkStream::BreakBeforeOpen(eHTMLTags aTag)
|
||||
{
|
||||
PRBool result = PR_FALSE;
|
||||
switch (aTag)
|
||||
{
|
||||
case eHTMLTag_html:
|
||||
result = PR_FALSE;
|
||||
break;
|
||||
|
||||
default:
|
||||
result = IsBlockLevel(aTag);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Desired line break state after the open tag.
|
||||
*/
|
||||
PRBool nsHTMLContentSinkStream::BreakAfterOpen(eHTMLTags aTag)
|
||||
{
|
||||
PRBool result = PR_FALSE;
|
||||
switch (aTag)
|
||||
{
|
||||
case eHTMLTag_html:
|
||||
case eHTMLTag_body:
|
||||
case eHTMLTag_ul:
|
||||
case eHTMLTag_ol:
|
||||
case eHTMLTag_table:
|
||||
case eHTMLTag_tbody:
|
||||
case eHTMLTag_style:
|
||||
case eHTMLTag_br:
|
||||
result = PR_TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Desired line break state before the close tag.
|
||||
*/
|
||||
PRBool nsHTMLContentSinkStream::BreakBeforeClose(eHTMLTags aTag)
|
||||
{
|
||||
PRBool result = PR_FALSE;
|
||||
|
||||
switch (aTag)
|
||||
{
|
||||
case eHTMLTag_html:
|
||||
case eHTMLTag_head:
|
||||
case eHTMLTag_body:
|
||||
case eHTMLTag_ul:
|
||||
case eHTMLTag_ol:
|
||||
case eHTMLTag_table:
|
||||
case eHTMLTag_tbody:
|
||||
case eHTMLTag_style:
|
||||
result = PR_TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Desired line break state after the close tag.
|
||||
*/
|
||||
PRBool nsHTMLContentSinkStream::BreakAfterClose(eHTMLTags aTag)
|
||||
{
|
||||
PRBool result = PR_FALSE;
|
||||
|
||||
switch (aTag)
|
||||
{
|
||||
case eHTMLTag_html:
|
||||
case eHTMLTag_tr:
|
||||
case eHTMLTag_th:
|
||||
case eHTMLTag_td:
|
||||
case eHTMLTag_pre:
|
||||
result = PR_TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
result = IsBlockLevel(aTag);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indent/outdent when the open/close tags are encountered.
|
||||
* This implies that BreakAfterOpen() and BreakBeforeClose()
|
||||
* are true no matter what those methods return.
|
||||
*/
|
||||
PRBool nsHTMLContentSinkStream::IndentChildren(eHTMLTags aTag)
|
||||
{
|
||||
PRBool result = PR_FALSE;
|
||||
|
||||
switch (aTag)
|
||||
{
|
||||
case eHTMLTag_table:
|
||||
case eHTMLTag_ul:
|
||||
case eHTMLTag_ol:
|
||||
case eHTMLTag_tbody:
|
||||
case eHTMLTag_form:
|
||||
case eHTMLTag_frameset:
|
||||
result = PR_TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
result = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method gets called when the parser begins the process
|
||||
@@ -1176,181 +1327,3 @@ nsHTMLContentSinkStream::NotifyError(const nsParserError* aError)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
//// Useful static methods
|
||||
/////////////////////////////////////////////////////////////
|
||||
|
||||
static PRBool IsInline(eHTMLTags aTag)
|
||||
{
|
||||
PRBool result = PR_FALSE;
|
||||
|
||||
switch (aTag)
|
||||
{
|
||||
case eHTMLTag_a:
|
||||
case eHTMLTag_address:
|
||||
case eHTMLTag_big:
|
||||
case eHTMLTag_blink:
|
||||
case eHTMLTag_b:
|
||||
case eHTMLTag_br:
|
||||
case eHTMLTag_cite:
|
||||
case eHTMLTag_code:
|
||||
case eHTMLTag_dfn:
|
||||
case eHTMLTag_em:
|
||||
case eHTMLTag_font:
|
||||
case eHTMLTag_img:
|
||||
case eHTMLTag_i:
|
||||
case eHTMLTag_kbd:
|
||||
case eHTMLTag_keygen:
|
||||
case eHTMLTag_nobr:
|
||||
case eHTMLTag_samp:
|
||||
case eHTMLTag_small:
|
||||
case eHTMLTag_spacer:
|
||||
case eHTMLTag_span:
|
||||
case eHTMLTag_strike:
|
||||
case eHTMLTag_strong:
|
||||
case eHTMLTag_sub:
|
||||
case eHTMLTag_sup:
|
||||
case eHTMLTag_textarea:
|
||||
case eHTMLTag_tt:
|
||||
case eHTMLTag_u:
|
||||
case eHTMLTag_var:
|
||||
case eHTMLTag_wbr:
|
||||
result = PR_TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static PRBool IsBlockLevel(eHTMLTags aTag)
|
||||
{
|
||||
return !IsInline(aTag);
|
||||
}
|
||||
|
||||
/**
|
||||
* **** Pretty Printing Methods ******
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Desired line break state before the open tag.
|
||||
*/
|
||||
static PRBool BreakBeforeOpen(eHTMLTags aTag)
|
||||
{
|
||||
PRBool result = PR_FALSE;
|
||||
switch (aTag)
|
||||
{
|
||||
case eHTMLTag_html:
|
||||
result = PR_FALSE;
|
||||
break;
|
||||
|
||||
default:
|
||||
result = IsBlockLevel(aTag);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Desired line break state after the open tag.
|
||||
*/
|
||||
static PRBool BreakAfterOpen(eHTMLTags aTag)
|
||||
{
|
||||
PRBool result = PR_FALSE;
|
||||
switch (aTag)
|
||||
{
|
||||
case eHTMLTag_html:
|
||||
case eHTMLTag_body:
|
||||
case eHTMLTag_ul:
|
||||
case eHTMLTag_ol:
|
||||
case eHTMLTag_table:
|
||||
case eHTMLTag_tbody:
|
||||
case eHTMLTag_style:
|
||||
case eHTMLTag_br:
|
||||
result = PR_TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Desired line break state before the close tag.
|
||||
*/
|
||||
static PRBool BreakBeforeClose(eHTMLTags aTag)
|
||||
{
|
||||
PRBool result = PR_FALSE;
|
||||
|
||||
switch (aTag)
|
||||
{
|
||||
case eHTMLTag_html:
|
||||
case eHTMLTag_head:
|
||||
case eHTMLTag_body:
|
||||
case eHTMLTag_ul:
|
||||
case eHTMLTag_ol:
|
||||
case eHTMLTag_table:
|
||||
case eHTMLTag_tbody:
|
||||
case eHTMLTag_style:
|
||||
result = PR_TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Desired line break state after the close tag.
|
||||
*/
|
||||
static PRBool BreakAfterClose(eHTMLTags aTag)
|
||||
{
|
||||
PRBool result = PR_FALSE;
|
||||
|
||||
switch (aTag)
|
||||
{
|
||||
case eHTMLTag_html:
|
||||
case eHTMLTag_tr:
|
||||
case eHTMLTag_th:
|
||||
case eHTMLTag_td:
|
||||
case eHTMLTag_pre:
|
||||
result = PR_TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
result = IsBlockLevel(aTag);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indent/outdent when the open/close tags are encountered.
|
||||
* This implies that BreakAfterOpen() and BreakBeforeClose()
|
||||
* are true no matter what those methods return.
|
||||
*/
|
||||
static PRBool IndentChildren(eHTMLTags aTag)
|
||||
{
|
||||
PRBool result = PR_FALSE;
|
||||
|
||||
switch (aTag)
|
||||
{
|
||||
case eHTMLTag_table:
|
||||
case eHTMLTag_ul:
|
||||
case eHTMLTag_ol:
|
||||
case eHTMLTag_tbody:
|
||||
case eHTMLTag_form:
|
||||
case eHTMLTag_frameset:
|
||||
result = PR_TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
result = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -62,6 +62,7 @@ class ostream;
|
||||
|
||||
class nsIParserNode;
|
||||
class nsIOutputStream;
|
||||
class nsIDTD;
|
||||
|
||||
class nsIHTMLContentSinkStream : public nsIHTMLContentSink {
|
||||
public:
|
||||
@@ -102,7 +103,6 @@ class nsHTMLContentSinkStream : public nsIHTMLContentSinkStream
|
||||
const nsAReadableString* aCharsetOverride,
|
||||
PRUint32 aFlags);
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* The following methods are inherited from nsIContentSink.
|
||||
* Please see that file for details.
|
||||
@@ -147,6 +147,13 @@ public:
|
||||
|
||||
protected:
|
||||
|
||||
PRBool IsBlockLevel(eHTMLTags aTag);
|
||||
PRInt32 BreakBeforeOpen(eHTMLTags aTag);
|
||||
PRInt32 BreakAfterOpen(eHTMLTags aTag);
|
||||
PRInt32 BreakBeforeClose(eHTMLTags aTag);
|
||||
PRInt32 BreakAfterClose(eHTMLTags aTag);
|
||||
PRBool IndentChildren(eHTMLTags aTag);
|
||||
|
||||
void WriteAttributes(const nsIParserNode& aNode);
|
||||
void AddStartTag(const nsIParserNode& aNode);
|
||||
void AddEndTag(const nsIParserNode& aNode);
|
||||
@@ -170,6 +177,8 @@ protected:
|
||||
nsIOutputStream* mStream;
|
||||
nsAWritableString* mString;
|
||||
|
||||
nsIDTD* mDTD;
|
||||
|
||||
int mTabLevel;
|
||||
char* mBuffer;
|
||||
PRInt32 mBufferSize;
|
||||
|
||||
@@ -56,6 +56,8 @@
|
||||
static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CID);
|
||||
static NS_DEFINE_CID(kLWBrkCID, NS_LWBRK_CID);
|
||||
static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID);
|
||||
static NS_DEFINE_IID(kCParserIID, NS_IPARSER_IID);
|
||||
static NS_DEFINE_IID(kCParserCID, NS_PARSER_IID);
|
||||
|
||||
#define PREF_STRUCTS "converter.html2txt.structs"
|
||||
#define PREF_HEADER_STRATEGY "converter.html2txt.header_strategy"
|
||||
@@ -73,8 +75,6 @@ const PRInt32 gIndentSizeList = (gTabSize > gOLNumberWidth+3) ? gTabSize: gOLNu
|
||||
// Indention of non-first lines of ul and ol
|
||||
const PRInt32 gIndentSizeDD = gTabSize; // Indention of <dd>
|
||||
|
||||
static PRBool IsInline(eHTMLTags aTag);
|
||||
static PRBool IsBlockLevel(eHTMLTags aTag);
|
||||
static PRInt32 HeaderLevel(eHTMLTags aTag);
|
||||
static PRInt32 unicharwidth(PRUnichar ucs);
|
||||
static PRInt32 unicharwidth(const PRUnichar* pwcs, PRInt32 n);
|
||||
@@ -186,6 +186,7 @@ static const PRUint32 OLStackSize = 100;
|
||||
nsHTMLToTXTSinkStream::nsHTMLToTXTSinkStream()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mDTD = 0;
|
||||
mColPos = 0;
|
||||
mIndent = 0;
|
||||
mCiteQuoteLevel = 0;
|
||||
@@ -236,6 +237,7 @@ nsHTMLToTXTSinkStream::~nsHTMLToTXTSinkStream()
|
||||
delete[] mBuffer;
|
||||
delete[] mTagStack;
|
||||
delete[] mOLStack;
|
||||
NS_IF_RELEASE(mDTD);
|
||||
NS_IF_RELEASE(mUnicodeEncoder);
|
||||
NS_IF_RELEASE(mLineBreaker);
|
||||
}
|
||||
@@ -416,6 +418,7 @@ nsHTMLToTXTSinkStream::AddProcessingInstruction(const nsIParserNode& aNode){
|
||||
NS_IMETHODIMP
|
||||
nsHTMLToTXTSinkStream::AddDocTypeDecl(const nsIParserNode& aNode, PRInt32 aMode)
|
||||
{
|
||||
// Should probably set DTD
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@@ -1603,62 +1606,31 @@ nsHTMLToTXTSinkStream::NotifyError(const nsParserError* aError)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRBool IsInline(eHTMLTags aTag)
|
||||
PRBool nsHTMLToTXTSinkStream::IsBlockLevel(eHTMLTags aTag)
|
||||
{
|
||||
PRBool result = PR_FALSE;
|
||||
|
||||
switch (aTag)
|
||||
if (!mDTD)
|
||||
{
|
||||
case eHTMLTag_a:
|
||||
case eHTMLTag_address:
|
||||
case eHTMLTag_b:
|
||||
case eHTMLTag_big:
|
||||
case eHTMLTag_blink:
|
||||
case eHTMLTag_br:
|
||||
case eHTMLTag_cite:
|
||||
case eHTMLTag_code:
|
||||
case eHTMLTag_dfn:
|
||||
case eHTMLTag_del:
|
||||
case eHTMLTag_em:
|
||||
case eHTMLTag_font:
|
||||
case eHTMLTag_i:
|
||||
case eHTMLTag_img:
|
||||
case eHTMLTag_ins:
|
||||
case eHTMLTag_kbd:
|
||||
case eHTMLTag_keygen:
|
||||
case eHTMLTag_nobr:
|
||||
case eHTMLTag_q:
|
||||
case eHTMLTag_samp:
|
||||
case eHTMLTag_small:
|
||||
case eHTMLTag_spacer:
|
||||
case eHTMLTag_span:
|
||||
case eHTMLTag_strike:
|
||||
case eHTMLTag_strong:
|
||||
case eHTMLTag_sub:
|
||||
case eHTMLTag_sup:
|
||||
case eHTMLTag_td:
|
||||
case eHTMLTag_textarea:
|
||||
case eHTMLTag_th:
|
||||
case eHTMLTag_tt:
|
||||
case eHTMLTag_u:
|
||||
case eHTMLTag_var:
|
||||
case eHTMLTag_wbr:
|
||||
result = PR_TRUE;
|
||||
break;
|
||||
nsCOMPtr<nsIParser> parser;
|
||||
nsresult rv = nsComponentManager::CreateInstance(kCParserCID,
|
||||
nsnull,
|
||||
kCParserIID,
|
||||
(void **)&parser);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (!parser) return NS_ERROR_FAILURE;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
PRBool IsBlockLevel(eHTMLTags aTag)
|
||||
{
|
||||
return !IsInline(aTag);
|
||||
nsAutoString htmlmime (NS_LITERAL_STRING("text/html"));
|
||||
rv = parser->CreateCompatibleDTD(&mDTD, 0, eViewNormal,
|
||||
&htmlmime, eDTDMode_transitional);
|
||||
/* XXX Note: We output linebreaks for blocks.
|
||||
I.e. we output linebreaks for "unknown" inline tags.
|
||||
I just hunted such a bug for <q>, same for <ins>, <col> etc..
|
||||
Better fallback to inline. /BenB */
|
||||
if (NS_FAILED(rv) || !mDTD)
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
// Now we can get the inline status from the DTD:
|
||||
return mDTD->IsBlockElement(aTag, eHTMLTag_unknown);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -46,6 +46,9 @@
|
||||
#include "nsHTMLTags.h"
|
||||
#include "nsParserCIID.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsHTMLTokens.h" // for eHTMLTags
|
||||
|
||||
class nsIDTD;
|
||||
|
||||
#define NS_IHTMLTOTEXTSINKSTREAM_IID \
|
||||
{0xa39c6bff, 0x15f0, 0x11d2, \
|
||||
@@ -157,6 +160,7 @@ protected:
|
||||
PRBool DoOutput();
|
||||
PRBool MayWrap();
|
||||
|
||||
PRBool IsBlockLevel(eHTMLTags aTag);
|
||||
|
||||
protected:
|
||||
nsIOutputStream* mStream;
|
||||
@@ -166,6 +170,8 @@ protected:
|
||||
nsAWritableString* mString;
|
||||
nsString mCurrentLine;
|
||||
|
||||
nsIDTD* mDTD;
|
||||
|
||||
PRInt32 mIndent;
|
||||
// mInIndentString keeps a header that has to be written in the indent.
|
||||
// That could be, for instance, the bullet in a bulleted list.
|
||||
|
||||
Reference in New Issue
Block a user