diff --git a/htmlparser/src/CNavDTD.cpp b/htmlparser/src/CNavDTD.cpp
index 51b69f1df0e..e578c7791d4 100644
--- a/htmlparser/src/CNavDTD.cpp
+++ b/htmlparser/src/CNavDTD.cpp
@@ -22,9 +22,10 @@
//#define ENABLE_CRC
//#define RICKG_DEBUG
-#define ENABLE_RESIDUALSTYLE
//#define ALLOW_TR_AS_CHILD_OF_TABLE //by setting this to true, TR is allowable directly in TABLE.
+#define ENABLE_RESIDUALSTYLE
+
#ifdef RICKG_DEBUG
#include
#endif
@@ -266,12 +267,24 @@ CNavDTD::~CNavDTD(){
/**
* Call this method if you want the DTD to construct a fresh
* instance of itself.
- * @update gess7/23/98
+ * @update gess 25May2000
* @param
* @return
*/
nsresult CNavDTD::CreateNewInstance(nsIDTD** aInstancePtrResult){
- return NS_NewNavHTMLDTD(aInstancePtrResult);
+
+ nsresult result=NS_NewNavHTMLDTD(aInstancePtrResult);
+
+ if(aInstancePtrResult) {
+ CNavDTD *theOtherDTD=(CNavDTD*)*aInstancePtrResult;
+ if(theOtherDTD) {
+ theOtherDTD->mDTDMode=mDTDMode;
+ theOtherDTD->mParserCommand=mParserCommand;
+ theOtherDTD->mDocType=mDocType;
+ }
+ }
+
+ return result;
}
/**
@@ -827,10 +840,9 @@ nsresult CNavDTD::DidHandleStartTag(nsCParserNode& aNode,eHTMLTags aChildTag){
{
PRInt32 theCount=mBodyContext->GetCount();
eHTMLTags theGrandParentTag=mBodyContext->TagAt(theCount-2);
- PRInt32 theCounter=mBodyContext->IncrementCounter(theGrandParentTag);
-
- nsString theNumber;
- theNumber.AppendInt(theCounter);
+
+ nsAutoString theNumber;
+ PRInt32 theCounter=mBodyContext->IncrementCounter(theGrandParentTag,aNode,theNumber);
CTextToken theToken(theNumber);
PRInt32 theLineNumber=0;
nsCParserNode theNode(&theToken,theLineNumber);
@@ -838,6 +850,35 @@ nsresult CNavDTD::DidHandleStartTag(nsCParserNode& aNode,eHTMLTags aChildTag){
}
break;
+ case eHTMLTag_meta:
+ {
+ //we should only enable user-defined entities in debug builds...
+
+ PRInt32 theCount=aNode.GetAttributeCount();
+ const nsString* theNamePtr=0;
+ const nsString* theValuePtr=0;
+
+ if(theCount) {
+ PRInt32 theIndex=0;
+ for(theIndex=0;theIndexRegisterEntity(*theNamePtr,*theValuePtr);
+ }
+ }
+ break;
+
default:
break;
}//switch
@@ -1846,6 +1887,27 @@ nsresult CNavDTD::HandleEntityToken(CToken* aToken) {
NS_PRECONDITION(0!=aToken,kNullToken);
nsresult result=NS_OK;
+
+ nsString& theStr=aToken->GetStringValueXXX();
+ PRUnichar theChar=theStr.CharAt(0);
+ if((kHashsign!=theChar) && (-1==nsHTMLEntities::EntityToUnicode(theStr))){
+
+ //before we just toss this away as a bogus entity, let's check...
+ CNamedEntity *theEntity=mBodyContext->GetEntity(theStr);
+ CToken *theToken=0;
+ if(theEntity) {
+ theToken=new CTextToken(theEntity->mValue);
+ }
+ else {
+ //if you're here we have a bogus entity.
+ //convert it into a text token.
+ nsAutoString temp; temp.AssignWithConversion("&");
+ temp.Append(theStr);
+ theToken=new CTextToken(temp);
+ }
+ return HandleStartToken(theToken);
+ }
+
eHTMLTags theParentTag=mBodyContext->Last();
nsCParserNode* theNode=mNodeRecycler->CreateNode();
diff --git a/htmlparser/src/COtherDTD.cpp b/htmlparser/src/COtherDTD.cpp
index 6392f0ed6f2..32dd63cedf1 100644
--- a/htmlparser/src/COtherDTD.cpp
+++ b/htmlparser/src/COtherDTD.cpp
@@ -4,24 +4,24 @@
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
- *
+ *
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
- *
+ *
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
- *
+ *
* Contributor(s):
*/
//#define ENABLE_CRC
-//#define RICKG_DEBUG
+//#define RICKG_DEBUG
#include "nsDebug.h"
@@ -131,7 +131,7 @@ NS_IMPL_RELEASE(COtherDTD)
* @param
* @return
*/
-COtherDTD::COtherDTD() : nsIDTD(), mMisplacedContent(0), mSkippedContent(0), mSharedNodes(0) {
+COtherDTD::COtherDTD() : nsIDTD(), mSharedNodes(0) {
NS_INIT_REFCNT();
mSink = 0;
mParser=0;
@@ -141,14 +141,17 @@ COtherDTD::COtherDTD() : nsIDTD(), mMisplacedContent(0), mSkippedContent(0), mSh
mHasOpenHead=0;
mHasOpenForm=PR_FALSE;
mHasOpenMap=PR_FALSE;
- mHeadContext=new nsDTDContext();
mBodyContext=new nsDTDContext();
- mFormContext=0;
mTokenizer=0;
mComputedCRC32=0;
mExpectedCRC32=0;
mDTDState=NS_OK;
- mDocType=ePlainText;
+ mDocType=eHTML4Text;
+ mHadFrameset=PR_FALSE;
+ mHadBody=PR_FALSE;
+ mHasOpenScript=PR_FALSE;
+ mTokenRecycler=0;
+ mParserCommand=eViewNormal;
char* theEnvString = PR_GetEnv("ENABLE_STRICT");
mEnableStrict=PRBool(theEnvString!=0);
@@ -280,7 +283,6 @@ const nsIID& COtherDTD::GetMostDerivedIID(void)const {
* @return
*/
COtherDTD::~COtherDTD(){
- delete mHeadContext;
delete mBodyContext;
NS_IF_RELEASE(mTokenizer);
@@ -336,7 +338,19 @@ NS_HTMLPARS nsresult NS_NewOtherHTMLDTD(nsIDTD** aInstancePtrResult) {
* @return
*/
nsresult COtherDTD::CreateNewInstance(nsIDTD** aInstancePtrResult){
- return NS_NewOtherHTMLDTD(aInstancePtrResult);
+ nsresult result=NS_NewOtherHTMLDTD(aInstancePtrResult);
+
+ if(aInstancePtrResult) {
+ COtherDTD *theOtherDTD=(COtherDTD*)*aInstancePtrResult;
+ if(theOtherDTD) {
+ theOtherDTD->mDTDMode=mDTDMode;
+ theOtherDTD->mParserCommand=mParserCommand;
+ theOtherDTD->mDocType=mDocType;
+ theOtherDTD->mEnableStrict=mEnableStrict;
+ }
+ }
+
+ return result;
}
/**
@@ -608,6 +622,7 @@ nsresult COtherDTD::HandleToken(CToken* aToken,nsIParser* aParser){
case eToken_start:
case eToken_whitespace:
case eToken_newline:
+ case eToken_doctypeDecl:
result=HandleStartToken(theToken); break;
case eToken_end:
@@ -722,7 +737,7 @@ nsresult COtherDTD::WillHandleStartTag(CToken* aToken,eHTMLTags aTag,nsCParserNo
MOZ_TIMER_DEBUGLOG(("Start: Parse Time: COtherDTD::WillHandleStartTag(), this=%p\n", this));
START_TIMER()
- return result;
+ return result;
}
@@ -762,20 +777,20 @@ nsresult COtherDTD::HandleStartToken(CToken* aToken) {
if(NS_OK==result) {
mLineNumber += aToken->mNewlineCount;
-
+
PRBool theTagWasHandled=PR_FALSE;
- switch(theChildTag) {
-
- case eHTMLTag_html:
+ switch(theChildTag) {
+
+ case eHTMLTag_html:
if(!HasOpenContainer(theChildTag)) {
mSink->OpenHTML(*theNode);
mBodyContext->Push(theNode,0);
}
theTagWasHandled=PR_TRUE;
- break;
-
- default:
+ break;
+
+ default:
CElement* theElement=gElementTable->mElements[theParent];
if(theElement) {
result=theElement->HandleStartToken(theNode,theChildTag,mBodyContext,mSink);
@@ -788,7 +803,7 @@ nsresult COtherDTD::HandleStartToken(CToken* aToken) {
DidHandleStartTag(*theNode,theChildTag);
}
- } //if
+ } //if
}//if
RecycleNode(theNode);
@@ -814,7 +829,7 @@ nsresult COtherDTD::HandleEndToken(CToken* aToken) {
nsresult result=NS_OK;
eHTMLTags theChildTag=(eHTMLTags)aToken->GetTypeID();
- #ifdef RICKG_DEBUG
+ #ifdef RICKG_DEBUG
WriteTokenToLog(aToken);
#endif
@@ -825,7 +840,7 @@ nsresult COtherDTD::HandleEndToken(CToken* aToken) {
break;
case eHTMLTag_script:
- mHasOpenScript=PR_FALSE;
+ mHasOpenScript=PR_FALSE;
default:
PRInt32 theCount=mBodyContext->GetCount();
@@ -838,7 +853,7 @@ nsresult COtherDTD::HandleEndToken(CToken* aToken) {
nsCParserNode theNode((CHTMLToken*)aToken,mLineNumber);
result=theElement->HandleEndToken(&theNode,theChildTag,mBodyContext,mSink);
}
- break;
+ break;
}
return result;
@@ -857,14 +872,12 @@ nsresult COtherDTD::CollectAttributes(nsCParserNode& aNode,eHTMLTags aTag,PRInt3
int attr=0;
nsresult result=NS_OK;
- int theAvailTokenCount=mTokenizer->GetCount() + mSkippedContent.GetSize();
+ int theAvailTokenCount=mTokenizer->GetCount();
if(aCount<=theAvailTokenCount) {
CToken* theToken=0;
eHTMLTags theSkipTarget=gElementTable->mElements[aTag]->GetSkipTarget();
for(attr=0;attrPopToken();
+ theToken=mTokenizer->PopToken();
if(theToken) {
// Sanitize the key for it might contain some non-alpha-non-digit characters
// at its end. Ex. - This will be tokenized as "<" "OPTION",
@@ -886,77 +899,6 @@ nsresult COtherDTD::CollectAttributes(nsCParserNode& aNode,eHTMLTags aTag,PRInt3
return result;
}
-
-/**
- * Causes the next skipped-content token (if any) to
- * be consumed by this node.
- * @update gess5/11/98
- * @param node to consume skipped-content
- * @param holds the number of skipped content elements encountered
- * @return Error condition.
- */
-nsresult COtherDTD::CollectSkippedContent(nsCParserNode& aNode,PRInt32 &aCount) {
-
- eHTMLTags theNodeTag=(eHTMLTags)aNode.GetNodeType();
-
- int aIndex=0;
- int aMax=mSkippedContent.GetSize();
-
- // XXX rickg This linefeed conversion stuff should be moved out of
- // the parser and into the form element code
- PRBool aMustConvertLinebreaks = PR_FALSE;
-
- mScratch.SetLength(0);
- aNode.SetSkippedContent(mScratch);
-
- for(aIndex=0;aIndexGetTokenType();
-
- mScratch.Truncate();
- // Dont worry about attributes here because it's already stored in
- // the start token as mTrailing content and will get appended in
- // start token's GetSource();
- if(eToken_attribute!=theTokenType) {
- if (eToken_entity==theTokenType) {
- if((eHTMLTag_textarea==theNodeTag) || (eHTMLTag_title==theNodeTag)) {
- ((CEntityToken*)theNextToken)->TranslateToUnicodeStr(mScratch);
- // since this is an entity, we know that it's only one character.
- // check to see if it's a CR, in which case we'll need to do line
- // termination conversion at the end.
- aMustConvertLinebreaks |= (mScratch[0] == kCR);
- }
- }
- else theNextToken->GetSource(mScratch);
-
- aNode.mSkippedContent->Append(mScratch);
- }
- mTokenRecycler->RecycleToken(theNextToken);
- }
-
- // if the string contained CRs (hence is either CR, or CRLF terminated)
- // we need to convert line breaks
- if (aMustConvertLinebreaks)
- {
- /*
- PRInt32 offset;
- while ((offset = aNode.mSkippedContent.Find("\r\n")) != kNotFound)
- aNode.mSkippedContent.Cut(offset, 1); // remove the CR
-
- // now replace remaining CRs with LFs
- aNode.mSkippedContent.ReplaceChar("\r", kNewLine);
- */
-#if 1
- nsLinebreakConverter::ConvertStringLineBreaks(*aNode.mSkippedContent,
- nsLinebreakConverter::eLinebreakAny, nsLinebreakConverter::eLinebreakContent);
-#endif
- }
-
- // Let's hope that this does not hamper the PERFORMANCE!!
- mLineNumber += aNode.mSkippedContent->CountChar(kNewLine);
- return NS_OK;
-}
/***********************************************************************************
The preceeding tables determine the set of elements each tag can contain...
diff --git a/htmlparser/src/COtherDTD.h b/htmlparser/src/COtherDTD.h
index 58cbec4829f..3cb2661b450 100644
--- a/htmlparser/src/COtherDTD.h
+++ b/htmlparser/src/COtherDTD.h
@@ -340,7 +340,6 @@ CLASS_EXPORT_HTMLPARS COtherDTD : public nsIDTD {
protected:
nsresult CollectAttributes(nsCParserNode& aNode,eHTMLTags aTag,PRInt32 aCount);
- nsresult CollectSkippedContent(nsCParserNode& aNode,PRInt32& aCount);
nsresult WillHandleStartTag(CToken* aToken,eHTMLTags aChildTag,nsCParserNode& aNode);
nsresult DidHandleStartTag(nsCParserNode& aNode,eHTMLTags aChildTag);
nsCParserNode* CreateNode(void);
@@ -349,9 +348,7 @@ protected:
nsIHTMLContentSink* mSink;
- nsDTDContext* mHeadContext;
nsDTDContext* mBodyContext;
- nsDTDContext* mFormContext;
PRBool mHasOpenForm;
PRBool mHasOpenMap;
PRInt32 mHasOpenHead;
@@ -364,10 +361,7 @@ protected:
nsParser* mParser;
nsITokenizer* mTokenizer;
CTokenRecycler* mTokenRecycler;
- nsDeque mMisplacedContent;
- nsDeque mSkippedContent;
PRBool mHasOpenScript;
- PRBool mSaveBadTokens;
eHTMLTags mSkipTarget;
nsDeque mSharedNodes;
nsresult mDTDState;
@@ -377,9 +371,8 @@ protected:
PRUint32 mComputedCRC32;
PRUint32 mExpectedCRC32;
nsAutoString mScratch; //used for various purposes; non-persistent
- PRBool mStyleHandlingEnabled;
- PRBool mEnableStrict;
eParserDocType mDocType;
+ PRBool mEnableStrict;
#ifdef NS_DEBUG
PRInt32 gNodeCount;
diff --git a/htmlparser/src/COtherElements.h b/htmlparser/src/COtherElements.h
index f98f53ac616..3f9bd1f6c5e 100644
--- a/htmlparser/src/COtherElements.h
+++ b/htmlparser/src/COtherElements.h
@@ -705,17 +705,19 @@ public:
case eHTMLTag_tr:
case eHTMLTag_th:
- if(!aContext->HasOpenContainer(eHTMLTag_tbody)) {
- nsCParserNode* theNode=new nsCParserNode();
- CToken* theToken=new CStartToken(eHTMLTag_tbody);
- theNode->Init(theToken,0,0); //this will likely leak...
+ if(aContext->mTableStates) {
+ if(aContext->mTableStates->CanOpenTBody()) {
+ nsCParserNode* theNode=new nsCParserNode();
+ CToken* theToken=new CStartToken(eHTMLTag_tbody);
+ theNode->Init(theToken,0,0); //this will likely leak...
- result=HandleStartToken(theNode,eHTMLTag_tbody,aContext,aSink);
- }
- if(NS_SUCCEEDED(result)) {
- CElement *theElement=GetElement(eHTMLTag_tbody);
- if(theElement) {
- result=theElement->HandleStartToken(aNode,aTag,aContext,aSink);
+ result=HandleStartToken(theNode,eHTMLTag_tbody,aContext,aSink);
+ }
+ if(NS_SUCCEEDED(result)) {
+ CElement *theElement=GetElement(eHTMLTag_tbody);
+ if(theElement) {
+ result=theElement->HandleStartToken(aNode,aTag,aContext,aSink);
+ }
}
}
@@ -738,6 +740,7 @@ public:
case eHTMLTag_caption:
case eHTMLTag_col:
case eHTMLTag_colgroup:
+ case eHTMLTag_tr:
case eHTMLTag_thead:
case eHTMLTag_tfoot:
case eHTMLTag_tbody:
@@ -928,23 +931,26 @@ public:
return CElement::HandleStartToken(aNode,aTag,aContext,aSink);
}
+
/**********************************************************
this gets called after each tag is opened in the given context
**********************************************************/
virtual nsresult OpenContainerInContext(nsIParserNode *aNode,eHTMLTags aTag,nsDTDContext *aContext,nsIHTMLContentSink *aSink) {
OpenContext(aNode,aTag,aContext,aSink);
+
nsresult result=OpenContainer(aNode,aTag,aContext,aSink);
if(NS_SUCCEEDED(result)) {
PRInt32 theCount=aContext->GetCount();
eHTMLTags theGrandParentTag=aContext->TagAt(theCount-2);
- PRInt32 theCounter=aContext->IncrementCounter(theGrandParentTag);
- nsString theNumber;
- theNumber.AppendInt(theCounter);
+ nsCParserNode *theNode=(nsCParserNode*)aNode;
+ nsAutoString theNumber;
+ PRInt32 theCounter=aContext->IncrementCounter(theGrandParentTag,*theNode,theNumber);
+
CTextToken theToken(theNumber);
PRInt32 theLineNumber=0;
- nsCParserNode theNode(&theToken,theLineNumber);
- result=aSink->AddLeaf(theNode);
+ nsCParserNode theNewNode(&theToken,theLineNumber);
+ result=aSink->AddLeaf(theNewNode);
}
return result;
}
@@ -1284,12 +1290,7 @@ public:
virtual nsresult NotifyClose(nsIParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
nsresult result=NS_OK;
- if(aContext->HasOpenContainer(eHTMLTag_html)) {
- aSink->OpenHead(*aNode);
- result=CTextContainer::NotifyClose(aNode,aTag,aContext,aSink);
- aSink->CloseHead(*aNode);
- }
- else {
+ if(aContext->HasOpenContainer(eHTMLTag_body)) {
//add the script to the body
CScriptToken theToken(mText);
PRInt32 theLineNumber=0;
@@ -1297,6 +1298,12 @@ public:
theNode.SetSkippedContent(mText);
result=aSink->AddLeaf(theNode);
}
+ else {
+ //add it to the head...
+ aSink->OpenHead(*aNode);
+ result=CTextContainer::NotifyClose(aNode,aTag,aContext,aSink);
+ aSink->CloseHead(*aNode);
+ }
mText.Truncate(0);
return result;
}
@@ -1628,6 +1635,28 @@ public:
CElement::Initialize(*this,aTag,CHTMLElement::GetGroup(),CHTMLElement::GetContainedGroups());
}
+ /**********************************************************
+ HTML handles the opening of it's own children
+ **********************************************************/
+ nsresult HandleDoctypeDecl( nsIParserNode* aNode,
+ eHTMLTags aTag,
+ nsDTDContext* aContext,
+ nsIHTMLContentSink* aSink) {
+
+ nsCParserNode *theNode=(nsCParserNode*)aNode;
+ nsresult result=NS_OK;
+ if(theNode) {
+ nsString theStr=theNode->mToken->GetStringValueXXX();
+ PRInt32 theLen=theStr.Length();
+ PRInt32 thePos=theStr.RFindChar(kGreaterThan);
+
+ theStr.Truncate(theLen-1);
+ theStr.Cut(0,2);
+
+ result = aSink->AddDocTypeDecl(*aNode,eDTDMode_strict);
+ }
+ return result;
+ }
/**********************************************************
HTML handles the opening of it's own children
@@ -1639,6 +1668,10 @@ public:
nsresult result=NS_OK;
switch(aTag) {
+ case eHTMLTag_markupDecl:
+ result=HandleDoctypeDecl(aNode,aTag,aContext,aSink);
+ break;
+
case eHTMLTag_body:
result=aSink->OpenBody(*aNode);
result=OpenContext(aNode,aTag,aContext,aSink);
@@ -1794,7 +1827,9 @@ public:
switch(aTag) {
- case eHTMLTag_div:
+ case eHTMLTag_script:
+ result=OpenContext(aNode,aTag,aContext,aSink);
+ break;
default:
//for now, let's drop other elements onto the floor.
@@ -1802,7 +1837,7 @@ public:
if(NS_SUCCEEDED(result)) {
nsCParserNode *theNode=(nsCParserNode*)aNode;
CStartToken *theToken=(CStartToken*)theNode->mToken;
- if(theToken->IsEmpty()){
+ if(theToken->IsEmpty() && (aTag==aContext->Last())){
result=CElement::HandleEndToken(aNode,aTag,aContext,aSink);
}
}
@@ -1817,7 +1852,15 @@ public:
a really convenient break point for debugging purposes.
**********************************************************/
virtual nsresult HandleEndToken(nsIParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
- return CElement::HandleEndToken(aNode,aTag,aContext,aSink);
+ nsresult result=NS_OK;
+ switch(aTag) {
+ case eHTMLTag_script:
+ result=CloseContext(aNode,aTag,aContext,aSink);
+ break;
+ default:
+ result=CElement::HandleEndToken(aNode,aTag,aContext,aSink);
+ }
+ return result;
}
/**********************************************************
diff --git a/htmlparser/src/nsDTDUtils.cpp b/htmlparser/src/nsDTDUtils.cpp
index 40b196980d3..7d856a73717 100644
--- a/htmlparser/src/nsDTDUtils.cpp
+++ b/htmlparser/src/nsDTDUtils.cpp
@@ -21,7 +21,7 @@
* Pierre Phaneuf
*/
-
+
#include "nsDTDUtils.h"
#include "CNavDTD.h"
#include "nsIParserNode.h"
@@ -363,7 +363,7 @@ CNodeRecycler* nsDTDContext::mNodeRecycler=0;
*
* @update gess 04.21.2000
*/
-nsDTDContext::nsDTDContext() : mStack() {
+nsDTDContext::nsDTDContext() : mStack(), mEntities(0){
MOZ_COUNT_CTOR(nsDTDContext);
mResidualStyleCount=0;
@@ -379,6 +379,17 @@ nsDTDContext::nsDTDContext() : mStack() {
}
+
+class CEntityDeallocator: public nsDequeFunctor{
+public:
+ virtual void* operator()(void* anObject) {
+ CNamedEntity *theEntity=(CNamedEntity*)anObject;
+ delete theEntity;
+ return 0;
+ }
+};
+
+
/**
*
* @update gess9/10/98
@@ -391,9 +402,284 @@ nsDTDContext::~nsDTDContext() {
CTableState *theState=mTableStates;
mTableStates=theState->mPrevious;
delete theState;
- }
+ }
+
+ CEntityDeallocator theDeallocator;
+ mEntities.ForEach(theDeallocator);
}
+
+CNamedEntity* nsDTDContext::GetEntity(const nsString& aName)const {
+ PRInt32 theCount=mEntities.GetSize();
+ PRInt32 theIndex=0;
+
+ PRInt32 theLen=aName.Length();
+ PRUnichar theChar=aName.Last();
+
+ if(theLen>2) {
+ if(kSemicolon==theChar) {
+ theLen--;
+ }
+
+ const PRUnichar *theBuf=aName.GetUnicode();
+ if(kQuote==theBuf[0]) {
+ theBuf++;
+ theLen--;
+ }
+ if(kQuote==theChar) {
+ theLen--;
+ }
+
+ for(theIndex=0;theIndexmName.EqualsWithConversion(theBuf,PR_TRUE,theLen)){
+ return theResult;
+ }
+ }
+ }
+ return 0;
+}
+
+CNamedEntity* nsDTDContext::RegisterEntity(const nsString& aName,const nsString& aValue) {
+ CNamedEntity *theEntity=GetEntity(aName);
+ if(!GetEntity(aName)){
+ theEntity=new CNamedEntity(aName,aValue);
+ mEntities.Push(theEntity);
+ }
+ return theEntity;
+}
+
+
+/****************************************************************
+ The abacus class is useful today for debug purposes, but it
+ will eventually serve as the implementation for css counters.
+
+ This implementation is fine for static documents, but woefully
+ inadequate for dynamic documents. (This about what happens if
+ someone inserts a new counter using the DOM? -- The other
+ numbers in that "group" should be renumbered.)
+
+ In order to be dynamic, we need a counter "group" manager that
+ is aware of layout (geometry at least) -- and that has a
+ mechanism for notifying markers that need to be updated, along
+ with the ability to cause incremental reflow to occur in a
+ localized context (so the counters display correctly).
+
+ ****************************************************************/
+
+class CAbacus {
+public:
+
+ enum eNumFormat {eUnknown,eAlpha,eDecimal,eRoman,eSpoken,eHex,eBinary,eFootnote,eUserSeries};
+
+ CAbacus(PRInt32 aDefaultValue=0,eNumFormat aFormat=eDecimal) {
+ mUserSeries=0;
+ mFormat=aFormat;
+ mCase=false;
+ mValue=0;
+ mUserBase=0;
+ }
+
+ ~CAbacus() {
+ }
+
+ void SetValue(int aStartValue) {mValue=aStartValue;}
+ void SetNumberingStyle(eNumFormat aFormat) {mFormat=aFormat;}
+ void SetUserSeries(const char* aSeries,int aUserBase) {mUserSeries=aSeries; mUserBase=aUserBase;}
+ void SetCase(PRBool alwaysUpper) {mCase=alwaysUpper;}
+
+ void GetNextValueAsString(nsString& aString) {
+ GetFormattedString(mFormat,mValue++,aString,mUserSeries,0,mUserBase);
+ }
+
+ void GetValueAsString(nsString& aString) {
+ GetFormattedString(mFormat,mValue,aString,mUserSeries,0,mUserBase);
+ }
+
+
+ static void GetFormattedString(eNumFormat aFormat,PRInt32 aValue, nsString& aString,const char* aCharSet, int anOffset, int aBase) {
+ switch (aFormat) {
+ case eDecimal: DecimalString(aValue,aString); break;
+ case eHex: HexString(aValue,aString); break;
+ case eBinary: BinaryString(aValue,aString); break;
+ case eAlpha: AlphaString(aValue,aString); break;
+ case eSpoken: SpokenString(aValue,aString); break;
+ case eRoman: RomanString(aValue,aString); break;
+ case eFootnote: FootnoteString(aValue,aString); break;
+ case eUserSeries: SeriesString(aValue,aString,aCharSet,anOffset,aBase);
+ }
+ }
+
+ static void SeriesString(PRInt32 aValue,nsString& aString,const char* aCharSet, int offset, int base) {
+ int ndex=0;
+ int root=1;
+ int next=base;
+ int expn=1;
+
+ aString.Truncate();
+ if(aValue<0)
+ aString.AppendWithConversion('-');
+
+ aValue=abs(aValue); // must be positive here...
+ while(next<=aValue) { // scale up in baseN; exceed current value.
+ root=next;
+ next*=base;
+ expn++;
+ }
+
+ while(expn--) {
+ ndex = ((root<=aValue) && (root)) ? (aValue/root): 0;
+ aValue%=root;
+ aString.AppendWithConversion(aCharSet[ndex+((root>1)*offset)]);
+ root/=base;
+ }
+ }
+
+ static void SpokenString(PRInt32 aValue,nsString& aString) {
+
+ static char ones[][12]= {"zero","one ","two ","three ","four ","five ","six ","seven ","eight ","nine ","ten "};
+ static char teens[][12]= {"ten ","eleven ","twelve ","thirteen ","fourteen ","fifteen ","sixteen ","seventeen ","eighteen ","nineteen "};
+ static char tens[][12]= {"","ten ","twenty ","thirty ","fourty ","fifty ","sixty ","seventy ","eighty ","ninety ","hundred "};
+ static char bases[][20]= {"","hundred ","thousand ","million ","billion ","trillion ","quadrillion ","quintillion ","bajillion "};
+
+ aString.Truncate();
+ if(aValue<0)
+ aString.AppendWithConversion('-');
+
+ PRInt32 root=1000000000;
+ PRInt32 expn=4;
+ PRInt32 modu=0;
+ PRInt32 div=0;
+ PRInt32 temp=0;
+
+ aValue=abs(aValue);
+ if(01)
+ aString.AppendWithConversion(bases[expn]);
+ }
+ expn--;
+ root/=1000;
+ }
+ }
+ else aString.AppendWithConversion(ones[0]);
+ }
+
+ static void DecimalString(PRInt32 aValue,nsString& aString) {
+ aString.Truncate();
+ aString.AppendInt(aValue);
+ }
+
+ static void BinaryString(PRInt32 aValue,nsString& aString) {
+ static char kBinarySet[]="01";
+
+ if (aValue<0)
+ aValue=65536-abs(aValue);
+ SeriesString(aValue,aString,kBinarySet,0,2);
+ }
+
+ static void HexString(PRInt32 aValue,nsString& aString) {
+ static char kHexSet[]="0123456789ABCDEF";
+
+ if (aValue<0)
+ aValue=65536-abs(aValue);
+ SeriesString(aValue,aString,kHexSet,0,16);
+ }
+
+ static void RomanString(PRInt32 aValue,nsString& aString) {
+ static char digitsA[] = "ixcm";
+ static char digitsB[] = "vld?";
+
+ aString.Truncate();
+ if(aValue<0)
+ aString.AppendWithConversion('-');
+
+ aValue=abs(aValue);
+ char decStr[20];
+ sprintf(decStr,"%d", aValue);
+
+ int len=strlen(decStr);
+ int romanPos=len;
+ int digitPos=0;
+ int n=0;
+
+ for(digitPos=0;digitPosmOrdinal=0;
+ }
+ aTag=eHTMLTag_userdefined;
+ }
+ else if(theKey.EqualsWithConversion("noincr",PR_TRUE)){
+ theIncrValue=0;
+ }
+ else if(theKey.EqualsWithConversion("format",PR_TRUE)){
+ PRUnichar theChar=theValue.CharAt(0);
+ if('"'==theChar)
+ theChar=theValue.CharAt(1);
+ switch(theChar){
+ case 'A': case 'a': theNumFormat=CAbacus::eAlpha; break;
+ case 'B': case 'b': theNumFormat=CAbacus::eBinary; break;
+ case 'D': case 'd': theNumFormat=CAbacus::eDecimal; break;
+ case 'H': case 'h': theNumFormat=CAbacus::eHex; break;
+ case 'R': case 'r': theNumFormat=CAbacus::eRoman; break;
+ case 'S': case 's': theNumFormat=CAbacus::eSpoken; break;
+ default:
+ theNumFormat=CAbacus::eDecimal;
+ break;
+ }
+ //determine numbering style
+ }
+ else if(theKey.EqualsWithConversion("value",PR_TRUE)){
+ PRInt32 err=0;
+ theNewValue=theValue.ToInteger(&err);
+ if(!err) {
+ theIncrValue=0;
+ mCounters[aTag]=theNewValue;
+ }
+ else theNewValue=-1;
+ }
+ }
+
+ if(theEntity && (eHTMLTag_userdefined==aTag)) {
+ result=theEntity->mOrdinal+=theIncrValue;
+ }
+ else result=mCounters[aTag]+=theIncrValue;
+ CAbacus::GetFormattedString(theNumFormat,result,aResult,0,0,0);
+
return result;
}
-/**
- *
- * @update gess 11May2000
- */
-void nsDTDContext::ResetCounter(eHTMLTags aTag,PRInt32 aValue) {
- mCounters[aTag]=aValue;
-}
/**
*
diff --git a/htmlparser/src/nsDTDUtils.h b/htmlparser/src/nsDTDUtils.h
index 69096e0ad72..de25793c90c 100644
--- a/htmlparser/src/nsDTDUtils.h
+++ b/htmlparser/src/nsDTDUtils.h
@@ -155,6 +155,11 @@ public:
return result;
}
+ PRBool CanOpenTBody() {
+ PRBool result=!(mHasTBody);
+ return result;
+ }
+
PRBool CanOpenTHead() {
PRBool result=!(mHasTHead || mHasTFoot || mHasTBody);
return result;
@@ -174,14 +179,42 @@ public:
};
+//used for named entities and counters (XXX debug only)
+class CNamedEntity {
+public:
+ CNamedEntity(const nsString& aName,const nsString& aValue) : mName(), mValue() {
+ PRUnichar theFirst=aName.First();
+ PRUnichar theLast=aName.Last();
+ PRInt32 theLen=aName.Length();
+ if((2GetStringValueXXX();
+
if((kHashsign!=theChar) && (-1==nsHTMLEntities::EntityToUnicode(theStr))){
//if you're here we have a bogus entity.
//convert it into a text token.
@@ -640,6 +642,7 @@ nsresult nsHTMLTokenizer::ConsumeEntity(PRUnichar aChar,CToken*& aToken,nsScanne
theRecycler->RecycleToken(aToken);
aToken=theToken;
}
+#endif
AddToken(aToken,result,&mTokenDeque,theRecycler);
}
}//if
diff --git a/htmlparser/src/nsParser.cpp b/htmlparser/src/nsParser.cpp
index 1cc3902465d..31446678871 100644
--- a/htmlparser/src/nsParser.cpp
+++ b/htmlparser/src/nsParser.cpp
@@ -102,12 +102,13 @@ public:
//Note: To cut down on startup time/overhead, we defer the construction of non-html DTD's.
nsIDTD* theDTD;
+
NS_NewNavHTMLDTD(&theDTD); //do this as a default HTML DTD...
mDTDDeque.Push(theDTD);
-#if 1
+
NS_NewOtherHTMLDTD(&theDTD); //do this as the default DTD for strict documents...
mDTDDeque.Push(theDTD);
-#endif
+
mHasViewSourceDTD=PR_FALSE;
mHasRTFDTD=mHasXMLDTD=PR_FALSE;
}
@@ -485,7 +486,7 @@ nsDTDMode nsParser::GetParseMode(void){
* @return parsermode (define in nsIParser.h)
*/
static
-void DetermineParseMode(nsString& aBuffer,nsDTDMode& aParseMode,eParserDocType& aDocType) {
+void DetermineParseMode(nsString& aBuffer,nsDTDMode& aParseMode,eParserDocType& aDocType,const nsString& aMimeType) {
const char* theModeStr= PR_GetEnv("PARSE_MODE");
aParseMode = eDTDMode_unknown;
@@ -613,8 +614,18 @@ void DetermineParseMode(nsString& aBuffer,nsDTDMode& aParseMode,eParserDocType&
}
}
else if(kNotFound<(theIndex=aBuffer.Find("?XML",PR_TRUE,0,128))) {
- aDocType=eXMLText;
aParseMode=eDTDMode_strict;
+ if(aMimeType.EqualsWithConversion(kHTMLTextContentType)) {
+ //this is here to prevent a crash if someone gives us an XML document,
+ //but necko tells us it's a text/html mimetype.
+ aDocType=eHTML4Text;
+ aParseMode=eDTDMode_strict;
+ }
+ else aDocType=eXMLText;
+ }
+ else if(aMimeType.EqualsWithConversion(kPlainTextContentType)) {
+ aDocType=ePlainText;
+ aParseMode=eDTDMode_quirks;
}
if(theModeStr) {
@@ -754,7 +765,11 @@ nsresult nsParser::CreateCompatibleDTD(nsIDTD** aDTD,
nsDTDMode theDTDMode=eDTDMode_unknown;
eParserDocType theDocType=ePlainText;
- DetermineParseMode(*aDocTypeStr,theDTDMode,theDocType);
+ if(!aMimeType) {
+ nsAutoString temp;
+ DetermineParseMode(*aDocTypeStr,theDTDMode,theDocType,temp);
+ }
+ else DetermineParseMode(*aDocTypeStr,theDTDMode,theDocType,*aMimeType);
NS_ASSERTION(aDTDMode==eDTDMode_unknown || aDTDMode==theDTDMode,"aDTDMode overrides the mode selected from the DOCTYPE ");
@@ -945,7 +960,7 @@ nsresult nsParser::WillBuildModel(nsString& aFilename){
while(*theDocType) {
nsAutoString theType;
theType.AssignWithConversion(*theDocType);
- DetermineParseMode(theType,theParseMode,theDocumentType);
+ DetermineParseMode(theType,theParseMode,theDocumentType,mParserContext->mMimeType);
theDocType++;
}
}
@@ -957,7 +972,7 @@ nsresult nsParser::WillBuildModel(nsString& aFilename){
mMinorIteration=-1;
nsString& theBuffer=mParserContext->mScanner->GetBuffer();
- DetermineParseMode(theBuffer,mParserContext->mDTDMode,mParserContext->mDocType);
+ DetermineParseMode(theBuffer,mParserContext->mDTDMode,mParserContext->mDocType,mParserContext->mMimeType);
if(PR_TRUE==FindSuitableDTD(*mParserContext,theBuffer)) {
mParserContext->mDTD->WillBuildModel( *mParserContext,mSink);
diff --git a/parser/htmlparser/src/CNavDTD.cpp b/parser/htmlparser/src/CNavDTD.cpp
index 51b69f1df0e..e578c7791d4 100644
--- a/parser/htmlparser/src/CNavDTD.cpp
+++ b/parser/htmlparser/src/CNavDTD.cpp
@@ -22,9 +22,10 @@
//#define ENABLE_CRC
//#define RICKG_DEBUG
-#define ENABLE_RESIDUALSTYLE
//#define ALLOW_TR_AS_CHILD_OF_TABLE //by setting this to true, TR is allowable directly in TABLE.
+#define ENABLE_RESIDUALSTYLE
+
#ifdef RICKG_DEBUG
#include
#endif
@@ -266,12 +267,24 @@ CNavDTD::~CNavDTD(){
/**
* Call this method if you want the DTD to construct a fresh
* instance of itself.
- * @update gess7/23/98
+ * @update gess 25May2000
* @param
* @return
*/
nsresult CNavDTD::CreateNewInstance(nsIDTD** aInstancePtrResult){
- return NS_NewNavHTMLDTD(aInstancePtrResult);
+
+ nsresult result=NS_NewNavHTMLDTD(aInstancePtrResult);
+
+ if(aInstancePtrResult) {
+ CNavDTD *theOtherDTD=(CNavDTD*)*aInstancePtrResult;
+ if(theOtherDTD) {
+ theOtherDTD->mDTDMode=mDTDMode;
+ theOtherDTD->mParserCommand=mParserCommand;
+ theOtherDTD->mDocType=mDocType;
+ }
+ }
+
+ return result;
}
/**
@@ -827,10 +840,9 @@ nsresult CNavDTD::DidHandleStartTag(nsCParserNode& aNode,eHTMLTags aChildTag){
{
PRInt32 theCount=mBodyContext->GetCount();
eHTMLTags theGrandParentTag=mBodyContext->TagAt(theCount-2);
- PRInt32 theCounter=mBodyContext->IncrementCounter(theGrandParentTag);
-
- nsString theNumber;
- theNumber.AppendInt(theCounter);
+
+ nsAutoString theNumber;
+ PRInt32 theCounter=mBodyContext->IncrementCounter(theGrandParentTag,aNode,theNumber);
CTextToken theToken(theNumber);
PRInt32 theLineNumber=0;
nsCParserNode theNode(&theToken,theLineNumber);
@@ -838,6 +850,35 @@ nsresult CNavDTD::DidHandleStartTag(nsCParserNode& aNode,eHTMLTags aChildTag){
}
break;
+ case eHTMLTag_meta:
+ {
+ //we should only enable user-defined entities in debug builds...
+
+ PRInt32 theCount=aNode.GetAttributeCount();
+ const nsString* theNamePtr=0;
+ const nsString* theValuePtr=0;
+
+ if(theCount) {
+ PRInt32 theIndex=0;
+ for(theIndex=0;theIndexRegisterEntity(*theNamePtr,*theValuePtr);
+ }
+ }
+ break;
+
default:
break;
}//switch
@@ -1846,6 +1887,27 @@ nsresult CNavDTD::HandleEntityToken(CToken* aToken) {
NS_PRECONDITION(0!=aToken,kNullToken);
nsresult result=NS_OK;
+
+ nsString& theStr=aToken->GetStringValueXXX();
+ PRUnichar theChar=theStr.CharAt(0);
+ if((kHashsign!=theChar) && (-1==nsHTMLEntities::EntityToUnicode(theStr))){
+
+ //before we just toss this away as a bogus entity, let's check...
+ CNamedEntity *theEntity=mBodyContext->GetEntity(theStr);
+ CToken *theToken=0;
+ if(theEntity) {
+ theToken=new CTextToken(theEntity->mValue);
+ }
+ else {
+ //if you're here we have a bogus entity.
+ //convert it into a text token.
+ nsAutoString temp; temp.AssignWithConversion("&");
+ temp.Append(theStr);
+ theToken=new CTextToken(temp);
+ }
+ return HandleStartToken(theToken);
+ }
+
eHTMLTags theParentTag=mBodyContext->Last();
nsCParserNode* theNode=mNodeRecycler->CreateNode();
diff --git a/parser/htmlparser/src/COtherDTD.cpp b/parser/htmlparser/src/COtherDTD.cpp
index 6392f0ed6f2..32dd63cedf1 100644
--- a/parser/htmlparser/src/COtherDTD.cpp
+++ b/parser/htmlparser/src/COtherDTD.cpp
@@ -4,24 +4,24 @@
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
- *
+ *
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
- *
+ *
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
- *
+ *
* Contributor(s):
*/
//#define ENABLE_CRC
-//#define RICKG_DEBUG
+//#define RICKG_DEBUG
#include "nsDebug.h"
@@ -131,7 +131,7 @@ NS_IMPL_RELEASE(COtherDTD)
* @param
* @return
*/
-COtherDTD::COtherDTD() : nsIDTD(), mMisplacedContent(0), mSkippedContent(0), mSharedNodes(0) {
+COtherDTD::COtherDTD() : nsIDTD(), mSharedNodes(0) {
NS_INIT_REFCNT();
mSink = 0;
mParser=0;
@@ -141,14 +141,17 @@ COtherDTD::COtherDTD() : nsIDTD(), mMisplacedContent(0), mSkippedContent(0), mSh
mHasOpenHead=0;
mHasOpenForm=PR_FALSE;
mHasOpenMap=PR_FALSE;
- mHeadContext=new nsDTDContext();
mBodyContext=new nsDTDContext();
- mFormContext=0;
mTokenizer=0;
mComputedCRC32=0;
mExpectedCRC32=0;
mDTDState=NS_OK;
- mDocType=ePlainText;
+ mDocType=eHTML4Text;
+ mHadFrameset=PR_FALSE;
+ mHadBody=PR_FALSE;
+ mHasOpenScript=PR_FALSE;
+ mTokenRecycler=0;
+ mParserCommand=eViewNormal;
char* theEnvString = PR_GetEnv("ENABLE_STRICT");
mEnableStrict=PRBool(theEnvString!=0);
@@ -280,7 +283,6 @@ const nsIID& COtherDTD::GetMostDerivedIID(void)const {
* @return
*/
COtherDTD::~COtherDTD(){
- delete mHeadContext;
delete mBodyContext;
NS_IF_RELEASE(mTokenizer);
@@ -336,7 +338,19 @@ NS_HTMLPARS nsresult NS_NewOtherHTMLDTD(nsIDTD** aInstancePtrResult) {
* @return
*/
nsresult COtherDTD::CreateNewInstance(nsIDTD** aInstancePtrResult){
- return NS_NewOtherHTMLDTD(aInstancePtrResult);
+ nsresult result=NS_NewOtherHTMLDTD(aInstancePtrResult);
+
+ if(aInstancePtrResult) {
+ COtherDTD *theOtherDTD=(COtherDTD*)*aInstancePtrResult;
+ if(theOtherDTD) {
+ theOtherDTD->mDTDMode=mDTDMode;
+ theOtherDTD->mParserCommand=mParserCommand;
+ theOtherDTD->mDocType=mDocType;
+ theOtherDTD->mEnableStrict=mEnableStrict;
+ }
+ }
+
+ return result;
}
/**
@@ -608,6 +622,7 @@ nsresult COtherDTD::HandleToken(CToken* aToken,nsIParser* aParser){
case eToken_start:
case eToken_whitespace:
case eToken_newline:
+ case eToken_doctypeDecl:
result=HandleStartToken(theToken); break;
case eToken_end:
@@ -722,7 +737,7 @@ nsresult COtherDTD::WillHandleStartTag(CToken* aToken,eHTMLTags aTag,nsCParserNo
MOZ_TIMER_DEBUGLOG(("Start: Parse Time: COtherDTD::WillHandleStartTag(), this=%p\n", this));
START_TIMER()
- return result;
+ return result;
}
@@ -762,20 +777,20 @@ nsresult COtherDTD::HandleStartToken(CToken* aToken) {
if(NS_OK==result) {
mLineNumber += aToken->mNewlineCount;
-
+
PRBool theTagWasHandled=PR_FALSE;
- switch(theChildTag) {
-
- case eHTMLTag_html:
+ switch(theChildTag) {
+
+ case eHTMLTag_html:
if(!HasOpenContainer(theChildTag)) {
mSink->OpenHTML(*theNode);
mBodyContext->Push(theNode,0);
}
theTagWasHandled=PR_TRUE;
- break;
-
- default:
+ break;
+
+ default:
CElement* theElement=gElementTable->mElements[theParent];
if(theElement) {
result=theElement->HandleStartToken(theNode,theChildTag,mBodyContext,mSink);
@@ -788,7 +803,7 @@ nsresult COtherDTD::HandleStartToken(CToken* aToken) {
DidHandleStartTag(*theNode,theChildTag);
}
- } //if
+ } //if
}//if
RecycleNode(theNode);
@@ -814,7 +829,7 @@ nsresult COtherDTD::HandleEndToken(CToken* aToken) {
nsresult result=NS_OK;
eHTMLTags theChildTag=(eHTMLTags)aToken->GetTypeID();
- #ifdef RICKG_DEBUG
+ #ifdef RICKG_DEBUG
WriteTokenToLog(aToken);
#endif
@@ -825,7 +840,7 @@ nsresult COtherDTD::HandleEndToken(CToken* aToken) {
break;
case eHTMLTag_script:
- mHasOpenScript=PR_FALSE;
+ mHasOpenScript=PR_FALSE;
default:
PRInt32 theCount=mBodyContext->GetCount();
@@ -838,7 +853,7 @@ nsresult COtherDTD::HandleEndToken(CToken* aToken) {
nsCParserNode theNode((CHTMLToken*)aToken,mLineNumber);
result=theElement->HandleEndToken(&theNode,theChildTag,mBodyContext,mSink);
}
- break;
+ break;
}
return result;
@@ -857,14 +872,12 @@ nsresult COtherDTD::CollectAttributes(nsCParserNode& aNode,eHTMLTags aTag,PRInt3
int attr=0;
nsresult result=NS_OK;
- int theAvailTokenCount=mTokenizer->GetCount() + mSkippedContent.GetSize();
+ int theAvailTokenCount=mTokenizer->GetCount();
if(aCount<=theAvailTokenCount) {
CToken* theToken=0;
eHTMLTags theSkipTarget=gElementTable->mElements[aTag]->GetSkipTarget();
for(attr=0;attrPopToken();
+ theToken=mTokenizer->PopToken();
if(theToken) {
// Sanitize the key for it might contain some non-alpha-non-digit characters
// at its end. Ex. - This will be tokenized as "<" "OPTION",
@@ -886,77 +899,6 @@ nsresult COtherDTD::CollectAttributes(nsCParserNode& aNode,eHTMLTags aTag,PRInt3
return result;
}
-
-/**
- * Causes the next skipped-content token (if any) to
- * be consumed by this node.
- * @update gess5/11/98
- * @param node to consume skipped-content
- * @param holds the number of skipped content elements encountered
- * @return Error condition.
- */
-nsresult COtherDTD::CollectSkippedContent(nsCParserNode& aNode,PRInt32 &aCount) {
-
- eHTMLTags theNodeTag=(eHTMLTags)aNode.GetNodeType();
-
- int aIndex=0;
- int aMax=mSkippedContent.GetSize();
-
- // XXX rickg This linefeed conversion stuff should be moved out of
- // the parser and into the form element code
- PRBool aMustConvertLinebreaks = PR_FALSE;
-
- mScratch.SetLength(0);
- aNode.SetSkippedContent(mScratch);
-
- for(aIndex=0;aIndexGetTokenType();
-
- mScratch.Truncate();
- // Dont worry about attributes here because it's already stored in
- // the start token as mTrailing content and will get appended in
- // start token's GetSource();
- if(eToken_attribute!=theTokenType) {
- if (eToken_entity==theTokenType) {
- if((eHTMLTag_textarea==theNodeTag) || (eHTMLTag_title==theNodeTag)) {
- ((CEntityToken*)theNextToken)->TranslateToUnicodeStr(mScratch);
- // since this is an entity, we know that it's only one character.
- // check to see if it's a CR, in which case we'll need to do line
- // termination conversion at the end.
- aMustConvertLinebreaks |= (mScratch[0] == kCR);
- }
- }
- else theNextToken->GetSource(mScratch);
-
- aNode.mSkippedContent->Append(mScratch);
- }
- mTokenRecycler->RecycleToken(theNextToken);
- }
-
- // if the string contained CRs (hence is either CR, or CRLF terminated)
- // we need to convert line breaks
- if (aMustConvertLinebreaks)
- {
- /*
- PRInt32 offset;
- while ((offset = aNode.mSkippedContent.Find("\r\n")) != kNotFound)
- aNode.mSkippedContent.Cut(offset, 1); // remove the CR
-
- // now replace remaining CRs with LFs
- aNode.mSkippedContent.ReplaceChar("\r", kNewLine);
- */
-#if 1
- nsLinebreakConverter::ConvertStringLineBreaks(*aNode.mSkippedContent,
- nsLinebreakConverter::eLinebreakAny, nsLinebreakConverter::eLinebreakContent);
-#endif
- }
-
- // Let's hope that this does not hamper the PERFORMANCE!!
- mLineNumber += aNode.mSkippedContent->CountChar(kNewLine);
- return NS_OK;
-}
/***********************************************************************************
The preceeding tables determine the set of elements each tag can contain...
diff --git a/parser/htmlparser/src/COtherDTD.h b/parser/htmlparser/src/COtherDTD.h
index 58cbec4829f..3cb2661b450 100644
--- a/parser/htmlparser/src/COtherDTD.h
+++ b/parser/htmlparser/src/COtherDTD.h
@@ -340,7 +340,6 @@ CLASS_EXPORT_HTMLPARS COtherDTD : public nsIDTD {
protected:
nsresult CollectAttributes(nsCParserNode& aNode,eHTMLTags aTag,PRInt32 aCount);
- nsresult CollectSkippedContent(nsCParserNode& aNode,PRInt32& aCount);
nsresult WillHandleStartTag(CToken* aToken,eHTMLTags aChildTag,nsCParserNode& aNode);
nsresult DidHandleStartTag(nsCParserNode& aNode,eHTMLTags aChildTag);
nsCParserNode* CreateNode(void);
@@ -349,9 +348,7 @@ protected:
nsIHTMLContentSink* mSink;
- nsDTDContext* mHeadContext;
nsDTDContext* mBodyContext;
- nsDTDContext* mFormContext;
PRBool mHasOpenForm;
PRBool mHasOpenMap;
PRInt32 mHasOpenHead;
@@ -364,10 +361,7 @@ protected:
nsParser* mParser;
nsITokenizer* mTokenizer;
CTokenRecycler* mTokenRecycler;
- nsDeque mMisplacedContent;
- nsDeque mSkippedContent;
PRBool mHasOpenScript;
- PRBool mSaveBadTokens;
eHTMLTags mSkipTarget;
nsDeque mSharedNodes;
nsresult mDTDState;
@@ -377,9 +371,8 @@ protected:
PRUint32 mComputedCRC32;
PRUint32 mExpectedCRC32;
nsAutoString mScratch; //used for various purposes; non-persistent
- PRBool mStyleHandlingEnabled;
- PRBool mEnableStrict;
eParserDocType mDocType;
+ PRBool mEnableStrict;
#ifdef NS_DEBUG
PRInt32 gNodeCount;
diff --git a/parser/htmlparser/src/COtherElements.h b/parser/htmlparser/src/COtherElements.h
index f98f53ac616..3f9bd1f6c5e 100644
--- a/parser/htmlparser/src/COtherElements.h
+++ b/parser/htmlparser/src/COtherElements.h
@@ -705,17 +705,19 @@ public:
case eHTMLTag_tr:
case eHTMLTag_th:
- if(!aContext->HasOpenContainer(eHTMLTag_tbody)) {
- nsCParserNode* theNode=new nsCParserNode();
- CToken* theToken=new CStartToken(eHTMLTag_tbody);
- theNode->Init(theToken,0,0); //this will likely leak...
+ if(aContext->mTableStates) {
+ if(aContext->mTableStates->CanOpenTBody()) {
+ nsCParserNode* theNode=new nsCParserNode();
+ CToken* theToken=new CStartToken(eHTMLTag_tbody);
+ theNode->Init(theToken,0,0); //this will likely leak...
- result=HandleStartToken(theNode,eHTMLTag_tbody,aContext,aSink);
- }
- if(NS_SUCCEEDED(result)) {
- CElement *theElement=GetElement(eHTMLTag_tbody);
- if(theElement) {
- result=theElement->HandleStartToken(aNode,aTag,aContext,aSink);
+ result=HandleStartToken(theNode,eHTMLTag_tbody,aContext,aSink);
+ }
+ if(NS_SUCCEEDED(result)) {
+ CElement *theElement=GetElement(eHTMLTag_tbody);
+ if(theElement) {
+ result=theElement->HandleStartToken(aNode,aTag,aContext,aSink);
+ }
}
}
@@ -738,6 +740,7 @@ public:
case eHTMLTag_caption:
case eHTMLTag_col:
case eHTMLTag_colgroup:
+ case eHTMLTag_tr:
case eHTMLTag_thead:
case eHTMLTag_tfoot:
case eHTMLTag_tbody:
@@ -928,23 +931,26 @@ public:
return CElement::HandleStartToken(aNode,aTag,aContext,aSink);
}
+
/**********************************************************
this gets called after each tag is opened in the given context
**********************************************************/
virtual nsresult OpenContainerInContext(nsIParserNode *aNode,eHTMLTags aTag,nsDTDContext *aContext,nsIHTMLContentSink *aSink) {
OpenContext(aNode,aTag,aContext,aSink);
+
nsresult result=OpenContainer(aNode,aTag,aContext,aSink);
if(NS_SUCCEEDED(result)) {
PRInt32 theCount=aContext->GetCount();
eHTMLTags theGrandParentTag=aContext->TagAt(theCount-2);
- PRInt32 theCounter=aContext->IncrementCounter(theGrandParentTag);
- nsString theNumber;
- theNumber.AppendInt(theCounter);
+ nsCParserNode *theNode=(nsCParserNode*)aNode;
+ nsAutoString theNumber;
+ PRInt32 theCounter=aContext->IncrementCounter(theGrandParentTag,*theNode,theNumber);
+
CTextToken theToken(theNumber);
PRInt32 theLineNumber=0;
- nsCParserNode theNode(&theToken,theLineNumber);
- result=aSink->AddLeaf(theNode);
+ nsCParserNode theNewNode(&theToken,theLineNumber);
+ result=aSink->AddLeaf(theNewNode);
}
return result;
}
@@ -1284,12 +1290,7 @@ public:
virtual nsresult NotifyClose(nsIParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
nsresult result=NS_OK;
- if(aContext->HasOpenContainer(eHTMLTag_html)) {
- aSink->OpenHead(*aNode);
- result=CTextContainer::NotifyClose(aNode,aTag,aContext,aSink);
- aSink->CloseHead(*aNode);
- }
- else {
+ if(aContext->HasOpenContainer(eHTMLTag_body)) {
//add the script to the body
CScriptToken theToken(mText);
PRInt32 theLineNumber=0;
@@ -1297,6 +1298,12 @@ public:
theNode.SetSkippedContent(mText);
result=aSink->AddLeaf(theNode);
}
+ else {
+ //add it to the head...
+ aSink->OpenHead(*aNode);
+ result=CTextContainer::NotifyClose(aNode,aTag,aContext,aSink);
+ aSink->CloseHead(*aNode);
+ }
mText.Truncate(0);
return result;
}
@@ -1628,6 +1635,28 @@ public:
CElement::Initialize(*this,aTag,CHTMLElement::GetGroup(),CHTMLElement::GetContainedGroups());
}
+ /**********************************************************
+ HTML handles the opening of it's own children
+ **********************************************************/
+ nsresult HandleDoctypeDecl( nsIParserNode* aNode,
+ eHTMLTags aTag,
+ nsDTDContext* aContext,
+ nsIHTMLContentSink* aSink) {
+
+ nsCParserNode *theNode=(nsCParserNode*)aNode;
+ nsresult result=NS_OK;
+ if(theNode) {
+ nsString theStr=theNode->mToken->GetStringValueXXX();
+ PRInt32 theLen=theStr.Length();
+ PRInt32 thePos=theStr.RFindChar(kGreaterThan);
+
+ theStr.Truncate(theLen-1);
+ theStr.Cut(0,2);
+
+ result = aSink->AddDocTypeDecl(*aNode,eDTDMode_strict);
+ }
+ return result;
+ }
/**********************************************************
HTML handles the opening of it's own children
@@ -1639,6 +1668,10 @@ public:
nsresult result=NS_OK;
switch(aTag) {
+ case eHTMLTag_markupDecl:
+ result=HandleDoctypeDecl(aNode,aTag,aContext,aSink);
+ break;
+
case eHTMLTag_body:
result=aSink->OpenBody(*aNode);
result=OpenContext(aNode,aTag,aContext,aSink);
@@ -1794,7 +1827,9 @@ public:
switch(aTag) {
- case eHTMLTag_div:
+ case eHTMLTag_script:
+ result=OpenContext(aNode,aTag,aContext,aSink);
+ break;
default:
//for now, let's drop other elements onto the floor.
@@ -1802,7 +1837,7 @@ public:
if(NS_SUCCEEDED(result)) {
nsCParserNode *theNode=(nsCParserNode*)aNode;
CStartToken *theToken=(CStartToken*)theNode->mToken;
- if(theToken->IsEmpty()){
+ if(theToken->IsEmpty() && (aTag==aContext->Last())){
result=CElement::HandleEndToken(aNode,aTag,aContext,aSink);
}
}
@@ -1817,7 +1852,15 @@ public:
a really convenient break point for debugging purposes.
**********************************************************/
virtual nsresult HandleEndToken(nsIParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
- return CElement::HandleEndToken(aNode,aTag,aContext,aSink);
+ nsresult result=NS_OK;
+ switch(aTag) {
+ case eHTMLTag_script:
+ result=CloseContext(aNode,aTag,aContext,aSink);
+ break;
+ default:
+ result=CElement::HandleEndToken(aNode,aTag,aContext,aSink);
+ }
+ return result;
}
/**********************************************************
diff --git a/parser/htmlparser/src/nsDTDUtils.cpp b/parser/htmlparser/src/nsDTDUtils.cpp
index 40b196980d3..7d856a73717 100644
--- a/parser/htmlparser/src/nsDTDUtils.cpp
+++ b/parser/htmlparser/src/nsDTDUtils.cpp
@@ -21,7 +21,7 @@
* Pierre Phaneuf
*/
-
+
#include "nsDTDUtils.h"
#include "CNavDTD.h"
#include "nsIParserNode.h"
@@ -363,7 +363,7 @@ CNodeRecycler* nsDTDContext::mNodeRecycler=0;
*
* @update gess 04.21.2000
*/
-nsDTDContext::nsDTDContext() : mStack() {
+nsDTDContext::nsDTDContext() : mStack(), mEntities(0){
MOZ_COUNT_CTOR(nsDTDContext);
mResidualStyleCount=0;
@@ -379,6 +379,17 @@ nsDTDContext::nsDTDContext() : mStack() {
}
+
+class CEntityDeallocator: public nsDequeFunctor{
+public:
+ virtual void* operator()(void* anObject) {
+ CNamedEntity *theEntity=(CNamedEntity*)anObject;
+ delete theEntity;
+ return 0;
+ }
+};
+
+
/**
*
* @update gess9/10/98
@@ -391,9 +402,284 @@ nsDTDContext::~nsDTDContext() {
CTableState *theState=mTableStates;
mTableStates=theState->mPrevious;
delete theState;
- }
+ }
+
+ CEntityDeallocator theDeallocator;
+ mEntities.ForEach(theDeallocator);
}
+
+CNamedEntity* nsDTDContext::GetEntity(const nsString& aName)const {
+ PRInt32 theCount=mEntities.GetSize();
+ PRInt32 theIndex=0;
+
+ PRInt32 theLen=aName.Length();
+ PRUnichar theChar=aName.Last();
+
+ if(theLen>2) {
+ if(kSemicolon==theChar) {
+ theLen--;
+ }
+
+ const PRUnichar *theBuf=aName.GetUnicode();
+ if(kQuote==theBuf[0]) {
+ theBuf++;
+ theLen--;
+ }
+ if(kQuote==theChar) {
+ theLen--;
+ }
+
+ for(theIndex=0;theIndexmName.EqualsWithConversion(theBuf,PR_TRUE,theLen)){
+ return theResult;
+ }
+ }
+ }
+ return 0;
+}
+
+CNamedEntity* nsDTDContext::RegisterEntity(const nsString& aName,const nsString& aValue) {
+ CNamedEntity *theEntity=GetEntity(aName);
+ if(!GetEntity(aName)){
+ theEntity=new CNamedEntity(aName,aValue);
+ mEntities.Push(theEntity);
+ }
+ return theEntity;
+}
+
+
+/****************************************************************
+ The abacus class is useful today for debug purposes, but it
+ will eventually serve as the implementation for css counters.
+
+ This implementation is fine for static documents, but woefully
+ inadequate for dynamic documents. (This about what happens if
+ someone inserts a new counter using the DOM? -- The other
+ numbers in that "group" should be renumbered.)
+
+ In order to be dynamic, we need a counter "group" manager that
+ is aware of layout (geometry at least) -- and that has a
+ mechanism for notifying markers that need to be updated, along
+ with the ability to cause incremental reflow to occur in a
+ localized context (so the counters display correctly).
+
+ ****************************************************************/
+
+class CAbacus {
+public:
+
+ enum eNumFormat {eUnknown,eAlpha,eDecimal,eRoman,eSpoken,eHex,eBinary,eFootnote,eUserSeries};
+
+ CAbacus(PRInt32 aDefaultValue=0,eNumFormat aFormat=eDecimal) {
+ mUserSeries=0;
+ mFormat=aFormat;
+ mCase=false;
+ mValue=0;
+ mUserBase=0;
+ }
+
+ ~CAbacus() {
+ }
+
+ void SetValue(int aStartValue) {mValue=aStartValue;}
+ void SetNumberingStyle(eNumFormat aFormat) {mFormat=aFormat;}
+ void SetUserSeries(const char* aSeries,int aUserBase) {mUserSeries=aSeries; mUserBase=aUserBase;}
+ void SetCase(PRBool alwaysUpper) {mCase=alwaysUpper;}
+
+ void GetNextValueAsString(nsString& aString) {
+ GetFormattedString(mFormat,mValue++,aString,mUserSeries,0,mUserBase);
+ }
+
+ void GetValueAsString(nsString& aString) {
+ GetFormattedString(mFormat,mValue,aString,mUserSeries,0,mUserBase);
+ }
+
+
+ static void GetFormattedString(eNumFormat aFormat,PRInt32 aValue, nsString& aString,const char* aCharSet, int anOffset, int aBase) {
+ switch (aFormat) {
+ case eDecimal: DecimalString(aValue,aString); break;
+ case eHex: HexString(aValue,aString); break;
+ case eBinary: BinaryString(aValue,aString); break;
+ case eAlpha: AlphaString(aValue,aString); break;
+ case eSpoken: SpokenString(aValue,aString); break;
+ case eRoman: RomanString(aValue,aString); break;
+ case eFootnote: FootnoteString(aValue,aString); break;
+ case eUserSeries: SeriesString(aValue,aString,aCharSet,anOffset,aBase);
+ }
+ }
+
+ static void SeriesString(PRInt32 aValue,nsString& aString,const char* aCharSet, int offset, int base) {
+ int ndex=0;
+ int root=1;
+ int next=base;
+ int expn=1;
+
+ aString.Truncate();
+ if(aValue<0)
+ aString.AppendWithConversion('-');
+
+ aValue=abs(aValue); // must be positive here...
+ while(next<=aValue) { // scale up in baseN; exceed current value.
+ root=next;
+ next*=base;
+ expn++;
+ }
+
+ while(expn--) {
+ ndex = ((root<=aValue) && (root)) ? (aValue/root): 0;
+ aValue%=root;
+ aString.AppendWithConversion(aCharSet[ndex+((root>1)*offset)]);
+ root/=base;
+ }
+ }
+
+ static void SpokenString(PRInt32 aValue,nsString& aString) {
+
+ static char ones[][12]= {"zero","one ","two ","three ","four ","five ","six ","seven ","eight ","nine ","ten "};
+ static char teens[][12]= {"ten ","eleven ","twelve ","thirteen ","fourteen ","fifteen ","sixteen ","seventeen ","eighteen ","nineteen "};
+ static char tens[][12]= {"","ten ","twenty ","thirty ","fourty ","fifty ","sixty ","seventy ","eighty ","ninety ","hundred "};
+ static char bases[][20]= {"","hundred ","thousand ","million ","billion ","trillion ","quadrillion ","quintillion ","bajillion "};
+
+ aString.Truncate();
+ if(aValue<0)
+ aString.AppendWithConversion('-');
+
+ PRInt32 root=1000000000;
+ PRInt32 expn=4;
+ PRInt32 modu=0;
+ PRInt32 div=0;
+ PRInt32 temp=0;
+
+ aValue=abs(aValue);
+ if(01)
+ aString.AppendWithConversion(bases[expn]);
+ }
+ expn--;
+ root/=1000;
+ }
+ }
+ else aString.AppendWithConversion(ones[0]);
+ }
+
+ static void DecimalString(PRInt32 aValue,nsString& aString) {
+ aString.Truncate();
+ aString.AppendInt(aValue);
+ }
+
+ static void BinaryString(PRInt32 aValue,nsString& aString) {
+ static char kBinarySet[]="01";
+
+ if (aValue<0)
+ aValue=65536-abs(aValue);
+ SeriesString(aValue,aString,kBinarySet,0,2);
+ }
+
+ static void HexString(PRInt32 aValue,nsString& aString) {
+ static char kHexSet[]="0123456789ABCDEF";
+
+ if (aValue<0)
+ aValue=65536-abs(aValue);
+ SeriesString(aValue,aString,kHexSet,0,16);
+ }
+
+ static void RomanString(PRInt32 aValue,nsString& aString) {
+ static char digitsA[] = "ixcm";
+ static char digitsB[] = "vld?";
+
+ aString.Truncate();
+ if(aValue<0)
+ aString.AppendWithConversion('-');
+
+ aValue=abs(aValue);
+ char decStr[20];
+ sprintf(decStr,"%d", aValue);
+
+ int len=strlen(decStr);
+ int romanPos=len;
+ int digitPos=0;
+ int n=0;
+
+ for(digitPos=0;digitPosmOrdinal=0;
+ }
+ aTag=eHTMLTag_userdefined;
+ }
+ else if(theKey.EqualsWithConversion("noincr",PR_TRUE)){
+ theIncrValue=0;
+ }
+ else if(theKey.EqualsWithConversion("format",PR_TRUE)){
+ PRUnichar theChar=theValue.CharAt(0);
+ if('"'==theChar)
+ theChar=theValue.CharAt(1);
+ switch(theChar){
+ case 'A': case 'a': theNumFormat=CAbacus::eAlpha; break;
+ case 'B': case 'b': theNumFormat=CAbacus::eBinary; break;
+ case 'D': case 'd': theNumFormat=CAbacus::eDecimal; break;
+ case 'H': case 'h': theNumFormat=CAbacus::eHex; break;
+ case 'R': case 'r': theNumFormat=CAbacus::eRoman; break;
+ case 'S': case 's': theNumFormat=CAbacus::eSpoken; break;
+ default:
+ theNumFormat=CAbacus::eDecimal;
+ break;
+ }
+ //determine numbering style
+ }
+ else if(theKey.EqualsWithConversion("value",PR_TRUE)){
+ PRInt32 err=0;
+ theNewValue=theValue.ToInteger(&err);
+ if(!err) {
+ theIncrValue=0;
+ mCounters[aTag]=theNewValue;
+ }
+ else theNewValue=-1;
+ }
+ }
+
+ if(theEntity && (eHTMLTag_userdefined==aTag)) {
+ result=theEntity->mOrdinal+=theIncrValue;
+ }
+ else result=mCounters[aTag]+=theIncrValue;
+ CAbacus::GetFormattedString(theNumFormat,result,aResult,0,0,0);
+
return result;
}
-/**
- *
- * @update gess 11May2000
- */
-void nsDTDContext::ResetCounter(eHTMLTags aTag,PRInt32 aValue) {
- mCounters[aTag]=aValue;
-}
/**
*
diff --git a/parser/htmlparser/src/nsDTDUtils.h b/parser/htmlparser/src/nsDTDUtils.h
index 69096e0ad72..de25793c90c 100644
--- a/parser/htmlparser/src/nsDTDUtils.h
+++ b/parser/htmlparser/src/nsDTDUtils.h
@@ -155,6 +155,11 @@ public:
return result;
}
+ PRBool CanOpenTBody() {
+ PRBool result=!(mHasTBody);
+ return result;
+ }
+
PRBool CanOpenTHead() {
PRBool result=!(mHasTHead || mHasTFoot || mHasTBody);
return result;
@@ -174,14 +179,42 @@ public:
};
+//used for named entities and counters (XXX debug only)
+class CNamedEntity {
+public:
+ CNamedEntity(const nsString& aName,const nsString& aValue) : mName(), mValue() {
+ PRUnichar theFirst=aName.First();
+ PRUnichar theLast=aName.Last();
+ PRInt32 theLen=aName.Length();
+ if((2GetStringValueXXX();
+
if((kHashsign!=theChar) && (-1==nsHTMLEntities::EntityToUnicode(theStr))){
//if you're here we have a bogus entity.
//convert it into a text token.
@@ -640,6 +642,7 @@ nsresult nsHTMLTokenizer::ConsumeEntity(PRUnichar aChar,CToken*& aToken,nsScanne
theRecycler->RecycleToken(aToken);
aToken=theToken;
}
+#endif
AddToken(aToken,result,&mTokenDeque,theRecycler);
}
}//if
diff --git a/parser/htmlparser/src/nsParser.cpp b/parser/htmlparser/src/nsParser.cpp
index 1cc3902465d..31446678871 100644
--- a/parser/htmlparser/src/nsParser.cpp
+++ b/parser/htmlparser/src/nsParser.cpp
@@ -102,12 +102,13 @@ public:
//Note: To cut down on startup time/overhead, we defer the construction of non-html DTD's.
nsIDTD* theDTD;
+
NS_NewNavHTMLDTD(&theDTD); //do this as a default HTML DTD...
mDTDDeque.Push(theDTD);
-#if 1
+
NS_NewOtherHTMLDTD(&theDTD); //do this as the default DTD for strict documents...
mDTDDeque.Push(theDTD);
-#endif
+
mHasViewSourceDTD=PR_FALSE;
mHasRTFDTD=mHasXMLDTD=PR_FALSE;
}
@@ -485,7 +486,7 @@ nsDTDMode nsParser::GetParseMode(void){
* @return parsermode (define in nsIParser.h)
*/
static
-void DetermineParseMode(nsString& aBuffer,nsDTDMode& aParseMode,eParserDocType& aDocType) {
+void DetermineParseMode(nsString& aBuffer,nsDTDMode& aParseMode,eParserDocType& aDocType,const nsString& aMimeType) {
const char* theModeStr= PR_GetEnv("PARSE_MODE");
aParseMode = eDTDMode_unknown;
@@ -613,8 +614,18 @@ void DetermineParseMode(nsString& aBuffer,nsDTDMode& aParseMode,eParserDocType&
}
}
else if(kNotFound<(theIndex=aBuffer.Find("?XML",PR_TRUE,0,128))) {
- aDocType=eXMLText;
aParseMode=eDTDMode_strict;
+ if(aMimeType.EqualsWithConversion(kHTMLTextContentType)) {
+ //this is here to prevent a crash if someone gives us an XML document,
+ //but necko tells us it's a text/html mimetype.
+ aDocType=eHTML4Text;
+ aParseMode=eDTDMode_strict;
+ }
+ else aDocType=eXMLText;
+ }
+ else if(aMimeType.EqualsWithConversion(kPlainTextContentType)) {
+ aDocType=ePlainText;
+ aParseMode=eDTDMode_quirks;
}
if(theModeStr) {
@@ -754,7 +765,11 @@ nsresult nsParser::CreateCompatibleDTD(nsIDTD** aDTD,
nsDTDMode theDTDMode=eDTDMode_unknown;
eParserDocType theDocType=ePlainText;
- DetermineParseMode(*aDocTypeStr,theDTDMode,theDocType);
+ if(!aMimeType) {
+ nsAutoString temp;
+ DetermineParseMode(*aDocTypeStr,theDTDMode,theDocType,temp);
+ }
+ else DetermineParseMode(*aDocTypeStr,theDTDMode,theDocType,*aMimeType);
NS_ASSERTION(aDTDMode==eDTDMode_unknown || aDTDMode==theDTDMode,"aDTDMode overrides the mode selected from the DOCTYPE ");
@@ -945,7 +960,7 @@ nsresult nsParser::WillBuildModel(nsString& aFilename){
while(*theDocType) {
nsAutoString theType;
theType.AssignWithConversion(*theDocType);
- DetermineParseMode(theType,theParseMode,theDocumentType);
+ DetermineParseMode(theType,theParseMode,theDocumentType,mParserContext->mMimeType);
theDocType++;
}
}
@@ -957,7 +972,7 @@ nsresult nsParser::WillBuildModel(nsString& aFilename){
mMinorIteration=-1;
nsString& theBuffer=mParserContext->mScanner->GetBuffer();
- DetermineParseMode(theBuffer,mParserContext->mDTDMode,mParserContext->mDocType);
+ DetermineParseMode(theBuffer,mParserContext->mDTDMode,mParserContext->mDocType,mParserContext->mMimeType);
if(PR_TRUE==FindSuitableDTD(*mParserContext,theBuffer)) {
mParserContext->mDTD->WillBuildModel( *mParserContext,mSink);