зеркало из https://github.com/mozilla/pjs.git
fixed beta2 bugs: 38203, 38228, 39520, 40060, and WIP for bug 40190; also enabled debug code for automated regression testing of content models.
This commit is contained in:
Родитель
8be92fb914
Коммит
8c6a6b0cb1
|
@ -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 <fstream.h>
|
||||
#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;theIndex<theCount;theIndex++){
|
||||
const nsString& theKey=aNode.GetKeyAt(theIndex);
|
||||
if(theKey.EqualsWithConversion("ENTITY",PR_TRUE)) {
|
||||
const nsString& theName=aNode.GetValueAt(theIndex);
|
||||
theNamePtr=&theName;
|
||||
}
|
||||
else if(theKey.EqualsWithConversion("VALUE",PR_TRUE)) {
|
||||
//store the named enity with the context...
|
||||
const nsString& theValue=aNode.GetValueAt(theIndex);
|
||||
theValuePtr=&theValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(theNamePtr && theValuePtr) {
|
||||
mBodyContext->RegisterEntity(*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();
|
||||
|
|
|
@ -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;attr<aCount;attr++){
|
||||
if((eHTMLTag_unknown!=theSkipTarget) && mSkippedContent.GetSize())
|
||||
theToken=(CToken*)mSkippedContent.PopFront();
|
||||
else theToken=mTokenizer->PopToken();
|
||||
theToken=mTokenizer->PopToken();
|
||||
if(theToken) {
|
||||
// Sanitize the key for it might contain some non-alpha-non-digit characters
|
||||
// at its end. Ex. <OPTION SELECTED/> - 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;aIndex<aMax;aIndex++){
|
||||
CHTMLToken* theNextToken=(CHTMLToken*)mSkippedContent.PopFront();
|
||||
|
||||
eHTMLTokenTypes theTokenType=(eHTMLTokenTypes)theNextToken->GetTokenType();
|
||||
|
||||
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...
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/**********************************************************
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
* Pierre Phaneuf <pp@ludusdesign.com>
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#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;theIndex<theCount;theIndex++) {
|
||||
CNamedEntity *theResult=(CNamedEntity*)mEntities.ObjectAt(theIndex);
|
||||
if(theResult && theResult->mName.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(0<aValue) {
|
||||
|
||||
while(root && aValue) {
|
||||
if(temp=aValue/root) {
|
||||
if (div=temp/100) {//start with hundreds part
|
||||
aString.AppendWithConversion(ones[div]);
|
||||
aString.AppendWithConversion(bases[1]);
|
||||
}
|
||||
modu=(temp%10);
|
||||
if (div=((temp%100)/10)) {
|
||||
if (div<2) {
|
||||
aString.AppendWithConversion(teens[modu]);
|
||||
modu=0;
|
||||
}
|
||||
else aString.AppendWithConversion(tens[div]);
|
||||
}
|
||||
if (modu)
|
||||
aString.AppendWithConversion(ones[modu]); //do remainder
|
||||
aValue-=(temp*root);
|
||||
if (expn>1)
|
||||
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;digitPos<len;digitPos++) {
|
||||
romanPos--;
|
||||
switch(decStr[digitPos]) {
|
||||
case '0': break;
|
||||
case '3': aString.AppendWithConversion(digitsA[romanPos]);
|
||||
case '2': aString.AppendWithConversion(digitsA[romanPos]);
|
||||
case '1': aString.AppendWithConversion(digitsA[romanPos]);
|
||||
break;
|
||||
case '4': aString.AppendWithConversion(digitsA[romanPos]);
|
||||
case '5': case '6':
|
||||
case '7': case '8':
|
||||
aString.AppendWithConversion(digitsB[romanPos]);
|
||||
for(n=0;n<(decStr[digitPos]-'5');n++)
|
||||
aString.AppendWithConversion(digitsA[romanPos]);
|
||||
break;
|
||||
case '9':
|
||||
aString.AppendWithConversion(digitsA[romanPos]);
|
||||
aString.AppendWithConversion(digitsA[romanPos]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void AlphaString(PRInt32 aValue,nsString& aString) {
|
||||
static const char kAlphaSet[]="abcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
if (0<aValue)
|
||||
SeriesString(aValue-1,aString,kAlphaSet,-1,26);
|
||||
}
|
||||
|
||||
static void FootnoteString(PRInt32 aValue,nsString& aString) {
|
||||
static char kFootnoteSet[]="abcdefg";
|
||||
|
||||
PRBool negative=(aValue<0);
|
||||
int seriesLen = strlen (kFootnoteSet) - 1;
|
||||
int count=0;
|
||||
int repCount=0;
|
||||
int modChar=0;
|
||||
|
||||
aString.Truncate();
|
||||
|
||||
aValue=abs(aValue);
|
||||
repCount=((aValue-1)/seriesLen);
|
||||
modChar=aValue-(repCount*seriesLen);
|
||||
|
||||
for(count=0;count<=repCount;count++) {
|
||||
aString.AppendWithConversion(kFootnoteSet[modChar]);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
const char* mUserSeries;
|
||||
eNumFormat mFormat;
|
||||
PRBool mCase;
|
||||
PRInt32 mValue;
|
||||
int mUserBase;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess 11May2000
|
||||
|
@ -402,22 +688,81 @@ void nsDTDContext::ResetCounters(void) {
|
|||
memset(mCounters,0,sizeof(mCounters));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess 11May2000
|
||||
*/
|
||||
PRInt32 nsDTDContext::IncrementCounter(eHTMLTags aTag) {
|
||||
PRInt32 result=++mCounters[aTag];
|
||||
/**********************************************************
|
||||
@update: rickg 17May2000
|
||||
|
||||
Call this to handle counter attributes:
|
||||
name="group"
|
||||
value="nnn"
|
||||
noincr="?"
|
||||
format="alpha|dec|footnote|hex|roman|spoken"
|
||||
|
||||
returns the newly incremented value for the (determined) group.
|
||||
**********************************************************/
|
||||
PRInt32 nsDTDContext::IncrementCounter(eHTMLTags aTag,nsCParserNode& aNode,nsString& aResult) {
|
||||
|
||||
PRInt32 result=0;
|
||||
|
||||
PRInt32 theIndex=0;
|
||||
PRInt32 theNewValue=-1; //-1 is interpreted to mean "don't reset the counter sequence.
|
||||
PRInt32 theIncrValue=1; //this may get set to 0 if we see a "noincr" key.
|
||||
PRInt32 theCount=aNode.GetAttributeCount();
|
||||
CNamedEntity *theEntity=0;
|
||||
|
||||
CAbacus::eNumFormat theNumFormat=CAbacus::eDecimal;
|
||||
|
||||
for(theIndex=0;theIndex<theCount;theIndex++){
|
||||
const nsString& theKey=aNode.GetKeyAt(theIndex);
|
||||
const nsString& theValue=aNode.GetValueAt(theIndex);
|
||||
|
||||
if(theKey.EqualsWithConversion("name",PR_TRUE)){
|
||||
theEntity=GetEntity(theValue);
|
||||
if(!theEntity) {
|
||||
theEntity=RegisterEntity(theValue,theValue);
|
||||
theEntity->mOrdinal=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;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
|
@ -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((2<theLen) && (theFirst==theLast) && (kQuote==theFirst)) {
|
||||
aName.Mid(mName,1,theLen-2);
|
||||
}
|
||||
else mName=aName;
|
||||
|
||||
theFirst=aValue.First();
|
||||
theLast=aValue.Last();
|
||||
theLen=aValue.Length();
|
||||
if((2<theLen) && (theFirst==theLast) && (kQuote==theFirst)) {
|
||||
aValue.Mid(mValue,1,theLen-2);
|
||||
}
|
||||
else mValue=aValue;
|
||||
|
||||
}
|
||||
|
||||
nsAutoString mName;
|
||||
nsAutoString mValue;
|
||||
PRInt32 mOrdinal;
|
||||
};
|
||||
|
||||
|
||||
/************************************************************************
|
||||
The dtdcontext class defines an ordered list of tags (a context).
|
||||
************************************************************************/
|
||||
|
||||
class nsDTDContext {
|
||||
public:
|
||||
nsDTDContext();
|
||||
~nsDTDContext();
|
||||
nsDTDContext();
|
||||
~nsDTDContext();
|
||||
|
||||
void Push(const nsIParserNode* aNode,nsEntryStack* aStyleStack=0);
|
||||
nsIParserNode* Pop(nsEntryStack*& aChildStack);
|
||||
|
@ -209,9 +242,11 @@ public:
|
|||
nsresult GetNodeRecycler(CNodeRecycler*& aNodeRecycler);
|
||||
static void FreeNodeRecycler(void);
|
||||
|
||||
CNamedEntity* RegisterEntity(const nsString& aName,const nsString& aValue);
|
||||
CNamedEntity* GetEntity(const nsString& aName)const;
|
||||
|
||||
void ResetCounters(void);
|
||||
void ResetCounter(eHTMLTags aTag,PRInt32 aNewValue);
|
||||
PRInt32 IncrementCounter(eHTMLTags aTag);
|
||||
PRInt32 IncrementCounter(eHTMLTags aTag,nsCParserNode& aNode,nsString& aResult);
|
||||
|
||||
nsEntryStack mStack; //this will hold a list of tagentries...
|
||||
PRInt32 mResidualStyleCount;
|
||||
|
@ -221,8 +256,10 @@ public:
|
|||
|
||||
static CNodeRecycler* mNodeRecycler;
|
||||
|
||||
CTableState *mTableStates;
|
||||
CTableState *mTableStates;
|
||||
PRInt32 mCounters[NS_HTML_TAG_MAX];
|
||||
nsString mDefaultEntity;
|
||||
nsDeque mEntities;
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
enum { eMaxTags = 100 };
|
||||
|
|
|
@ -630,7 +630,9 @@ nsresult nsHTMLTokenizer::ConsumeEntity(PRUnichar aChar,CToken*& aToken,nsScanne
|
|||
return ConsumeText(temp,aToken,aScanner);
|
||||
}//if
|
||||
if(aToken){
|
||||
#if 0
|
||||
nsString& theStr=aToken->GetStringValueXXX();
|
||||
|
||||
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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 <fstream.h>
|
||||
#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;theIndex<theCount;theIndex++){
|
||||
const nsString& theKey=aNode.GetKeyAt(theIndex);
|
||||
if(theKey.EqualsWithConversion("ENTITY",PR_TRUE)) {
|
||||
const nsString& theName=aNode.GetValueAt(theIndex);
|
||||
theNamePtr=&theName;
|
||||
}
|
||||
else if(theKey.EqualsWithConversion("VALUE",PR_TRUE)) {
|
||||
//store the named enity with the context...
|
||||
const nsString& theValue=aNode.GetValueAt(theIndex);
|
||||
theValuePtr=&theValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(theNamePtr && theValuePtr) {
|
||||
mBodyContext->RegisterEntity(*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();
|
||||
|
|
|
@ -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;attr<aCount;attr++){
|
||||
if((eHTMLTag_unknown!=theSkipTarget) && mSkippedContent.GetSize())
|
||||
theToken=(CToken*)mSkippedContent.PopFront();
|
||||
else theToken=mTokenizer->PopToken();
|
||||
theToken=mTokenizer->PopToken();
|
||||
if(theToken) {
|
||||
// Sanitize the key for it might contain some non-alpha-non-digit characters
|
||||
// at its end. Ex. <OPTION SELECTED/> - 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;aIndex<aMax;aIndex++){
|
||||
CHTMLToken* theNextToken=(CHTMLToken*)mSkippedContent.PopFront();
|
||||
|
||||
eHTMLTokenTypes theTokenType=(eHTMLTokenTypes)theNextToken->GetTokenType();
|
||||
|
||||
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...
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/**********************************************************
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
* Pierre Phaneuf <pp@ludusdesign.com>
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#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;theIndex<theCount;theIndex++) {
|
||||
CNamedEntity *theResult=(CNamedEntity*)mEntities.ObjectAt(theIndex);
|
||||
if(theResult && theResult->mName.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(0<aValue) {
|
||||
|
||||
while(root && aValue) {
|
||||
if(temp=aValue/root) {
|
||||
if (div=temp/100) {//start with hundreds part
|
||||
aString.AppendWithConversion(ones[div]);
|
||||
aString.AppendWithConversion(bases[1]);
|
||||
}
|
||||
modu=(temp%10);
|
||||
if (div=((temp%100)/10)) {
|
||||
if (div<2) {
|
||||
aString.AppendWithConversion(teens[modu]);
|
||||
modu=0;
|
||||
}
|
||||
else aString.AppendWithConversion(tens[div]);
|
||||
}
|
||||
if (modu)
|
||||
aString.AppendWithConversion(ones[modu]); //do remainder
|
||||
aValue-=(temp*root);
|
||||
if (expn>1)
|
||||
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;digitPos<len;digitPos++) {
|
||||
romanPos--;
|
||||
switch(decStr[digitPos]) {
|
||||
case '0': break;
|
||||
case '3': aString.AppendWithConversion(digitsA[romanPos]);
|
||||
case '2': aString.AppendWithConversion(digitsA[romanPos]);
|
||||
case '1': aString.AppendWithConversion(digitsA[romanPos]);
|
||||
break;
|
||||
case '4': aString.AppendWithConversion(digitsA[romanPos]);
|
||||
case '5': case '6':
|
||||
case '7': case '8':
|
||||
aString.AppendWithConversion(digitsB[romanPos]);
|
||||
for(n=0;n<(decStr[digitPos]-'5');n++)
|
||||
aString.AppendWithConversion(digitsA[romanPos]);
|
||||
break;
|
||||
case '9':
|
||||
aString.AppendWithConversion(digitsA[romanPos]);
|
||||
aString.AppendWithConversion(digitsA[romanPos]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void AlphaString(PRInt32 aValue,nsString& aString) {
|
||||
static const char kAlphaSet[]="abcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
if (0<aValue)
|
||||
SeriesString(aValue-1,aString,kAlphaSet,-1,26);
|
||||
}
|
||||
|
||||
static void FootnoteString(PRInt32 aValue,nsString& aString) {
|
||||
static char kFootnoteSet[]="abcdefg";
|
||||
|
||||
PRBool negative=(aValue<0);
|
||||
int seriesLen = strlen (kFootnoteSet) - 1;
|
||||
int count=0;
|
||||
int repCount=0;
|
||||
int modChar=0;
|
||||
|
||||
aString.Truncate();
|
||||
|
||||
aValue=abs(aValue);
|
||||
repCount=((aValue-1)/seriesLen);
|
||||
modChar=aValue-(repCount*seriesLen);
|
||||
|
||||
for(count=0;count<=repCount;count++) {
|
||||
aString.AppendWithConversion(kFootnoteSet[modChar]);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
const char* mUserSeries;
|
||||
eNumFormat mFormat;
|
||||
PRBool mCase;
|
||||
PRInt32 mValue;
|
||||
int mUserBase;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess 11May2000
|
||||
|
@ -402,22 +688,81 @@ void nsDTDContext::ResetCounters(void) {
|
|||
memset(mCounters,0,sizeof(mCounters));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess 11May2000
|
||||
*/
|
||||
PRInt32 nsDTDContext::IncrementCounter(eHTMLTags aTag) {
|
||||
PRInt32 result=++mCounters[aTag];
|
||||
/**********************************************************
|
||||
@update: rickg 17May2000
|
||||
|
||||
Call this to handle counter attributes:
|
||||
name="group"
|
||||
value="nnn"
|
||||
noincr="?"
|
||||
format="alpha|dec|footnote|hex|roman|spoken"
|
||||
|
||||
returns the newly incremented value for the (determined) group.
|
||||
**********************************************************/
|
||||
PRInt32 nsDTDContext::IncrementCounter(eHTMLTags aTag,nsCParserNode& aNode,nsString& aResult) {
|
||||
|
||||
PRInt32 result=0;
|
||||
|
||||
PRInt32 theIndex=0;
|
||||
PRInt32 theNewValue=-1; //-1 is interpreted to mean "don't reset the counter sequence.
|
||||
PRInt32 theIncrValue=1; //this may get set to 0 if we see a "noincr" key.
|
||||
PRInt32 theCount=aNode.GetAttributeCount();
|
||||
CNamedEntity *theEntity=0;
|
||||
|
||||
CAbacus::eNumFormat theNumFormat=CAbacus::eDecimal;
|
||||
|
||||
for(theIndex=0;theIndex<theCount;theIndex++){
|
||||
const nsString& theKey=aNode.GetKeyAt(theIndex);
|
||||
const nsString& theValue=aNode.GetValueAt(theIndex);
|
||||
|
||||
if(theKey.EqualsWithConversion("name",PR_TRUE)){
|
||||
theEntity=GetEntity(theValue);
|
||||
if(!theEntity) {
|
||||
theEntity=RegisterEntity(theValue,theValue);
|
||||
theEntity->mOrdinal=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;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
|
@ -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((2<theLen) && (theFirst==theLast) && (kQuote==theFirst)) {
|
||||
aName.Mid(mName,1,theLen-2);
|
||||
}
|
||||
else mName=aName;
|
||||
|
||||
theFirst=aValue.First();
|
||||
theLast=aValue.Last();
|
||||
theLen=aValue.Length();
|
||||
if((2<theLen) && (theFirst==theLast) && (kQuote==theFirst)) {
|
||||
aValue.Mid(mValue,1,theLen-2);
|
||||
}
|
||||
else mValue=aValue;
|
||||
|
||||
}
|
||||
|
||||
nsAutoString mName;
|
||||
nsAutoString mValue;
|
||||
PRInt32 mOrdinal;
|
||||
};
|
||||
|
||||
|
||||
/************************************************************************
|
||||
The dtdcontext class defines an ordered list of tags (a context).
|
||||
************************************************************************/
|
||||
|
||||
class nsDTDContext {
|
||||
public:
|
||||
nsDTDContext();
|
||||
~nsDTDContext();
|
||||
nsDTDContext();
|
||||
~nsDTDContext();
|
||||
|
||||
void Push(const nsIParserNode* aNode,nsEntryStack* aStyleStack=0);
|
||||
nsIParserNode* Pop(nsEntryStack*& aChildStack);
|
||||
|
@ -209,9 +242,11 @@ public:
|
|||
nsresult GetNodeRecycler(CNodeRecycler*& aNodeRecycler);
|
||||
static void FreeNodeRecycler(void);
|
||||
|
||||
CNamedEntity* RegisterEntity(const nsString& aName,const nsString& aValue);
|
||||
CNamedEntity* GetEntity(const nsString& aName)const;
|
||||
|
||||
void ResetCounters(void);
|
||||
void ResetCounter(eHTMLTags aTag,PRInt32 aNewValue);
|
||||
PRInt32 IncrementCounter(eHTMLTags aTag);
|
||||
PRInt32 IncrementCounter(eHTMLTags aTag,nsCParserNode& aNode,nsString& aResult);
|
||||
|
||||
nsEntryStack mStack; //this will hold a list of tagentries...
|
||||
PRInt32 mResidualStyleCount;
|
||||
|
@ -221,8 +256,10 @@ public:
|
|||
|
||||
static CNodeRecycler* mNodeRecycler;
|
||||
|
||||
CTableState *mTableStates;
|
||||
CTableState *mTableStates;
|
||||
PRInt32 mCounters[NS_HTML_TAG_MAX];
|
||||
nsString mDefaultEntity;
|
||||
nsDeque mEntities;
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
enum { eMaxTags = 100 };
|
||||
|
|
|
@ -630,7 +630,9 @@ nsresult nsHTMLTokenizer::ConsumeEntity(PRUnichar aChar,CToken*& aToken,nsScanne
|
|||
return ConsumeText(temp,aToken,aScanner);
|
||||
}//if
|
||||
if(aToken){
|
||||
#if 0
|
||||
nsString& theStr=aToken->GetStringValueXXX();
|
||||
|
||||
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
|
||||
|
|
|
@ -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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче