diff --git a/content/html/document/src/nsHTMLContentSink.cpp b/content/html/document/src/nsHTMLContentSink.cpp
index 0758053c0a7..2217af19cbc 100644
--- a/content/html/document/src/nsHTMLContentSink.cpp
+++ b/content/html/document/src/nsHTMLContentSink.cpp
@@ -551,115 +551,6 @@ GetEntityTerminator(nsString& aSource,PRUnichar& aChar,PRInt32 aStartOffset=0) {
return -1;
}
-
-void HTMLContentSink::ReduceEntities(nsString& aString) {
- if (mParser) {
- nsCOMPtr dtd;
-
- nsresult rv = mParser->GetDTD(getter_AddRefs(dtd));
-
- if (NS_SUCCEEDED(rv)) {
-
- // XXX Note: as coded today, this will only convert well formed
- // entities. This may not be compatible enough.
- // XXX there is a table in navigator that translates some numeric entities
- // should we be doing that? If so then it needs to live in two places (bad)
- // so we should add a translate numeric entity method from the parser...
-
- nsAutoString theOutString;
- nsAutoString theNCRStr;
-
- PRInt32 theLen=aString.Length();
- PRInt32 theAmpPos = aString.FindChar('&');
- PRInt32 theStartPos=0;
- PRInt32 theTermPos=-1;
- PRUnichar theTermChar='\0';
- const PRUnichar *theBuf=aString.GetUnicode();
-
- nsDTDMode mode;
- mHTMLDocument->GetDTDMode(mode);
-
- while(-1!=theAmpPos) {
-
- if(theStartPostheAmpPos+1) ? aString.CharAt(theAmpPos+1) : '\0';
- PRUnichar theEntity=0;
- PRInt32 theErr=0;
- PRInt32 theNCRValue=0;
-
- switch(theChar) {
- case '#':
- theNCRValue=theNCRStr.ToInteger(&theErr,kAutoDetect);
- theEntity=PRUnichar(theNCRValue);
- break;
- case '{':
- //XXX Write ME!
- break;
- default:
- if(nsCRT::IsAsciiAlpha(theChar)) {
- dtd->ConvertEntityToUnicode(theNCRStr, &theNCRValue);
- if (eDTDMode_strict!=mode) {
- // XXX - Hack - Nav. does not support entity values > 255
- // on the other hand IE supports entity values > 255 with a
- // semicolon. I think it's reasonable to emulate IE than Nav.
- if(theNCRValue>255 && theTermChar!=';') break;
- }
- if(-1!=theNCRValue) {
- theEntity=PRUnichar(theNCRValue);
- }
- }
- break;
- } //switch
-
- if(theEntity) {
- theOutString.Append(theEntity);
- if(theTermChar!='\0' && theTermChar!='&' && theTermChar!=';') {
- theOutString.Append(theTermChar);
- }
- }
- else {
- //what looked like an entity is not really one.
- //so let's copy the ncrstring back to the output string
- if(theTermChar!='&') { theTermPos++; }
- aString.Mid(theNCRStr,theAmpPos,theTermPos-theAmpPos);
- theOutString.Append(theNCRStr);
- }
- theAmpPos = aString.FindChar('&',PR_FALSE,theTermPos);
- } //while
-
- if(0CompressWhitespace(PR_TRUE, PR_TRUE);
nsCOMPtr domDoc(do_QueryInterface(mHTMLDocument));
diff --git a/content/html/document/src/nsHTMLFragmentContentSink.cpp b/content/html/document/src/nsHTMLFragmentContentSink.cpp
index b5df48cd06f..0ffa2f14331 100644
--- a/content/html/document/src/nsHTMLFragmentContentSink.cpp
+++ b/content/html/document/src/nsHTMLFragmentContentSink.cpp
@@ -860,117 +860,6 @@ nsHTMLFragmentContentSink::GetAttributeValueAt(const nsIParserNode& aNode,
}
}
}
-
- if (mParser) {
- nsCOMPtr dtd;
-
- nsresult rv = mParser->GetDTD(getter_AddRefs(dtd));
-
- if (NS_SUCCEEDED(rv)) {
- // Reduce any entities
- // XXX Note: as coded today, this will only convert well formed
- // entities. This may not be compatible enough.
- // XXX there is a table in navigator that translates some numeric entities
- // should we be doing that? If so then it needs to live in two places (bad)
- // so we should add a translate numeric entity method from the parser...
- char cbuf[100];
- PRInt32 indx = 0;
- while (indx < aResult.Length()) {
- // If we have the start of an entity (and it's not at the end of
- // our string) then translate the entity into it's unicode value.
- if ((aResult.CharAt(indx++) == '&') && (indx < aResult.Length())) {
- PRInt32 start = indx - 1;
- PRUnichar e = aResult.CharAt(indx);
- if (e == '#') {
- // Convert a numeric character reference
- indx++;
- char* cp = cbuf;
- char* limit = cp + sizeof(cbuf) - 1;
- PRBool ok = PR_FALSE;
- PRInt32 slen = aResult.Length();
- while ((indx < slen) && (cp < limit)) {
- e = aResult.CharAt(indx);
- if (e == ';') {
- indx++;
- ok = PR_TRUE;
- break;
- }
- if ((e >= '0') && (e <= '9')) {
- *cp++ = char(e);
- indx++;
- continue;
- }
- break;
- }
- if (!ok || (cp == cbuf)) {
- continue;
- }
- *cp = '\0';
- if (cp - cbuf > 5) {
- continue;
- }
- PRInt32 ch = PRInt32( ::atoi(cbuf) );
- if (ch > 65535) {
- continue;
- }
-
- // Remove entity from string and replace it with the integer
- // value.
- aResult.Cut(start, indx - start);
- aResult.Insert(PRUnichar(ch), start);
- indx = start + 1;
- }
- else if (((e >= 'A') && (e <= 'Z')) ||
- ((e >= 'a') && (e <= 'z'))) {
- // Convert a named entity
- indx++;
- char* cp = cbuf;
- char* limit = cp + sizeof(cbuf) - 1;
- *cp++ = char(e);
- PRBool ok = PR_FALSE;
- PRInt32 slen = aResult.Length();
- while ((indx < slen) && (cp < limit)) {
- e = aResult.CharAt(indx);
- if (e == ';') {
- indx++;
- ok = PR_TRUE;
- break;
- }
- if (((e >= '0') && (e <= '9')) ||
- ((e >= 'A') && (e <= 'Z')) ||
- ((e >= 'a') && (e <= 'z'))) {
- *cp++ = char(e);
- indx++;
- continue;
- }
- break;
- }
- if (!ok || (cp == cbuf)) {
- continue;
- }
- *cp = '\0';
- PRInt32 ch;
- nsAutoString str; str.AssignWithConversion(cbuf);
- dtd->ConvertEntityToUnicode(str, &ch);
-
- if (ch < 0) {
- continue;
- }
-
- // Remove entity from string and replace it with the integer
- // value.
- aResult.Cut(start, indx - start);
- aResult.Insert(PRUnichar(ch), start);
- indx = start + 1;
- }
- else if (e == '{') {
- // Convert a script entity
- // XXX write me!
- }
- }
- }
- }
- }
}
// XXX Code copied from nsHTMLContentSink. It should be shared.
diff --git a/htmlparser/src/CNavDTD.cpp b/htmlparser/src/CNavDTD.cpp
index df96e56b787..6621c1bd9e7 100644
--- a/htmlparser/src/CNavDTD.cpp
+++ b/htmlparser/src/CNavDTD.cpp
@@ -189,26 +189,6 @@ CNavDTD::CNavDTD() : nsIDTD(),
}
-/**
- * This method recycles the nodes on a nodestack.
- * NOTE: Unlike recycleNode(), we force the usecount
- * to 0 of all nodes, then force them to recycle.
- * @update gess1/8/99
- * @param aNodeStack
- * @return nothing
- */
-void CNavDTD::RecycleNodes(nsEntryStack *aNodeStack) {
- if(aNodeStack) {
- PRInt32 theCount=aNodeStack->mCount;
- PRInt32 theIndex=0;
-
- for(theIndex=0;theIndexNodeAt(theIndex);
- IF_FREE(node, &mNodeAllocator);
- }
- }
-}
-
/**
*
* @update gess1/8/99
@@ -631,12 +611,9 @@ nsresult CNavDTD::DidBuildModel(nsresult anErrorCode,PRBool aNotifySink,nsIParse
nsEntryStack *theChildStyles=0;
nsCParserNode* theNode=mBodyContext->Pop(theChildStyles);
- if(theNode) {
- if(theChildStyles) {
- delete theChildStyles;
- }
- IF_FREE(theNode, &mNodeAllocator);
- }
+
+ IF_DELETE(theChildStyles,&mNodeAllocator);
+ IF_FREE(theNode, &mNodeAllocator);
}
}
@@ -2926,8 +2903,22 @@ nsresult CNavDTD::OpenTransientStyles(eHTMLTags aChildTag){
if(1==theNode->mUseCount) {
eHTMLTags theNodeTag=(eHTMLTags)theNode->GetNodeType();
if(gHTMLElements[theNodeTag].CanContain(aChildTag)) {
- theEntry->mParent=theStack; //we do this too, because this entry differs from the new one we're pushing...
- result=OpenContainer(theNode,theNodeTag,PR_FALSE,theStack);
+ theEntry->mParent = theStack; //we do this too, because this entry differs from the new one we're pushing...
+ if(gHTMLElements[mBodyContext->Last()].IsMemberOf(kHeading)) {
+ // Bug 77352
+ // The style system needs to identify residual style tags
+ // within heading tags so that heading tags' size can take
+ // precedence over the residual style tags' size info..
+ // *Note: Make sure that this attribute is transient since it
+ // should not get carried over to cases other than heading.
+ CAttributeToken theAttrToken(NS_LITERAL_STRING("_moz-rs-heading"),NS_LITERAL_STRING(""));
+ theNode->AddAttribute(&theAttrToken);
+ result = OpenContainer(theNode,theNodeTag,PR_FALSE,theStack);
+ theNode->PopAttributeToken();
+ }
+ else {
+ result = OpenContainer(theNode,theNodeTag,PR_FALSE,theStack);
+ }
}
else {
//if the node tag can't contain the child tag, then remove the child tag from the style stack
@@ -3658,10 +3649,7 @@ nsresult CNavDTD::CloseContainersTo(PRInt32 anIndex,eHTMLTags aTarget, PRBool aC
mBodyContext->PushStyles(theChildStyleStack);
}
else{
- //add code here to recycle styles...
- RecycleNodes(theChildStyleStack);
- delete theChildStyleStack; // XXX try to recycle this...
- theChildStyleStack=0;
+ IF_DELETE(theChildStyleStack,&mNodeAllocator);
}
}
else if (0==theNode->mUseCount) {
@@ -3687,9 +3675,7 @@ nsresult CNavDTD::CloseContainersTo(PRInt32 anIndex,eHTMLTags aTarget, PRBool aC
//the tag is not a style tag...
if(theChildStyleStack) {
if(theStyleDoesntLeakOut) {
- RecycleNodes(theChildStyleStack);
- delete theChildStyleStack; // XXX try to recycle this...
- theChildStyleStack=0;
+ IF_DELETE(theChildStyleStack,&mNodeAllocator);
}
else mBodyContext->PushStyles(theChildStyleStack);
}
@@ -3726,7 +3712,8 @@ nsresult CNavDTD::CloseContainersTo(eHTMLTags aTarget,PRBool aClosedByStartTag){
PRBool theTagIsSynonymous=((nsHTMLElement::IsResidualStyleTag(aTarget)) && (nsHTMLElement::IsResidualStyleTag(theTopTag)));
if(!theTagIsSynonymous){
- theTagIsSynonymous=((nsHTMLElement::IsHeadingTag(aTarget)) && (nsHTMLElement::IsHeadingTag(theTopTag)));
+ theTagIsSynonymous=(gHTMLElements[aTarget].IsMemberOf(kHeading) &&
+ gHTMLElements[theTopTag].IsMemberOf(kHeading));
}
if(theTagIsSynonymous) {
diff --git a/htmlparser/src/CNavDTD.h b/htmlparser/src/CNavDTD.h
index b740511cc28..9bb624aeeb5 100644
--- a/htmlparser/src/CNavDTD.h
+++ b/htmlparser/src/CNavDTD.h
@@ -490,7 +490,6 @@ protected:
nsresult HandleOmittedTag(CToken* aToken,eHTMLTags aChildTag,eHTMLTags aParent,nsIParserNode *aNode);
nsresult HandleSavedTokens(PRInt32 anIndex);
nsresult HandleKeyGen(nsIParserNode *aNode);
- void RecycleNodes(nsEntryStack *aNodeStack);
nsDeque mMisplacedContent;
nsDeque mSkippedContent;
diff --git a/htmlparser/src/nsDTDUtils.cpp b/htmlparser/src/nsDTDUtils.cpp
index 68799060cb7..fcccbe937a8 100644
--- a/htmlparser/src/nsDTDUtils.cpp
+++ b/htmlparser/src/nsDTDUtils.cpp
@@ -83,6 +83,23 @@ nsEntryStack::~nsEntryStack() {
mCount=mCapacity=0;
}
+/**
+ * Release all objects in the entry stack
+ */
+void
+nsEntryStack::ReleaseAll(nsNodeAllocator* aNodeAllocator)
+{
+ NS_WARN_IF_FALSE(aNodeAllocator,"no allocator? - potential leak!");
+
+ if(aNodeAllocator) {
+ NS_WARN_IF_FALSE(mCount >= 0,"count should not be negative");
+ while(mCount > 0) {
+ nsCParserNode* node=this->Pop();
+ IF_FREE(node,aNodeAllocator);
+ }
+ }
+}
+
/**
* Resets state of stack to be empty.
* @update harishd 04/04/99
@@ -1045,10 +1062,7 @@ void nsDTDContext::PushStyles(nsEntryStack *aStyles){
// If you're here it means that we have hit the rock bottom
// ,of the stack, and there's no need to handle anymore styles.
// Fix for bug 29048
- nsCParserNode* theNode=aStyles->Pop();
- IF_HOLD(theNode);
- delete aStyles;
- aStyles=0;
+ IF_DELETE(aStyles,mNodeAllocator);
}
}//if(aStyles)
}
diff --git a/htmlparser/src/nsDTDUtils.h b/htmlparser/src/nsDTDUtils.h
index 5c154cd6d10..66480905d1c 100644
--- a/htmlparser/src/nsDTDUtils.h
+++ b/htmlparser/src/nsDTDUtils.h
@@ -45,8 +45,31 @@
#include "nsFixedSizeAllocator.h"
#include "nsVoidArray.h"
-#define IF_HOLD(_ptr) if(_ptr) { _ptr->AddRef(); }
-#define IF_FREE(_ptr, _allocator) if(_ptr) { _ptr->Release((_allocator)->GetArenaPool()); _ptr=0; } // recycles _ptr
+#define IF_HOLD(_ptr) \
+ PR_BEGIN_MACRO \
+ if(_ptr) { \
+ _ptr->AddRef(); \
+ } \
+ PR_END_MACRO
+
+// recycles _ptr
+#define IF_FREE(_ptr, _allocator) \
+ PR_BEGIN_MACRO \
+ if(_ptr) { \
+ _ptr->Release((_allocator)->GetArenaPool()); \
+ _ptr=0; \
+ } \
+ PR_END_MACRO
+
+// release objects and destroy _ptr
+#define IF_DELETE(_ptr, _allocator) \
+ PR_BEGIN_MACRO \
+ if(_ptr) { \
+ _ptr->ReleaseAll(_allocator); \
+ delete(_ptr); \
+ _ptr=0; \
+ } \
+ PR_END_MACRO
class nsIParserNode;
class nsCParserNode;
@@ -73,6 +96,7 @@ struct nsTagEntry {
};
class nsEntryStack {
+
public:
nsEntryStack();
~nsEntryStack();
@@ -91,6 +115,11 @@ public:
eHTMLTags Last() const;
void Empty(void);
+ /*
+ * Release all objects in the entry stack
+ */
+ void ReleaseAll(nsNodeAllocator* aNodeAllocator);
+
/**
* Find the first instance of given tag on the stack.
* @update gess 12/14/99
diff --git a/htmlparser/src/nsElementTable.cpp b/htmlparser/src/nsElementTable.cpp
index 958986ca0d9..b04398c98ef 100644
--- a/htmlparser/src/nsElementTable.cpp
+++ b/htmlparser/src/nsElementTable.cpp
@@ -104,7 +104,7 @@ TagList gULKids={2,{eHTMLTag_li,eHTMLTag_p}};
//*********************************************************************************************
TagList gRootTags={4,{eHTMLTag_body,eHTMLTag_td,eHTMLTag_table,eHTMLTag_applet}};
-TagList gTableRootTags={7,{eHTMLTag_applet,eHTMLTag_body,eHTMLTag_dl,eHTMLTag_ol,eHTMLTag_td,eHTMLTag_th,eHTMLTag_ul}};
+TagList gTableRootTags={6,{eHTMLTag_applet,eHTMLTag_body,eHTMLTag_dl,eHTMLTag_ol,eHTMLTag_td,eHTMLTag_th}};
TagList gHTMLRootTags={1,{eHTMLTag_unknown}};
TagList gLIRootTags={8,{eHTMLTag_ul,eHTMLTag_ol,eHTMLTag_dir,eHTMLTag_menu,eHTMLTag_p,eHTMLTag_body,eHTMLTag_td,eHTMLTag_th}};
@@ -1956,17 +1956,6 @@ PRBool nsHTMLElement::IsResidualStyleTag(eHTMLTags aChild) {
return result;
}
-/**
- *
- * @update gess12/13/98
- * @param
- * @return
- */
-PRBool nsHTMLElement::IsHeadingTag(eHTMLTags aChild) {
- return FindTagInSet(aChild,gHeadingTags.mTags,gHeadingTags.mCount);
-}
-
-
/**
*
* @update gess12/13/98
diff --git a/htmlparser/src/nsElementTable.h b/htmlparser/src/nsElementTable.h
index b6af72e5056..eb376f57886 100644
--- a/htmlparser/src/nsElementTable.h
+++ b/htmlparser/src/nsElementTable.h
@@ -209,7 +209,6 @@ struct nsHTMLElement {
static PRBool CanContain(eHTMLTags aParent,eHTMLTags aChild);
static PRBool IsContainer(eHTMLTags aTag) ;
static PRBool IsResidualStyleTag(eHTMLTags aTag) ;
- static PRBool IsHeadingTag(eHTMLTags aTag) ;
static PRBool IsTextTag(eHTMLTags aTag);
static PRBool IsWhitespaceTag(eHTMLTags aTag);
diff --git a/htmlparser/src/nsHTMLTokenizer.cpp b/htmlparser/src/nsHTMLTokenizer.cpp
index d6dd2eaba70..b54d09d9dfe 100644
--- a/htmlparser/src/nsHTMLTokenizer.cpp
+++ b/htmlparser/src/nsHTMLTokenizer.cpp
@@ -28,7 +28,6 @@
*/
#include "nsHTMLTokenizer.h"
-#include "nsParser.h"
#include "nsScanner.h"
#include "nsElementTable.h"
#include "nsHTMLEntities.h"
@@ -85,12 +84,17 @@ nsresult nsHTMLTokenizer::QueryInterface(const nsIID& aIID, void** aInstancePtr)
* @return NS_xxx error result
*/
-NS_HTMLPARS nsresult NS_NewHTMLTokenizer(nsITokenizer** aInstancePtrResult,PRInt32 aMode,eParserDocType aDocType, eParserCommands aCommand) {
+NS_HTMLPARS
+nsresult NS_NewHTMLTokenizer(nsITokenizer** aInstancePtrResult,
+ PRInt32 aFlag,
+ eParserDocType aDocType,
+ eParserCommands aCommand)
+{
NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr");
if (nsnull == aInstancePtrResult) {
return NS_ERROR_NULL_POINTER;
}
- nsHTMLTokenizer* it = new nsHTMLTokenizer(aMode,aDocType,aCommand);
+ nsHTMLTokenizer* it = new nsHTMLTokenizer(aFlag,aDocType,aCommand);
if (nsnull == it) {
return NS_ERROR_OUT_OF_MEMORY;
}
@@ -112,13 +116,45 @@ NS_IMPL_RELEASE(nsHTMLTokenizer)
nsHTMLTokenizer::nsHTMLTokenizer(PRInt32 aParseMode,
eParserDocType aDocType,
eParserCommands aCommand) :
- nsITokenizer(), mTokenDeque(0), mParseMode(aParseMode)
+ nsITokenizer(), mTokenDeque(0)
{
NS_INIT_REFCNT();
- mDoXMLEmptyTags=((eDTDMode_strict==aParseMode) || (eDTDMode_transitional==aParseMode));
- mDocType=aDocType;
+
+ if (aParseMode==eDTDMode_strict) {
+ mFlags = NS_IPARSER_FLAG_STRICT_MODE;
+ }
+ else if (aParseMode==eDTDMode_transitional) {
+ mFlags = NS_IPARSER_FLAG_TRANSITIONAL_MODE;
+ }
+ else if (aParseMode==eDTDMode_quirks) {
+ mFlags = NS_IPARSER_FLAG_QUIRKS_MODE;
+ }
+ else if (aParseMode==eDTDMode_autodetect) {
+ mFlags = NS_IPARSER_FLAG_AUTO_DETECT_MODE;
+ }
+ else {
+ mFlags = NS_IPARSER_FLAG_UNKNOWN_MODE;
+ }
+
+ if (aDocType==ePlainText) {
+ mFlags |= NS_IPARSER_FLAG_PLAIN_TEXT;
+ }
+ else if (aDocType==eXMLText) {
+ mFlags |= NS_IPARSER_FLAG_XML_TEXT;
+ }
+ else if (aDocType==eXHTMLText) {
+ mFlags |= NS_IPARSER_FLAG_XHTML_TEXT;
+ }
+ else if (aDocType==eHTML3Text) {
+ mFlags |= NS_IPARSER_FLAG_HTML3_TEXT;
+ }
+ else if (aDocType==eHTML4Text) {
+ mFlags |= NS_IPARSER_FLAG_HTML4_TEXT;
+ }
+
+ mFlags |= (aCommand==eViewSource)? NS_IPARSER_FLAG_VIEW_SOURCE:NS_IPARSER_FLAG_VIEW_NORMAL;
+
mRecordTrailingContent=PR_FALSE;
- mParserCommand=aCommand;
mTokenAllocator=nsnull;
mTokenScanPos=0;
}
@@ -448,7 +484,7 @@ nsresult nsHTMLTokenizer::ConsumeToken(nsScanner& aScanner,PRBool& aFlushTokens)
case NS_OK:
default:
- if(ePlainText!=mDocType) {
+ if(!(mFlags & NS_IPARSER_FLAG_PLAIN_TEXT)) {
if(kLessThan==theChar) {
return ConsumeTag(theChar,theToken,aScanner,aFlushTokens);
}
@@ -505,7 +541,7 @@ nsresult nsHTMLTokenizer::ConsumeTag(PRUnichar aChar,CToken*& aToken,nsScanner&
result=aScanner.Peek(theNextChar, 1);
if(NS_OK==result) {
// xml allow non ASCII tag name, consume as end tag. need to make xml view source work
- PRBool isXML=((eXMLText==mDocType) || (eXHTMLText==mDocType));
+ PRBool isXML=(mFlags & (NS_IPARSER_FLAG_XML_TEXT | NS_IPARSER_FLAG_XHTML_TEXT));
if(nsCRT::IsAsciiAlpha(theNextChar)||(kGreaterThan==theNextChar)||
(isXML && (! nsCRT::IsAscii(theNextChar)))) {
result=ConsumeEndTag(aChar,aToken,aScanner);
@@ -571,7 +607,7 @@ nsresult nsHTMLTokenizer::ConsumeAttributes(PRUnichar aChar,CStartToken* aToken,
while((!done) && (result==NS_OK)) {
CAttributeToken* theToken= NS_STATIC_CAST(CAttributeToken*, theAllocator->CreateTokenOfType(eToken_attribute,eHTMLTag_unknown));
if(theToken){
- result=theToken->Consume(aChar,aScanner,PRBool(eViewSource==mParserCommand)); //tell new token to finish consuming text...
+ result=theToken->Consume(aChar,aScanner,mFlags); //tell new token to finish consuming text...
//Much as I hate to do this, here's some special case code.
//This handles the case of empty-tags in XML. Our last
@@ -585,7 +621,7 @@ nsresult nsHTMLTokenizer::ConsumeAttributes(PRUnichar aChar,CStartToken* aToken,
// support XML like syntax to fix bugs like 44186
if(!key.IsEmpty() && kForwardSlash==key.First() && text.IsEmpty()) {
aToken->SetEmpty(PR_TRUE);
- isUsableAttr=!mDoXMLEmptyTags;
+ isUsableAttr = !(mFlags & (NS_IPARSER_FLAG_STRICT_MODE|NS_IPARSER_FLAG_TRANSITIONAL_MODE));
}
if(isUsableAttr) {
theAttrCount++;
@@ -655,8 +691,7 @@ nsresult nsHTMLTokenizer::ConsumeStartTag(PRUnichar aChar,CToken*& aToken,nsScan
nsReadingIterator origin;
aScanner.CurrentPosition(origin);
- PRBool isHTML=((eHTML3Text==mDocType) || (eHTML4Text==mDocType));
- result= aToken->Consume(aChar,aScanner,isHTML); //tell new token to finish consuming text...
+ result= aToken->Consume(aChar,aScanner,mFlags); //tell new token to finish consuming text...
if(NS_SUCCEEDED(result)) {
@@ -668,7 +703,12 @@ nsresult nsHTMLTokenizer::ConsumeStartTag(PRUnichar aChar,CToken*& aToken,nsScan
PRBool theTagHasAttributes=PR_FALSE;
nsReadingIterator start, end;
if(NS_OK==result) {
- result=(eViewSource==mParserCommand) ? aScanner.ReadWhitespace(start, end) : aScanner.SkipWhitespace();
+ if (mFlags & NS_IPARSER_FLAG_VIEW_SOURCE) {
+ result = aScanner.ReadWhitespace(start, end);
+ }
+ else {
+ result = aScanner.SkipWhitespace();
+ }
aToken->mNewlineCount += aScanner.GetNewlinesSkipped();
if(NS_OK==result) {
result=aScanner.Peek(aChar);
@@ -686,7 +726,7 @@ nsresult nsHTMLTokenizer::ConsumeStartTag(PRUnichar aChar,CToken*& aToken,nsScan
CStartToken* theStartToken=NS_STATIC_CAST(CStartToken*,aToken);
if(theTagHasAttributes) {
- if (eViewSource==mParserCommand) {
+ if (mFlags & NS_IPARSER_FLAG_VIEW_SOURCE) {
// Since we conserve whitespace in view-source mode,
// go back to the beginning of the whitespace section
// and let the first attribute grab it.
@@ -719,7 +759,7 @@ nsresult nsHTMLTokenizer::ConsumeStartTag(PRUnichar aChar,CToken*& aToken,nsScan
CToken* text=theAllocator->CreateTokenOfType(eToken_text,eHTMLTag_text);
CTextToken* textToken=NS_STATIC_CAST(CTextToken*,text);
- result=textToken->ConsumeUntil(0,theTag!=eHTMLTag_script,aScanner,endText,mParseMode,aFlushTokens); //tell new token to finish consuming text...
+ result=textToken->ConsumeUntil(0,theTag!=eHTMLTag_script,aScanner,endText,mFlags,aFlushTokens); //tell new token to finish consuming text...
// Fix bug 44186
// Support XML like syntax, i.e., ==
@@ -770,8 +810,7 @@ nsresult nsHTMLTokenizer::ConsumeEndTag(PRUnichar aChar,CToken*& aToken,nsScanne
nsresult result=NS_OK;
if(aToken) {
- PRBool isHTML=((eHTML3Text==mDocType) || (eHTML4Text==mDocType));
- result= aToken->Consume(aChar,aScanner,isHTML); //tell new token to finish consuming text...
+ result= aToken->Consume(aChar,aScanner,mFlags); //tell new token to finish consuming text...
AddToken(aToken,result,&mTokenDeque,theAllocator);
if(NS_SUCCEEDED(result)) {
@@ -810,7 +849,7 @@ nsresult nsHTMLTokenizer::ConsumeEntity(PRUnichar aChar,CToken*& aToken,nsScanne
// Get the first entity character
aScanner.GetChar(theChar);
- result = aToken->Consume(theChar,aScanner,mParseMode); //tell new token to finish consuming text...
+ result = aToken->Consume(theChar,aScanner,mFlags); //tell new token to finish consuming text...
}
else if(kHashsign==theChar) {
// Get the "&"
@@ -819,7 +858,7 @@ nsresult nsHTMLTokenizer::ConsumeEntity(PRUnichar aChar,CToken*& aToken,nsScanne
// Get the first numerical entity character
aScanner.GetChar(theChar);
- result=aToken->Consume(theChar,aScanner,mParseMode);
+ result=aToken->Consume(theChar,aScanner,mFlags);
}
else {
//oops, we're actually looking at plain text...
@@ -854,7 +893,7 @@ nsresult nsHTMLTokenizer::ConsumeWhitespace(PRUnichar aChar,CToken*& aToken,nsSc
aToken = theAllocator->CreateTokenOfType(eToken_whitespace,eHTMLTag_whitespace);
nsresult result=NS_OK;
if(aToken) {
- result=aToken->Consume(aChar,aScanner,mParseMode);
+ result=aToken->Consume(aChar,aScanner,mFlags);
AddToken(aToken,result,&mTokenDeque,theAllocator);
}
return result;
@@ -878,7 +917,7 @@ nsresult nsHTMLTokenizer::ConsumeComment(PRUnichar aChar,CToken*& aToken,nsScann
aToken = theAllocator->CreateTokenOfType(eToken_comment,eHTMLTag_comment);
nsresult result=NS_OK;
if(aToken) {
- result=aToken->Consume(aChar,aScanner,mParseMode);
+ result=aToken->Consume(aChar,aScanner,mFlags);
AddToken(aToken,result,&mTokenDeque,theAllocator);
}
return result;
@@ -900,7 +939,7 @@ nsresult nsHTMLTokenizer::ConsumeText(CToken*& aToken,nsScanner& aScanner){
CTextToken* theToken = (CTextToken*)theAllocator->CreateTokenOfType(eToken_text,eHTMLTag_text);
if(theToken) {
PRUnichar ch=0;
- result=theToken->Consume(ch,aScanner,mParseMode);
+ result=theToken->Consume(ch,aScanner,mFlags);
if(!NS_SUCCEEDED(result)) {
if(0==theToken->GetTextLength()){
IF_FREE(aToken, mTokenAllocator);
@@ -953,7 +992,7 @@ nsresult nsHTMLTokenizer::ConsumeSpecialMarkup(PRUnichar aChar,CToken*& aToken,n
aToken = theAllocator->CreateTokenOfType(eToken_doctypeDecl,eHTMLTag_doctypeDecl);
if(aToken) {
- result=aToken->Consume(aChar,aScanner,mParseMode);
+ result=aToken->Consume(aChar,aScanner,mFlags);
AddToken(aToken,result,&mTokenDeque,theAllocator);
}
return result;
@@ -976,7 +1015,7 @@ nsresult nsHTMLTokenizer::ConsumeNewline(PRUnichar aChar,CToken*& aToken,nsScann
aToken=theAllocator->CreateTokenOfType(eToken_newline,eHTMLTag_newline);
nsresult result=NS_OK;
if(aToken) {
- result=aToken->Consume(aChar,aScanner,mParseMode);
+ result=aToken->Consume(aChar,aScanner,mFlags);
AddToken(aToken,result,&mTokenDeque,theAllocator);
}
return result;
@@ -1001,7 +1040,7 @@ nsresult nsHTMLTokenizer::ConsumeProcessingInstruction(PRUnichar aChar,CToken*&
aToken=theAllocator->CreateTokenOfType(eToken_instruction,eHTMLTag_unknown);
nsresult result=NS_OK;
if(aToken) {
- result=aToken->Consume(aChar,aScanner,mParseMode);
+ result=aToken->Consume(aChar,aScanner,mFlags);
AddToken(aToken,result,&mTokenDeque,theAllocator);
}
return result;
diff --git a/htmlparser/src/nsHTMLTokenizer.h b/htmlparser/src/nsHTMLTokenizer.h
index a22553eeaa7..005dc2e8ebf 100644
--- a/htmlparser/src/nsHTMLTokenizer.h
+++ b/htmlparser/src/nsHTMLTokenizer.h
@@ -97,11 +97,8 @@ protected:
static void AddToken(CToken*& aToken,nsresult aResult,nsDeque* aDeque,nsTokenAllocator* aTokenAllocator);
nsDeque mTokenDeque;
- PRBool mDoXMLEmptyTags;
- PRInt32 mParseMode;
- eParserDocType mDocType;
+ PRInt32 mFlags;
PRBool mRecordTrailingContent;
- eParserCommands mParserCommand; //tells us to viewcontent/viewsource/viewerrors...
nsTokenAllocator* mTokenAllocator;
PRInt32 mTokenScanPos;
PRBool mIsFinalChunk;
diff --git a/htmlparser/src/nsHTMLTokens.cpp b/htmlparser/src/nsHTMLTokens.cpp
index e320cf3b281..e41f4aca1ca 100644
--- a/htmlparser/src/nsHTMLTokens.cpp
+++ b/htmlparser/src/nsHTMLTokens.cpp
@@ -26,7 +26,6 @@
#include "nsScanner.h"
#include "nsToken.h"
#include "nsHTMLTokens.h"
-#include "nsIParser.h"
#include "prtypes.h"
#include "nsDebug.h"
#include "nsHTMLTags.h"
@@ -38,6 +37,13 @@
static const char* gUserdefined = "userdefined";
+static const PRUnichar kAttributeTerminalChars[] = {
+ PRUnichar('&'), PRUnichar('\b'), PRUnichar('\t'),
+ PRUnichar('\n'), PRUnichar('\r'), PRUnichar(' '),
+ PRUnichar('>'),
+ PRUnichar(0)
+};
+
/**************************************************************
And now for the token classes...
@@ -194,10 +200,10 @@ PRBool CStartToken::IsEmpty(void) {
* @update gess 3/25/98
* @param aChar -- last char consumed from stream
* @param aScanner -- controller of underlying input source
- * @param aMode -- 1=HTML; 0=text (or other ML)
+ * @param aFlag - contains information such as |dtd mode|view mode|doctype|etc...
* @return error result
*/
-nsresult CStartToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aMode) {
+nsresult CStartToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aFlag) {
//if you're here, we've already Consumed the < char, and are
//ready to Consume the rest of the open tag identifier.
@@ -205,7 +211,7 @@ nsresult CStartToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aMode
//NOTE: We don't Consume the tag attributes here, nor do we eat the ">"
nsresult result=NS_OK;
- if(1==aMode) {
+ if(aFlag & (NS_IPARSER_FLAG_HTML3_TEXT | NS_IPARSER_FLAG_HTML4_TEXT)) {
nsAutoString theSubstr;
result=aScanner.GetIdentifier(theSubstr,PR_TRUE);
mTypeID = (PRInt32)nsHTMLTags::LookupTag(theSubstr);
@@ -321,10 +327,10 @@ CEndToken::CEndToken(const nsAReadableString& aName,eHTMLTags aTag) : CHTMLToken
* @update gess 3/25/98
* @param aChar -- last char consumed from stream
* @param aScanner -- controller of underlying input source
- * @param aMode -- 1=HTML; 0=text (or other ML)
+ * @param aFlag - contains information such as |dtd mode|view mode|doctype|etc...
* @return error result
*/
-nsresult CEndToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aMode) {
+nsresult CEndToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aFlag) {
//if you're here, we've already Consumed the '.
@@ -333,7 +339,7 @@ nsresult CEndToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aMode)
nsresult result=NS_OK;
nsAutoString buffer;
PRInt32 offset;
- if(1==aMode) {
+ if(aFlag & (NS_IPARSER_FLAG_HTML3_TEXT | NS_IPARSER_FLAG_HTML4_TEXT)) {
nsAutoString theSubstr;
result=aScanner.ReadUntil(theSubstr,kGreaterThan,PR_FALSE);
if (NS_FAILED(result)) {
@@ -526,7 +532,7 @@ PRInt32 CTextToken::GetTextLength(void) {
* @param aScanner -- controller of underlying input source
* @return error result
*/
-nsresult CTextToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aMode) {
+nsresult CTextToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aFlag) {
static const PRUnichar theTerminalsChars[] =
{ PRUnichar('\n'), PRUnichar('\r'), PRUnichar('&'), PRUnichar('<'),
PRUnichar(0) };
@@ -593,7 +599,7 @@ nsresult CTextToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aMode)
* @return error result
*/
nsresult CTextToken::ConsumeUntil(PRUnichar aChar,PRBool aIgnoreComments,nsScanner& aScanner,
- nsString& aTerminalString,PRInt32 aMode,PRBool& aFlushTokens){
+ nsString& aTerminalString,PRInt32 aFlag,PRBool& aFlushTokens){
nsresult result=NS_OK;
nsReadingIterator theStartOffset, theCurrOffset, theTermStrPos, theStartCommentPos, theAltTermStrPos, endPos;
PRBool done=PR_FALSE;
@@ -659,7 +665,8 @@ nsresult CTextToken::ConsumeUntil(PRUnichar aChar,PRBool aIgnoreComments,nsScann
}
if (theTermStrPos != endPos) {
- if((aMode != eDTDMode_strict) && (aMode != eDTDMode_transitional) &&
+ if(!(aFlag & NS_IPARSER_FLAG_STRICT_MODE) &&
+ !(aFlag & NS_IPARSER_FLAG_TRANSITIONAL_MODE) &&
!theLastIteration && !aIgnoreComments) {
nsReadingIterator endComment(theCurrOffset);
endComment.advance(5);
@@ -798,7 +805,7 @@ PRInt32 CCDATASectionToken::GetTokenType(void) {
* @param aScanner -- controller of underlying input source
* @return error result
*/
-nsresult CCDATASectionToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aMode) {
+nsresult CCDATASectionToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aFlag) {
static const char* theTerminals="\r]";
nsresult result=NS_OK;
PRBool done=PR_FALSE;
@@ -900,7 +907,7 @@ PRInt32 CMarkupDeclToken::GetTokenType(void) {
* @param aScanner -- controller of underlying input source
* @return error result
*/
-nsresult CMarkupDeclToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aMode) {
+nsresult CMarkupDeclToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aFlag) {
static const PRUnichar theTerminalsChars[] =
{ PRUnichar('\n'), PRUnichar('\r'), PRUnichar('\''), PRUnichar('"'),
PRUnichar('>'),
@@ -1180,23 +1187,16 @@ nsresult ConsumeComment(PRUnichar aChar, nsScanner& aScanner,nsString& aString)
* @param aScanner -- controller of underlying input source
* @return error result
*/
-nsresult CCommentToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aMode) {
+nsresult CCommentToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aFlag) {
nsresult result=PR_TRUE;
- switch(aMode) {
-
-#if 1 //set to 1 if you want strict comments. Bug 53011 and 2749 contradicts!!!!
- case eDTDMode_strict:
- result=ConsumeStrictComment(aChar,aScanner,mTextValue);
- break;
-#endif
-
- case eDTDMode_transitional:
- default:
- result=ConsumeComment(aChar,aScanner,mTextValue);
- break;
- } //switch
-
+ if (aFlag & NS_IPARSER_FLAG_STRICT_MODE) {
+ //Enabling strict comment parsing for Bug 53011 and 2749 contradicts!!!!
+ result=ConsumeStrictComment(aChar,aScanner,mTextValue);
+ }
+ else {
+ result=ConsumeComment(aChar,aScanner,mTextValue);
+ }
return result;
}
@@ -1293,7 +1293,7 @@ const nsAReadableString& CNewlineToken::GetStringValue(void) {
* @param aScanner -- controller of underlying input source
* @return error result
*/
-nsresult CNewlineToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aMode) {
+nsresult CNewlineToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aFlag) {
/*******************************************************************
@@ -1473,37 +1473,133 @@ void CAttributeToken::AppendSource(nsString& anOutputString){
// anOutputString.AppendWithConversion(";");
}
+/*
+ * @param aScanner -- controller of underlying input source
+ * @param aFlag -- If NS_IPARSER_FLAG_VIEW_SOURCE do not reduce entities...
+ * @return error result
+ *
+ */
+static
+nsresult ConsumeAttributeEntity(nsString& aString,
+ nsScanner& aScanner,
+ PRInt32 aFlag)
+{
+
+ nsresult result=NS_OK;
+
+ PRUnichar ch;
+ result=aScanner.Peek(ch, 1);
+
+ if (NS_SUCCEEDED(result)) {
+ PRUnichar amp=0;
+ PRInt32 theNCRValue=0;
+ nsAutoString entity;
+
+ if (nsCRT::IsAsciiAlpha(ch) && !(aFlag & NS_IPARSER_FLAG_VIEW_SOURCE)) {
+ aScanner.GetChar(amp); // Get '&'
+ result=CEntityToken::ConsumeEntity(ch,entity,aScanner);
+ if (NS_SUCCEEDED(result)) {
+ theNCRValue = nsHTMLEntities::EntityToUnicode(entity);
+ PRUnichar theTermChar=entity.Last();
+ // If an entity value is greater than 255 then:
+ // Nav 4.x does not treat it as an entity,
+ // IE treats it as an entity if terminated with a semicolon.
+ // Resembling IE!!
+ if(theNCRValue < 0 || (theNCRValue > 255 && theTermChar != ';')) {
+ // Looks like we're not dealing with an entity
+ aString.Append(amp);
+ aString.Append(entity);
+ }
+ else {
+ // A valid entity so reduce it.
+ aString.Append(PRUnichar(theNCRValue));
+ }
+ }
+ }
+ else if (ch==kHashsign && !(aFlag & NS_IPARSER_FLAG_VIEW_SOURCE)) {
+ aScanner.GetChar(amp); // Discard '&'
+ PRInt32 err;
+ result=CEntityToken::ConsumeEntity(ch,entity,aScanner);
+ if (NS_SUCCEEDED(result)) {
+ theNCRValue=entity.ToInteger(&err,kAutoDetect);
+ aString.Append(PRUnichar(theNCRValue));
+ }
+ }
+ else {
+ // What we thought as entity is not really an entity...
+ aScanner.GetChar(amp);
+ aString.Append(amp);
+ }//if
+ }
+
+ return result;
+}
+
+/*
+ * This general purpose method is used when you want to
+ * consume attributed text value.
+ * Note: It also reduces entities within attributes.
+ *
+ * @param aScanner -- controller of underlying input source
+ * @param aTerminalChars -- characters that stop consuming attribute.
+ * @param aFlag - contains information such as |dtd mode|view mode|doctype|etc...
+ * @return error result
+ */
+static
+nsresult ConsumeAttributeValueText(nsString& aString,
+ nsScanner& aScanner,
+ const PRUnichar *aTerminalChars,
+ PRInt32 aFlag)
+{
+ const nsLocalString theTerminals(aTerminalChars,
+ sizeof(aTerminalChars)/sizeof(aTerminalChars[0]) - 1);
+
+ nsresult result=aScanner.ReadUntil(aString,theTerminals,PR_FALSE);
+
+ if(NS_SUCCEEDED(result)) {
+ PRUnichar ch;
+ aScanner.Peek(ch);
+ if(ch==kAmpersand) {
+ result=ConsumeAttributeEntity(aString,aScanner,aFlag);
+ if (NS_SUCCEEDED(result)) {
+ result=ConsumeAttributeValueText(aString,aScanner,aTerminalChars,aFlag);
+ }
+ }
+ }
+
+ return result;
+}
+
/*
* This general purpose method is used when you want to
* consume a known quoted string.
*
- * @update gess 3/25/98
- * @param aChar -- last char consumed from stream
* @param aScanner -- controller of underlying input source
+ * @param aTerminalChars -- characters that stop consuming attribute.
+ * @param aFlag - contains information such as |dtd mode|view mode|doctype|etc...
* @return error result
*/
-nsresult ConsumeQuotedString(PRUnichar aChar,nsString& aString,nsScanner& aScanner,PRBool aRetainQuote=PR_FALSE){
+static
+nsresult ConsumeQuottedString(PRUnichar aChar,
+ nsString& aString,
+ nsScanner& aScanner,
+ PRInt32 aFlag)
+{
+ NS_ASSERTION(aChar==kQuote || aChar==kApostrophe,"char is neither quote nor apostrophe");
+
+ const PRUnichar theTerminalChars[] = {
+ aChar, PRUnichar('&'),
+ PRUnichar(0)
+ };
+
nsresult result=NS_OK;
nsReadingIterator theOffset;
aScanner.CurrentPosition(theOffset);
- if(aRetainQuote) {
- aString.Append(aChar);
- }
+ result=ConsumeAttributeValueText(aString,aScanner,theTerminalChars,aFlag);
- switch(aChar) {
- case kQuote:
- result=aScanner.ReadUntil(aString,kQuote,aRetainQuote);
- if(NS_OK==result)
- result=aScanner.SkipOver(kQuote); //this code is here in case someone mistakenly adds multiple quotes...
- break;
- case kApostrophe:
- result=aScanner.ReadUntil(aString,kApostrophe,aRetainQuote);
- if(NS_OK==result)
- result=aScanner.SkipOver(kApostrophe); //this code is here in case someone mistakenly adds multiple apostrophes...
- break;
- default:
- break;
+ if(NS_SUCCEEDED(result)) {
+ result = aScanner.SkipOver(aChar); // aChar should be " or '
}
// Ref: Bug 35806
@@ -1511,59 +1607,23 @@ nsresult ConsumeQuotedString(PRUnichar aChar,nsString& aString,nsScanner& aScann
// Ex QueryInterface(kClassIID, (void **) aInstancePtrResult);
-}
-
-
-NS_IMPL_ADDREF(nsXMLTokenizer)
-NS_IMPL_RELEASE(nsXMLTokenizer)
-
-
-/**
- * Default constructor
- *
- * @update gess 4/9/98
- * @param
- * @return
- */
-nsXMLTokenizer::nsXMLTokenizer() : nsHTMLTokenizer() {
- NS_INIT_REFCNT();
- mDoXMLEmptyTags=PR_TRUE;
- mDocType=eXMLText;
-}
-
-/**
- * Default constructor
- *
- * @update gess 4/9/98
- * @param
- * @return
- */
-nsXMLTokenizer::~nsXMLTokenizer(){
-}
-
-
-/*******************************************************************
- Here begins the real working methods for the tokenizer.
- *******************************************************************/
-
-/**
- * This method repeatedly called by the tokenizer.
- * Each time, we determine the kind of token were about to
- * read, and then we call the appropriate method to handle
- * that token type.
- *
- * @update gess 3/25/98
- * @param aChar: last char read
- * @param aScanner: see nsScanner.h
- * @param anErrorCode: arg that will hold error condition
- * @return new token or null
- */
-nsresult nsXMLTokenizer::ConsumeToken(nsScanner& aScanner,PRBool& aFlushTokens) {
- return nsHTMLTokenizer::ConsumeToken(aScanner,aFlushTokens);
-}
-
-
-nsTokenAllocator* nsXMLTokenizer::GetTokenAllocator(void) {
- return nsHTMLTokenizer::GetTokenAllocator();
-}
-
-/*
- * Consume characters as long as they match the string passed in.
- * If they don't match, put them all back.
- * XXX The scanner should be able to do this.
- *
- * @update vidur 11/12/98
- */
-static
-nsresult ConsumeConditional(nsScanner& aScanner,const nsString& aMatchString,PRBool& aMatch) {
- nsresult result=NS_OK;
- nsAutoString str;
- PRUint32 len = aMatchString.Length();
-
- result = aScanner.Peek(str, len);
- if ((NS_OK == result) && str.Equals(aMatchString)) {
- aMatch = PR_TRUE;
- nsReadingIterator curPos;
- aScanner.CurrentPosition(curPos);
- curPos.advance(len);
- aScanner.SetPosition(curPos);
- }
- else {
- aMatch = PR_FALSE;
- }
-
- return result;
-}
-
-/**
- * This method is called just after a "GetTokenAllocator();
-
- if(theAllocator) {
- nsAutoString theEmpty;
- aToken=theAllocator->CreateTokenOfType(eToken_comment,eHTMLTag_comment,theEmpty);
- if(aToken) {
- result=aToken->Consume(aChar,aScanner,eDTDMode_strict);
- AddToken(aToken,result,&mTokenDeque,theAllocator);
- }
- }
-
- return result;
-}
-
-/**
- * This method is called just after a "GetTokenAllocator();
-
- if(theAllocator) {
- PRUnichar theChar;
- aScanner.Peek(theChar);
- PRBool isComment=PR_TRUE;
- nsAutoString theEmpty;
- if(theChar==kLeftSquareBracket) {
- nsAutoString CDATAString; CDATAString.AssignWithConversion("[CDATA[");
- PRBool isCDATA = PR_FALSE;
- result = ConsumeConditional(aScanner, CDATAString, isCDATA);
- if (NS_OK == result) {
- if (isCDATA) {
- aToken=theAllocator->CreateTokenOfType(eToken_cdatasection,eHTMLTag_unknown,theEmpty);
- isComment=PR_FALSE;
- }
- }
- }
-
- if(isComment) aToken = theAllocator->CreateTokenOfType(eToken_comment,eHTMLTag_comment,theEmpty);
-
- if(aToken) {
- result=aToken->Consume(aChar,aScanner,eDTDMode_strict);
- AddToken(aToken,result,&mTokenDeque,theAllocator);
- }
- }
- return result;
-}
-
-
-/**
- *
- * @update gess12/28/98
- * @param
- * @return
- */
-nsresult nsXMLTokenizer::HandleSkippedContent(nsScanner& aScanner,CToken*& aToken) {
- nsresult result=NS_OK;
- return result;
-}
diff --git a/layout/html/document/src/quirk.css b/layout/html/document/src/quirk.css
index 41e6ebe8eca..baba06708c4 100644
--- a/layout/html/document/src/quirk.css
+++ b/layout/html/document/src/quirk.css
@@ -205,3 +205,13 @@ img[align=right] {
margin-left: 3px;
}
+/* Quirk: Make sure that the residual style tags' size info.
+ * does not take precedence over heading tags' size. (b=77352)
+ * Note: This special attribute is set only for a residual
+ * style tag within a heading tag.
+ */
+*[_moz-rs-heading] {
+ font-size: inherit !important;
+}
+
+
diff --git a/layout/style/quirk.css b/layout/style/quirk.css
index 41e6ebe8eca..baba06708c4 100644
--- a/layout/style/quirk.css
+++ b/layout/style/quirk.css
@@ -205,3 +205,13 @@ img[align=right] {
margin-left: 3px;
}
+/* Quirk: Make sure that the residual style tags' size info.
+ * does not take precedence over heading tags' size. (b=77352)
+ * Note: This special attribute is set only for a residual
+ * style tag within a heading tag.
+ */
+*[_moz-rs-heading] {
+ font-size: inherit !important;
+}
+
+
diff --git a/parser/htmlparser/src/CNavDTD.cpp b/parser/htmlparser/src/CNavDTD.cpp
index df96e56b787..6621c1bd9e7 100644
--- a/parser/htmlparser/src/CNavDTD.cpp
+++ b/parser/htmlparser/src/CNavDTD.cpp
@@ -189,26 +189,6 @@ CNavDTD::CNavDTD() : nsIDTD(),
}
-/**
- * This method recycles the nodes on a nodestack.
- * NOTE: Unlike recycleNode(), we force the usecount
- * to 0 of all nodes, then force them to recycle.
- * @update gess1/8/99
- * @param aNodeStack
- * @return nothing
- */
-void CNavDTD::RecycleNodes(nsEntryStack *aNodeStack) {
- if(aNodeStack) {
- PRInt32 theCount=aNodeStack->mCount;
- PRInt32 theIndex=0;
-
- for(theIndex=0;theIndexNodeAt(theIndex);
- IF_FREE(node, &mNodeAllocator);
- }
- }
-}
-
/**
*
* @update gess1/8/99
@@ -631,12 +611,9 @@ nsresult CNavDTD::DidBuildModel(nsresult anErrorCode,PRBool aNotifySink,nsIParse
nsEntryStack *theChildStyles=0;
nsCParserNode* theNode=mBodyContext->Pop(theChildStyles);
- if(theNode) {
- if(theChildStyles) {
- delete theChildStyles;
- }
- IF_FREE(theNode, &mNodeAllocator);
- }
+
+ IF_DELETE(theChildStyles,&mNodeAllocator);
+ IF_FREE(theNode, &mNodeAllocator);
}
}
@@ -2926,8 +2903,22 @@ nsresult CNavDTD::OpenTransientStyles(eHTMLTags aChildTag){
if(1==theNode->mUseCount) {
eHTMLTags theNodeTag=(eHTMLTags)theNode->GetNodeType();
if(gHTMLElements[theNodeTag].CanContain(aChildTag)) {
- theEntry->mParent=theStack; //we do this too, because this entry differs from the new one we're pushing...
- result=OpenContainer(theNode,theNodeTag,PR_FALSE,theStack);
+ theEntry->mParent = theStack; //we do this too, because this entry differs from the new one we're pushing...
+ if(gHTMLElements[mBodyContext->Last()].IsMemberOf(kHeading)) {
+ // Bug 77352
+ // The style system needs to identify residual style tags
+ // within heading tags so that heading tags' size can take
+ // precedence over the residual style tags' size info..
+ // *Note: Make sure that this attribute is transient since it
+ // should not get carried over to cases other than heading.
+ CAttributeToken theAttrToken(NS_LITERAL_STRING("_moz-rs-heading"),NS_LITERAL_STRING(""));
+ theNode->AddAttribute(&theAttrToken);
+ result = OpenContainer(theNode,theNodeTag,PR_FALSE,theStack);
+ theNode->PopAttributeToken();
+ }
+ else {
+ result = OpenContainer(theNode,theNodeTag,PR_FALSE,theStack);
+ }
}
else {
//if the node tag can't contain the child tag, then remove the child tag from the style stack
@@ -3658,10 +3649,7 @@ nsresult CNavDTD::CloseContainersTo(PRInt32 anIndex,eHTMLTags aTarget, PRBool aC
mBodyContext->PushStyles(theChildStyleStack);
}
else{
- //add code here to recycle styles...
- RecycleNodes(theChildStyleStack);
- delete theChildStyleStack; // XXX try to recycle this...
- theChildStyleStack=0;
+ IF_DELETE(theChildStyleStack,&mNodeAllocator);
}
}
else if (0==theNode->mUseCount) {
@@ -3687,9 +3675,7 @@ nsresult CNavDTD::CloseContainersTo(PRInt32 anIndex,eHTMLTags aTarget, PRBool aC
//the tag is not a style tag...
if(theChildStyleStack) {
if(theStyleDoesntLeakOut) {
- RecycleNodes(theChildStyleStack);
- delete theChildStyleStack; // XXX try to recycle this...
- theChildStyleStack=0;
+ IF_DELETE(theChildStyleStack,&mNodeAllocator);
}
else mBodyContext->PushStyles(theChildStyleStack);
}
@@ -3726,7 +3712,8 @@ nsresult CNavDTD::CloseContainersTo(eHTMLTags aTarget,PRBool aClosedByStartTag){
PRBool theTagIsSynonymous=((nsHTMLElement::IsResidualStyleTag(aTarget)) && (nsHTMLElement::IsResidualStyleTag(theTopTag)));
if(!theTagIsSynonymous){
- theTagIsSynonymous=((nsHTMLElement::IsHeadingTag(aTarget)) && (nsHTMLElement::IsHeadingTag(theTopTag)));
+ theTagIsSynonymous=(gHTMLElements[aTarget].IsMemberOf(kHeading) &&
+ gHTMLElements[theTopTag].IsMemberOf(kHeading));
}
if(theTagIsSynonymous) {
diff --git a/parser/htmlparser/src/CNavDTD.h b/parser/htmlparser/src/CNavDTD.h
index b740511cc28..9bb624aeeb5 100644
--- a/parser/htmlparser/src/CNavDTD.h
+++ b/parser/htmlparser/src/CNavDTD.h
@@ -490,7 +490,6 @@ protected:
nsresult HandleOmittedTag(CToken* aToken,eHTMLTags aChildTag,eHTMLTags aParent,nsIParserNode *aNode);
nsresult HandleSavedTokens(PRInt32 anIndex);
nsresult HandleKeyGen(nsIParserNode *aNode);
- void RecycleNodes(nsEntryStack *aNodeStack);
nsDeque mMisplacedContent;
nsDeque mSkippedContent;
diff --git a/parser/htmlparser/src/nsDTDUtils.cpp b/parser/htmlparser/src/nsDTDUtils.cpp
index 68799060cb7..fcccbe937a8 100644
--- a/parser/htmlparser/src/nsDTDUtils.cpp
+++ b/parser/htmlparser/src/nsDTDUtils.cpp
@@ -83,6 +83,23 @@ nsEntryStack::~nsEntryStack() {
mCount=mCapacity=0;
}
+/**
+ * Release all objects in the entry stack
+ */
+void
+nsEntryStack::ReleaseAll(nsNodeAllocator* aNodeAllocator)
+{
+ NS_WARN_IF_FALSE(aNodeAllocator,"no allocator? - potential leak!");
+
+ if(aNodeAllocator) {
+ NS_WARN_IF_FALSE(mCount >= 0,"count should not be negative");
+ while(mCount > 0) {
+ nsCParserNode* node=this->Pop();
+ IF_FREE(node,aNodeAllocator);
+ }
+ }
+}
+
/**
* Resets state of stack to be empty.
* @update harishd 04/04/99
@@ -1045,10 +1062,7 @@ void nsDTDContext::PushStyles(nsEntryStack *aStyles){
// If you're here it means that we have hit the rock bottom
// ,of the stack, and there's no need to handle anymore styles.
// Fix for bug 29048
- nsCParserNode* theNode=aStyles->Pop();
- IF_HOLD(theNode);
- delete aStyles;
- aStyles=0;
+ IF_DELETE(aStyles,mNodeAllocator);
}
}//if(aStyles)
}
diff --git a/parser/htmlparser/src/nsDTDUtils.h b/parser/htmlparser/src/nsDTDUtils.h
index 5c154cd6d10..66480905d1c 100644
--- a/parser/htmlparser/src/nsDTDUtils.h
+++ b/parser/htmlparser/src/nsDTDUtils.h
@@ -45,8 +45,31 @@
#include "nsFixedSizeAllocator.h"
#include "nsVoidArray.h"
-#define IF_HOLD(_ptr) if(_ptr) { _ptr->AddRef(); }
-#define IF_FREE(_ptr, _allocator) if(_ptr) { _ptr->Release((_allocator)->GetArenaPool()); _ptr=0; } // recycles _ptr
+#define IF_HOLD(_ptr) \
+ PR_BEGIN_MACRO \
+ if(_ptr) { \
+ _ptr->AddRef(); \
+ } \
+ PR_END_MACRO
+
+// recycles _ptr
+#define IF_FREE(_ptr, _allocator) \
+ PR_BEGIN_MACRO \
+ if(_ptr) { \
+ _ptr->Release((_allocator)->GetArenaPool()); \
+ _ptr=0; \
+ } \
+ PR_END_MACRO
+
+// release objects and destroy _ptr
+#define IF_DELETE(_ptr, _allocator) \
+ PR_BEGIN_MACRO \
+ if(_ptr) { \
+ _ptr->ReleaseAll(_allocator); \
+ delete(_ptr); \
+ _ptr=0; \
+ } \
+ PR_END_MACRO
class nsIParserNode;
class nsCParserNode;
@@ -73,6 +96,7 @@ struct nsTagEntry {
};
class nsEntryStack {
+
public:
nsEntryStack();
~nsEntryStack();
@@ -91,6 +115,11 @@ public:
eHTMLTags Last() const;
void Empty(void);
+ /*
+ * Release all objects in the entry stack
+ */
+ void ReleaseAll(nsNodeAllocator* aNodeAllocator);
+
/**
* Find the first instance of given tag on the stack.
* @update gess 12/14/99
diff --git a/parser/htmlparser/src/nsElementTable.cpp b/parser/htmlparser/src/nsElementTable.cpp
index 958986ca0d9..b04398c98ef 100644
--- a/parser/htmlparser/src/nsElementTable.cpp
+++ b/parser/htmlparser/src/nsElementTable.cpp
@@ -104,7 +104,7 @@ TagList gULKids={2,{eHTMLTag_li,eHTMLTag_p}};
//*********************************************************************************************
TagList gRootTags={4,{eHTMLTag_body,eHTMLTag_td,eHTMLTag_table,eHTMLTag_applet}};
-TagList gTableRootTags={7,{eHTMLTag_applet,eHTMLTag_body,eHTMLTag_dl,eHTMLTag_ol,eHTMLTag_td,eHTMLTag_th,eHTMLTag_ul}};
+TagList gTableRootTags={6,{eHTMLTag_applet,eHTMLTag_body,eHTMLTag_dl,eHTMLTag_ol,eHTMLTag_td,eHTMLTag_th}};
TagList gHTMLRootTags={1,{eHTMLTag_unknown}};
TagList gLIRootTags={8,{eHTMLTag_ul,eHTMLTag_ol,eHTMLTag_dir,eHTMLTag_menu,eHTMLTag_p,eHTMLTag_body,eHTMLTag_td,eHTMLTag_th}};
@@ -1956,17 +1956,6 @@ PRBool nsHTMLElement::IsResidualStyleTag(eHTMLTags aChild) {
return result;
}
-/**
- *
- * @update gess12/13/98
- * @param
- * @return
- */
-PRBool nsHTMLElement::IsHeadingTag(eHTMLTags aChild) {
- return FindTagInSet(aChild,gHeadingTags.mTags,gHeadingTags.mCount);
-}
-
-
/**
*
* @update gess12/13/98
diff --git a/parser/htmlparser/src/nsElementTable.h b/parser/htmlparser/src/nsElementTable.h
index b6af72e5056..eb376f57886 100644
--- a/parser/htmlparser/src/nsElementTable.h
+++ b/parser/htmlparser/src/nsElementTable.h
@@ -209,7 +209,6 @@ struct nsHTMLElement {
static PRBool CanContain(eHTMLTags aParent,eHTMLTags aChild);
static PRBool IsContainer(eHTMLTags aTag) ;
static PRBool IsResidualStyleTag(eHTMLTags aTag) ;
- static PRBool IsHeadingTag(eHTMLTags aTag) ;
static PRBool IsTextTag(eHTMLTags aTag);
static PRBool IsWhitespaceTag(eHTMLTags aTag);
diff --git a/parser/htmlparser/src/nsHTMLTokenizer.cpp b/parser/htmlparser/src/nsHTMLTokenizer.cpp
index d6dd2eaba70..b54d09d9dfe 100644
--- a/parser/htmlparser/src/nsHTMLTokenizer.cpp
+++ b/parser/htmlparser/src/nsHTMLTokenizer.cpp
@@ -28,7 +28,6 @@
*/
#include "nsHTMLTokenizer.h"
-#include "nsParser.h"
#include "nsScanner.h"
#include "nsElementTable.h"
#include "nsHTMLEntities.h"
@@ -85,12 +84,17 @@ nsresult nsHTMLTokenizer::QueryInterface(const nsIID& aIID, void** aInstancePtr)
* @return NS_xxx error result
*/
-NS_HTMLPARS nsresult NS_NewHTMLTokenizer(nsITokenizer** aInstancePtrResult,PRInt32 aMode,eParserDocType aDocType, eParserCommands aCommand) {
+NS_HTMLPARS
+nsresult NS_NewHTMLTokenizer(nsITokenizer** aInstancePtrResult,
+ PRInt32 aFlag,
+ eParserDocType aDocType,
+ eParserCommands aCommand)
+{
NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr");
if (nsnull == aInstancePtrResult) {
return NS_ERROR_NULL_POINTER;
}
- nsHTMLTokenizer* it = new nsHTMLTokenizer(aMode,aDocType,aCommand);
+ nsHTMLTokenizer* it = new nsHTMLTokenizer(aFlag,aDocType,aCommand);
if (nsnull == it) {
return NS_ERROR_OUT_OF_MEMORY;
}
@@ -112,13 +116,45 @@ NS_IMPL_RELEASE(nsHTMLTokenizer)
nsHTMLTokenizer::nsHTMLTokenizer(PRInt32 aParseMode,
eParserDocType aDocType,
eParserCommands aCommand) :
- nsITokenizer(), mTokenDeque(0), mParseMode(aParseMode)
+ nsITokenizer(), mTokenDeque(0)
{
NS_INIT_REFCNT();
- mDoXMLEmptyTags=((eDTDMode_strict==aParseMode) || (eDTDMode_transitional==aParseMode));
- mDocType=aDocType;
+
+ if (aParseMode==eDTDMode_strict) {
+ mFlags = NS_IPARSER_FLAG_STRICT_MODE;
+ }
+ else if (aParseMode==eDTDMode_transitional) {
+ mFlags = NS_IPARSER_FLAG_TRANSITIONAL_MODE;
+ }
+ else if (aParseMode==eDTDMode_quirks) {
+ mFlags = NS_IPARSER_FLAG_QUIRKS_MODE;
+ }
+ else if (aParseMode==eDTDMode_autodetect) {
+ mFlags = NS_IPARSER_FLAG_AUTO_DETECT_MODE;
+ }
+ else {
+ mFlags = NS_IPARSER_FLAG_UNKNOWN_MODE;
+ }
+
+ if (aDocType==ePlainText) {
+ mFlags |= NS_IPARSER_FLAG_PLAIN_TEXT;
+ }
+ else if (aDocType==eXMLText) {
+ mFlags |= NS_IPARSER_FLAG_XML_TEXT;
+ }
+ else if (aDocType==eXHTMLText) {
+ mFlags |= NS_IPARSER_FLAG_XHTML_TEXT;
+ }
+ else if (aDocType==eHTML3Text) {
+ mFlags |= NS_IPARSER_FLAG_HTML3_TEXT;
+ }
+ else if (aDocType==eHTML4Text) {
+ mFlags |= NS_IPARSER_FLAG_HTML4_TEXT;
+ }
+
+ mFlags |= (aCommand==eViewSource)? NS_IPARSER_FLAG_VIEW_SOURCE:NS_IPARSER_FLAG_VIEW_NORMAL;
+
mRecordTrailingContent=PR_FALSE;
- mParserCommand=aCommand;
mTokenAllocator=nsnull;
mTokenScanPos=0;
}
@@ -448,7 +484,7 @@ nsresult nsHTMLTokenizer::ConsumeToken(nsScanner& aScanner,PRBool& aFlushTokens)
case NS_OK:
default:
- if(ePlainText!=mDocType) {
+ if(!(mFlags & NS_IPARSER_FLAG_PLAIN_TEXT)) {
if(kLessThan==theChar) {
return ConsumeTag(theChar,theToken,aScanner,aFlushTokens);
}
@@ -505,7 +541,7 @@ nsresult nsHTMLTokenizer::ConsumeTag(PRUnichar aChar,CToken*& aToken,nsScanner&
result=aScanner.Peek(theNextChar, 1);
if(NS_OK==result) {
// xml allow non ASCII tag name, consume as end tag. need to make xml view source work
- PRBool isXML=((eXMLText==mDocType) || (eXHTMLText==mDocType));
+ PRBool isXML=(mFlags & (NS_IPARSER_FLAG_XML_TEXT | NS_IPARSER_FLAG_XHTML_TEXT));
if(nsCRT::IsAsciiAlpha(theNextChar)||(kGreaterThan==theNextChar)||
(isXML && (! nsCRT::IsAscii(theNextChar)))) {
result=ConsumeEndTag(aChar,aToken,aScanner);
@@ -571,7 +607,7 @@ nsresult nsHTMLTokenizer::ConsumeAttributes(PRUnichar aChar,CStartToken* aToken,
while((!done) && (result==NS_OK)) {
CAttributeToken* theToken= NS_STATIC_CAST(CAttributeToken*, theAllocator->CreateTokenOfType(eToken_attribute,eHTMLTag_unknown));
if(theToken){
- result=theToken->Consume(aChar,aScanner,PRBool(eViewSource==mParserCommand)); //tell new token to finish consuming text...
+ result=theToken->Consume(aChar,aScanner,mFlags); //tell new token to finish consuming text...
//Much as I hate to do this, here's some special case code.
//This handles the case of empty-tags in XML. Our last
@@ -585,7 +621,7 @@ nsresult nsHTMLTokenizer::ConsumeAttributes(PRUnichar aChar,CStartToken* aToken,
// support XML like syntax to fix bugs like 44186
if(!key.IsEmpty() && kForwardSlash==key.First() && text.IsEmpty()) {
aToken->SetEmpty(PR_TRUE);
- isUsableAttr=!mDoXMLEmptyTags;
+ isUsableAttr = !(mFlags & (NS_IPARSER_FLAG_STRICT_MODE|NS_IPARSER_FLAG_TRANSITIONAL_MODE));
}
if(isUsableAttr) {
theAttrCount++;
@@ -655,8 +691,7 @@ nsresult nsHTMLTokenizer::ConsumeStartTag(PRUnichar aChar,CToken*& aToken,nsScan
nsReadingIterator origin;
aScanner.CurrentPosition(origin);
- PRBool isHTML=((eHTML3Text==mDocType) || (eHTML4Text==mDocType));
- result= aToken->Consume(aChar,aScanner,isHTML); //tell new token to finish consuming text...
+ result= aToken->Consume(aChar,aScanner,mFlags); //tell new token to finish consuming text...
if(NS_SUCCEEDED(result)) {
@@ -668,7 +703,12 @@ nsresult nsHTMLTokenizer::ConsumeStartTag(PRUnichar aChar,CToken*& aToken,nsScan
PRBool theTagHasAttributes=PR_FALSE;
nsReadingIterator start, end;
if(NS_OK==result) {
- result=(eViewSource==mParserCommand) ? aScanner.ReadWhitespace(start, end) : aScanner.SkipWhitespace();
+ if (mFlags & NS_IPARSER_FLAG_VIEW_SOURCE) {
+ result = aScanner.ReadWhitespace(start, end);
+ }
+ else {
+ result = aScanner.SkipWhitespace();
+ }
aToken->mNewlineCount += aScanner.GetNewlinesSkipped();
if(NS_OK==result) {
result=aScanner.Peek(aChar);
@@ -686,7 +726,7 @@ nsresult nsHTMLTokenizer::ConsumeStartTag(PRUnichar aChar,CToken*& aToken,nsScan
CStartToken* theStartToken=NS_STATIC_CAST(CStartToken*,aToken);
if(theTagHasAttributes) {
- if (eViewSource==mParserCommand) {
+ if (mFlags & NS_IPARSER_FLAG_VIEW_SOURCE) {
// Since we conserve whitespace in view-source mode,
// go back to the beginning of the whitespace section
// and let the first attribute grab it.
@@ -719,7 +759,7 @@ nsresult nsHTMLTokenizer::ConsumeStartTag(PRUnichar aChar,CToken*& aToken,nsScan
CToken* text=theAllocator->CreateTokenOfType(eToken_text,eHTMLTag_text);
CTextToken* textToken=NS_STATIC_CAST(CTextToken*,text);
- result=textToken->ConsumeUntil(0,theTag!=eHTMLTag_script,aScanner,endText,mParseMode,aFlushTokens); //tell new token to finish consuming text...
+ result=textToken->ConsumeUntil(0,theTag!=eHTMLTag_script,aScanner,endText,mFlags,aFlushTokens); //tell new token to finish consuming text...
// Fix bug 44186
// Support XML like syntax, i.e., ==
@@ -770,8 +810,7 @@ nsresult nsHTMLTokenizer::ConsumeEndTag(PRUnichar aChar,CToken*& aToken,nsScanne
nsresult result=NS_OK;
if(aToken) {
- PRBool isHTML=((eHTML3Text==mDocType) || (eHTML4Text==mDocType));
- result= aToken->Consume(aChar,aScanner,isHTML); //tell new token to finish consuming text...
+ result= aToken->Consume(aChar,aScanner,mFlags); //tell new token to finish consuming text...
AddToken(aToken,result,&mTokenDeque,theAllocator);
if(NS_SUCCEEDED(result)) {
@@ -810,7 +849,7 @@ nsresult nsHTMLTokenizer::ConsumeEntity(PRUnichar aChar,CToken*& aToken,nsScanne
// Get the first entity character
aScanner.GetChar(theChar);
- result = aToken->Consume(theChar,aScanner,mParseMode); //tell new token to finish consuming text...
+ result = aToken->Consume(theChar,aScanner,mFlags); //tell new token to finish consuming text...
}
else if(kHashsign==theChar) {
// Get the "&"
@@ -819,7 +858,7 @@ nsresult nsHTMLTokenizer::ConsumeEntity(PRUnichar aChar,CToken*& aToken,nsScanne
// Get the first numerical entity character
aScanner.GetChar(theChar);
- result=aToken->Consume(theChar,aScanner,mParseMode);
+ result=aToken->Consume(theChar,aScanner,mFlags);
}
else {
//oops, we're actually looking at plain text...
@@ -854,7 +893,7 @@ nsresult nsHTMLTokenizer::ConsumeWhitespace(PRUnichar aChar,CToken*& aToken,nsSc
aToken = theAllocator->CreateTokenOfType(eToken_whitespace,eHTMLTag_whitespace);
nsresult result=NS_OK;
if(aToken) {
- result=aToken->Consume(aChar,aScanner,mParseMode);
+ result=aToken->Consume(aChar,aScanner,mFlags);
AddToken(aToken,result,&mTokenDeque,theAllocator);
}
return result;
@@ -878,7 +917,7 @@ nsresult nsHTMLTokenizer::ConsumeComment(PRUnichar aChar,CToken*& aToken,nsScann
aToken = theAllocator->CreateTokenOfType(eToken_comment,eHTMLTag_comment);
nsresult result=NS_OK;
if(aToken) {
- result=aToken->Consume(aChar,aScanner,mParseMode);
+ result=aToken->Consume(aChar,aScanner,mFlags);
AddToken(aToken,result,&mTokenDeque,theAllocator);
}
return result;
@@ -900,7 +939,7 @@ nsresult nsHTMLTokenizer::ConsumeText(CToken*& aToken,nsScanner& aScanner){
CTextToken* theToken = (CTextToken*)theAllocator->CreateTokenOfType(eToken_text,eHTMLTag_text);
if(theToken) {
PRUnichar ch=0;
- result=theToken->Consume(ch,aScanner,mParseMode);
+ result=theToken->Consume(ch,aScanner,mFlags);
if(!NS_SUCCEEDED(result)) {
if(0==theToken->GetTextLength()){
IF_FREE(aToken, mTokenAllocator);
@@ -953,7 +992,7 @@ nsresult nsHTMLTokenizer::ConsumeSpecialMarkup(PRUnichar aChar,CToken*& aToken,n
aToken = theAllocator->CreateTokenOfType(eToken_doctypeDecl,eHTMLTag_doctypeDecl);
if(aToken) {
- result=aToken->Consume(aChar,aScanner,mParseMode);
+ result=aToken->Consume(aChar,aScanner,mFlags);
AddToken(aToken,result,&mTokenDeque,theAllocator);
}
return result;
@@ -976,7 +1015,7 @@ nsresult nsHTMLTokenizer::ConsumeNewline(PRUnichar aChar,CToken*& aToken,nsScann
aToken=theAllocator->CreateTokenOfType(eToken_newline,eHTMLTag_newline);
nsresult result=NS_OK;
if(aToken) {
- result=aToken->Consume(aChar,aScanner,mParseMode);
+ result=aToken->Consume(aChar,aScanner,mFlags);
AddToken(aToken,result,&mTokenDeque,theAllocator);
}
return result;
@@ -1001,7 +1040,7 @@ nsresult nsHTMLTokenizer::ConsumeProcessingInstruction(PRUnichar aChar,CToken*&
aToken=theAllocator->CreateTokenOfType(eToken_instruction,eHTMLTag_unknown);
nsresult result=NS_OK;
if(aToken) {
- result=aToken->Consume(aChar,aScanner,mParseMode);
+ result=aToken->Consume(aChar,aScanner,mFlags);
AddToken(aToken,result,&mTokenDeque,theAllocator);
}
return result;
diff --git a/parser/htmlparser/src/nsHTMLTokenizer.h b/parser/htmlparser/src/nsHTMLTokenizer.h
index a22553eeaa7..005dc2e8ebf 100644
--- a/parser/htmlparser/src/nsHTMLTokenizer.h
+++ b/parser/htmlparser/src/nsHTMLTokenizer.h
@@ -97,11 +97,8 @@ protected:
static void AddToken(CToken*& aToken,nsresult aResult,nsDeque* aDeque,nsTokenAllocator* aTokenAllocator);
nsDeque mTokenDeque;
- PRBool mDoXMLEmptyTags;
- PRInt32 mParseMode;
- eParserDocType mDocType;
+ PRInt32 mFlags;
PRBool mRecordTrailingContent;
- eParserCommands mParserCommand; //tells us to viewcontent/viewsource/viewerrors...
nsTokenAllocator* mTokenAllocator;
PRInt32 mTokenScanPos;
PRBool mIsFinalChunk;
diff --git a/parser/htmlparser/src/nsHTMLTokens.cpp b/parser/htmlparser/src/nsHTMLTokens.cpp
index e320cf3b281..e41f4aca1ca 100644
--- a/parser/htmlparser/src/nsHTMLTokens.cpp
+++ b/parser/htmlparser/src/nsHTMLTokens.cpp
@@ -26,7 +26,6 @@
#include "nsScanner.h"
#include "nsToken.h"
#include "nsHTMLTokens.h"
-#include "nsIParser.h"
#include "prtypes.h"
#include "nsDebug.h"
#include "nsHTMLTags.h"
@@ -38,6 +37,13 @@
static const char* gUserdefined = "userdefined";
+static const PRUnichar kAttributeTerminalChars[] = {
+ PRUnichar('&'), PRUnichar('\b'), PRUnichar('\t'),
+ PRUnichar('\n'), PRUnichar('\r'), PRUnichar(' '),
+ PRUnichar('>'),
+ PRUnichar(0)
+};
+
/**************************************************************
And now for the token classes...
@@ -194,10 +200,10 @@ PRBool CStartToken::IsEmpty(void) {
* @update gess 3/25/98
* @param aChar -- last char consumed from stream
* @param aScanner -- controller of underlying input source
- * @param aMode -- 1=HTML; 0=text (or other ML)
+ * @param aFlag - contains information such as |dtd mode|view mode|doctype|etc...
* @return error result
*/
-nsresult CStartToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aMode) {
+nsresult CStartToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aFlag) {
//if you're here, we've already Consumed the < char, and are
//ready to Consume the rest of the open tag identifier.
@@ -205,7 +211,7 @@ nsresult CStartToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aMode
//NOTE: We don't Consume the tag attributes here, nor do we eat the ">"
nsresult result=NS_OK;
- if(1==aMode) {
+ if(aFlag & (NS_IPARSER_FLAG_HTML3_TEXT | NS_IPARSER_FLAG_HTML4_TEXT)) {
nsAutoString theSubstr;
result=aScanner.GetIdentifier(theSubstr,PR_TRUE);
mTypeID = (PRInt32)nsHTMLTags::LookupTag(theSubstr);
@@ -321,10 +327,10 @@ CEndToken::CEndToken(const nsAReadableString& aName,eHTMLTags aTag) : CHTMLToken
* @update gess 3/25/98
* @param aChar -- last char consumed from stream
* @param aScanner -- controller of underlying input source
- * @param aMode -- 1=HTML; 0=text (or other ML)
+ * @param aFlag - contains information such as |dtd mode|view mode|doctype|etc...
* @return error result
*/
-nsresult CEndToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aMode) {
+nsresult CEndToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aFlag) {
//if you're here, we've already Consumed the '.
@@ -333,7 +339,7 @@ nsresult CEndToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aMode)
nsresult result=NS_OK;
nsAutoString buffer;
PRInt32 offset;
- if(1==aMode) {
+ if(aFlag & (NS_IPARSER_FLAG_HTML3_TEXT | NS_IPARSER_FLAG_HTML4_TEXT)) {
nsAutoString theSubstr;
result=aScanner.ReadUntil(theSubstr,kGreaterThan,PR_FALSE);
if (NS_FAILED(result)) {
@@ -526,7 +532,7 @@ PRInt32 CTextToken::GetTextLength(void) {
* @param aScanner -- controller of underlying input source
* @return error result
*/
-nsresult CTextToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aMode) {
+nsresult CTextToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aFlag) {
static const PRUnichar theTerminalsChars[] =
{ PRUnichar('\n'), PRUnichar('\r'), PRUnichar('&'), PRUnichar('<'),
PRUnichar(0) };
@@ -593,7 +599,7 @@ nsresult CTextToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aMode)
* @return error result
*/
nsresult CTextToken::ConsumeUntil(PRUnichar aChar,PRBool aIgnoreComments,nsScanner& aScanner,
- nsString& aTerminalString,PRInt32 aMode,PRBool& aFlushTokens){
+ nsString& aTerminalString,PRInt32 aFlag,PRBool& aFlushTokens){
nsresult result=NS_OK;
nsReadingIterator theStartOffset, theCurrOffset, theTermStrPos, theStartCommentPos, theAltTermStrPos, endPos;
PRBool done=PR_FALSE;
@@ -659,7 +665,8 @@ nsresult CTextToken::ConsumeUntil(PRUnichar aChar,PRBool aIgnoreComments,nsScann
}
if (theTermStrPos != endPos) {
- if((aMode != eDTDMode_strict) && (aMode != eDTDMode_transitional) &&
+ if(!(aFlag & NS_IPARSER_FLAG_STRICT_MODE) &&
+ !(aFlag & NS_IPARSER_FLAG_TRANSITIONAL_MODE) &&
!theLastIteration && !aIgnoreComments) {
nsReadingIterator endComment(theCurrOffset);
endComment.advance(5);
@@ -798,7 +805,7 @@ PRInt32 CCDATASectionToken::GetTokenType(void) {
* @param aScanner -- controller of underlying input source
* @return error result
*/
-nsresult CCDATASectionToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aMode) {
+nsresult CCDATASectionToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aFlag) {
static const char* theTerminals="\r]";
nsresult result=NS_OK;
PRBool done=PR_FALSE;
@@ -900,7 +907,7 @@ PRInt32 CMarkupDeclToken::GetTokenType(void) {
* @param aScanner -- controller of underlying input source
* @return error result
*/
-nsresult CMarkupDeclToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aMode) {
+nsresult CMarkupDeclToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aFlag) {
static const PRUnichar theTerminalsChars[] =
{ PRUnichar('\n'), PRUnichar('\r'), PRUnichar('\''), PRUnichar('"'),
PRUnichar('>'),
@@ -1180,23 +1187,16 @@ nsresult ConsumeComment(PRUnichar aChar, nsScanner& aScanner,nsString& aString)
* @param aScanner -- controller of underlying input source
* @return error result
*/
-nsresult CCommentToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aMode) {
+nsresult CCommentToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aFlag) {
nsresult result=PR_TRUE;
- switch(aMode) {
-
-#if 1 //set to 1 if you want strict comments. Bug 53011 and 2749 contradicts!!!!
- case eDTDMode_strict:
- result=ConsumeStrictComment(aChar,aScanner,mTextValue);
- break;
-#endif
-
- case eDTDMode_transitional:
- default:
- result=ConsumeComment(aChar,aScanner,mTextValue);
- break;
- } //switch
-
+ if (aFlag & NS_IPARSER_FLAG_STRICT_MODE) {
+ //Enabling strict comment parsing for Bug 53011 and 2749 contradicts!!!!
+ result=ConsumeStrictComment(aChar,aScanner,mTextValue);
+ }
+ else {
+ result=ConsumeComment(aChar,aScanner,mTextValue);
+ }
return result;
}
@@ -1293,7 +1293,7 @@ const nsAReadableString& CNewlineToken::GetStringValue(void) {
* @param aScanner -- controller of underlying input source
* @return error result
*/
-nsresult CNewlineToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aMode) {
+nsresult CNewlineToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aFlag) {
/*******************************************************************
@@ -1473,37 +1473,133 @@ void CAttributeToken::AppendSource(nsString& anOutputString){
// anOutputString.AppendWithConversion(";");
}
+/*
+ * @param aScanner -- controller of underlying input source
+ * @param aFlag -- If NS_IPARSER_FLAG_VIEW_SOURCE do not reduce entities...
+ * @return error result
+ *
+ */
+static
+nsresult ConsumeAttributeEntity(nsString& aString,
+ nsScanner& aScanner,
+ PRInt32 aFlag)
+{
+
+ nsresult result=NS_OK;
+
+ PRUnichar ch;
+ result=aScanner.Peek(ch, 1);
+
+ if (NS_SUCCEEDED(result)) {
+ PRUnichar amp=0;
+ PRInt32 theNCRValue=0;
+ nsAutoString entity;
+
+ if (nsCRT::IsAsciiAlpha(ch) && !(aFlag & NS_IPARSER_FLAG_VIEW_SOURCE)) {
+ aScanner.GetChar(amp); // Get '&'
+ result=CEntityToken::ConsumeEntity(ch,entity,aScanner);
+ if (NS_SUCCEEDED(result)) {
+ theNCRValue = nsHTMLEntities::EntityToUnicode(entity);
+ PRUnichar theTermChar=entity.Last();
+ // If an entity value is greater than 255 then:
+ // Nav 4.x does not treat it as an entity,
+ // IE treats it as an entity if terminated with a semicolon.
+ // Resembling IE!!
+ if(theNCRValue < 0 || (theNCRValue > 255 && theTermChar != ';')) {
+ // Looks like we're not dealing with an entity
+ aString.Append(amp);
+ aString.Append(entity);
+ }
+ else {
+ // A valid entity so reduce it.
+ aString.Append(PRUnichar(theNCRValue));
+ }
+ }
+ }
+ else if (ch==kHashsign && !(aFlag & NS_IPARSER_FLAG_VIEW_SOURCE)) {
+ aScanner.GetChar(amp); // Discard '&'
+ PRInt32 err;
+ result=CEntityToken::ConsumeEntity(ch,entity,aScanner);
+ if (NS_SUCCEEDED(result)) {
+ theNCRValue=entity.ToInteger(&err,kAutoDetect);
+ aString.Append(PRUnichar(theNCRValue));
+ }
+ }
+ else {
+ // What we thought as entity is not really an entity...
+ aScanner.GetChar(amp);
+ aString.Append(amp);
+ }//if
+ }
+
+ return result;
+}
+
+/*
+ * This general purpose method is used when you want to
+ * consume attributed text value.
+ * Note: It also reduces entities within attributes.
+ *
+ * @param aScanner -- controller of underlying input source
+ * @param aTerminalChars -- characters that stop consuming attribute.
+ * @param aFlag - contains information such as |dtd mode|view mode|doctype|etc...
+ * @return error result
+ */
+static
+nsresult ConsumeAttributeValueText(nsString& aString,
+ nsScanner& aScanner,
+ const PRUnichar *aTerminalChars,
+ PRInt32 aFlag)
+{
+ const nsLocalString theTerminals(aTerminalChars,
+ sizeof(aTerminalChars)/sizeof(aTerminalChars[0]) - 1);
+
+ nsresult result=aScanner.ReadUntil(aString,theTerminals,PR_FALSE);
+
+ if(NS_SUCCEEDED(result)) {
+ PRUnichar ch;
+ aScanner.Peek(ch);
+ if(ch==kAmpersand) {
+ result=ConsumeAttributeEntity(aString,aScanner,aFlag);
+ if (NS_SUCCEEDED(result)) {
+ result=ConsumeAttributeValueText(aString,aScanner,aTerminalChars,aFlag);
+ }
+ }
+ }
+
+ return result;
+}
+
/*
* This general purpose method is used when you want to
* consume a known quoted string.
*
- * @update gess 3/25/98
- * @param aChar -- last char consumed from stream
* @param aScanner -- controller of underlying input source
+ * @param aTerminalChars -- characters that stop consuming attribute.
+ * @param aFlag - contains information such as |dtd mode|view mode|doctype|etc...
* @return error result
*/
-nsresult ConsumeQuotedString(PRUnichar aChar,nsString& aString,nsScanner& aScanner,PRBool aRetainQuote=PR_FALSE){
+static
+nsresult ConsumeQuottedString(PRUnichar aChar,
+ nsString& aString,
+ nsScanner& aScanner,
+ PRInt32 aFlag)
+{
+ NS_ASSERTION(aChar==kQuote || aChar==kApostrophe,"char is neither quote nor apostrophe");
+
+ const PRUnichar theTerminalChars[] = {
+ aChar, PRUnichar('&'),
+ PRUnichar(0)
+ };
+
nsresult result=NS_OK;
nsReadingIterator theOffset;
aScanner.CurrentPosition(theOffset);
- if(aRetainQuote) {
- aString.Append(aChar);
- }
+ result=ConsumeAttributeValueText(aString,aScanner,theTerminalChars,aFlag);
- switch(aChar) {
- case kQuote:
- result=aScanner.ReadUntil(aString,kQuote,aRetainQuote);
- if(NS_OK==result)
- result=aScanner.SkipOver(kQuote); //this code is here in case someone mistakenly adds multiple quotes...
- break;
- case kApostrophe:
- result=aScanner.ReadUntil(aString,kApostrophe,aRetainQuote);
- if(NS_OK==result)
- result=aScanner.SkipOver(kApostrophe); //this code is here in case someone mistakenly adds multiple apostrophes...
- break;
- default:
- break;
+ if(NS_SUCCEEDED(result)) {
+ result = aScanner.SkipOver(aChar); // aChar should be " or '
}
// Ref: Bug 35806
@@ -1511,59 +1607,23 @@ nsresult ConsumeQuotedString(PRUnichar aChar,nsString& aString,nsScanner& aScann
// Ex QueryInterface(kClassIID, (void **) aInstancePtrResult);
-}
-
-
-NS_IMPL_ADDREF(nsXMLTokenizer)
-NS_IMPL_RELEASE(nsXMLTokenizer)
-
-
-/**
- * Default constructor
- *
- * @update gess 4/9/98
- * @param
- * @return
- */
-nsXMLTokenizer::nsXMLTokenizer() : nsHTMLTokenizer() {
- NS_INIT_REFCNT();
- mDoXMLEmptyTags=PR_TRUE;
- mDocType=eXMLText;
-}
-
-/**
- * Default constructor
- *
- * @update gess 4/9/98
- * @param
- * @return
- */
-nsXMLTokenizer::~nsXMLTokenizer(){
-}
-
-
-/*******************************************************************
- Here begins the real working methods for the tokenizer.
- *******************************************************************/
-
-/**
- * This method repeatedly called by the tokenizer.
- * Each time, we determine the kind of token were about to
- * read, and then we call the appropriate method to handle
- * that token type.
- *
- * @update gess 3/25/98
- * @param aChar: last char read
- * @param aScanner: see nsScanner.h
- * @param anErrorCode: arg that will hold error condition
- * @return new token or null
- */
-nsresult nsXMLTokenizer::ConsumeToken(nsScanner& aScanner,PRBool& aFlushTokens) {
- return nsHTMLTokenizer::ConsumeToken(aScanner,aFlushTokens);
-}
-
-
-nsTokenAllocator* nsXMLTokenizer::GetTokenAllocator(void) {
- return nsHTMLTokenizer::GetTokenAllocator();
-}
-
-/*
- * Consume characters as long as they match the string passed in.
- * If they don't match, put them all back.
- * XXX The scanner should be able to do this.
- *
- * @update vidur 11/12/98
- */
-static
-nsresult ConsumeConditional(nsScanner& aScanner,const nsString& aMatchString,PRBool& aMatch) {
- nsresult result=NS_OK;
- nsAutoString str;
- PRUint32 len = aMatchString.Length();
-
- result = aScanner.Peek(str, len);
- if ((NS_OK == result) && str.Equals(aMatchString)) {
- aMatch = PR_TRUE;
- nsReadingIterator curPos;
- aScanner.CurrentPosition(curPos);
- curPos.advance(len);
- aScanner.SetPosition(curPos);
- }
- else {
- aMatch = PR_FALSE;
- }
-
- return result;
-}
-
-/**
- * This method is called just after a "GetTokenAllocator();
-
- if(theAllocator) {
- nsAutoString theEmpty;
- aToken=theAllocator->CreateTokenOfType(eToken_comment,eHTMLTag_comment,theEmpty);
- if(aToken) {
- result=aToken->Consume(aChar,aScanner,eDTDMode_strict);
- AddToken(aToken,result,&mTokenDeque,theAllocator);
- }
- }
-
- return result;
-}
-
-/**
- * This method is called just after a "GetTokenAllocator();
-
- if(theAllocator) {
- PRUnichar theChar;
- aScanner.Peek(theChar);
- PRBool isComment=PR_TRUE;
- nsAutoString theEmpty;
- if(theChar==kLeftSquareBracket) {
- nsAutoString CDATAString; CDATAString.AssignWithConversion("[CDATA[");
- PRBool isCDATA = PR_FALSE;
- result = ConsumeConditional(aScanner, CDATAString, isCDATA);
- if (NS_OK == result) {
- if (isCDATA) {
- aToken=theAllocator->CreateTokenOfType(eToken_cdatasection,eHTMLTag_unknown,theEmpty);
- isComment=PR_FALSE;
- }
- }
- }
-
- if(isComment) aToken = theAllocator->CreateTokenOfType(eToken_comment,eHTMLTag_comment,theEmpty);
-
- if(aToken) {
- result=aToken->Consume(aChar,aScanner,eDTDMode_strict);
- AddToken(aToken,result,&mTokenDeque,theAllocator);
- }
- }
- return result;
-}
-
-
-/**
- *
- * @update gess12/28/98
- * @param
- * @return
- */
-nsresult nsXMLTokenizer::HandleSkippedContent(nsScanner& aScanner,CToken*& aToken) {
- nsresult result=NS_OK;
- return result;
-}