зеркало из 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 ENABLE_CRC
|
||||||
//#define RICKG_DEBUG
|
//#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 ALLOW_TR_AS_CHILD_OF_TABLE //by setting this to true, TR is allowable directly in TABLE.
|
||||||
|
|
||||||
|
#define ENABLE_RESIDUALSTYLE
|
||||||
|
|
||||||
#ifdef RICKG_DEBUG
|
#ifdef RICKG_DEBUG
|
||||||
#include <fstream.h>
|
#include <fstream.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -266,12 +267,24 @@ CNavDTD::~CNavDTD(){
|
||||||
/**
|
/**
|
||||||
* Call this method if you want the DTD to construct a fresh
|
* Call this method if you want the DTD to construct a fresh
|
||||||
* instance of itself.
|
* instance of itself.
|
||||||
* @update gess7/23/98
|
* @update gess 25May2000
|
||||||
* @param
|
* @param
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
nsresult CNavDTD::CreateNewInstance(nsIDTD** aInstancePtrResult){
|
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();
|
PRInt32 theCount=mBodyContext->GetCount();
|
||||||
eHTMLTags theGrandParentTag=mBodyContext->TagAt(theCount-2);
|
eHTMLTags theGrandParentTag=mBodyContext->TagAt(theCount-2);
|
||||||
PRInt32 theCounter=mBodyContext->IncrementCounter(theGrandParentTag);
|
|
||||||
|
nsAutoString theNumber;
|
||||||
nsString theNumber;
|
PRInt32 theCounter=mBodyContext->IncrementCounter(theGrandParentTag,aNode,theNumber);
|
||||||
theNumber.AppendInt(theCounter);
|
|
||||||
CTextToken theToken(theNumber);
|
CTextToken theToken(theNumber);
|
||||||
PRInt32 theLineNumber=0;
|
PRInt32 theLineNumber=0;
|
||||||
nsCParserNode theNode(&theToken,theLineNumber);
|
nsCParserNode theNode(&theToken,theLineNumber);
|
||||||
|
@ -838,6 +850,35 @@ nsresult CNavDTD::DidHandleStartTag(nsCParserNode& aNode,eHTMLTags aChildTag){
|
||||||
}
|
}
|
||||||
break;
|
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:
|
default:
|
||||||
break;
|
break;
|
||||||
}//switch
|
}//switch
|
||||||
|
@ -1846,6 +1887,27 @@ nsresult CNavDTD::HandleEntityToken(CToken* aToken) {
|
||||||
NS_PRECONDITION(0!=aToken,kNullToken);
|
NS_PRECONDITION(0!=aToken,kNullToken);
|
||||||
|
|
||||||
nsresult result=NS_OK;
|
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();
|
eHTMLTags theParentTag=mBodyContext->Last();
|
||||||
|
|
||||||
nsCParserNode* theNode=mNodeRecycler->CreateNode();
|
nsCParserNode* theNode=mNodeRecycler->CreateNode();
|
||||||
|
|
|
@ -4,24 +4,24 @@
|
||||||
* License Version 1.1 (the "License"); you may not use this file
|
* License Version 1.1 (the "License"); you may not use this file
|
||||||
* except in compliance with the License. You may obtain a copy of
|
* except in compliance with the License. You may obtain a copy of
|
||||||
* the License at http://www.mozilla.org/NPL/
|
* the License at http://www.mozilla.org/NPL/
|
||||||
*
|
*
|
||||||
* Software distributed under the License is distributed on an "AS
|
* Software distributed under the License is distributed on an "AS
|
||||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||||
* implied. See the License for the specific language governing
|
* implied. See the License for the specific language governing
|
||||||
* rights and limitations under the License.
|
* rights and limitations under the License.
|
||||||
*
|
*
|
||||||
* The Original Code is mozilla.org code.
|
* The Original Code is mozilla.org code.
|
||||||
*
|
*
|
||||||
* The Initial Developer of the Original Code is Netscape
|
* The Initial Developer of the Original Code is Netscape
|
||||||
* Communications Corporation. Portions created by Netscape are
|
* Communications Corporation. Portions created by Netscape are
|
||||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||||
* Rights Reserved.
|
* Rights Reserved.
|
||||||
*
|
*
|
||||||
* Contributor(s):
|
* Contributor(s):
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//#define ENABLE_CRC
|
//#define ENABLE_CRC
|
||||||
//#define RICKG_DEBUG
|
//#define RICKG_DEBUG
|
||||||
|
|
||||||
|
|
||||||
#include "nsDebug.h"
|
#include "nsDebug.h"
|
||||||
|
@ -131,7 +131,7 @@ NS_IMPL_RELEASE(COtherDTD)
|
||||||
* @param
|
* @param
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
COtherDTD::COtherDTD() : nsIDTD(), mMisplacedContent(0), mSkippedContent(0), mSharedNodes(0) {
|
COtherDTD::COtherDTD() : nsIDTD(), mSharedNodes(0) {
|
||||||
NS_INIT_REFCNT();
|
NS_INIT_REFCNT();
|
||||||
mSink = 0;
|
mSink = 0;
|
||||||
mParser=0;
|
mParser=0;
|
||||||
|
@ -141,14 +141,17 @@ COtherDTD::COtherDTD() : nsIDTD(), mMisplacedContent(0), mSkippedContent(0), mSh
|
||||||
mHasOpenHead=0;
|
mHasOpenHead=0;
|
||||||
mHasOpenForm=PR_FALSE;
|
mHasOpenForm=PR_FALSE;
|
||||||
mHasOpenMap=PR_FALSE;
|
mHasOpenMap=PR_FALSE;
|
||||||
mHeadContext=new nsDTDContext();
|
|
||||||
mBodyContext=new nsDTDContext();
|
mBodyContext=new nsDTDContext();
|
||||||
mFormContext=0;
|
|
||||||
mTokenizer=0;
|
mTokenizer=0;
|
||||||
mComputedCRC32=0;
|
mComputedCRC32=0;
|
||||||
mExpectedCRC32=0;
|
mExpectedCRC32=0;
|
||||||
mDTDState=NS_OK;
|
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");
|
char* theEnvString = PR_GetEnv("ENABLE_STRICT");
|
||||||
mEnableStrict=PRBool(theEnvString!=0);
|
mEnableStrict=PRBool(theEnvString!=0);
|
||||||
|
@ -280,7 +283,6 @@ const nsIID& COtherDTD::GetMostDerivedIID(void)const {
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
COtherDTD::~COtherDTD(){
|
COtherDTD::~COtherDTD(){
|
||||||
delete mHeadContext;
|
|
||||||
delete mBodyContext;
|
delete mBodyContext;
|
||||||
|
|
||||||
NS_IF_RELEASE(mTokenizer);
|
NS_IF_RELEASE(mTokenizer);
|
||||||
|
@ -336,7 +338,19 @@ NS_HTMLPARS nsresult NS_NewOtherHTMLDTD(nsIDTD** aInstancePtrResult) {
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
nsresult COtherDTD::CreateNewInstance(nsIDTD** aInstancePtrResult){
|
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_start:
|
||||||
case eToken_whitespace:
|
case eToken_whitespace:
|
||||||
case eToken_newline:
|
case eToken_newline:
|
||||||
|
case eToken_doctypeDecl:
|
||||||
result=HandleStartToken(theToken); break;
|
result=HandleStartToken(theToken); break;
|
||||||
|
|
||||||
case eToken_end:
|
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));
|
MOZ_TIMER_DEBUGLOG(("Start: Parse Time: COtherDTD::WillHandleStartTag(), this=%p\n", this));
|
||||||
START_TIMER()
|
START_TIMER()
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -762,20 +777,20 @@ nsresult COtherDTD::HandleStartToken(CToken* aToken) {
|
||||||
if(NS_OK==result) {
|
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:
|
case eHTMLTag_html:
|
||||||
if(!HasOpenContainer(theChildTag)) {
|
if(!HasOpenContainer(theChildTag)) {
|
||||||
mSink->OpenHTML(*theNode);
|
mSink->OpenHTML(*theNode);
|
||||||
mBodyContext->Push(theNode,0);
|
mBodyContext->Push(theNode,0);
|
||||||
}
|
}
|
||||||
theTagWasHandled=PR_TRUE;
|
theTagWasHandled=PR_TRUE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
CElement* theElement=gElementTable->mElements[theParent];
|
CElement* theElement=gElementTable->mElements[theParent];
|
||||||
if(theElement) {
|
if(theElement) {
|
||||||
result=theElement->HandleStartToken(theNode,theChildTag,mBodyContext,mSink);
|
result=theElement->HandleStartToken(theNode,theChildTag,mBodyContext,mSink);
|
||||||
|
@ -788,7 +803,7 @@ nsresult COtherDTD::HandleStartToken(CToken* aToken) {
|
||||||
DidHandleStartTag(*theNode,theChildTag);
|
DidHandleStartTag(*theNode,theChildTag);
|
||||||
}
|
}
|
||||||
|
|
||||||
} //if
|
} //if
|
||||||
}//if
|
}//if
|
||||||
|
|
||||||
RecycleNode(theNode);
|
RecycleNode(theNode);
|
||||||
|
@ -814,7 +829,7 @@ nsresult COtherDTD::HandleEndToken(CToken* aToken) {
|
||||||
nsresult result=NS_OK;
|
nsresult result=NS_OK;
|
||||||
eHTMLTags theChildTag=(eHTMLTags)aToken->GetTypeID();
|
eHTMLTags theChildTag=(eHTMLTags)aToken->GetTypeID();
|
||||||
|
|
||||||
#ifdef RICKG_DEBUG
|
#ifdef RICKG_DEBUG
|
||||||
WriteTokenToLog(aToken);
|
WriteTokenToLog(aToken);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -825,7 +840,7 @@ nsresult COtherDTD::HandleEndToken(CToken* aToken) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case eHTMLTag_script:
|
case eHTMLTag_script:
|
||||||
mHasOpenScript=PR_FALSE;
|
mHasOpenScript=PR_FALSE;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
PRInt32 theCount=mBodyContext->GetCount();
|
PRInt32 theCount=mBodyContext->GetCount();
|
||||||
|
@ -838,7 +853,7 @@ nsresult COtherDTD::HandleEndToken(CToken* aToken) {
|
||||||
nsCParserNode theNode((CHTMLToken*)aToken,mLineNumber);
|
nsCParserNode theNode((CHTMLToken*)aToken,mLineNumber);
|
||||||
result=theElement->HandleEndToken(&theNode,theChildTag,mBodyContext,mSink);
|
result=theElement->HandleEndToken(&theNode,theChildTag,mBodyContext,mSink);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -857,14 +872,12 @@ nsresult COtherDTD::CollectAttributes(nsCParserNode& aNode,eHTMLTags aTag,PRInt3
|
||||||
int attr=0;
|
int attr=0;
|
||||||
|
|
||||||
nsresult result=NS_OK;
|
nsresult result=NS_OK;
|
||||||
int theAvailTokenCount=mTokenizer->GetCount() + mSkippedContent.GetSize();
|
int theAvailTokenCount=mTokenizer->GetCount();
|
||||||
if(aCount<=theAvailTokenCount) {
|
if(aCount<=theAvailTokenCount) {
|
||||||
CToken* theToken=0;
|
CToken* theToken=0;
|
||||||
eHTMLTags theSkipTarget=gElementTable->mElements[aTag]->GetSkipTarget();
|
eHTMLTags theSkipTarget=gElementTable->mElements[aTag]->GetSkipTarget();
|
||||||
for(attr=0;attr<aCount;attr++){
|
for(attr=0;attr<aCount;attr++){
|
||||||
if((eHTMLTag_unknown!=theSkipTarget) && mSkippedContent.GetSize())
|
theToken=mTokenizer->PopToken();
|
||||||
theToken=(CToken*)mSkippedContent.PopFront();
|
|
||||||
else theToken=mTokenizer->PopToken();
|
|
||||||
if(theToken) {
|
if(theToken) {
|
||||||
// Sanitize the key for it might contain some non-alpha-non-digit characters
|
// 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",
|
// 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;
|
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...
|
The preceeding tables determine the set of elements each tag can contain...
|
||||||
|
|
|
@ -340,7 +340,6 @@ CLASS_EXPORT_HTMLPARS COtherDTD : public nsIDTD {
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
nsresult CollectAttributes(nsCParserNode& aNode,eHTMLTags aTag,PRInt32 aCount);
|
nsresult CollectAttributes(nsCParserNode& aNode,eHTMLTags aTag,PRInt32 aCount);
|
||||||
nsresult CollectSkippedContent(nsCParserNode& aNode,PRInt32& aCount);
|
|
||||||
nsresult WillHandleStartTag(CToken* aToken,eHTMLTags aChildTag,nsCParserNode& aNode);
|
nsresult WillHandleStartTag(CToken* aToken,eHTMLTags aChildTag,nsCParserNode& aNode);
|
||||||
nsresult DidHandleStartTag(nsCParserNode& aNode,eHTMLTags aChildTag);
|
nsresult DidHandleStartTag(nsCParserNode& aNode,eHTMLTags aChildTag);
|
||||||
nsCParserNode* CreateNode(void);
|
nsCParserNode* CreateNode(void);
|
||||||
|
@ -349,9 +348,7 @@ protected:
|
||||||
|
|
||||||
nsIHTMLContentSink* mSink;
|
nsIHTMLContentSink* mSink;
|
||||||
|
|
||||||
nsDTDContext* mHeadContext;
|
|
||||||
nsDTDContext* mBodyContext;
|
nsDTDContext* mBodyContext;
|
||||||
nsDTDContext* mFormContext;
|
|
||||||
PRBool mHasOpenForm;
|
PRBool mHasOpenForm;
|
||||||
PRBool mHasOpenMap;
|
PRBool mHasOpenMap;
|
||||||
PRInt32 mHasOpenHead;
|
PRInt32 mHasOpenHead;
|
||||||
|
@ -364,10 +361,7 @@ protected:
|
||||||
nsParser* mParser;
|
nsParser* mParser;
|
||||||
nsITokenizer* mTokenizer;
|
nsITokenizer* mTokenizer;
|
||||||
CTokenRecycler* mTokenRecycler;
|
CTokenRecycler* mTokenRecycler;
|
||||||
nsDeque mMisplacedContent;
|
|
||||||
nsDeque mSkippedContent;
|
|
||||||
PRBool mHasOpenScript;
|
PRBool mHasOpenScript;
|
||||||
PRBool mSaveBadTokens;
|
|
||||||
eHTMLTags mSkipTarget;
|
eHTMLTags mSkipTarget;
|
||||||
nsDeque mSharedNodes;
|
nsDeque mSharedNodes;
|
||||||
nsresult mDTDState;
|
nsresult mDTDState;
|
||||||
|
@ -377,9 +371,8 @@ protected:
|
||||||
PRUint32 mComputedCRC32;
|
PRUint32 mComputedCRC32;
|
||||||
PRUint32 mExpectedCRC32;
|
PRUint32 mExpectedCRC32;
|
||||||
nsAutoString mScratch; //used for various purposes; non-persistent
|
nsAutoString mScratch; //used for various purposes; non-persistent
|
||||||
PRBool mStyleHandlingEnabled;
|
|
||||||
PRBool mEnableStrict;
|
|
||||||
eParserDocType mDocType;
|
eParserDocType mDocType;
|
||||||
|
PRBool mEnableStrict;
|
||||||
|
|
||||||
#ifdef NS_DEBUG
|
#ifdef NS_DEBUG
|
||||||
PRInt32 gNodeCount;
|
PRInt32 gNodeCount;
|
||||||
|
|
|
@ -705,17 +705,19 @@ public:
|
||||||
case eHTMLTag_tr:
|
case eHTMLTag_tr:
|
||||||
case eHTMLTag_th:
|
case eHTMLTag_th:
|
||||||
|
|
||||||
if(!aContext->HasOpenContainer(eHTMLTag_tbody)) {
|
if(aContext->mTableStates) {
|
||||||
nsCParserNode* theNode=new nsCParserNode();
|
if(aContext->mTableStates->CanOpenTBody()) {
|
||||||
CToken* theToken=new CStartToken(eHTMLTag_tbody);
|
nsCParserNode* theNode=new nsCParserNode();
|
||||||
theNode->Init(theToken,0,0); //this will likely leak...
|
CToken* theToken=new CStartToken(eHTMLTag_tbody);
|
||||||
|
theNode->Init(theToken,0,0); //this will likely leak...
|
||||||
|
|
||||||
result=HandleStartToken(theNode,eHTMLTag_tbody,aContext,aSink);
|
result=HandleStartToken(theNode,eHTMLTag_tbody,aContext,aSink);
|
||||||
}
|
}
|
||||||
if(NS_SUCCEEDED(result)) {
|
if(NS_SUCCEEDED(result)) {
|
||||||
CElement *theElement=GetElement(eHTMLTag_tbody);
|
CElement *theElement=GetElement(eHTMLTag_tbody);
|
||||||
if(theElement) {
|
if(theElement) {
|
||||||
result=theElement->HandleStartToken(aNode,aTag,aContext,aSink);
|
result=theElement->HandleStartToken(aNode,aTag,aContext,aSink);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -738,6 +740,7 @@ public:
|
||||||
case eHTMLTag_caption:
|
case eHTMLTag_caption:
|
||||||
case eHTMLTag_col:
|
case eHTMLTag_col:
|
||||||
case eHTMLTag_colgroup:
|
case eHTMLTag_colgroup:
|
||||||
|
case eHTMLTag_tr:
|
||||||
case eHTMLTag_thead:
|
case eHTMLTag_thead:
|
||||||
case eHTMLTag_tfoot:
|
case eHTMLTag_tfoot:
|
||||||
case eHTMLTag_tbody:
|
case eHTMLTag_tbody:
|
||||||
|
@ -928,23 +931,26 @@ public:
|
||||||
return CElement::HandleStartToken(aNode,aTag,aContext,aSink);
|
return CElement::HandleStartToken(aNode,aTag,aContext,aSink);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**********************************************************
|
/**********************************************************
|
||||||
this gets called after each tag is opened in the given context
|
this gets called after each tag is opened in the given context
|
||||||
**********************************************************/
|
**********************************************************/
|
||||||
virtual nsresult OpenContainerInContext(nsIParserNode *aNode,eHTMLTags aTag,nsDTDContext *aContext,nsIHTMLContentSink *aSink) {
|
virtual nsresult OpenContainerInContext(nsIParserNode *aNode,eHTMLTags aTag,nsDTDContext *aContext,nsIHTMLContentSink *aSink) {
|
||||||
OpenContext(aNode,aTag,aContext,aSink);
|
OpenContext(aNode,aTag,aContext,aSink);
|
||||||
|
|
||||||
nsresult result=OpenContainer(aNode,aTag,aContext,aSink);
|
nsresult result=OpenContainer(aNode,aTag,aContext,aSink);
|
||||||
if(NS_SUCCEEDED(result)) {
|
if(NS_SUCCEEDED(result)) {
|
||||||
PRInt32 theCount=aContext->GetCount();
|
PRInt32 theCount=aContext->GetCount();
|
||||||
eHTMLTags theGrandParentTag=aContext->TagAt(theCount-2);
|
eHTMLTags theGrandParentTag=aContext->TagAt(theCount-2);
|
||||||
PRInt32 theCounter=aContext->IncrementCounter(theGrandParentTag);
|
|
||||||
|
|
||||||
nsString theNumber;
|
nsCParserNode *theNode=(nsCParserNode*)aNode;
|
||||||
theNumber.AppendInt(theCounter);
|
nsAutoString theNumber;
|
||||||
|
PRInt32 theCounter=aContext->IncrementCounter(theGrandParentTag,*theNode,theNumber);
|
||||||
|
|
||||||
CTextToken theToken(theNumber);
|
CTextToken theToken(theNumber);
|
||||||
PRInt32 theLineNumber=0;
|
PRInt32 theLineNumber=0;
|
||||||
nsCParserNode theNode(&theToken,theLineNumber);
|
nsCParserNode theNewNode(&theToken,theLineNumber);
|
||||||
result=aSink->AddLeaf(theNode);
|
result=aSink->AddLeaf(theNewNode);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -1284,12 +1290,7 @@ public:
|
||||||
virtual nsresult NotifyClose(nsIParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
|
virtual nsresult NotifyClose(nsIParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
|
||||||
nsresult result=NS_OK;
|
nsresult result=NS_OK;
|
||||||
|
|
||||||
if(aContext->HasOpenContainer(eHTMLTag_html)) {
|
if(aContext->HasOpenContainer(eHTMLTag_body)) {
|
||||||
aSink->OpenHead(*aNode);
|
|
||||||
result=CTextContainer::NotifyClose(aNode,aTag,aContext,aSink);
|
|
||||||
aSink->CloseHead(*aNode);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
//add the script to the body
|
//add the script to the body
|
||||||
CScriptToken theToken(mText);
|
CScriptToken theToken(mText);
|
||||||
PRInt32 theLineNumber=0;
|
PRInt32 theLineNumber=0;
|
||||||
|
@ -1297,6 +1298,12 @@ public:
|
||||||
theNode.SetSkippedContent(mText);
|
theNode.SetSkippedContent(mText);
|
||||||
result=aSink->AddLeaf(theNode);
|
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);
|
mText.Truncate(0);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -1628,6 +1635,28 @@ public:
|
||||||
CElement::Initialize(*this,aTag,CHTMLElement::GetGroup(),CHTMLElement::GetContainedGroups());
|
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
|
HTML handles the opening of it's own children
|
||||||
|
@ -1639,6 +1668,10 @@ public:
|
||||||
nsresult result=NS_OK;
|
nsresult result=NS_OK;
|
||||||
|
|
||||||
switch(aTag) {
|
switch(aTag) {
|
||||||
|
case eHTMLTag_markupDecl:
|
||||||
|
result=HandleDoctypeDecl(aNode,aTag,aContext,aSink);
|
||||||
|
break;
|
||||||
|
|
||||||
case eHTMLTag_body:
|
case eHTMLTag_body:
|
||||||
result=aSink->OpenBody(*aNode);
|
result=aSink->OpenBody(*aNode);
|
||||||
result=OpenContext(aNode,aTag,aContext,aSink);
|
result=OpenContext(aNode,aTag,aContext,aSink);
|
||||||
|
@ -1794,7 +1827,9 @@ public:
|
||||||
|
|
||||||
switch(aTag) {
|
switch(aTag) {
|
||||||
|
|
||||||
case eHTMLTag_div:
|
case eHTMLTag_script:
|
||||||
|
result=OpenContext(aNode,aTag,aContext,aSink);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
//for now, let's drop other elements onto the floor.
|
//for now, let's drop other elements onto the floor.
|
||||||
|
@ -1802,7 +1837,7 @@ public:
|
||||||
if(NS_SUCCEEDED(result)) {
|
if(NS_SUCCEEDED(result)) {
|
||||||
nsCParserNode *theNode=(nsCParserNode*)aNode;
|
nsCParserNode *theNode=(nsCParserNode*)aNode;
|
||||||
CStartToken *theToken=(CStartToken*)theNode->mToken;
|
CStartToken *theToken=(CStartToken*)theNode->mToken;
|
||||||
if(theToken->IsEmpty()){
|
if(theToken->IsEmpty() && (aTag==aContext->Last())){
|
||||||
result=CElement::HandleEndToken(aNode,aTag,aContext,aSink);
|
result=CElement::HandleEndToken(aNode,aTag,aContext,aSink);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1817,7 +1852,15 @@ public:
|
||||||
a really convenient break point for debugging purposes.
|
a really convenient break point for debugging purposes.
|
||||||
**********************************************************/
|
**********************************************************/
|
||||||
virtual nsresult HandleEndToken(nsIParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
|
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>
|
* Pierre Phaneuf <pp@ludusdesign.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "nsDTDUtils.h"
|
#include "nsDTDUtils.h"
|
||||||
#include "CNavDTD.h"
|
#include "CNavDTD.h"
|
||||||
#include "nsIParserNode.h"
|
#include "nsIParserNode.h"
|
||||||
|
@ -363,7 +363,7 @@ CNodeRecycler* nsDTDContext::mNodeRecycler=0;
|
||||||
*
|
*
|
||||||
* @update gess 04.21.2000
|
* @update gess 04.21.2000
|
||||||
*/
|
*/
|
||||||
nsDTDContext::nsDTDContext() : mStack() {
|
nsDTDContext::nsDTDContext() : mStack(), mEntities(0){
|
||||||
|
|
||||||
MOZ_COUNT_CTOR(nsDTDContext);
|
MOZ_COUNT_CTOR(nsDTDContext);
|
||||||
mResidualStyleCount=0;
|
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
|
* @update gess9/10/98
|
||||||
|
@ -391,9 +402,284 @@ nsDTDContext::~nsDTDContext() {
|
||||||
CTableState *theState=mTableStates;
|
CTableState *theState=mTableStates;
|
||||||
mTableStates=theState->mPrevious;
|
mTableStates=theState->mPrevious;
|
||||||
delete theState;
|
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
|
* @update gess 11May2000
|
||||||
|
@ -402,22 +688,81 @@ void nsDTDContext::ResetCounters(void) {
|
||||||
memset(mCounters,0,sizeof(mCounters));
|
memset(mCounters,0,sizeof(mCounters));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**********************************************************
|
||||||
*
|
@update: rickg 17May2000
|
||||||
* @update gess 11May2000
|
|
||||||
*/
|
Call this to handle counter attributes:
|
||||||
PRInt32 nsDTDContext::IncrementCounter(eHTMLTags aTag) {
|
name="group"
|
||||||
PRInt32 result=++mCounters[aTag];
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @update gess 11May2000
|
|
||||||
*/
|
|
||||||
void nsDTDContext::ResetCounter(eHTMLTags aTag,PRInt32 aValue) {
|
|
||||||
mCounters[aTag]=aValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|
|
@ -155,6 +155,11 @@ public:
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PRBool CanOpenTBody() {
|
||||||
|
PRBool result=!(mHasTBody);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
PRBool CanOpenTHead() {
|
PRBool CanOpenTHead() {
|
||||||
PRBool result=!(mHasTHead || mHasTFoot || mHasTBody);
|
PRBool result=!(mHasTHead || mHasTFoot || mHasTBody);
|
||||||
return result;
|
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).
|
The dtdcontext class defines an ordered list of tags (a context).
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
|
|
||||||
class nsDTDContext {
|
class nsDTDContext {
|
||||||
public:
|
public:
|
||||||
nsDTDContext();
|
nsDTDContext();
|
||||||
~nsDTDContext();
|
~nsDTDContext();
|
||||||
|
|
||||||
void Push(const nsIParserNode* aNode,nsEntryStack* aStyleStack=0);
|
void Push(const nsIParserNode* aNode,nsEntryStack* aStyleStack=0);
|
||||||
nsIParserNode* Pop(nsEntryStack*& aChildStack);
|
nsIParserNode* Pop(nsEntryStack*& aChildStack);
|
||||||
|
@ -209,9 +242,11 @@ public:
|
||||||
nsresult GetNodeRecycler(CNodeRecycler*& aNodeRecycler);
|
nsresult GetNodeRecycler(CNodeRecycler*& aNodeRecycler);
|
||||||
static void FreeNodeRecycler(void);
|
static void FreeNodeRecycler(void);
|
||||||
|
|
||||||
|
CNamedEntity* RegisterEntity(const nsString& aName,const nsString& aValue);
|
||||||
|
CNamedEntity* GetEntity(const nsString& aName)const;
|
||||||
|
|
||||||
void ResetCounters(void);
|
void ResetCounters(void);
|
||||||
void ResetCounter(eHTMLTags aTag,PRInt32 aNewValue);
|
PRInt32 IncrementCounter(eHTMLTags aTag,nsCParserNode& aNode,nsString& aResult);
|
||||||
PRInt32 IncrementCounter(eHTMLTags aTag);
|
|
||||||
|
|
||||||
nsEntryStack mStack; //this will hold a list of tagentries...
|
nsEntryStack mStack; //this will hold a list of tagentries...
|
||||||
PRInt32 mResidualStyleCount;
|
PRInt32 mResidualStyleCount;
|
||||||
|
@ -221,8 +256,10 @@ public:
|
||||||
|
|
||||||
static CNodeRecycler* mNodeRecycler;
|
static CNodeRecycler* mNodeRecycler;
|
||||||
|
|
||||||
CTableState *mTableStates;
|
CTableState *mTableStates;
|
||||||
PRInt32 mCounters[NS_HTML_TAG_MAX];
|
PRInt32 mCounters[NS_HTML_TAG_MAX];
|
||||||
|
nsString mDefaultEntity;
|
||||||
|
nsDeque mEntities;
|
||||||
|
|
||||||
#ifdef NS_DEBUG
|
#ifdef NS_DEBUG
|
||||||
enum { eMaxTags = 100 };
|
enum { eMaxTags = 100 };
|
||||||
|
|
|
@ -630,7 +630,9 @@ nsresult nsHTMLTokenizer::ConsumeEntity(PRUnichar aChar,CToken*& aToken,nsScanne
|
||||||
return ConsumeText(temp,aToken,aScanner);
|
return ConsumeText(temp,aToken,aScanner);
|
||||||
}//if
|
}//if
|
||||||
if(aToken){
|
if(aToken){
|
||||||
|
#if 0
|
||||||
nsString& theStr=aToken->GetStringValueXXX();
|
nsString& theStr=aToken->GetStringValueXXX();
|
||||||
|
|
||||||
if((kHashsign!=theChar) && (-1==nsHTMLEntities::EntityToUnicode(theStr))){
|
if((kHashsign!=theChar) && (-1==nsHTMLEntities::EntityToUnicode(theStr))){
|
||||||
//if you're here we have a bogus entity.
|
//if you're here we have a bogus entity.
|
||||||
//convert it into a text token.
|
//convert it into a text token.
|
||||||
|
@ -640,6 +642,7 @@ nsresult nsHTMLTokenizer::ConsumeEntity(PRUnichar aChar,CToken*& aToken,nsScanne
|
||||||
theRecycler->RecycleToken(aToken);
|
theRecycler->RecycleToken(aToken);
|
||||||
aToken=theToken;
|
aToken=theToken;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
AddToken(aToken,result,&mTokenDeque,theRecycler);
|
AddToken(aToken,result,&mTokenDeque,theRecycler);
|
||||||
}
|
}
|
||||||
}//if
|
}//if
|
||||||
|
|
|
@ -102,12 +102,13 @@ public:
|
||||||
//Note: To cut down on startup time/overhead, we defer the construction of non-html DTD's.
|
//Note: To cut down on startup time/overhead, we defer the construction of non-html DTD's.
|
||||||
|
|
||||||
nsIDTD* theDTD;
|
nsIDTD* theDTD;
|
||||||
|
|
||||||
NS_NewNavHTMLDTD(&theDTD); //do this as a default HTML DTD...
|
NS_NewNavHTMLDTD(&theDTD); //do this as a default HTML DTD...
|
||||||
mDTDDeque.Push(theDTD);
|
mDTDDeque.Push(theDTD);
|
||||||
#if 1
|
|
||||||
NS_NewOtherHTMLDTD(&theDTD); //do this as the default DTD for strict documents...
|
NS_NewOtherHTMLDTD(&theDTD); //do this as the default DTD for strict documents...
|
||||||
mDTDDeque.Push(theDTD);
|
mDTDDeque.Push(theDTD);
|
||||||
#endif
|
|
||||||
mHasViewSourceDTD=PR_FALSE;
|
mHasViewSourceDTD=PR_FALSE;
|
||||||
mHasRTFDTD=mHasXMLDTD=PR_FALSE;
|
mHasRTFDTD=mHasXMLDTD=PR_FALSE;
|
||||||
}
|
}
|
||||||
|
@ -485,7 +486,7 @@ nsDTDMode nsParser::GetParseMode(void){
|
||||||
* @return parsermode (define in nsIParser.h)
|
* @return parsermode (define in nsIParser.h)
|
||||||
*/
|
*/
|
||||||
static
|
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");
|
const char* theModeStr= PR_GetEnv("PARSE_MODE");
|
||||||
|
|
||||||
aParseMode = eDTDMode_unknown;
|
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))) {
|
else if(kNotFound<(theIndex=aBuffer.Find("?XML",PR_TRUE,0,128))) {
|
||||||
aDocType=eXMLText;
|
|
||||||
aParseMode=eDTDMode_strict;
|
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) {
|
if(theModeStr) {
|
||||||
|
@ -754,7 +765,11 @@ nsresult nsParser::CreateCompatibleDTD(nsIDTD** aDTD,
|
||||||
nsDTDMode theDTDMode=eDTDMode_unknown;
|
nsDTDMode theDTDMode=eDTDMode_unknown;
|
||||||
eParserDocType theDocType=ePlainText;
|
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 ");
|
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) {
|
while(*theDocType) {
|
||||||
nsAutoString theType;
|
nsAutoString theType;
|
||||||
theType.AssignWithConversion(*theDocType);
|
theType.AssignWithConversion(*theDocType);
|
||||||
DetermineParseMode(theType,theParseMode,theDocumentType);
|
DetermineParseMode(theType,theParseMode,theDocumentType,mParserContext->mMimeType);
|
||||||
theDocType++;
|
theDocType++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -957,7 +972,7 @@ nsresult nsParser::WillBuildModel(nsString& aFilename){
|
||||||
mMinorIteration=-1;
|
mMinorIteration=-1;
|
||||||
|
|
||||||
nsString& theBuffer=mParserContext->mScanner->GetBuffer();
|
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)) {
|
if(PR_TRUE==FindSuitableDTD(*mParserContext,theBuffer)) {
|
||||||
mParserContext->mDTD->WillBuildModel( *mParserContext,mSink);
|
mParserContext->mDTD->WillBuildModel( *mParserContext,mSink);
|
||||||
|
|
|
@ -22,9 +22,10 @@
|
||||||
|
|
||||||
//#define ENABLE_CRC
|
//#define ENABLE_CRC
|
||||||
//#define RICKG_DEBUG
|
//#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 ALLOW_TR_AS_CHILD_OF_TABLE //by setting this to true, TR is allowable directly in TABLE.
|
||||||
|
|
||||||
|
#define ENABLE_RESIDUALSTYLE
|
||||||
|
|
||||||
#ifdef RICKG_DEBUG
|
#ifdef RICKG_DEBUG
|
||||||
#include <fstream.h>
|
#include <fstream.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -266,12 +267,24 @@ CNavDTD::~CNavDTD(){
|
||||||
/**
|
/**
|
||||||
* Call this method if you want the DTD to construct a fresh
|
* Call this method if you want the DTD to construct a fresh
|
||||||
* instance of itself.
|
* instance of itself.
|
||||||
* @update gess7/23/98
|
* @update gess 25May2000
|
||||||
* @param
|
* @param
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
nsresult CNavDTD::CreateNewInstance(nsIDTD** aInstancePtrResult){
|
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();
|
PRInt32 theCount=mBodyContext->GetCount();
|
||||||
eHTMLTags theGrandParentTag=mBodyContext->TagAt(theCount-2);
|
eHTMLTags theGrandParentTag=mBodyContext->TagAt(theCount-2);
|
||||||
PRInt32 theCounter=mBodyContext->IncrementCounter(theGrandParentTag);
|
|
||||||
|
nsAutoString theNumber;
|
||||||
nsString theNumber;
|
PRInt32 theCounter=mBodyContext->IncrementCounter(theGrandParentTag,aNode,theNumber);
|
||||||
theNumber.AppendInt(theCounter);
|
|
||||||
CTextToken theToken(theNumber);
|
CTextToken theToken(theNumber);
|
||||||
PRInt32 theLineNumber=0;
|
PRInt32 theLineNumber=0;
|
||||||
nsCParserNode theNode(&theToken,theLineNumber);
|
nsCParserNode theNode(&theToken,theLineNumber);
|
||||||
|
@ -838,6 +850,35 @@ nsresult CNavDTD::DidHandleStartTag(nsCParserNode& aNode,eHTMLTags aChildTag){
|
||||||
}
|
}
|
||||||
break;
|
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:
|
default:
|
||||||
break;
|
break;
|
||||||
}//switch
|
}//switch
|
||||||
|
@ -1846,6 +1887,27 @@ nsresult CNavDTD::HandleEntityToken(CToken* aToken) {
|
||||||
NS_PRECONDITION(0!=aToken,kNullToken);
|
NS_PRECONDITION(0!=aToken,kNullToken);
|
||||||
|
|
||||||
nsresult result=NS_OK;
|
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();
|
eHTMLTags theParentTag=mBodyContext->Last();
|
||||||
|
|
||||||
nsCParserNode* theNode=mNodeRecycler->CreateNode();
|
nsCParserNode* theNode=mNodeRecycler->CreateNode();
|
||||||
|
|
|
@ -4,24 +4,24 @@
|
||||||
* License Version 1.1 (the "License"); you may not use this file
|
* License Version 1.1 (the "License"); you may not use this file
|
||||||
* except in compliance with the License. You may obtain a copy of
|
* except in compliance with the License. You may obtain a copy of
|
||||||
* the License at http://www.mozilla.org/NPL/
|
* the License at http://www.mozilla.org/NPL/
|
||||||
*
|
*
|
||||||
* Software distributed under the License is distributed on an "AS
|
* Software distributed under the License is distributed on an "AS
|
||||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||||
* implied. See the License for the specific language governing
|
* implied. See the License for the specific language governing
|
||||||
* rights and limitations under the License.
|
* rights and limitations under the License.
|
||||||
*
|
*
|
||||||
* The Original Code is mozilla.org code.
|
* The Original Code is mozilla.org code.
|
||||||
*
|
*
|
||||||
* The Initial Developer of the Original Code is Netscape
|
* The Initial Developer of the Original Code is Netscape
|
||||||
* Communications Corporation. Portions created by Netscape are
|
* Communications Corporation. Portions created by Netscape are
|
||||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||||
* Rights Reserved.
|
* Rights Reserved.
|
||||||
*
|
*
|
||||||
* Contributor(s):
|
* Contributor(s):
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//#define ENABLE_CRC
|
//#define ENABLE_CRC
|
||||||
//#define RICKG_DEBUG
|
//#define RICKG_DEBUG
|
||||||
|
|
||||||
|
|
||||||
#include "nsDebug.h"
|
#include "nsDebug.h"
|
||||||
|
@ -131,7 +131,7 @@ NS_IMPL_RELEASE(COtherDTD)
|
||||||
* @param
|
* @param
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
COtherDTD::COtherDTD() : nsIDTD(), mMisplacedContent(0), mSkippedContent(0), mSharedNodes(0) {
|
COtherDTD::COtherDTD() : nsIDTD(), mSharedNodes(0) {
|
||||||
NS_INIT_REFCNT();
|
NS_INIT_REFCNT();
|
||||||
mSink = 0;
|
mSink = 0;
|
||||||
mParser=0;
|
mParser=0;
|
||||||
|
@ -141,14 +141,17 @@ COtherDTD::COtherDTD() : nsIDTD(), mMisplacedContent(0), mSkippedContent(0), mSh
|
||||||
mHasOpenHead=0;
|
mHasOpenHead=0;
|
||||||
mHasOpenForm=PR_FALSE;
|
mHasOpenForm=PR_FALSE;
|
||||||
mHasOpenMap=PR_FALSE;
|
mHasOpenMap=PR_FALSE;
|
||||||
mHeadContext=new nsDTDContext();
|
|
||||||
mBodyContext=new nsDTDContext();
|
mBodyContext=new nsDTDContext();
|
||||||
mFormContext=0;
|
|
||||||
mTokenizer=0;
|
mTokenizer=0;
|
||||||
mComputedCRC32=0;
|
mComputedCRC32=0;
|
||||||
mExpectedCRC32=0;
|
mExpectedCRC32=0;
|
||||||
mDTDState=NS_OK;
|
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");
|
char* theEnvString = PR_GetEnv("ENABLE_STRICT");
|
||||||
mEnableStrict=PRBool(theEnvString!=0);
|
mEnableStrict=PRBool(theEnvString!=0);
|
||||||
|
@ -280,7 +283,6 @@ const nsIID& COtherDTD::GetMostDerivedIID(void)const {
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
COtherDTD::~COtherDTD(){
|
COtherDTD::~COtherDTD(){
|
||||||
delete mHeadContext;
|
|
||||||
delete mBodyContext;
|
delete mBodyContext;
|
||||||
|
|
||||||
NS_IF_RELEASE(mTokenizer);
|
NS_IF_RELEASE(mTokenizer);
|
||||||
|
@ -336,7 +338,19 @@ NS_HTMLPARS nsresult NS_NewOtherHTMLDTD(nsIDTD** aInstancePtrResult) {
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
nsresult COtherDTD::CreateNewInstance(nsIDTD** aInstancePtrResult){
|
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_start:
|
||||||
case eToken_whitespace:
|
case eToken_whitespace:
|
||||||
case eToken_newline:
|
case eToken_newline:
|
||||||
|
case eToken_doctypeDecl:
|
||||||
result=HandleStartToken(theToken); break;
|
result=HandleStartToken(theToken); break;
|
||||||
|
|
||||||
case eToken_end:
|
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));
|
MOZ_TIMER_DEBUGLOG(("Start: Parse Time: COtherDTD::WillHandleStartTag(), this=%p\n", this));
|
||||||
START_TIMER()
|
START_TIMER()
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -762,20 +777,20 @@ nsresult COtherDTD::HandleStartToken(CToken* aToken) {
|
||||||
if(NS_OK==result) {
|
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:
|
case eHTMLTag_html:
|
||||||
if(!HasOpenContainer(theChildTag)) {
|
if(!HasOpenContainer(theChildTag)) {
|
||||||
mSink->OpenHTML(*theNode);
|
mSink->OpenHTML(*theNode);
|
||||||
mBodyContext->Push(theNode,0);
|
mBodyContext->Push(theNode,0);
|
||||||
}
|
}
|
||||||
theTagWasHandled=PR_TRUE;
|
theTagWasHandled=PR_TRUE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
CElement* theElement=gElementTable->mElements[theParent];
|
CElement* theElement=gElementTable->mElements[theParent];
|
||||||
if(theElement) {
|
if(theElement) {
|
||||||
result=theElement->HandleStartToken(theNode,theChildTag,mBodyContext,mSink);
|
result=theElement->HandleStartToken(theNode,theChildTag,mBodyContext,mSink);
|
||||||
|
@ -788,7 +803,7 @@ nsresult COtherDTD::HandleStartToken(CToken* aToken) {
|
||||||
DidHandleStartTag(*theNode,theChildTag);
|
DidHandleStartTag(*theNode,theChildTag);
|
||||||
}
|
}
|
||||||
|
|
||||||
} //if
|
} //if
|
||||||
}//if
|
}//if
|
||||||
|
|
||||||
RecycleNode(theNode);
|
RecycleNode(theNode);
|
||||||
|
@ -814,7 +829,7 @@ nsresult COtherDTD::HandleEndToken(CToken* aToken) {
|
||||||
nsresult result=NS_OK;
|
nsresult result=NS_OK;
|
||||||
eHTMLTags theChildTag=(eHTMLTags)aToken->GetTypeID();
|
eHTMLTags theChildTag=(eHTMLTags)aToken->GetTypeID();
|
||||||
|
|
||||||
#ifdef RICKG_DEBUG
|
#ifdef RICKG_DEBUG
|
||||||
WriteTokenToLog(aToken);
|
WriteTokenToLog(aToken);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -825,7 +840,7 @@ nsresult COtherDTD::HandleEndToken(CToken* aToken) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case eHTMLTag_script:
|
case eHTMLTag_script:
|
||||||
mHasOpenScript=PR_FALSE;
|
mHasOpenScript=PR_FALSE;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
PRInt32 theCount=mBodyContext->GetCount();
|
PRInt32 theCount=mBodyContext->GetCount();
|
||||||
|
@ -838,7 +853,7 @@ nsresult COtherDTD::HandleEndToken(CToken* aToken) {
|
||||||
nsCParserNode theNode((CHTMLToken*)aToken,mLineNumber);
|
nsCParserNode theNode((CHTMLToken*)aToken,mLineNumber);
|
||||||
result=theElement->HandleEndToken(&theNode,theChildTag,mBodyContext,mSink);
|
result=theElement->HandleEndToken(&theNode,theChildTag,mBodyContext,mSink);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -857,14 +872,12 @@ nsresult COtherDTD::CollectAttributes(nsCParserNode& aNode,eHTMLTags aTag,PRInt3
|
||||||
int attr=0;
|
int attr=0;
|
||||||
|
|
||||||
nsresult result=NS_OK;
|
nsresult result=NS_OK;
|
||||||
int theAvailTokenCount=mTokenizer->GetCount() + mSkippedContent.GetSize();
|
int theAvailTokenCount=mTokenizer->GetCount();
|
||||||
if(aCount<=theAvailTokenCount) {
|
if(aCount<=theAvailTokenCount) {
|
||||||
CToken* theToken=0;
|
CToken* theToken=0;
|
||||||
eHTMLTags theSkipTarget=gElementTable->mElements[aTag]->GetSkipTarget();
|
eHTMLTags theSkipTarget=gElementTable->mElements[aTag]->GetSkipTarget();
|
||||||
for(attr=0;attr<aCount;attr++){
|
for(attr=0;attr<aCount;attr++){
|
||||||
if((eHTMLTag_unknown!=theSkipTarget) && mSkippedContent.GetSize())
|
theToken=mTokenizer->PopToken();
|
||||||
theToken=(CToken*)mSkippedContent.PopFront();
|
|
||||||
else theToken=mTokenizer->PopToken();
|
|
||||||
if(theToken) {
|
if(theToken) {
|
||||||
// Sanitize the key for it might contain some non-alpha-non-digit characters
|
// 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",
|
// 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;
|
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...
|
The preceeding tables determine the set of elements each tag can contain...
|
||||||
|
|
|
@ -340,7 +340,6 @@ CLASS_EXPORT_HTMLPARS COtherDTD : public nsIDTD {
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
nsresult CollectAttributes(nsCParserNode& aNode,eHTMLTags aTag,PRInt32 aCount);
|
nsresult CollectAttributes(nsCParserNode& aNode,eHTMLTags aTag,PRInt32 aCount);
|
||||||
nsresult CollectSkippedContent(nsCParserNode& aNode,PRInt32& aCount);
|
|
||||||
nsresult WillHandleStartTag(CToken* aToken,eHTMLTags aChildTag,nsCParserNode& aNode);
|
nsresult WillHandleStartTag(CToken* aToken,eHTMLTags aChildTag,nsCParserNode& aNode);
|
||||||
nsresult DidHandleStartTag(nsCParserNode& aNode,eHTMLTags aChildTag);
|
nsresult DidHandleStartTag(nsCParserNode& aNode,eHTMLTags aChildTag);
|
||||||
nsCParserNode* CreateNode(void);
|
nsCParserNode* CreateNode(void);
|
||||||
|
@ -349,9 +348,7 @@ protected:
|
||||||
|
|
||||||
nsIHTMLContentSink* mSink;
|
nsIHTMLContentSink* mSink;
|
||||||
|
|
||||||
nsDTDContext* mHeadContext;
|
|
||||||
nsDTDContext* mBodyContext;
|
nsDTDContext* mBodyContext;
|
||||||
nsDTDContext* mFormContext;
|
|
||||||
PRBool mHasOpenForm;
|
PRBool mHasOpenForm;
|
||||||
PRBool mHasOpenMap;
|
PRBool mHasOpenMap;
|
||||||
PRInt32 mHasOpenHead;
|
PRInt32 mHasOpenHead;
|
||||||
|
@ -364,10 +361,7 @@ protected:
|
||||||
nsParser* mParser;
|
nsParser* mParser;
|
||||||
nsITokenizer* mTokenizer;
|
nsITokenizer* mTokenizer;
|
||||||
CTokenRecycler* mTokenRecycler;
|
CTokenRecycler* mTokenRecycler;
|
||||||
nsDeque mMisplacedContent;
|
|
||||||
nsDeque mSkippedContent;
|
|
||||||
PRBool mHasOpenScript;
|
PRBool mHasOpenScript;
|
||||||
PRBool mSaveBadTokens;
|
|
||||||
eHTMLTags mSkipTarget;
|
eHTMLTags mSkipTarget;
|
||||||
nsDeque mSharedNodes;
|
nsDeque mSharedNodes;
|
||||||
nsresult mDTDState;
|
nsresult mDTDState;
|
||||||
|
@ -377,9 +371,8 @@ protected:
|
||||||
PRUint32 mComputedCRC32;
|
PRUint32 mComputedCRC32;
|
||||||
PRUint32 mExpectedCRC32;
|
PRUint32 mExpectedCRC32;
|
||||||
nsAutoString mScratch; //used for various purposes; non-persistent
|
nsAutoString mScratch; //used for various purposes; non-persistent
|
||||||
PRBool mStyleHandlingEnabled;
|
|
||||||
PRBool mEnableStrict;
|
|
||||||
eParserDocType mDocType;
|
eParserDocType mDocType;
|
||||||
|
PRBool mEnableStrict;
|
||||||
|
|
||||||
#ifdef NS_DEBUG
|
#ifdef NS_DEBUG
|
||||||
PRInt32 gNodeCount;
|
PRInt32 gNodeCount;
|
||||||
|
|
|
@ -705,17 +705,19 @@ public:
|
||||||
case eHTMLTag_tr:
|
case eHTMLTag_tr:
|
||||||
case eHTMLTag_th:
|
case eHTMLTag_th:
|
||||||
|
|
||||||
if(!aContext->HasOpenContainer(eHTMLTag_tbody)) {
|
if(aContext->mTableStates) {
|
||||||
nsCParserNode* theNode=new nsCParserNode();
|
if(aContext->mTableStates->CanOpenTBody()) {
|
||||||
CToken* theToken=new CStartToken(eHTMLTag_tbody);
|
nsCParserNode* theNode=new nsCParserNode();
|
||||||
theNode->Init(theToken,0,0); //this will likely leak...
|
CToken* theToken=new CStartToken(eHTMLTag_tbody);
|
||||||
|
theNode->Init(theToken,0,0); //this will likely leak...
|
||||||
|
|
||||||
result=HandleStartToken(theNode,eHTMLTag_tbody,aContext,aSink);
|
result=HandleStartToken(theNode,eHTMLTag_tbody,aContext,aSink);
|
||||||
}
|
}
|
||||||
if(NS_SUCCEEDED(result)) {
|
if(NS_SUCCEEDED(result)) {
|
||||||
CElement *theElement=GetElement(eHTMLTag_tbody);
|
CElement *theElement=GetElement(eHTMLTag_tbody);
|
||||||
if(theElement) {
|
if(theElement) {
|
||||||
result=theElement->HandleStartToken(aNode,aTag,aContext,aSink);
|
result=theElement->HandleStartToken(aNode,aTag,aContext,aSink);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -738,6 +740,7 @@ public:
|
||||||
case eHTMLTag_caption:
|
case eHTMLTag_caption:
|
||||||
case eHTMLTag_col:
|
case eHTMLTag_col:
|
||||||
case eHTMLTag_colgroup:
|
case eHTMLTag_colgroup:
|
||||||
|
case eHTMLTag_tr:
|
||||||
case eHTMLTag_thead:
|
case eHTMLTag_thead:
|
||||||
case eHTMLTag_tfoot:
|
case eHTMLTag_tfoot:
|
||||||
case eHTMLTag_tbody:
|
case eHTMLTag_tbody:
|
||||||
|
@ -928,23 +931,26 @@ public:
|
||||||
return CElement::HandleStartToken(aNode,aTag,aContext,aSink);
|
return CElement::HandleStartToken(aNode,aTag,aContext,aSink);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**********************************************************
|
/**********************************************************
|
||||||
this gets called after each tag is opened in the given context
|
this gets called after each tag is opened in the given context
|
||||||
**********************************************************/
|
**********************************************************/
|
||||||
virtual nsresult OpenContainerInContext(nsIParserNode *aNode,eHTMLTags aTag,nsDTDContext *aContext,nsIHTMLContentSink *aSink) {
|
virtual nsresult OpenContainerInContext(nsIParserNode *aNode,eHTMLTags aTag,nsDTDContext *aContext,nsIHTMLContentSink *aSink) {
|
||||||
OpenContext(aNode,aTag,aContext,aSink);
|
OpenContext(aNode,aTag,aContext,aSink);
|
||||||
|
|
||||||
nsresult result=OpenContainer(aNode,aTag,aContext,aSink);
|
nsresult result=OpenContainer(aNode,aTag,aContext,aSink);
|
||||||
if(NS_SUCCEEDED(result)) {
|
if(NS_SUCCEEDED(result)) {
|
||||||
PRInt32 theCount=aContext->GetCount();
|
PRInt32 theCount=aContext->GetCount();
|
||||||
eHTMLTags theGrandParentTag=aContext->TagAt(theCount-2);
|
eHTMLTags theGrandParentTag=aContext->TagAt(theCount-2);
|
||||||
PRInt32 theCounter=aContext->IncrementCounter(theGrandParentTag);
|
|
||||||
|
|
||||||
nsString theNumber;
|
nsCParserNode *theNode=(nsCParserNode*)aNode;
|
||||||
theNumber.AppendInt(theCounter);
|
nsAutoString theNumber;
|
||||||
|
PRInt32 theCounter=aContext->IncrementCounter(theGrandParentTag,*theNode,theNumber);
|
||||||
|
|
||||||
CTextToken theToken(theNumber);
|
CTextToken theToken(theNumber);
|
||||||
PRInt32 theLineNumber=0;
|
PRInt32 theLineNumber=0;
|
||||||
nsCParserNode theNode(&theToken,theLineNumber);
|
nsCParserNode theNewNode(&theToken,theLineNumber);
|
||||||
result=aSink->AddLeaf(theNode);
|
result=aSink->AddLeaf(theNewNode);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -1284,12 +1290,7 @@ public:
|
||||||
virtual nsresult NotifyClose(nsIParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
|
virtual nsresult NotifyClose(nsIParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
|
||||||
nsresult result=NS_OK;
|
nsresult result=NS_OK;
|
||||||
|
|
||||||
if(aContext->HasOpenContainer(eHTMLTag_html)) {
|
if(aContext->HasOpenContainer(eHTMLTag_body)) {
|
||||||
aSink->OpenHead(*aNode);
|
|
||||||
result=CTextContainer::NotifyClose(aNode,aTag,aContext,aSink);
|
|
||||||
aSink->CloseHead(*aNode);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
//add the script to the body
|
//add the script to the body
|
||||||
CScriptToken theToken(mText);
|
CScriptToken theToken(mText);
|
||||||
PRInt32 theLineNumber=0;
|
PRInt32 theLineNumber=0;
|
||||||
|
@ -1297,6 +1298,12 @@ public:
|
||||||
theNode.SetSkippedContent(mText);
|
theNode.SetSkippedContent(mText);
|
||||||
result=aSink->AddLeaf(theNode);
|
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);
|
mText.Truncate(0);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -1628,6 +1635,28 @@ public:
|
||||||
CElement::Initialize(*this,aTag,CHTMLElement::GetGroup(),CHTMLElement::GetContainedGroups());
|
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
|
HTML handles the opening of it's own children
|
||||||
|
@ -1639,6 +1668,10 @@ public:
|
||||||
nsresult result=NS_OK;
|
nsresult result=NS_OK;
|
||||||
|
|
||||||
switch(aTag) {
|
switch(aTag) {
|
||||||
|
case eHTMLTag_markupDecl:
|
||||||
|
result=HandleDoctypeDecl(aNode,aTag,aContext,aSink);
|
||||||
|
break;
|
||||||
|
|
||||||
case eHTMLTag_body:
|
case eHTMLTag_body:
|
||||||
result=aSink->OpenBody(*aNode);
|
result=aSink->OpenBody(*aNode);
|
||||||
result=OpenContext(aNode,aTag,aContext,aSink);
|
result=OpenContext(aNode,aTag,aContext,aSink);
|
||||||
|
@ -1794,7 +1827,9 @@ public:
|
||||||
|
|
||||||
switch(aTag) {
|
switch(aTag) {
|
||||||
|
|
||||||
case eHTMLTag_div:
|
case eHTMLTag_script:
|
||||||
|
result=OpenContext(aNode,aTag,aContext,aSink);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
//for now, let's drop other elements onto the floor.
|
//for now, let's drop other elements onto the floor.
|
||||||
|
@ -1802,7 +1837,7 @@ public:
|
||||||
if(NS_SUCCEEDED(result)) {
|
if(NS_SUCCEEDED(result)) {
|
||||||
nsCParserNode *theNode=(nsCParserNode*)aNode;
|
nsCParserNode *theNode=(nsCParserNode*)aNode;
|
||||||
CStartToken *theToken=(CStartToken*)theNode->mToken;
|
CStartToken *theToken=(CStartToken*)theNode->mToken;
|
||||||
if(theToken->IsEmpty()){
|
if(theToken->IsEmpty() && (aTag==aContext->Last())){
|
||||||
result=CElement::HandleEndToken(aNode,aTag,aContext,aSink);
|
result=CElement::HandleEndToken(aNode,aTag,aContext,aSink);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1817,7 +1852,15 @@ public:
|
||||||
a really convenient break point for debugging purposes.
|
a really convenient break point for debugging purposes.
|
||||||
**********************************************************/
|
**********************************************************/
|
||||||
virtual nsresult HandleEndToken(nsIParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
|
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>
|
* Pierre Phaneuf <pp@ludusdesign.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "nsDTDUtils.h"
|
#include "nsDTDUtils.h"
|
||||||
#include "CNavDTD.h"
|
#include "CNavDTD.h"
|
||||||
#include "nsIParserNode.h"
|
#include "nsIParserNode.h"
|
||||||
|
@ -363,7 +363,7 @@ CNodeRecycler* nsDTDContext::mNodeRecycler=0;
|
||||||
*
|
*
|
||||||
* @update gess 04.21.2000
|
* @update gess 04.21.2000
|
||||||
*/
|
*/
|
||||||
nsDTDContext::nsDTDContext() : mStack() {
|
nsDTDContext::nsDTDContext() : mStack(), mEntities(0){
|
||||||
|
|
||||||
MOZ_COUNT_CTOR(nsDTDContext);
|
MOZ_COUNT_CTOR(nsDTDContext);
|
||||||
mResidualStyleCount=0;
|
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
|
* @update gess9/10/98
|
||||||
|
@ -391,9 +402,284 @@ nsDTDContext::~nsDTDContext() {
|
||||||
CTableState *theState=mTableStates;
|
CTableState *theState=mTableStates;
|
||||||
mTableStates=theState->mPrevious;
|
mTableStates=theState->mPrevious;
|
||||||
delete theState;
|
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
|
* @update gess 11May2000
|
||||||
|
@ -402,22 +688,81 @@ void nsDTDContext::ResetCounters(void) {
|
||||||
memset(mCounters,0,sizeof(mCounters));
|
memset(mCounters,0,sizeof(mCounters));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**********************************************************
|
||||||
*
|
@update: rickg 17May2000
|
||||||
* @update gess 11May2000
|
|
||||||
*/
|
Call this to handle counter attributes:
|
||||||
PRInt32 nsDTDContext::IncrementCounter(eHTMLTags aTag) {
|
name="group"
|
||||||
PRInt32 result=++mCounters[aTag];
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @update gess 11May2000
|
|
||||||
*/
|
|
||||||
void nsDTDContext::ResetCounter(eHTMLTags aTag,PRInt32 aValue) {
|
|
||||||
mCounters[aTag]=aValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|
|
@ -155,6 +155,11 @@ public:
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PRBool CanOpenTBody() {
|
||||||
|
PRBool result=!(mHasTBody);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
PRBool CanOpenTHead() {
|
PRBool CanOpenTHead() {
|
||||||
PRBool result=!(mHasTHead || mHasTFoot || mHasTBody);
|
PRBool result=!(mHasTHead || mHasTFoot || mHasTBody);
|
||||||
return result;
|
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).
|
The dtdcontext class defines an ordered list of tags (a context).
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
|
|
||||||
class nsDTDContext {
|
class nsDTDContext {
|
||||||
public:
|
public:
|
||||||
nsDTDContext();
|
nsDTDContext();
|
||||||
~nsDTDContext();
|
~nsDTDContext();
|
||||||
|
|
||||||
void Push(const nsIParserNode* aNode,nsEntryStack* aStyleStack=0);
|
void Push(const nsIParserNode* aNode,nsEntryStack* aStyleStack=0);
|
||||||
nsIParserNode* Pop(nsEntryStack*& aChildStack);
|
nsIParserNode* Pop(nsEntryStack*& aChildStack);
|
||||||
|
@ -209,9 +242,11 @@ public:
|
||||||
nsresult GetNodeRecycler(CNodeRecycler*& aNodeRecycler);
|
nsresult GetNodeRecycler(CNodeRecycler*& aNodeRecycler);
|
||||||
static void FreeNodeRecycler(void);
|
static void FreeNodeRecycler(void);
|
||||||
|
|
||||||
|
CNamedEntity* RegisterEntity(const nsString& aName,const nsString& aValue);
|
||||||
|
CNamedEntity* GetEntity(const nsString& aName)const;
|
||||||
|
|
||||||
void ResetCounters(void);
|
void ResetCounters(void);
|
||||||
void ResetCounter(eHTMLTags aTag,PRInt32 aNewValue);
|
PRInt32 IncrementCounter(eHTMLTags aTag,nsCParserNode& aNode,nsString& aResult);
|
||||||
PRInt32 IncrementCounter(eHTMLTags aTag);
|
|
||||||
|
|
||||||
nsEntryStack mStack; //this will hold a list of tagentries...
|
nsEntryStack mStack; //this will hold a list of tagentries...
|
||||||
PRInt32 mResidualStyleCount;
|
PRInt32 mResidualStyleCount;
|
||||||
|
@ -221,8 +256,10 @@ public:
|
||||||
|
|
||||||
static CNodeRecycler* mNodeRecycler;
|
static CNodeRecycler* mNodeRecycler;
|
||||||
|
|
||||||
CTableState *mTableStates;
|
CTableState *mTableStates;
|
||||||
PRInt32 mCounters[NS_HTML_TAG_MAX];
|
PRInt32 mCounters[NS_HTML_TAG_MAX];
|
||||||
|
nsString mDefaultEntity;
|
||||||
|
nsDeque mEntities;
|
||||||
|
|
||||||
#ifdef NS_DEBUG
|
#ifdef NS_DEBUG
|
||||||
enum { eMaxTags = 100 };
|
enum { eMaxTags = 100 };
|
||||||
|
|
|
@ -630,7 +630,9 @@ nsresult nsHTMLTokenizer::ConsumeEntity(PRUnichar aChar,CToken*& aToken,nsScanne
|
||||||
return ConsumeText(temp,aToken,aScanner);
|
return ConsumeText(temp,aToken,aScanner);
|
||||||
}//if
|
}//if
|
||||||
if(aToken){
|
if(aToken){
|
||||||
|
#if 0
|
||||||
nsString& theStr=aToken->GetStringValueXXX();
|
nsString& theStr=aToken->GetStringValueXXX();
|
||||||
|
|
||||||
if((kHashsign!=theChar) && (-1==nsHTMLEntities::EntityToUnicode(theStr))){
|
if((kHashsign!=theChar) && (-1==nsHTMLEntities::EntityToUnicode(theStr))){
|
||||||
//if you're here we have a bogus entity.
|
//if you're here we have a bogus entity.
|
||||||
//convert it into a text token.
|
//convert it into a text token.
|
||||||
|
@ -640,6 +642,7 @@ nsresult nsHTMLTokenizer::ConsumeEntity(PRUnichar aChar,CToken*& aToken,nsScanne
|
||||||
theRecycler->RecycleToken(aToken);
|
theRecycler->RecycleToken(aToken);
|
||||||
aToken=theToken;
|
aToken=theToken;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
AddToken(aToken,result,&mTokenDeque,theRecycler);
|
AddToken(aToken,result,&mTokenDeque,theRecycler);
|
||||||
}
|
}
|
||||||
}//if
|
}//if
|
||||||
|
|
|
@ -102,12 +102,13 @@ public:
|
||||||
//Note: To cut down on startup time/overhead, we defer the construction of non-html DTD's.
|
//Note: To cut down on startup time/overhead, we defer the construction of non-html DTD's.
|
||||||
|
|
||||||
nsIDTD* theDTD;
|
nsIDTD* theDTD;
|
||||||
|
|
||||||
NS_NewNavHTMLDTD(&theDTD); //do this as a default HTML DTD...
|
NS_NewNavHTMLDTD(&theDTD); //do this as a default HTML DTD...
|
||||||
mDTDDeque.Push(theDTD);
|
mDTDDeque.Push(theDTD);
|
||||||
#if 1
|
|
||||||
NS_NewOtherHTMLDTD(&theDTD); //do this as the default DTD for strict documents...
|
NS_NewOtherHTMLDTD(&theDTD); //do this as the default DTD for strict documents...
|
||||||
mDTDDeque.Push(theDTD);
|
mDTDDeque.Push(theDTD);
|
||||||
#endif
|
|
||||||
mHasViewSourceDTD=PR_FALSE;
|
mHasViewSourceDTD=PR_FALSE;
|
||||||
mHasRTFDTD=mHasXMLDTD=PR_FALSE;
|
mHasRTFDTD=mHasXMLDTD=PR_FALSE;
|
||||||
}
|
}
|
||||||
|
@ -485,7 +486,7 @@ nsDTDMode nsParser::GetParseMode(void){
|
||||||
* @return parsermode (define in nsIParser.h)
|
* @return parsermode (define in nsIParser.h)
|
||||||
*/
|
*/
|
||||||
static
|
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");
|
const char* theModeStr= PR_GetEnv("PARSE_MODE");
|
||||||
|
|
||||||
aParseMode = eDTDMode_unknown;
|
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))) {
|
else if(kNotFound<(theIndex=aBuffer.Find("?XML",PR_TRUE,0,128))) {
|
||||||
aDocType=eXMLText;
|
|
||||||
aParseMode=eDTDMode_strict;
|
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) {
|
if(theModeStr) {
|
||||||
|
@ -754,7 +765,11 @@ nsresult nsParser::CreateCompatibleDTD(nsIDTD** aDTD,
|
||||||
nsDTDMode theDTDMode=eDTDMode_unknown;
|
nsDTDMode theDTDMode=eDTDMode_unknown;
|
||||||
eParserDocType theDocType=ePlainText;
|
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 ");
|
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) {
|
while(*theDocType) {
|
||||||
nsAutoString theType;
|
nsAutoString theType;
|
||||||
theType.AssignWithConversion(*theDocType);
|
theType.AssignWithConversion(*theDocType);
|
||||||
DetermineParseMode(theType,theParseMode,theDocumentType);
|
DetermineParseMode(theType,theParseMode,theDocumentType,mParserContext->mMimeType);
|
||||||
theDocType++;
|
theDocType++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -957,7 +972,7 @@ nsresult nsParser::WillBuildModel(nsString& aFilename){
|
||||||
mMinorIteration=-1;
|
mMinorIteration=-1;
|
||||||
|
|
||||||
nsString& theBuffer=mParserContext->mScanner->GetBuffer();
|
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)) {
|
if(PR_TRUE==FindSuitableDTD(*mParserContext,theBuffer)) {
|
||||||
mParserContext->mDTD->WillBuildModel( *mParserContext,mSink);
|
mParserContext->mDTD->WillBuildModel( *mParserContext,mSink);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче