fixed a few nsbeta2+ bugs; r=harishd and kmcclusk
git-svn-id: svn://10.0.0.236/trunk@72354 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
@@ -17,15 +17,15 @@
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s): rickg@netscape.com
|
||||
* Contributor(s): rickg@netscape.com
|
||||
*/
|
||||
|
||||
//#define ENABLE_CRC
|
||||
//#define RICKG_DEBUG
|
||||
|
||||
//#define ENABLE_CRC
|
||||
//#define RICKG_DEBUG
|
||||
|
||||
|
||||
|
||||
#include "nsDebug.h"
|
||||
#include "nsIDTDDebug.h"
|
||||
#include "nsIDTDDebug.h"
|
||||
#include "COtherDTD.h"
|
||||
#include "nsHTMLTokens.h"
|
||||
#include "nsCRT.h"
|
||||
@@ -148,7 +148,6 @@ COtherDTD::COtherDTD() : nsIDTD(), mSharedNodes(0) {
|
||||
mHadFrameset=PR_FALSE;
|
||||
mHadBody=PR_FALSE;
|
||||
mHasOpenScript=PR_FALSE;
|
||||
mTokenRecycler=0;
|
||||
mParserCommand=eViewNormal;
|
||||
|
||||
#if 1 //set this to 1 if you want strictDTD to be based on the environment setting.
|
||||
@@ -206,67 +205,6 @@ nsCParserNode* COtherDTD::CreateNode(void) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method recycles a given node
|
||||
* @update gess1/8/99
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
void COtherDTD::RecycleNode(nsCParserNode* aNode) {
|
||||
if(aNode && (!aNode->mUseCount)) {
|
||||
|
||||
if(aNode->mToken) {
|
||||
if(!aNode->mToken->mUseCount) {
|
||||
mTokenRecycler->RecycleToken(aNode->mToken);
|
||||
}
|
||||
}
|
||||
|
||||
CToken* theToken=0;
|
||||
while((theToken=(CToken*)aNode->PopAttributeToken())){
|
||||
if(!theToken->mUseCount) {
|
||||
mTokenRecycler->RecycleToken(theToken);
|
||||
}
|
||||
}
|
||||
|
||||
mSharedNodes.Push(aNode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 COtherDTD::RecycleNodes(nsEntryStack *aNodeStack) {
|
||||
if(aNodeStack) {
|
||||
PRInt32 theCount=aNodeStack->mCount;
|
||||
PRInt32 theIndex=0;
|
||||
|
||||
for(theIndex=0;theIndex<theCount;theIndex++) {
|
||||
nsCParserNode* theNode=(nsCParserNode*)aNodeStack->NodeAt(theIndex);
|
||||
if(theNode) {
|
||||
|
||||
theNode->mUseCount=0;
|
||||
if(theNode->mToken) {
|
||||
theNode->mToken->mUseCount=0;
|
||||
mTokenRecycler->RecycleToken(theNode->mToken);
|
||||
}
|
||||
|
||||
CToken* theToken=0;
|
||||
while((theToken=(CToken*)theNode->PopAttributeToken())){
|
||||
theNode->mToken->mUseCount=0;
|
||||
mTokenRecycler->RecycleToken(theToken);
|
||||
}
|
||||
|
||||
mSharedNodes.Push(theNode);
|
||||
} //if
|
||||
} //while
|
||||
} //if
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess1/8/99
|
||||
@@ -476,10 +414,10 @@ nsresult COtherDTD::WillBuildModel( const CParserContext& aParserContext,nsICon
|
||||
STOP_TIMER();
|
||||
MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: COtherDTD::WillBuildModel(), this=%p\n", this));
|
||||
|
||||
mTokenRecycler=0;
|
||||
|
||||
mDocType=aParserContext.mDocType;
|
||||
mBodyContext->mTransitional=PRBool(aParserContext.mDTDMode==eDTDMode_transitional);
|
||||
mBodyContext->GetTokenRecycler();
|
||||
|
||||
if(aSink && (!mSink)) {
|
||||
result=aSink->QueryInterface(kIHTMLContentSinkIID, (void **)&mSink);
|
||||
}
|
||||
@@ -521,12 +459,11 @@ nsresult COtherDTD::BuildModel(nsIParser* aParser,nsITokenizer* aTokenizer,nsITo
|
||||
|
||||
if(mTokenizer) {
|
||||
|
||||
mTokenRecycler=(CTokenRecycler*)mTokenizer->GetTokenRecycler();
|
||||
if(mSink) {
|
||||
|
||||
if(!mBodyContext->GetCount()) {
|
||||
//if the content model is empty, then begin by opening <html>...
|
||||
CStartToken *theToken=(CStartToken*)mTokenRecycler->CreateTokenOfType(eToken_start,eHTMLTag_html,NS_ConvertToString("html"));
|
||||
CStartToken *theToken=(CStartToken*)mBodyContext->gTokenRecycler->CreateTokenOfType(eToken_start,eHTMLTag_html,NS_ConvertToString("html"));
|
||||
HandleStartToken(theToken); //this token should get pushed on the context stack, don't recycle it.
|
||||
}
|
||||
|
||||
@@ -593,11 +530,13 @@ nsresult COtherDTD::DidBuildModel(nsresult anErrorCode,PRBool aNotifySink,nsIPar
|
||||
|
||||
nsEntryStack *theChildStyles=0;
|
||||
nsCParserNode* theNode=(nsCParserNode*)mBodyContext->Pop(theChildStyles);
|
||||
theNode->mUseCount=0;
|
||||
RecycleNode(theNode);
|
||||
if(theChildStyles) {
|
||||
delete theChildStyles;
|
||||
}
|
||||
if(theNode) {
|
||||
theNode->mUseCount=0;
|
||||
mBodyContext->RecycleNode(theNode);
|
||||
if(theChildStyles) {
|
||||
delete theChildStyles;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -653,7 +592,7 @@ nsresult COtherDTD::HandleToken(CToken* aToken,nsIParser* aParser){
|
||||
|
||||
if(NS_SUCCEEDED(result) || (NS_ERROR_HTMLPARSER_BLOCK==result)) {
|
||||
if(0>=theToken->mUseCount)
|
||||
mTokenRecycler->RecycleToken(theToken);
|
||||
mBodyContext->gTokenRecycler->RecycleToken(theToken);
|
||||
}
|
||||
else if(result==NS_ERROR_HTMLPARSER_STOPPARSING)
|
||||
mDTDState=result;
|
||||
@@ -796,7 +735,7 @@ nsresult COtherDTD::WillHandleStartTag(CToken* aToken,eHTMLTags aTag,nsCParserNo
|
||||
* to be stored in
|
||||
* 2) close the top container, and add this to
|
||||
* whatever container ends up on top.
|
||||
*
|
||||
*
|
||||
* @update gess 1/04/99
|
||||
* @param aToken -- next (start) token to be handled
|
||||
* @param aNode -- CParserNode representing this start token
|
||||
@@ -809,49 +748,54 @@ nsresult COtherDTD::HandleStartToken(CToken* aToken) {
|
||||
|
||||
//Begin by gathering up attributes...
|
||||
|
||||
nsresult result=NS_OK;
|
||||
nsCParserNode* theNode=CreateNode();
|
||||
theNode->Init(aToken,mLineNumber,mTokenRecycler);
|
||||
if(theNode) {
|
||||
theNode->Init(aToken,mLineNumber,mBodyContext->gTokenRecycler);
|
||||
|
||||
eHTMLTags theChildTag=(eHTMLTags)aToken->GetTypeID();
|
||||
PRInt16 attrCount=aToken->GetAttributeCount();
|
||||
eHTMLTags theParent=mBodyContext->Last();
|
||||
nsresult result=(0==attrCount) ? NS_OK : CollectAttributes(*theNode,theChildTag,attrCount);
|
||||
eHTMLTags theChildTag=(eHTMLTags)aToken->GetTypeID();
|
||||
PRInt16 attrCount=aToken->GetAttributeCount();
|
||||
eHTMLTags theParent=mBodyContext->Last();
|
||||
|
||||
result=(0==attrCount) ? NS_OK : CollectAttributes(*theNode,theChildTag,attrCount);
|
||||
|
||||
if(NS_OK==result) {
|
||||
result=WillHandleStartTag(aToken,theChildTag,*theNode);
|
||||
if(NS_OK==result) {
|
||||
result=WillHandleStartTag(aToken,theChildTag,*theNode);
|
||||
if(NS_OK==result) {
|
||||
|
||||
mLineNumber += aToken->mNewlineCount;
|
||||
mLineNumber += aToken->mNewlineCount;
|
||||
|
||||
PRBool theTagWasHandled=PR_FALSE;
|
||||
PRBool theTagWasHandled=PR_FALSE;
|
||||
|
||||
switch(theChildTag) {
|
||||
switch(theChildTag) {
|
||||
|
||||
case eHTMLTag_html:
|
||||
if(!mBodyContext->HasOpenContainer(theChildTag)){
|
||||
mSink->OpenHTML(*theNode);
|
||||
mBodyContext->Push(theNode,0);
|
||||
}
|
||||
theTagWasHandled=PR_TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
CElement* theElement=gElementTable->mElements[theParent];
|
||||
if(theElement) {
|
||||
result=theElement->HandleStartToken(theNode,theChildTag,mBodyContext,mSink);
|
||||
theTagWasHandled=PR_TRUE;
|
||||
}
|
||||
break;
|
||||
}//switch
|
||||
|
||||
if(theTagWasHandled) {
|
||||
DidHandleStartTag(*theNode,theChildTag);
|
||||
}
|
||||
case eHTMLTag_html:
|
||||
if(!mBodyContext->HasOpenContainer(theChildTag)){
|
||||
mSink->OpenHTML(*theNode);
|
||||
mBodyContext->Push(theNode,0);
|
||||
}
|
||||
theTagWasHandled=PR_TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
CElement* theElement=gElementTable->mElements[theParent];
|
||||
if(theElement) {
|
||||
result=theElement->HandleStartToken(theNode,theChildTag,mBodyContext,mSink);
|
||||
theTagWasHandled=PR_TRUE;
|
||||
}
|
||||
break;
|
||||
}//switch
|
||||
|
||||
if(theTagWasHandled) {
|
||||
DidHandleStartTag(*theNode,theChildTag);
|
||||
}
|
||||
|
||||
} //if
|
||||
}//if
|
||||
|
||||
RecycleNode(theNode);
|
||||
} //if
|
||||
}//if
|
||||
mBodyContext->RecycleNode(theNode);
|
||||
}
|
||||
else result=NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -872,18 +816,18 @@ nsresult COtherDTD::HandleEndToken(CToken* aToken) {
|
||||
nsresult result=NS_OK;
|
||||
eHTMLTags theChildTag=(eHTMLTags)aToken->GetTypeID();
|
||||
|
||||
#ifdef RICKG_DEBUG
|
||||
#ifdef RICKG_DEBUG
|
||||
WriteTokenToLog(aToken);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
switch(theChildTag) {
|
||||
|
||||
case eHTMLTag_body: //we intentionally don't let the user close HTML or BODY
|
||||
case eHTMLTag_html:
|
||||
break;
|
||||
break;
|
||||
|
||||
case eHTMLTag_script:
|
||||
mHasOpenScript=PR_FALSE;
|
||||
case eHTMLTag_script:
|
||||
mHasOpenScript=PR_FALSE;
|
||||
|
||||
default:
|
||||
PRInt32 theCount=mBodyContext->GetCount();
|
||||
@@ -898,10 +842,10 @@ nsresult COtherDTD::HandleEndToken(CToken* aToken) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the attributes for this node, and add then into
|
||||
* the node.
|
||||
@@ -955,11 +899,12 @@ nsresult COtherDTD::HandleEntityToken(CToken* aToken) {
|
||||
|
||||
nsString& theStr=aToken->GetStringValueXXX();
|
||||
PRUnichar theChar=theStr.CharAt(0);
|
||||
CToken *theToken=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);
|
||||
}
|
||||
@@ -972,6 +917,16 @@ nsresult COtherDTD::HandleEntityToken(CToken* aToken) {
|
||||
}
|
||||
result=HandleStartToken(theToken);
|
||||
}
|
||||
else {
|
||||
|
||||
//add this code to fix bug 42629 (entities were getting dropped).
|
||||
eHTMLTags theParent=mBodyContext->Last();
|
||||
CElement* theElement=gElementTable->mElements[theParent];
|
||||
if(theElement) {
|
||||
nsCParserNode theNode(aToken,mLineNumber,0);
|
||||
result=theElement->HandleStartToken(&theNode,eHTMLTag_text,mBodyContext,mSink);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1084,22 +1039,6 @@ nsresult COtherDTD::GetTokenizer(nsITokenizer*& aTokenizer) {
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess8/4/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
nsITokenRecycler* COtherDTD::GetTokenRecycler(void){
|
||||
if(!mTokenRecycler) {
|
||||
nsresult result=GetTokenizer(mTokenizer);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
mTokenRecycler=(CTokenRecycler*)mTokenizer->GetTokenRecycler();
|
||||
}
|
||||
}
|
||||
return mTokenRecycler;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
|
||||
@@ -225,12 +225,13 @@ CLASS_EXPORT_HTMLPARS COtherDTD : public nsIDTD {
|
||||
NS_IMETHOD GetTokenizer(nsITokenizer*& aTokenizer);
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess12/28/98
|
||||
* @param
|
||||
* @return
|
||||
* Note that the otherDTD get's it's recycler from
|
||||
* the body context.
|
||||
*
|
||||
* @update rickg 16June2000
|
||||
* @return always 0
|
||||
*/
|
||||
virtual nsITokenRecycler* GetTokenRecycler(void);
|
||||
virtual nsITokenRecycler* GetTokenRecycler(void) {return 0;}
|
||||
|
||||
/**
|
||||
* If the parse process gets interrupted, this method gets called
|
||||
@@ -318,8 +319,6 @@ protected:
|
||||
nsresult WillHandleStartTag(CToken* aToken,eHTMLTags aChildTag,nsCParserNode& aNode);
|
||||
nsresult DidHandleStartTag(nsCParserNode& aNode,eHTMLTags aChildTag);
|
||||
nsCParserNode* CreateNode(void);
|
||||
void RecycleNode(nsCParserNode* aNode);
|
||||
void RecycleNodes(nsEntryStack *aNodeStack);
|
||||
|
||||
nsIHTMLContentSink* mSink;
|
||||
|
||||
@@ -335,7 +334,6 @@ protected:
|
||||
PRInt32 mLineNumber;
|
||||
nsParser* mParser;
|
||||
nsITokenizer* mTokenizer;
|
||||
CTokenRecycler* mTokenRecycler;
|
||||
PRBool mHasOpenScript;
|
||||
eHTMLTags mSkipTarget;
|
||||
nsDeque mSharedNodes;
|
||||
|
||||
@@ -161,7 +161,7 @@ public:
|
||||
|
||||
static PRBool HasOptionalEndTag(CElement* anElement) {
|
||||
static eHTMLTags gContainersWithOptionalEndTag[]={eHTMLTag_body,eHTMLTag_colgroup,eHTMLTag_dd,eHTMLTag_dt,
|
||||
eHTMLTag_head,eHTMLTag_html,eHTMLTag_li,eHTMLTag_option,
|
||||
eHTMLTag_head,eHTMLTag_li,eHTMLTag_option,
|
||||
eHTMLTag_p,eHTMLTag_tbody,eHTMLTag_td,eHTMLTag_tfoot,
|
||||
eHTMLTag_th,eHTMLTag_thead,eHTMLTag_tr,eHTMLTag_unknown};
|
||||
if(anElement) {
|
||||
@@ -174,9 +174,29 @@ public:
|
||||
inline CElement* GetDefaultContainerFor(CElement* anElement);
|
||||
|
||||
virtual PRBool CanContain(CElement* anElement,nsDTDContext* aContext);
|
||||
virtual PRBool CanBeClosedByStartTag(CElement* anElement,nsDTDContext* aContext);
|
||||
virtual PRInt32 FindAutoCloseIndexForStartTag(CElement* anElement,PRInt32 aParentIndex,nsDTDContext* aContext);
|
||||
virtual PRBool CanBeClosedByEndTag(CElement* anElement,nsDTDContext* aContext);
|
||||
|
||||
//This tells us whether this tag can potentially close other blocks.
|
||||
//That DOES NOT mean that this tag is necessarily a block itself (condsider TBODY,TR,TD...)
|
||||
virtual PRBool IsBlockCloser(void) {
|
||||
PRBool result=IsBlockElement(eHTMLTag_body);
|
||||
if(!result) {
|
||||
if(IsInlineElement(eHTMLTag_body) ||
|
||||
mGroup.mBits.mHead ||
|
||||
mGroup.mBits.mHeadMisc ||
|
||||
mGroup.mBits.mFormControl ||
|
||||
mGroup.mBits.mFrame ||
|
||||
mGroup.mBits.mLeaf ||
|
||||
mGroup.mBits.mComment ||
|
||||
mGroup.mBits.mTextContainer ||
|
||||
mGroup.mBits.mWhiteSpace)
|
||||
result=PR_FALSE;
|
||||
else result=PR_TRUE;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//this tells us whether this tag is a block tag within the given parent
|
||||
virtual PRBool IsBlockElement(eHTMLTags aParentID);
|
||||
|
||||
@@ -305,11 +325,13 @@ public:
|
||||
this gets called to close a tag in the given context
|
||||
**********************************************************/
|
||||
virtual nsresult CloseContext(nsIParserNode *aNode,eHTMLTags aTag,nsDTDContext *aContext,nsIHTMLContentSink *aSink) {
|
||||
nsEntryStack* theStack=0;
|
||||
aContext->Pop(theStack);
|
||||
nsEntryStack *theStack=0;
|
||||
nsIParserNode *theNode=aContext->Pop(theStack);
|
||||
|
||||
CElement *theElement=(aTag==mTag) ? this : GetElement(aTag);
|
||||
theElement->NotifyClose(aNode,aTag,aContext,aSink);
|
||||
theElement->NotifyClose(theNode,aTag,aContext,aSink);
|
||||
|
||||
aContext->RecycleNode((nsCParserNode*)theNode);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@@ -585,6 +607,13 @@ public:
|
||||
return result;
|
||||
}
|
||||
|
||||
/**********************************************************
|
||||
this gets called after each tag is opened in the given context
|
||||
**********************************************************/
|
||||
virtual nsresult OpenContainer(nsIParserNode *aNode,eHTMLTags aTag,nsDTDContext *aContext,nsIHTMLContentSink *aSink) {
|
||||
nsresult result=aSink->OpenForm(*aNode);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
@@ -673,6 +702,39 @@ public:
|
||||
CElement::Initialize(*this,aTag,CBlockElement::GetGroup(),CTableElement::GetContainedGroups());
|
||||
}
|
||||
|
||||
PRBool CanContain(CElement* anElement,nsDTDContext* aContext) {
|
||||
PRBool result=PR_FALSE;
|
||||
|
||||
switch(anElement->mTag) {
|
||||
|
||||
case eHTMLTag_caption:
|
||||
result=(aContext->mTableStates && aContext->mTableStates->CanOpenCaption());
|
||||
break;
|
||||
|
||||
case eHTMLTag_colgroup:
|
||||
result=(aContext->mTableStates && aContext->mTableStates->CanOpenCols());
|
||||
break;
|
||||
|
||||
case eHTMLTag_thead: //nothing to do for these empty tags...
|
||||
result=(aContext->mTableStates && aContext->mTableStates->CanOpenTHead());
|
||||
break;
|
||||
|
||||
case eHTMLTag_tfoot:
|
||||
result=(aContext->mTableStates && aContext->mTableStates->CanOpenTFoot());
|
||||
break;
|
||||
|
||||
case eHTMLTag_tr:
|
||||
case eHTMLTag_th:
|
||||
result=(aContext->mTableStates && aContext->mTableStates->CanOpenTBody());
|
||||
break;
|
||||
|
||||
default:
|
||||
result=CElement::CanContain(anElement,aContext);
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**********************************************************
|
||||
Table needs to be notified so it can manage table states.
|
||||
**********************************************************/
|
||||
@@ -806,7 +868,8 @@ public:
|
||||
end tags, can't deal with the given tag, and want you
|
||||
to handle it.
|
||||
**********************************************************/
|
||||
virtual PRInt32 FindAutoCloseTargetForEndTag(nsIParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink, PRInt32& anIndex) {
|
||||
virtual PRInt32 FindAutoCloseTargetForEndTag(nsIParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink, PRInt32& anIndex) {
|
||||
PRInt32 result=kNotFound;
|
||||
|
||||
switch(aTag) {
|
||||
case eHTMLTag_table:
|
||||
@@ -818,14 +881,20 @@ public:
|
||||
case eHTMLTag_tbody:
|
||||
case eHTMLTag_tr:
|
||||
case eHTMLTag_td:
|
||||
return anIndex;
|
||||
{
|
||||
PRInt32 theTablePos=aContext->LastOf(eHTMLTag_table);
|
||||
PRInt32 theTagPos=aContext->LastOf(aTag);
|
||||
if((kNotFound!=theTagPos) && (theTablePos<=theTagPos)) {
|
||||
result=theTagPos;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
} //switch
|
||||
|
||||
return -1;
|
||||
return result;
|
||||
}
|
||||
|
||||
};
|
||||
@@ -846,6 +915,7 @@ public:
|
||||
|
||||
CTableRowElement(eHTMLTags aTag=eHTMLTag_tr) : CElement(aTag) {
|
||||
CTableRowElement::Initialize(*this,aTag);
|
||||
mContainsGroups.mBits.mSelf=0;
|
||||
}
|
||||
|
||||
virtual nsresult HandleEndTokenForChild(CElement *aChild,nsIParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
|
||||
@@ -925,6 +995,11 @@ public:
|
||||
return CElement::HandleStartToken(aNode,aTag,aContext,aSink);
|
||||
}
|
||||
|
||||
virtual PRBool CanContain(CElement* anElement,nsDTDContext* aContext) {
|
||||
PRBool result=(mTag==anElement->mTag) ? result=PR_FALSE : CElement::CanContain(anElement,aContext);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**********************************************************
|
||||
LI handles the closing of it's own children
|
||||
**********************************************************/
|
||||
@@ -1051,11 +1126,13 @@ public:
|
||||
|
||||
static void Initialize(CElement& anElement,eHTMLTags aTag){
|
||||
anElement.mProperties.mIsContainer=1;
|
||||
anElement.mProperties.mIsSinkContainer=1;
|
||||
anElement.mTag=aTag;
|
||||
anElement.mGroup.mAllBits=0;
|
||||
anElement.mGroup.mBits.mFrame=1;
|
||||
anElement.mContainsGroups.mAllBits=0;
|
||||
anElement.mContainsGroups.mBits.mFrame=1;
|
||||
anElement.mContainsGroups.mBits.mSelf=1;
|
||||
}
|
||||
|
||||
CFrameElement(eHTMLTags aTag) : CElement(aTag) {
|
||||
@@ -1167,11 +1244,16 @@ public:
|
||||
virtual nsresult NotifyClose(nsIParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
|
||||
nsresult result=NS_OK;
|
||||
if(aNode) {
|
||||
#if 0
|
||||
CStartToken theToken(aTag);
|
||||
PRInt32 theLineNumber=0;
|
||||
nsCParserNode theNode(&theToken,theLineNumber);
|
||||
theNode.SetSkippedContent(mText);
|
||||
result=aSink->AddLeaf(theNode);
|
||||
#endif
|
||||
nsCParserNode *theNode=(nsCParserNode*)aNode;
|
||||
theNode->SetSkippedContent(mText);
|
||||
result=aSink->AddLeaf(*theNode);
|
||||
}
|
||||
mText.Truncate(0);
|
||||
return result;
|
||||
@@ -1333,6 +1415,19 @@ public:
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**********************************************************
|
||||
this gets called to close a tag in the given context
|
||||
**********************************************************/
|
||||
virtual nsresult CloseContext(nsIParserNode *aNode,eHTMLTags aTag,nsDTDContext *aContext,nsIHTMLContentSink *aSink) {
|
||||
nsEntryStack* theStack=0;
|
||||
nsIParserNode *theNode=aContext->Pop(theStack);
|
||||
|
||||
CElement *theElement=(aTag==mTag) ? this : GetElement(aTag);
|
||||
theElement->NotifyClose(theNode,aTag,aContext,aSink);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**********************************************************
|
||||
Call this for each element as it get's closed
|
||||
**********************************************************/
|
||||
@@ -1345,7 +1440,9 @@ public:
|
||||
PRInt32 theLineNumber=0;
|
||||
nsCParserNode theNode(&theToken,theLineNumber);
|
||||
theNode.SetSkippedContent(mText);
|
||||
result=aSink->AddLeaf(theNode);
|
||||
//result=aSink->AddLeaf(theNode);
|
||||
|
||||
result=aSink->AddLeaf(*aNode);
|
||||
}
|
||||
else {
|
||||
//add it to the head...
|
||||
@@ -1363,14 +1460,14 @@ public:
|
||||
/**********************************************************
|
||||
This defines the preformatted element group, (PRE).
|
||||
**********************************************************/
|
||||
class CPreformattedElement: public CInlineElement {
|
||||
class CPreformattedElement: public CBlockElement {
|
||||
public:
|
||||
|
||||
static void Initialize(CElement& anElement,eHTMLTags aTag){
|
||||
CInlineElement::Initialize(anElement,aTag);
|
||||
CBlockElement::Initialize(anElement,aTag);
|
||||
}
|
||||
|
||||
CPreformattedElement(eHTMLTags aTag) : CInlineElement(aTag) {
|
||||
CPreformattedElement(eHTMLTags aTag) : CBlockElement(aTag) {
|
||||
mGroup=GetGroup();
|
||||
mContainsGroups=GetContainedGroups();
|
||||
mProperties.mIsContainer=1;
|
||||
@@ -1810,7 +1907,10 @@ public:
|
||||
nsDTDContext* aContext,
|
||||
nsIHTMLContentSink* aSink) {
|
||||
//for now, let's drop other elements onto the floor.
|
||||
|
||||
nsresult result=CElement::HandleStartToken(aNode,aTag,aContext,aSink);
|
||||
|
||||
CElement *theElement=GetElement(aTag);
|
||||
if(NS_SUCCEEDED(result)) {
|
||||
nsCParserNode *theNode=(nsCParserNode*)aNode;
|
||||
CStartToken *theToken=(CStartToken*)theNode->mToken;
|
||||
@@ -1879,8 +1979,8 @@ public:
|
||||
memset(mElements,0,sizeof(mElements));
|
||||
InitializeElements();
|
||||
|
||||
//DebugDumpBlockElements();
|
||||
//DebugDumpInlineElements();
|
||||
//DebugDumpBlockElements("test");
|
||||
//DebugDumpInlineElements("test");
|
||||
|
||||
//DebugDumpContainment("all elements");
|
||||
}
|
||||
@@ -2053,7 +2153,7 @@ void CElementTable::InitializeElements() {
|
||||
|
||||
CFrameElement::Initialize( mDfltElements[eHTMLTag_frameset], eHTMLTag_frameset);
|
||||
mDfltElements[eHTMLTag_frameset].mIncludeKids=kFramesetKids;
|
||||
|
||||
|
||||
CBlockElement::Initialize( mDfltElements[eHTMLTag_h1], eHTMLTag_h1);
|
||||
CBlockElement::Initialize( mDfltElements[eHTMLTag_h2], eHTMLTag_h2);
|
||||
CBlockElement::Initialize( mDfltElements[eHTMLTag_h3], eHTMLTag_h3);
|
||||
@@ -2174,7 +2274,7 @@ void CElementTable::InitializeElements() {
|
||||
mDfltElements[eHTMLTag_tfoot].mIncludeKids=kTBodyKids;
|
||||
mDfltElements[eHTMLTag_tfoot].mContainsGroups.mBits.mSelf=0;
|
||||
|
||||
CTableRowElement::Initialize( mDfltElements[eHTMLTag_th], eHTMLTag_th);
|
||||
CElement::Initialize( mDfltElements[eHTMLTag_th], eHTMLTag_th, CElement::GetEmptyGroup(), CFlowElement::GetContainedGroups());
|
||||
mDfltElements[eHTMLTag_th].mContainsGroups.mBits.mSelf=0;
|
||||
|
||||
CElement::Initialize( mDfltElements[eHTMLTag_thead], eHTMLTag_thead, CTableElement::GetGroup(), CLeafElement::GetContainedGroups());
|
||||
@@ -2388,27 +2488,35 @@ void CElementTable::DebugDumpContainment(const char* aTitle){
|
||||
Yes, I know it's inconvenient to find this methods here, but it's easier
|
||||
for the compiler -- and making it's life easier is my top priority.
|
||||
******************************************************************************/
|
||||
PRBool CElement::CanBeClosedByStartTag(CElement* anElement,nsDTDContext* aContext) {
|
||||
PRBool result=PR_FALSE;
|
||||
PRInt32 CElement::FindAutoCloseIndexForStartTag(CElement* anElement,PRInt32 aParentIndex,nsDTDContext* aContext) {
|
||||
PRInt32 result=kNotFound;
|
||||
|
||||
//first, let's see if we can contain the given tag based on group info...
|
||||
if(anElement) {
|
||||
if(ListContainsTag(mAutoClose,anElement->mTag)) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
else if((this==anElement) && (!mContainsGroups.mBits.mSelf)){
|
||||
return PR_TRUE;
|
||||
}
|
||||
else {
|
||||
eHTMLTags theTag=aContext->Last();
|
||||
CElement* theElement=gElementTable->mElements[theTag];
|
||||
if(HasOptionalEndTag(theElement)) {
|
||||
if(anElement->CanContain(theElement,aContext)){
|
||||
result=PR_TRUE;
|
||||
eHTMLTags theParentTag=aContext->TagAt(aParentIndex);
|
||||
if(eHTMLTag_unknown!=theParentTag) {
|
||||
|
||||
CElement* theParent=gElementTable->mElements[theParentTag];
|
||||
|
||||
if(!theParent->CanContain(anElement,aContext)) {
|
||||
if(HasOptionalEndTag(theParent)) {
|
||||
|
||||
if(ListContainsTag(theParent->mAutoClose,anElement->mTag)) {
|
||||
result=theParent->FindAutoCloseIndexForStartTag(anElement,aParentIndex-1,aContext);
|
||||
}
|
||||
else if((theParent->mTag==anElement->mTag) && (!theParent->mContainsGroups.mBits.mSelf)){
|
||||
result=aParentIndex;
|
||||
}
|
||||
else if(eHTMLTag_body!=theParent->mTag) {
|
||||
result=theParent->FindAutoCloseIndexForStartTag(anElement,aParentIndex-1,aContext);
|
||||
}
|
||||
else result=aParentIndex+1;
|
||||
}
|
||||
}
|
||||
else result=kNotFound;
|
||||
}
|
||||
else result=aParentIndex+1;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -2473,7 +2581,7 @@ PRBool CElement::CanContain(CElement* anElement,nsDTDContext* aContext) {
|
||||
***************************************************/
|
||||
|
||||
if((!result) && (aContext->mTransitional)) {
|
||||
switch(anElement->mTag) {
|
||||
switch(mTag) {
|
||||
case eHTMLTag_address:
|
||||
if(eHTMLTag_p==anElement->mTag)
|
||||
result=PR_TRUE;
|
||||
@@ -2540,29 +2648,43 @@ nsresult CElement::HandleStartToken( nsIParserNode* aNode,
|
||||
result=aSink->AddLeaf(*aNode);
|
||||
}
|
||||
}
|
||||
else if(theElement->IsContainer()){
|
||||
else if(theElement->IsBlockCloser()){
|
||||
|
||||
//Ok, so we have a start token that is misplaced. Before handing this off
|
||||
//to a default container (parent), let's check the autoclose condition.
|
||||
if(ListContainsTag(mAutoClose,theElement->mTag) || (aTag==mTag)) {
|
||||
if(HasOptionalEndTag(theElement)) {
|
||||
//aha! We have a case where this tag is autoclosed by anElement.
|
||||
//Let's close this container, then try to open theElement.
|
||||
eHTMLTags theParentTag=aContext->Last();
|
||||
CElement* theParent=gElementTable->mElements[theParentTag];
|
||||
while(NS_SUCCEEDED(result) && theParent->CanBeClosedByStartTag(this,aContext)) {
|
||||
result=theParent->HandleEndToken(aNode,theParentTag,aContext,aSink);
|
||||
if(HasOptionalEndTag(this)) {
|
||||
|
||||
//aha! We have a case where this tag is autoclosed by anElement.
|
||||
//Let's close this container, then try to open theElement.
|
||||
PRInt32 theCount=aContext->GetCount();
|
||||
PRInt32 theIndex=FindAutoCloseIndexForStartTag(theElement,theCount-2,aContext);
|
||||
|
||||
//continue ripping code out here...
|
||||
|
||||
if(kNotFound!=theIndex) {
|
||||
eHTMLTags theParentTag=eHTMLTag_unknown;
|
||||
CElement* theParent=0;
|
||||
|
||||
while(NS_SUCCEEDED(result) && (theCount>theIndex)) {
|
||||
|
||||
theParentTag=aContext->Last();
|
||||
theParent=gElementTable->mElements[theParentTag];
|
||||
|
||||
nsIParserNode *theNode=aContext->PeekNode(); //this will get popped later...
|
||||
if(theParent->IsSinkContainer()) {
|
||||
CloseContainerInContext(theNode,theParentTag,aContext,aSink);
|
||||
}
|
||||
else CloseContext(theNode,theParentTag,aContext,aSink);
|
||||
theCount--;
|
||||
}
|
||||
|
||||
if(NS_SUCCEEDED(result)){
|
||||
theParentTag=aContext->Last();
|
||||
theParent=gElementTable->mElements[theParentTag];
|
||||
return theParent->HandleStartToken(aNode,aTag,aContext,aSink);
|
||||
result=theParent->HandleStartToken(aNode,aTag,aContext,aSink);
|
||||
}
|
||||
else return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -2630,7 +2752,7 @@ nsresult CElement::HandleEndToken(nsIParserNode* aNode,eHTMLTags aTag,nsDTDConte
|
||||
result=theGrandParent->HandleEndToken(aNode,theTag,aContext,aSink);
|
||||
theCount--;
|
||||
}
|
||||
return result;
|
||||
//return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -357,7 +357,9 @@ eHTMLTags nsEntryStack::Last() const {
|
||||
/***************************************************************
|
||||
Now define the dtdcontext class
|
||||
***************************************************************/
|
||||
CNodeRecycler* nsDTDContext::mNodeRecycler=0;
|
||||
|
||||
CNodeRecycler *nsDTDContext::gNodeRecycler=0;
|
||||
CTokenRecycler *nsDTDContext::gTokenRecycler=0;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -499,6 +501,15 @@ public:
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a counter string in the given style for the given value.
|
||||
*
|
||||
* @update rickg 6June2000
|
||||
*
|
||||
* @param aFormat -- format of choice
|
||||
* @param aValue -- cardinal value of string
|
||||
* @param aString -- will hold result
|
||||
*/
|
||||
static void GetFormattedString(eNumFormat aFormat,PRInt32 aValue, nsString& aString,const char* aCharSet, int anOffset, int aBase) {
|
||||
switch (aFormat) {
|
||||
case eDecimal: DecimalString(aValue,aString); break;
|
||||
@@ -514,6 +525,14 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute a counter string in the casted-series style for the given value.
|
||||
*
|
||||
* @update rickg 6June2000
|
||||
*
|
||||
* @param aValue -- cardinal value of string
|
||||
* @param aString -- will hold result
|
||||
*/
|
||||
static void SeriesString(PRInt32 aValue,nsString& aString,const char* aCharSet, int offset, int base) {
|
||||
int ndex=0;
|
||||
int root=1;
|
||||
@@ -539,6 +558,14 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute a counter string in the spelled style for the given value.
|
||||
*
|
||||
* @update rickg 6June2000
|
||||
*
|
||||
* @param aValue -- cardinal value of string
|
||||
* @param aString -- will hold result
|
||||
*/
|
||||
static void SpelledString(PRInt32 aValue,nsString& aString) {
|
||||
|
||||
static char ones[][12]= {"zero","one ","two ","three ","four ","five ","six ","seven ","eight ","nine ","ten "};
|
||||
@@ -553,26 +580,26 @@ public:
|
||||
PRInt32 root=1000000000;
|
||||
PRInt32 expn=4;
|
||||
PRInt32 modu=0;
|
||||
PRInt32 temp=0;
|
||||
|
||||
aValue=abs(aValue);
|
||||
if(0<aValue) {
|
||||
|
||||
while(root && aValue) {
|
||||
if(temp=aValue/root) {
|
||||
PRInt32 div=temp/100;
|
||||
if (div) {//start with hundreds part
|
||||
aString.AppendWithConversion(ones[div]);
|
||||
PRInt32 temp=aValue/root;
|
||||
if(temp) {
|
||||
PRInt32 theDiv=temp/100;
|
||||
if (theDiv) {//start with hundreds part
|
||||
aString.AppendWithConversion(ones[theDiv]);
|
||||
aString.AppendWithConversion(bases[1]);
|
||||
}
|
||||
modu=(temp%10);
|
||||
div=(temp%100)/10;
|
||||
if (div) {
|
||||
if (div<2) {
|
||||
theDiv=(temp%100)/10;
|
||||
if (theDiv) {
|
||||
if (theDiv<2) {
|
||||
aString.AppendWithConversion(teens[modu]);
|
||||
modu=0;
|
||||
}
|
||||
else aString.AppendWithConversion(tens[div]);
|
||||
else aString.AppendWithConversion(tens[theDiv]);
|
||||
}
|
||||
if (modu)
|
||||
aString.AppendWithConversion(ones[modu]); //do remainder
|
||||
@@ -587,11 +614,27 @@ public:
|
||||
else aString.AppendWithConversion(ones[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute a counter string in the decimal format for the given value.
|
||||
*
|
||||
* @update rickg 6June2000
|
||||
*
|
||||
* @param aValue -- cardinal value of string
|
||||
* @param aString -- will hold result
|
||||
*/
|
||||
static void DecimalString(PRInt32 aValue,nsString& aString) {
|
||||
aString.Truncate();
|
||||
aString.AppendInt(aValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute a counter string in binary format for the given value.
|
||||
*
|
||||
* @update rickg 6June2000
|
||||
*
|
||||
* @param aValue -- cardinal value of string
|
||||
* @param aString -- will hold result
|
||||
*/
|
||||
static void BinaryString(PRInt32 aValue,nsString& aString) {
|
||||
static char kBinarySet[]="01";
|
||||
|
||||
@@ -600,6 +643,14 @@ public:
|
||||
SeriesString(aValue,aString,kBinarySet,0,2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute a counter string in hex format for the given value.
|
||||
*
|
||||
* @update rickg 6June2000
|
||||
*
|
||||
* @param aValue -- cardinal value of string
|
||||
* @param aString -- will hold result
|
||||
*/
|
||||
static void HexString(PRInt32 aValue,nsString& aString) {
|
||||
static char kHexSet[]="0123456789ABCDEF";
|
||||
|
||||
@@ -608,6 +659,14 @@ public:
|
||||
SeriesString(aValue,aString,kHexSet,0,16);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute a counter string in the roman style for the given value.
|
||||
*
|
||||
* @update rickg 6June2000
|
||||
*
|
||||
* @param aValue -- cardinal value of string
|
||||
* @param aString -- will hold result
|
||||
*/
|
||||
static void RomanString(PRInt32 aValue,nsString& aString) {
|
||||
static char digitsA[] = "ixcm";
|
||||
static char digitsB[] = "vld?";
|
||||
@@ -648,6 +707,14 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute a counter string in the alpha style for the given value.
|
||||
*
|
||||
* @update rickg 6June2000
|
||||
*
|
||||
* @param aValue -- cardinal value of string
|
||||
* @param aString -- will hold result
|
||||
*/
|
||||
static void AlphaString(PRInt32 aValue,nsString& aString) {
|
||||
static const char kAlphaSet[]="abcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
@@ -655,6 +722,14 @@ public:
|
||||
SeriesString(aValue-1,aString,kAlphaSet,-1,26);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute a counter string in the footnote style for the given value.
|
||||
*
|
||||
* @update rickg 6June2000
|
||||
*
|
||||
* @param aValue -- cardinal value of string
|
||||
* @param aString -- will hold result
|
||||
*/
|
||||
static void FootnoteString(PRInt32 aValue,nsString& aString) {
|
||||
static char kFootnoteSet[]="abcdefg";
|
||||
|
||||
@@ -822,7 +897,7 @@ nsIParserNode* nsDTDContext::Pop(nsEntryStack *&aChildStyleStack) {
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @update harishd 04/07/00
|
||||
@@ -1024,21 +1099,67 @@ nsIParserNode* nsDTDContext::RemoveStyle(eHTMLTags aTag){
|
||||
*/
|
||||
nsresult nsDTDContext::GetNodeRecycler(CNodeRecycler*& aNodeRecycler){
|
||||
nsresult result=NS_OK;
|
||||
if(!mNodeRecycler) {
|
||||
mNodeRecycler=new CNodeRecycler();
|
||||
if(mNodeRecycler==0) result=NS_ERROR_OUT_OF_MEMORY;
|
||||
if(!gNodeRecycler) {
|
||||
gNodeRecycler=new CNodeRecycler();
|
||||
if(gNodeRecycler==0) result=NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
aNodeRecycler=mNodeRecycler;
|
||||
aNodeRecycler=gNodeRecycler;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* This gets called someone wants to create a token of the given type.
|
||||
*
|
||||
* @update hairshd 04/10/00
|
||||
* @update rickg 16June2000
|
||||
* @param aType
|
||||
* @param aTag
|
||||
* @param aString
|
||||
* @return new CToken* or 0.
|
||||
*/
|
||||
void nsDTDContext::FreeNodeRecycler(){
|
||||
if(mNodeRecycler) {
|
||||
delete mNodeRecycler;
|
||||
CTokenRecycler* nsDTDContext::GetTokenRecycler(void) {
|
||||
if(!gTokenRecycler) {
|
||||
gTokenRecycler = new CTokenRecycler();
|
||||
}
|
||||
return gTokenRecycler;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @update rickg 16June2000
|
||||
*/
|
||||
void nsDTDContext::RecycleNode(nsCParserNode* aNode) {
|
||||
nsresult result=NS_OK;
|
||||
|
||||
if(aNode) {
|
||||
if(!gNodeRecycler)
|
||||
result=nsDTDContext::GetNodeRecycler(gNodeRecycler);
|
||||
|
||||
if(NS_SUCCEEDED(result)) {
|
||||
if(!gTokenRecycler)
|
||||
GetTokenRecycler();
|
||||
gNodeRecycler->RecycleNode(aNode,gTokenRecycler);
|
||||
}
|
||||
else {
|
||||
delete aNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This gets called when the parser module is getting unloaded
|
||||
*
|
||||
* @return nada
|
||||
*/
|
||||
void nsDTDContext::ReleaseGlobalObjects(){
|
||||
if(gNodeRecycler) {
|
||||
delete gNodeRecycler;
|
||||
gNodeRecycler=0;
|
||||
}
|
||||
if(gTokenRecycler) {
|
||||
delete gTokenRecycler;
|
||||
gTokenRecycler=0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1124,10 +1245,14 @@ void CTokenRecycler::RecycleToken(CToken* aToken) {
|
||||
|
||||
|
||||
/**
|
||||
* Let's get this code ready to be reused by all the contexts.
|
||||
*
|
||||
* @update vidur 11/12/98
|
||||
* @param
|
||||
* @return
|
||||
* @update rickg 12June2000
|
||||
* @param aType -- tells you the type of token to create
|
||||
* @param aTag -- tells you the type of tag to init with this token
|
||||
* @param aString -- gives a default string value for the token
|
||||
*
|
||||
* @return ptr to new token (or 0).
|
||||
*/
|
||||
CToken* CTokenRecycler::CreateTokenOfType(eHTMLTokenTypes aType,eHTMLTags aTag, const nsString& aString) {
|
||||
|
||||
@@ -1164,10 +1289,13 @@ CToken* CTokenRecycler::CreateTokenOfType(eHTMLTokenTypes aType,eHTMLTags aTag,
|
||||
}
|
||||
|
||||
/**
|
||||
* Let's get this code ready to be reused by all the contexts.
|
||||
*
|
||||
* @update vidur 11/12/98
|
||||
* @param
|
||||
* @return
|
||||
* @update rickg 12June2000
|
||||
* @param aType -- tells you the type of token to create
|
||||
* @param aTag -- tells you the type of tag to init with this token
|
||||
*
|
||||
* @return ptr to new token (or 0).
|
||||
*/
|
||||
CToken* CTokenRecycler::CreateTokenOfType(eHTMLTokenTypes aType,eHTMLTags aTag) {
|
||||
|
||||
|
||||
@@ -206,6 +206,56 @@ public:
|
||||
PRInt32 mOrdinal;
|
||||
};
|
||||
|
||||
/************************************************************************
|
||||
CTokenRecycler class implementation.
|
||||
This class is used to recycle tokens.
|
||||
By using this simple class, we cut WAY down on the number of tokens
|
||||
that get created during the run of the system.
|
||||
************************************************************************/
|
||||
class CTokenRecycler : public nsITokenRecycler {
|
||||
public:
|
||||
|
||||
// enum {eCacheMaxSize=100};
|
||||
|
||||
CTokenRecycler();
|
||||
virtual ~CTokenRecycler();
|
||||
virtual void RecycleToken(CToken* aToken);
|
||||
virtual CToken* CreateTokenOfType(eHTMLTokenTypes aType,eHTMLTags aTag, const nsString& aString);
|
||||
virtual CToken* CreateTokenOfType(eHTMLTokenTypes aType,eHTMLTags aTag);
|
||||
|
||||
protected:
|
||||
nsDeque* mTokenCache[eToken_last-1];
|
||||
nsString mEmpty;
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
int mTotals[eToken_last-1];
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
/************************************************************************
|
||||
CNodeRecycler class implementation.
|
||||
This class is used to recycle nodes.
|
||||
By using this simple class, we cut down on the number of nodes
|
||||
that get created during the run of the system.
|
||||
************************************************************************/
|
||||
|
||||
class CNodeRecycler {
|
||||
public:
|
||||
|
||||
CNodeRecycler();
|
||||
virtual ~CNodeRecycler();
|
||||
virtual nsCParserNode* CreateNode(void);
|
||||
virtual void RecycleNode(nsCParserNode* aNode,nsITokenRecycler* aTokenRecycler=0);
|
||||
|
||||
protected:
|
||||
nsDeque mSharedNodes;
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
PRInt32 gNodeCount;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
/************************************************************************
|
||||
The dtdcontext class defines an ordered list of tags (a context).
|
||||
@@ -240,7 +290,9 @@ public:
|
||||
nsIParserNode* RemoveStyle(eHTMLTags aTag);
|
||||
|
||||
nsresult GetNodeRecycler(CNodeRecycler*& aNodeRecycler);
|
||||
static void FreeNodeRecycler(void);
|
||||
void RecycleNode(nsCParserNode *aNode);
|
||||
CTokenRecycler* GetTokenRecycler(void);
|
||||
static void ReleaseGlobalObjects(void);
|
||||
|
||||
CNamedEntity* RegisterEntity(const nsString& aName,const nsString& aValue);
|
||||
CNamedEntity* GetEntity(const nsString& aName)const;
|
||||
@@ -256,7 +308,8 @@ public:
|
||||
PRBool mTransitional;
|
||||
PRBool mHadDocTypeDecl;
|
||||
|
||||
static CNodeRecycler* mNodeRecycler;
|
||||
static CNodeRecycler *gNodeRecycler;
|
||||
static CTokenRecycler *gTokenRecycler;
|
||||
|
||||
CTableState *mTableStates;
|
||||
PRInt32 mCounters[NS_HTML_TAG_MAX];
|
||||
@@ -282,55 +335,6 @@ public:
|
||||
};
|
||||
|
||||
|
||||
/************************************************************************
|
||||
CTokenRecycler class implementation.
|
||||
This class is used to recycle tokens.
|
||||
By using this simple class, we cut WAY down on the number of tokens
|
||||
that get created during the run of the system.
|
||||
************************************************************************/
|
||||
class CTokenRecycler : public nsITokenRecycler {
|
||||
public:
|
||||
|
||||
// enum {eCacheMaxSize=100};
|
||||
|
||||
CTokenRecycler();
|
||||
virtual ~CTokenRecycler();
|
||||
virtual void RecycleToken(CToken* aToken);
|
||||
virtual CToken* CreateTokenOfType(eHTMLTokenTypes aType,eHTMLTags aTag, const nsString& aString);
|
||||
virtual CToken* CreateTokenOfType(eHTMLTokenTypes aType,eHTMLTags aTag);
|
||||
|
||||
protected:
|
||||
nsDeque* mTokenCache[eToken_last-1];
|
||||
nsString mEmpty;
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
int mTotals[eToken_last-1];
|
||||
#endif
|
||||
};
|
||||
|
||||
/************************************************************************
|
||||
CNodeRecycler class implementation.
|
||||
This class is used to recycle nodes.
|
||||
By using this simple class, we cut down on the number of nodes
|
||||
that get created during the run of the system.
|
||||
************************************************************************/
|
||||
|
||||
class CNodeRecycler {
|
||||
public:
|
||||
|
||||
CNodeRecycler();
|
||||
virtual ~CNodeRecycler();
|
||||
virtual nsCParserNode* CreateNode(void);
|
||||
virtual void RecycleNode(nsCParserNode* aNode,nsITokenRecycler* aTokenRecycler=0);
|
||||
|
||||
protected:
|
||||
nsDeque mSharedNodes;
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
PRInt32 gNodeCount;
|
||||
#endif
|
||||
};
|
||||
|
||||
/************************************************************************
|
||||
ITagHandler class offers an API for taking care of specific tokens.
|
||||
************************************************************************/
|
||||
|
||||
@@ -900,7 +900,7 @@ nsresult ConsumeComment(PRUnichar aChar, nsScanner& aScanner,nsString& aString)
|
||||
|
||||
while((NS_OK==result)) {
|
||||
theCurrOffset=theBuffer.FindChar(kGreaterThan,PR_TRUE,theCurrOffset);
|
||||
if(theCurrOffset>kNotFound) {
|
||||
if(kNotFound!=theCurrOffset) {
|
||||
theCurrOffset++;
|
||||
aChar=theBuffer[theCurrOffset-3];
|
||||
if(kMinus==aChar) {
|
||||
@@ -955,7 +955,7 @@ nsresult ConsumeComment(PRUnichar aChar, nsScanner& aScanner,nsString& aString)
|
||||
* Consume the identifier portion of the comment.
|
||||
* Note that we've already eaten the "<!" portion.
|
||||
*
|
||||
* @update gess 1/27/99
|
||||
* @update gess 16June2000
|
||||
* @param aChar -- last char consumed from stream
|
||||
* @param aScanner -- controller of underlying input source
|
||||
* @return error result
|
||||
@@ -965,11 +965,11 @@ nsresult CCommentToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aMo
|
||||
|
||||
switch(aMode) {
|
||||
case eDTDMode_strict:
|
||||
ConsumeStrictComment(aChar,aScanner,mTextValue);
|
||||
result=ConsumeStrictComment(aChar,aScanner,mTextValue);
|
||||
break;
|
||||
case eDTDMode_transitional:
|
||||
default:
|
||||
ConsumeComment(aChar,aScanner,mTextValue);
|
||||
result=ConsumeComment(aChar,aScanner,mTextValue);
|
||||
break;
|
||||
} //switch
|
||||
|
||||
@@ -977,7 +977,7 @@ nsresult CCommentToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aMo
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
/*
|
||||
*
|
||||
*
|
||||
* @update gess 3/25/98
|
||||
|
||||
@@ -104,10 +104,8 @@ public:
|
||||
|
||||
nsIDTD* theDTD;
|
||||
|
||||
#if 1
|
||||
NS_NewNavHTMLDTD(&theDTD); //do this as a default HTML DTD...
|
||||
mDTDDeque.Push(theDTD);
|
||||
#endif
|
||||
|
||||
NS_NewOtherHTMLDTD(&mOtherDTD); //do this as the default DTD for strict documents...
|
||||
mDTDDeque.Push(mOtherDTD);
|
||||
@@ -627,16 +625,6 @@ void DetermineParseMode(nsString& aBuffer,nsDTDMode& aParseMode,eParserDocType&
|
||||
}
|
||||
|
||||
} //if
|
||||
else {
|
||||
PRInt32 thePos=aBuffer.Find("HTML",PR_TRUE,1,50);
|
||||
if(kNotFound!=thePos) {
|
||||
aDocType=eHTML4Text;
|
||||
PRInt32 theIDPos=aBuffer.Find("PublicID",thePos);
|
||||
if(kNotFound==theIDPos)
|
||||
theIDPos=aBuffer.Find("SystemID",thePos);
|
||||
aParseMode=(kNotFound==theIDPos) ? eDTDMode_quirks : eDTDMode_strict;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(kNotFound<(theIndex=aBuffer.Find("?XML",PR_TRUE,0,128))) {
|
||||
aParseMode=eDTDMode_strict;
|
||||
@@ -731,6 +719,13 @@ PRBool FindSuitableDTD( CParserContext& aParserContext,nsString& aBuffer) {
|
||||
}
|
||||
|
||||
if(theBestDTD) {
|
||||
|
||||
//#define FORCE_HTML_THROUGH_STRICT_DTD
|
||||
#if FORCE_HTML_THROUGH_STRICT_DTD
|
||||
if(theBestDTD==gSharedObjects.mDTDDeque.ObjectAt(0))
|
||||
theBestDTD=(nsIDTD*)gSharedObjects.mDTDDeque.ObjectAt(1);
|
||||
#endif
|
||||
|
||||
theBestDTD->CreateNewInstance(&aParserContext.mDTD);
|
||||
return PR_TRUE;
|
||||
}
|
||||
@@ -755,7 +750,7 @@ nsresult nsParser::CreateCompatibleDTD(nsIDTD** aDTD,
|
||||
const nsString* aMimeType,
|
||||
nsDTDMode aDTDMode)
|
||||
{
|
||||
nsresult result=NS_OK;
|
||||
nsresult result=NS_OK;
|
||||
const nsCID* theDTDClassID=0;
|
||||
|
||||
/**
|
||||
@@ -1026,6 +1021,22 @@ nsresult nsParser::WillBuildModel(nsString& aFilename){
|
||||
nsString& theBuffer=mParserContext->mScanner->GetBuffer();
|
||||
DetermineParseMode(theBuffer,mParserContext->mDTDMode,mParserContext->mDocType,mParserContext->mMimeType);
|
||||
|
||||
#define DISABLE_TRANSITIONAL_MODE
|
||||
#ifdef DISABLE_TRANSITIONAL_MODE
|
||||
|
||||
/********************************************************************************************
|
||||
The following code is here because to deal with a nasty backward compatibility problem.
|
||||
The composer product emits <doctype HTML 4.0 Transitional> for the documents it creates,
|
||||
but the documents aren't really compliant. To prevent lots of pages from breaking, well
|
||||
disable proper handling of Transitional doctypes and use quirks mode instead. If lucky,
|
||||
we'll get to add a pref to allow power users to get the right answer.
|
||||
********************************************************************************************/
|
||||
|
||||
if(eDTDMode_transitional==mParserContext->mDTDMode) {
|
||||
mParserContext->mDTDMode=eDTDMode_quirks;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(PR_TRUE==FindSuitableDTD(*mParserContext,theBuffer)) {
|
||||
mParserContext->mDTD->WillBuildModel( *mParserContext,mSink);
|
||||
}//if
|
||||
|
||||
@@ -211,7 +211,7 @@ nsParserModule::Shutdown()
|
||||
nsHTMLTokenizer::FreeTokenRecycler();
|
||||
nsXMLTokenizer::FreeTokenRecycler();
|
||||
nsExpatTokenizer::FreeTokenRecycler();
|
||||
nsDTDContext::FreeNodeRecycler();
|
||||
nsDTDContext::ReleaseGlobalObjects();
|
||||
nsParser::FreeSharedObjects();
|
||||
mInitialized = PR_FALSE;
|
||||
COtherDTD::ReleaseTable();
|
||||
|
||||
Reference in New Issue
Block a user