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:
rickg%netscape.com 2000-05-25 06:19:32 +00:00
Родитель 8be92fb914
Коммит 8c6a6b0cb1
16 изменённых файлов: 1208 добавлений и 328 удалений

Просмотреть файл

@ -22,9 +22,10 @@
//#define ENABLE_CRC
//#define RICKG_DEBUG
#define ENABLE_RESIDUALSTYLE
//#define ALLOW_TR_AS_CHILD_OF_TABLE //by setting this to true, TR is allowable directly in TABLE.
#define ENABLE_RESIDUALSTYLE
#ifdef RICKG_DEBUG
#include <fstream.h>
#endif
@ -266,12 +267,24 @@ CNavDTD::~CNavDTD(){
/**
* Call this method if you want the DTD to construct a fresh
* instance of itself.
* @update gess7/23/98
* @update gess 25May2000
* @param
* @return
*/
nsresult CNavDTD::CreateNewInstance(nsIDTD** aInstancePtrResult){
return NS_NewNavHTMLDTD(aInstancePtrResult);
nsresult result=NS_NewNavHTMLDTD(aInstancePtrResult);
if(aInstancePtrResult) {
CNavDTD *theOtherDTD=(CNavDTD*)*aInstancePtrResult;
if(theOtherDTD) {
theOtherDTD->mDTDMode=mDTDMode;
theOtherDTD->mParserCommand=mParserCommand;
theOtherDTD->mDocType=mDocType;
}
}
return result;
}
/**
@ -827,10 +840,9 @@ nsresult CNavDTD::DidHandleStartTag(nsCParserNode& aNode,eHTMLTags aChildTag){
{
PRInt32 theCount=mBodyContext->GetCount();
eHTMLTags theGrandParentTag=mBodyContext->TagAt(theCount-2);
PRInt32 theCounter=mBodyContext->IncrementCounter(theGrandParentTag);
nsString theNumber;
theNumber.AppendInt(theCounter);
nsAutoString theNumber;
PRInt32 theCounter=mBodyContext->IncrementCounter(theGrandParentTag,aNode,theNumber);
CTextToken theToken(theNumber);
PRInt32 theLineNumber=0;
nsCParserNode theNode(&theToken,theLineNumber);
@ -838,6 +850,35 @@ nsresult CNavDTD::DidHandleStartTag(nsCParserNode& aNode,eHTMLTags aChildTag){
}
break;
case eHTMLTag_meta:
{
//we should only enable user-defined entities in debug builds...
PRInt32 theCount=aNode.GetAttributeCount();
const nsString* theNamePtr=0;
const nsString* theValuePtr=0;
if(theCount) {
PRInt32 theIndex=0;
for(theIndex=0;theIndex<theCount;theIndex++){
const nsString& theKey=aNode.GetKeyAt(theIndex);
if(theKey.EqualsWithConversion("ENTITY",PR_TRUE)) {
const nsString& theName=aNode.GetValueAt(theIndex);
theNamePtr=&theName;
}
else if(theKey.EqualsWithConversion("VALUE",PR_TRUE)) {
//store the named enity with the context...
const nsString& theValue=aNode.GetValueAt(theIndex);
theValuePtr=&theValue;
}
}
}
if(theNamePtr && theValuePtr) {
mBodyContext->RegisterEntity(*theNamePtr,*theValuePtr);
}
}
break;
default:
break;
}//switch
@ -1846,6 +1887,27 @@ nsresult CNavDTD::HandleEntityToken(CToken* aToken) {
NS_PRECONDITION(0!=aToken,kNullToken);
nsresult result=NS_OK;
nsString& theStr=aToken->GetStringValueXXX();
PRUnichar theChar=theStr.CharAt(0);
if((kHashsign!=theChar) && (-1==nsHTMLEntities::EntityToUnicode(theStr))){
//before we just toss this away as a bogus entity, let's check...
CNamedEntity *theEntity=mBodyContext->GetEntity(theStr);
CToken *theToken=0;
if(theEntity) {
theToken=new CTextToken(theEntity->mValue);
}
else {
//if you're here we have a bogus entity.
//convert it into a text token.
nsAutoString temp; temp.AssignWithConversion("&");
temp.Append(theStr);
theToken=new CTextToken(temp);
}
return HandleStartToken(theToken);
}
eHTMLTags theParentTag=mBodyContext->Last();
nsCParserNode* theNode=mNodeRecycler->CreateNode();

Просмотреть файл

@ -4,24 +4,24 @@
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
*
* Contributor(s):
*/
//#define ENABLE_CRC
//#define RICKG_DEBUG
//#define RICKG_DEBUG
#include "nsDebug.h"
@ -131,7 +131,7 @@ NS_IMPL_RELEASE(COtherDTD)
* @param
* @return
*/
COtherDTD::COtherDTD() : nsIDTD(), mMisplacedContent(0), mSkippedContent(0), mSharedNodes(0) {
COtherDTD::COtherDTD() : nsIDTD(), mSharedNodes(0) {
NS_INIT_REFCNT();
mSink = 0;
mParser=0;
@ -141,14 +141,17 @@ COtherDTD::COtherDTD() : nsIDTD(), mMisplacedContent(0), mSkippedContent(0), mSh
mHasOpenHead=0;
mHasOpenForm=PR_FALSE;
mHasOpenMap=PR_FALSE;
mHeadContext=new nsDTDContext();
mBodyContext=new nsDTDContext();
mFormContext=0;
mTokenizer=0;
mComputedCRC32=0;
mExpectedCRC32=0;
mDTDState=NS_OK;
mDocType=ePlainText;
mDocType=eHTML4Text;
mHadFrameset=PR_FALSE;
mHadBody=PR_FALSE;
mHasOpenScript=PR_FALSE;
mTokenRecycler=0;
mParserCommand=eViewNormal;
char* theEnvString = PR_GetEnv("ENABLE_STRICT");
mEnableStrict=PRBool(theEnvString!=0);
@ -280,7 +283,6 @@ const nsIID& COtherDTD::GetMostDerivedIID(void)const {
* @return
*/
COtherDTD::~COtherDTD(){
delete mHeadContext;
delete mBodyContext;
NS_IF_RELEASE(mTokenizer);
@ -336,7 +338,19 @@ NS_HTMLPARS nsresult NS_NewOtherHTMLDTD(nsIDTD** aInstancePtrResult) {
* @return
*/
nsresult COtherDTD::CreateNewInstance(nsIDTD** aInstancePtrResult){
return NS_NewOtherHTMLDTD(aInstancePtrResult);
nsresult result=NS_NewOtherHTMLDTD(aInstancePtrResult);
if(aInstancePtrResult) {
COtherDTD *theOtherDTD=(COtherDTD*)*aInstancePtrResult;
if(theOtherDTD) {
theOtherDTD->mDTDMode=mDTDMode;
theOtherDTD->mParserCommand=mParserCommand;
theOtherDTD->mDocType=mDocType;
theOtherDTD->mEnableStrict=mEnableStrict;
}
}
return result;
}
/**
@ -608,6 +622,7 @@ nsresult COtherDTD::HandleToken(CToken* aToken,nsIParser* aParser){
case eToken_start:
case eToken_whitespace:
case eToken_newline:
case eToken_doctypeDecl:
result=HandleStartToken(theToken); break;
case eToken_end:
@ -722,7 +737,7 @@ nsresult COtherDTD::WillHandleStartTag(CToken* aToken,eHTMLTags aTag,nsCParserNo
MOZ_TIMER_DEBUGLOG(("Start: Parse Time: COtherDTD::WillHandleStartTag(), this=%p\n", this));
START_TIMER()
return result;
return result;
}
@ -762,20 +777,20 @@ nsresult COtherDTD::HandleStartToken(CToken* aToken) {
if(NS_OK==result) {
mLineNumber += aToken->mNewlineCount;
PRBool theTagWasHandled=PR_FALSE;
switch(theChildTag) {
case eHTMLTag_html:
switch(theChildTag) {
case eHTMLTag_html:
if(!HasOpenContainer(theChildTag)) {
mSink->OpenHTML(*theNode);
mBodyContext->Push(theNode,0);
}
theTagWasHandled=PR_TRUE;
break;
default:
break;
default:
CElement* theElement=gElementTable->mElements[theParent];
if(theElement) {
result=theElement->HandleStartToken(theNode,theChildTag,mBodyContext,mSink);
@ -788,7 +803,7 @@ nsresult COtherDTD::HandleStartToken(CToken* aToken) {
DidHandleStartTag(*theNode,theChildTag);
}
} //if
} //if
}//if
RecycleNode(theNode);
@ -814,7 +829,7 @@ nsresult COtherDTD::HandleEndToken(CToken* aToken) {
nsresult result=NS_OK;
eHTMLTags theChildTag=(eHTMLTags)aToken->GetTypeID();
#ifdef RICKG_DEBUG
#ifdef RICKG_DEBUG
WriteTokenToLog(aToken);
#endif
@ -825,7 +840,7 @@ nsresult COtherDTD::HandleEndToken(CToken* aToken) {
break;
case eHTMLTag_script:
mHasOpenScript=PR_FALSE;
mHasOpenScript=PR_FALSE;
default:
PRInt32 theCount=mBodyContext->GetCount();
@ -838,7 +853,7 @@ nsresult COtherDTD::HandleEndToken(CToken* aToken) {
nsCParserNode theNode((CHTMLToken*)aToken,mLineNumber);
result=theElement->HandleEndToken(&theNode,theChildTag,mBodyContext,mSink);
}
break;
break;
}
return result;
@ -857,14 +872,12 @@ nsresult COtherDTD::CollectAttributes(nsCParserNode& aNode,eHTMLTags aTag,PRInt3
int attr=0;
nsresult result=NS_OK;
int theAvailTokenCount=mTokenizer->GetCount() + mSkippedContent.GetSize();
int theAvailTokenCount=mTokenizer->GetCount();
if(aCount<=theAvailTokenCount) {
CToken* theToken=0;
eHTMLTags theSkipTarget=gElementTable->mElements[aTag]->GetSkipTarget();
for(attr=0;attr<aCount;attr++){
if((eHTMLTag_unknown!=theSkipTarget) && mSkippedContent.GetSize())
theToken=(CToken*)mSkippedContent.PopFront();
else theToken=mTokenizer->PopToken();
theToken=mTokenizer->PopToken();
if(theToken) {
// Sanitize the key for it might contain some non-alpha-non-digit characters
// at its end. Ex. <OPTION SELECTED/> - This will be tokenized as "<" "OPTION",
@ -886,77 +899,6 @@ nsresult COtherDTD::CollectAttributes(nsCParserNode& aNode,eHTMLTags aTag,PRInt3
return result;
}
/**
* Causes the next skipped-content token (if any) to
* be consumed by this node.
* @update gess5/11/98
* @param node to consume skipped-content
* @param holds the number of skipped content elements encountered
* @return Error condition.
*/
nsresult COtherDTD::CollectSkippedContent(nsCParserNode& aNode,PRInt32 &aCount) {
eHTMLTags theNodeTag=(eHTMLTags)aNode.GetNodeType();
int aIndex=0;
int aMax=mSkippedContent.GetSize();
// XXX rickg This linefeed conversion stuff should be moved out of
// the parser and into the form element code
PRBool aMustConvertLinebreaks = PR_FALSE;
mScratch.SetLength(0);
aNode.SetSkippedContent(mScratch);
for(aIndex=0;aIndex<aMax;aIndex++){
CHTMLToken* theNextToken=(CHTMLToken*)mSkippedContent.PopFront();
eHTMLTokenTypes theTokenType=(eHTMLTokenTypes)theNextToken->GetTokenType();
mScratch.Truncate();
// Dont worry about attributes here because it's already stored in
// the start token as mTrailing content and will get appended in
// start token's GetSource();
if(eToken_attribute!=theTokenType) {
if (eToken_entity==theTokenType) {
if((eHTMLTag_textarea==theNodeTag) || (eHTMLTag_title==theNodeTag)) {
((CEntityToken*)theNextToken)->TranslateToUnicodeStr(mScratch);
// since this is an entity, we know that it's only one character.
// check to see if it's a CR, in which case we'll need to do line
// termination conversion at the end.
aMustConvertLinebreaks |= (mScratch[0] == kCR);
}
}
else theNextToken->GetSource(mScratch);
aNode.mSkippedContent->Append(mScratch);
}
mTokenRecycler->RecycleToken(theNextToken);
}
// if the string contained CRs (hence is either CR, or CRLF terminated)
// we need to convert line breaks
if (aMustConvertLinebreaks)
{
/*
PRInt32 offset;
while ((offset = aNode.mSkippedContent.Find("\r\n")) != kNotFound)
aNode.mSkippedContent.Cut(offset, 1); // remove the CR
// now replace remaining CRs with LFs
aNode.mSkippedContent.ReplaceChar("\r", kNewLine);
*/
#if 1
nsLinebreakConverter::ConvertStringLineBreaks(*aNode.mSkippedContent,
nsLinebreakConverter::eLinebreakAny, nsLinebreakConverter::eLinebreakContent);
#endif
}
// Let's hope that this does not hamper the PERFORMANCE!!
mLineNumber += aNode.mSkippedContent->CountChar(kNewLine);
return NS_OK;
}
/***********************************************************************************
The preceeding tables determine the set of elements each tag can contain...

Просмотреть файл

@ -340,7 +340,6 @@ CLASS_EXPORT_HTMLPARS COtherDTD : public nsIDTD {
protected:
nsresult CollectAttributes(nsCParserNode& aNode,eHTMLTags aTag,PRInt32 aCount);
nsresult CollectSkippedContent(nsCParserNode& aNode,PRInt32& aCount);
nsresult WillHandleStartTag(CToken* aToken,eHTMLTags aChildTag,nsCParserNode& aNode);
nsresult DidHandleStartTag(nsCParserNode& aNode,eHTMLTags aChildTag);
nsCParserNode* CreateNode(void);
@ -349,9 +348,7 @@ protected:
nsIHTMLContentSink* mSink;
nsDTDContext* mHeadContext;
nsDTDContext* mBodyContext;
nsDTDContext* mFormContext;
PRBool mHasOpenForm;
PRBool mHasOpenMap;
PRInt32 mHasOpenHead;
@ -364,10 +361,7 @@ protected:
nsParser* mParser;
nsITokenizer* mTokenizer;
CTokenRecycler* mTokenRecycler;
nsDeque mMisplacedContent;
nsDeque mSkippedContent;
PRBool mHasOpenScript;
PRBool mSaveBadTokens;
eHTMLTags mSkipTarget;
nsDeque mSharedNodes;
nsresult mDTDState;
@ -377,9 +371,8 @@ protected:
PRUint32 mComputedCRC32;
PRUint32 mExpectedCRC32;
nsAutoString mScratch; //used for various purposes; non-persistent
PRBool mStyleHandlingEnabled;
PRBool mEnableStrict;
eParserDocType mDocType;
PRBool mEnableStrict;
#ifdef NS_DEBUG
PRInt32 gNodeCount;

Просмотреть файл

@ -705,17 +705,19 @@ public:
case eHTMLTag_tr:
case eHTMLTag_th:
if(!aContext->HasOpenContainer(eHTMLTag_tbody)) {
nsCParserNode* theNode=new nsCParserNode();
CToken* theToken=new CStartToken(eHTMLTag_tbody);
theNode->Init(theToken,0,0); //this will likely leak...
if(aContext->mTableStates) {
if(aContext->mTableStates->CanOpenTBody()) {
nsCParserNode* theNode=new nsCParserNode();
CToken* theToken=new CStartToken(eHTMLTag_tbody);
theNode->Init(theToken,0,0); //this will likely leak...
result=HandleStartToken(theNode,eHTMLTag_tbody,aContext,aSink);
}
if(NS_SUCCEEDED(result)) {
CElement *theElement=GetElement(eHTMLTag_tbody);
if(theElement) {
result=theElement->HandleStartToken(aNode,aTag,aContext,aSink);
result=HandleStartToken(theNode,eHTMLTag_tbody,aContext,aSink);
}
if(NS_SUCCEEDED(result)) {
CElement *theElement=GetElement(eHTMLTag_tbody);
if(theElement) {
result=theElement->HandleStartToken(aNode,aTag,aContext,aSink);
}
}
}
@ -738,6 +740,7 @@ public:
case eHTMLTag_caption:
case eHTMLTag_col:
case eHTMLTag_colgroup:
case eHTMLTag_tr:
case eHTMLTag_thead:
case eHTMLTag_tfoot:
case eHTMLTag_tbody:
@ -928,23 +931,26 @@ public:
return CElement::HandleStartToken(aNode,aTag,aContext,aSink);
}
/**********************************************************
this gets called after each tag is opened in the given context
**********************************************************/
virtual nsresult OpenContainerInContext(nsIParserNode *aNode,eHTMLTags aTag,nsDTDContext *aContext,nsIHTMLContentSink *aSink) {
OpenContext(aNode,aTag,aContext,aSink);
nsresult result=OpenContainer(aNode,aTag,aContext,aSink);
if(NS_SUCCEEDED(result)) {
PRInt32 theCount=aContext->GetCount();
eHTMLTags theGrandParentTag=aContext->TagAt(theCount-2);
PRInt32 theCounter=aContext->IncrementCounter(theGrandParentTag);
nsString theNumber;
theNumber.AppendInt(theCounter);
nsCParserNode *theNode=(nsCParserNode*)aNode;
nsAutoString theNumber;
PRInt32 theCounter=aContext->IncrementCounter(theGrandParentTag,*theNode,theNumber);
CTextToken theToken(theNumber);
PRInt32 theLineNumber=0;
nsCParserNode theNode(&theToken,theLineNumber);
result=aSink->AddLeaf(theNode);
nsCParserNode theNewNode(&theToken,theLineNumber);
result=aSink->AddLeaf(theNewNode);
}
return result;
}
@ -1284,12 +1290,7 @@ public:
virtual nsresult NotifyClose(nsIParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
nsresult result=NS_OK;
if(aContext->HasOpenContainer(eHTMLTag_html)) {
aSink->OpenHead(*aNode);
result=CTextContainer::NotifyClose(aNode,aTag,aContext,aSink);
aSink->CloseHead(*aNode);
}
else {
if(aContext->HasOpenContainer(eHTMLTag_body)) {
//add the script to the body
CScriptToken theToken(mText);
PRInt32 theLineNumber=0;
@ -1297,6 +1298,12 @@ public:
theNode.SetSkippedContent(mText);
result=aSink->AddLeaf(theNode);
}
else {
//add it to the head...
aSink->OpenHead(*aNode);
result=CTextContainer::NotifyClose(aNode,aTag,aContext,aSink);
aSink->CloseHead(*aNode);
}
mText.Truncate(0);
return result;
}
@ -1628,6 +1635,28 @@ public:
CElement::Initialize(*this,aTag,CHTMLElement::GetGroup(),CHTMLElement::GetContainedGroups());
}
/**********************************************************
HTML handles the opening of it's own children
**********************************************************/
nsresult HandleDoctypeDecl( nsIParserNode* aNode,
eHTMLTags aTag,
nsDTDContext* aContext,
nsIHTMLContentSink* aSink) {
nsCParserNode *theNode=(nsCParserNode*)aNode;
nsresult result=NS_OK;
if(theNode) {
nsString theStr=theNode->mToken->GetStringValueXXX();
PRInt32 theLen=theStr.Length();
PRInt32 thePos=theStr.RFindChar(kGreaterThan);
theStr.Truncate(theLen-1);
theStr.Cut(0,2);
result = aSink->AddDocTypeDecl(*aNode,eDTDMode_strict);
}
return result;
}
/**********************************************************
HTML handles the opening of it's own children
@ -1639,6 +1668,10 @@ public:
nsresult result=NS_OK;
switch(aTag) {
case eHTMLTag_markupDecl:
result=HandleDoctypeDecl(aNode,aTag,aContext,aSink);
break;
case eHTMLTag_body:
result=aSink->OpenBody(*aNode);
result=OpenContext(aNode,aTag,aContext,aSink);
@ -1794,7 +1827,9 @@ public:
switch(aTag) {
case eHTMLTag_div:
case eHTMLTag_script:
result=OpenContext(aNode,aTag,aContext,aSink);
break;
default:
//for now, let's drop other elements onto the floor.
@ -1802,7 +1837,7 @@ public:
if(NS_SUCCEEDED(result)) {
nsCParserNode *theNode=(nsCParserNode*)aNode;
CStartToken *theToken=(CStartToken*)theNode->mToken;
if(theToken->IsEmpty()){
if(theToken->IsEmpty() && (aTag==aContext->Last())){
result=CElement::HandleEndToken(aNode,aTag,aContext,aSink);
}
}
@ -1817,7 +1852,15 @@ public:
a really convenient break point for debugging purposes.
**********************************************************/
virtual nsresult HandleEndToken(nsIParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
return CElement::HandleEndToken(aNode,aTag,aContext,aSink);
nsresult result=NS_OK;
switch(aTag) {
case eHTMLTag_script:
result=CloseContext(aNode,aTag,aContext,aSink);
break;
default:
result=CElement::HandleEndToken(aNode,aTag,aContext,aSink);
}
return result;
}
/**********************************************************

Просмотреть файл

@ -21,7 +21,7 @@
* Pierre Phaneuf <pp@ludusdesign.com>
*/
#include "nsDTDUtils.h"
#include "CNavDTD.h"
#include "nsIParserNode.h"
@ -363,7 +363,7 @@ CNodeRecycler* nsDTDContext::mNodeRecycler=0;
*
* @update gess 04.21.2000
*/
nsDTDContext::nsDTDContext() : mStack() {
nsDTDContext::nsDTDContext() : mStack(), mEntities(0){
MOZ_COUNT_CTOR(nsDTDContext);
mResidualStyleCount=0;
@ -379,6 +379,17 @@ nsDTDContext::nsDTDContext() : mStack() {
}
class CEntityDeallocator: public nsDequeFunctor{
public:
virtual void* operator()(void* anObject) {
CNamedEntity *theEntity=(CNamedEntity*)anObject;
delete theEntity;
return 0;
}
};
/**
*
* @update gess9/10/98
@ -391,9 +402,284 @@ nsDTDContext::~nsDTDContext() {
CTableState *theState=mTableStates;
mTableStates=theState->mPrevious;
delete theState;
}
}
CEntityDeallocator theDeallocator;
mEntities.ForEach(theDeallocator);
}
CNamedEntity* nsDTDContext::GetEntity(const nsString& aName)const {
PRInt32 theCount=mEntities.GetSize();
PRInt32 theIndex=0;
PRInt32 theLen=aName.Length();
PRUnichar theChar=aName.Last();
if(theLen>2) {
if(kSemicolon==theChar) {
theLen--;
}
const PRUnichar *theBuf=aName.GetUnicode();
if(kQuote==theBuf[0]) {
theBuf++;
theLen--;
}
if(kQuote==theChar) {
theLen--;
}
for(theIndex=0;theIndex<theCount;theIndex++) {
CNamedEntity *theResult=(CNamedEntity*)mEntities.ObjectAt(theIndex);
if(theResult && theResult->mName.EqualsWithConversion(theBuf,PR_TRUE,theLen)){
return theResult;
}
}
}
return 0;
}
CNamedEntity* nsDTDContext::RegisterEntity(const nsString& aName,const nsString& aValue) {
CNamedEntity *theEntity=GetEntity(aName);
if(!GetEntity(aName)){
theEntity=new CNamedEntity(aName,aValue);
mEntities.Push(theEntity);
}
return theEntity;
}
/****************************************************************
The abacus class is useful today for debug purposes, but it
will eventually serve as the implementation for css counters.
This implementation is fine for static documents, but woefully
inadequate for dynamic documents. (This about what happens if
someone inserts a new counter using the DOM? -- The other
numbers in that "group" should be renumbered.)
In order to be dynamic, we need a counter "group" manager that
is aware of layout (geometry at least) -- and that has a
mechanism for notifying markers that need to be updated, along
with the ability to cause incremental reflow to occur in a
localized context (so the counters display correctly).
****************************************************************/
class CAbacus {
public:
enum eNumFormat {eUnknown,eAlpha,eDecimal,eRoman,eSpoken,eHex,eBinary,eFootnote,eUserSeries};
CAbacus(PRInt32 aDefaultValue=0,eNumFormat aFormat=eDecimal) {
mUserSeries=0;
mFormat=aFormat;
mCase=false;
mValue=0;
mUserBase=0;
}
~CAbacus() {
}
void SetValue(int aStartValue) {mValue=aStartValue;}
void SetNumberingStyle(eNumFormat aFormat) {mFormat=aFormat;}
void SetUserSeries(const char* aSeries,int aUserBase) {mUserSeries=aSeries; mUserBase=aUserBase;}
void SetCase(PRBool alwaysUpper) {mCase=alwaysUpper;}
void GetNextValueAsString(nsString& aString) {
GetFormattedString(mFormat,mValue++,aString,mUserSeries,0,mUserBase);
}
void GetValueAsString(nsString& aString) {
GetFormattedString(mFormat,mValue,aString,mUserSeries,0,mUserBase);
}
static void GetFormattedString(eNumFormat aFormat,PRInt32 aValue, nsString& aString,const char* aCharSet, int anOffset, int aBase) {
switch (aFormat) {
case eDecimal: DecimalString(aValue,aString); break;
case eHex: HexString(aValue,aString); break;
case eBinary: BinaryString(aValue,aString); break;
case eAlpha: AlphaString(aValue,aString); break;
case eSpoken: SpokenString(aValue,aString); break;
case eRoman: RomanString(aValue,aString); break;
case eFootnote: FootnoteString(aValue,aString); break;
case eUserSeries: SeriesString(aValue,aString,aCharSet,anOffset,aBase);
}
}
static void SeriesString(PRInt32 aValue,nsString& aString,const char* aCharSet, int offset, int base) {
int ndex=0;
int root=1;
int next=base;
int expn=1;
aString.Truncate();
if(aValue<0)
aString.AppendWithConversion('-');
aValue=abs(aValue); // must be positive here...
while(next<=aValue) { // scale up in baseN; exceed current value.
root=next;
next*=base;
expn++;
}
while(expn--) {
ndex = ((root<=aValue) && (root)) ? (aValue/root): 0;
aValue%=root;
aString.AppendWithConversion(aCharSet[ndex+((root>1)*offset)]);
root/=base;
}
}
static void SpokenString(PRInt32 aValue,nsString& aString) {
static char ones[][12]= {"zero","one ","two ","three ","four ","five ","six ","seven ","eight ","nine ","ten "};
static char teens[][12]= {"ten ","eleven ","twelve ","thirteen ","fourteen ","fifteen ","sixteen ","seventeen ","eighteen ","nineteen "};
static char tens[][12]= {"","ten ","twenty ","thirty ","fourty ","fifty ","sixty ","seventy ","eighty ","ninety ","hundred "};
static char bases[][20]= {"","hundred ","thousand ","million ","billion ","trillion ","quadrillion ","quintillion ","bajillion "};
aString.Truncate();
if(aValue<0)
aString.AppendWithConversion('-');
PRInt32 root=1000000000;
PRInt32 expn=4;
PRInt32 modu=0;
PRInt32 div=0;
PRInt32 temp=0;
aValue=abs(aValue);
if(0<aValue) {
while(root && aValue) {
if(temp=aValue/root) {
if (div=temp/100) {//start with hundreds part
aString.AppendWithConversion(ones[div]);
aString.AppendWithConversion(bases[1]);
}
modu=(temp%10);
if (div=((temp%100)/10)) {
if (div<2) {
aString.AppendWithConversion(teens[modu]);
modu=0;
}
else aString.AppendWithConversion(tens[div]);
}
if (modu)
aString.AppendWithConversion(ones[modu]); //do remainder
aValue-=(temp*root);
if (expn>1)
aString.AppendWithConversion(bases[expn]);
}
expn--;
root/=1000;
}
}
else aString.AppendWithConversion(ones[0]);
}
static void DecimalString(PRInt32 aValue,nsString& aString) {
aString.Truncate();
aString.AppendInt(aValue);
}
static void BinaryString(PRInt32 aValue,nsString& aString) {
static char kBinarySet[]="01";
if (aValue<0)
aValue=65536-abs(aValue);
SeriesString(aValue,aString,kBinarySet,0,2);
}
static void HexString(PRInt32 aValue,nsString& aString) {
static char kHexSet[]="0123456789ABCDEF";
if (aValue<0)
aValue=65536-abs(aValue);
SeriesString(aValue,aString,kHexSet,0,16);
}
static void RomanString(PRInt32 aValue,nsString& aString) {
static char digitsA[] = "ixcm";
static char digitsB[] = "vld?";
aString.Truncate();
if(aValue<0)
aString.AppendWithConversion('-');
aValue=abs(aValue);
char decStr[20];
sprintf(decStr,"%d", aValue);
int len=strlen(decStr);
int romanPos=len;
int digitPos=0;
int n=0;
for(digitPos=0;digitPos<len;digitPos++) {
romanPos--;
switch(decStr[digitPos]) {
case '0': break;
case '3': aString.AppendWithConversion(digitsA[romanPos]);
case '2': aString.AppendWithConversion(digitsA[romanPos]);
case '1': aString.AppendWithConversion(digitsA[romanPos]);
break;
case '4': aString.AppendWithConversion(digitsA[romanPos]);
case '5': case '6':
case '7': case '8':
aString.AppendWithConversion(digitsB[romanPos]);
for(n=0;n<(decStr[digitPos]-'5');n++)
aString.AppendWithConversion(digitsA[romanPos]);
break;
case '9':
aString.AppendWithConversion(digitsA[romanPos]);
aString.AppendWithConversion(digitsA[romanPos]);
break;
}
}
}
static void AlphaString(PRInt32 aValue,nsString& aString) {
static const char kAlphaSet[]="abcdefghijklmnopqrstuvwxyz";
if (0<aValue)
SeriesString(aValue-1,aString,kAlphaSet,-1,26);
}
static void FootnoteString(PRInt32 aValue,nsString& aString) {
static char kFootnoteSet[]="abcdefg";
PRBool negative=(aValue<0);
int seriesLen = strlen (kFootnoteSet) - 1;
int count=0;
int repCount=0;
int modChar=0;
aString.Truncate();
aValue=abs(aValue);
repCount=((aValue-1)/seriesLen);
modChar=aValue-(repCount*seriesLen);
for(count=0;count<=repCount;count++) {
aString.AppendWithConversion(kFootnoteSet[modChar]);
}
}
protected:
const char* mUserSeries;
eNumFormat mFormat;
PRBool mCase;
PRInt32 mValue;
int mUserBase;
};
/**
*
* @update gess 11May2000
@ -402,22 +688,81 @@ void nsDTDContext::ResetCounters(void) {
memset(mCounters,0,sizeof(mCounters));
}
/**
*
* @update gess 11May2000
*/
PRInt32 nsDTDContext::IncrementCounter(eHTMLTags aTag) {
PRInt32 result=++mCounters[aTag];
/**********************************************************
@update: rickg 17May2000
Call this to handle counter attributes:
name="group"
value="nnn"
noincr="?"
format="alpha|dec|footnote|hex|roman|spoken"
returns the newly incremented value for the (determined) group.
**********************************************************/
PRInt32 nsDTDContext::IncrementCounter(eHTMLTags aTag,nsCParserNode& aNode,nsString& aResult) {
PRInt32 result=0;
PRInt32 theIndex=0;
PRInt32 theNewValue=-1; //-1 is interpreted to mean "don't reset the counter sequence.
PRInt32 theIncrValue=1; //this may get set to 0 if we see a "noincr" key.
PRInt32 theCount=aNode.GetAttributeCount();
CNamedEntity *theEntity=0;
CAbacus::eNumFormat theNumFormat=CAbacus::eDecimal;
for(theIndex=0;theIndex<theCount;theIndex++){
const nsString& theKey=aNode.GetKeyAt(theIndex);
const nsString& theValue=aNode.GetValueAt(theIndex);
if(theKey.EqualsWithConversion("name",PR_TRUE)){
theEntity=GetEntity(theValue);
if(!theEntity) {
theEntity=RegisterEntity(theValue,theValue);
theEntity->mOrdinal=0;
}
aTag=eHTMLTag_userdefined;
}
else if(theKey.EqualsWithConversion("noincr",PR_TRUE)){
theIncrValue=0;
}
else if(theKey.EqualsWithConversion("format",PR_TRUE)){
PRUnichar theChar=theValue.CharAt(0);
if('"'==theChar)
theChar=theValue.CharAt(1);
switch(theChar){
case 'A': case 'a': theNumFormat=CAbacus::eAlpha; break;
case 'B': case 'b': theNumFormat=CAbacus::eBinary; break;
case 'D': case 'd': theNumFormat=CAbacus::eDecimal; break;
case 'H': case 'h': theNumFormat=CAbacus::eHex; break;
case 'R': case 'r': theNumFormat=CAbacus::eRoman; break;
case 'S': case 's': theNumFormat=CAbacus::eSpoken; break;
default:
theNumFormat=CAbacus::eDecimal;
break;
}
//determine numbering style
}
else if(theKey.EqualsWithConversion("value",PR_TRUE)){
PRInt32 err=0;
theNewValue=theValue.ToInteger(&err);
if(!err) {
theIncrValue=0;
mCounters[aTag]=theNewValue;
}
else theNewValue=-1;
}
}
if(theEntity && (eHTMLTag_userdefined==aTag)) {
result=theEntity->mOrdinal+=theIncrValue;
}
else result=mCounters[aTag]+=theIncrValue;
CAbacus::GetFormattedString(theNumFormat,result,aResult,0,0,0);
return result;
}
/**
*
* @update gess 11May2000
*/
void nsDTDContext::ResetCounter(eHTMLTags aTag,PRInt32 aValue) {
mCounters[aTag]=aValue;
}
/**
*

Просмотреть файл

@ -155,6 +155,11 @@ public:
return result;
}
PRBool CanOpenTBody() {
PRBool result=!(mHasTBody);
return result;
}
PRBool CanOpenTHead() {
PRBool result=!(mHasTHead || mHasTFoot || mHasTBody);
return result;
@ -174,14 +179,42 @@ public:
};
//used for named entities and counters (XXX debug only)
class CNamedEntity {
public:
CNamedEntity(const nsString& aName,const nsString& aValue) : mName(), mValue() {
PRUnichar theFirst=aName.First();
PRUnichar theLast=aName.Last();
PRInt32 theLen=aName.Length();
if((2<theLen) && (theFirst==theLast) && (kQuote==theFirst)) {
aName.Mid(mName,1,theLen-2);
}
else mName=aName;
theFirst=aValue.First();
theLast=aValue.Last();
theLen=aValue.Length();
if((2<theLen) && (theFirst==theLast) && (kQuote==theFirst)) {
aValue.Mid(mValue,1,theLen-2);
}
else mValue=aValue;
}
nsAutoString mName;
nsAutoString mValue;
PRInt32 mOrdinal;
};
/************************************************************************
The dtdcontext class defines an ordered list of tags (a context).
************************************************************************/
class nsDTDContext {
public:
nsDTDContext();
~nsDTDContext();
nsDTDContext();
~nsDTDContext();
void Push(const nsIParserNode* aNode,nsEntryStack* aStyleStack=0);
nsIParserNode* Pop(nsEntryStack*& aChildStack);
@ -209,9 +242,11 @@ public:
nsresult GetNodeRecycler(CNodeRecycler*& aNodeRecycler);
static void FreeNodeRecycler(void);
CNamedEntity* RegisterEntity(const nsString& aName,const nsString& aValue);
CNamedEntity* GetEntity(const nsString& aName)const;
void ResetCounters(void);
void ResetCounter(eHTMLTags aTag,PRInt32 aNewValue);
PRInt32 IncrementCounter(eHTMLTags aTag);
PRInt32 IncrementCounter(eHTMLTags aTag,nsCParserNode& aNode,nsString& aResult);
nsEntryStack mStack; //this will hold a list of tagentries...
PRInt32 mResidualStyleCount;
@ -221,8 +256,10 @@ public:
static CNodeRecycler* mNodeRecycler;
CTableState *mTableStates;
CTableState *mTableStates;
PRInt32 mCounters[NS_HTML_TAG_MAX];
nsString mDefaultEntity;
nsDeque mEntities;
#ifdef NS_DEBUG
enum { eMaxTags = 100 };

Просмотреть файл

@ -630,7 +630,9 @@ nsresult nsHTMLTokenizer::ConsumeEntity(PRUnichar aChar,CToken*& aToken,nsScanne
return ConsumeText(temp,aToken,aScanner);
}//if
if(aToken){
#if 0
nsString& theStr=aToken->GetStringValueXXX();
if((kHashsign!=theChar) && (-1==nsHTMLEntities::EntityToUnicode(theStr))){
//if you're here we have a bogus entity.
//convert it into a text token.
@ -640,6 +642,7 @@ nsresult nsHTMLTokenizer::ConsumeEntity(PRUnichar aChar,CToken*& aToken,nsScanne
theRecycler->RecycleToken(aToken);
aToken=theToken;
}
#endif
AddToken(aToken,result,&mTokenDeque,theRecycler);
}
}//if

Просмотреть файл

@ -102,12 +102,13 @@ public:
//Note: To cut down on startup time/overhead, we defer the construction of non-html DTD's.
nsIDTD* theDTD;
NS_NewNavHTMLDTD(&theDTD); //do this as a default HTML DTD...
mDTDDeque.Push(theDTD);
#if 1
NS_NewOtherHTMLDTD(&theDTD); //do this as the default DTD for strict documents...
mDTDDeque.Push(theDTD);
#endif
mHasViewSourceDTD=PR_FALSE;
mHasRTFDTD=mHasXMLDTD=PR_FALSE;
}
@ -485,7 +486,7 @@ nsDTDMode nsParser::GetParseMode(void){
* @return parsermode (define in nsIParser.h)
*/
static
void DetermineParseMode(nsString& aBuffer,nsDTDMode& aParseMode,eParserDocType& aDocType) {
void DetermineParseMode(nsString& aBuffer,nsDTDMode& aParseMode,eParserDocType& aDocType,const nsString& aMimeType) {
const char* theModeStr= PR_GetEnv("PARSE_MODE");
aParseMode = eDTDMode_unknown;
@ -613,8 +614,18 @@ void DetermineParseMode(nsString& aBuffer,nsDTDMode& aParseMode,eParserDocType&
}
}
else if(kNotFound<(theIndex=aBuffer.Find("?XML",PR_TRUE,0,128))) {
aDocType=eXMLText;
aParseMode=eDTDMode_strict;
if(aMimeType.EqualsWithConversion(kHTMLTextContentType)) {
//this is here to prevent a crash if someone gives us an XML document,
//but necko tells us it's a text/html mimetype.
aDocType=eHTML4Text;
aParseMode=eDTDMode_strict;
}
else aDocType=eXMLText;
}
else if(aMimeType.EqualsWithConversion(kPlainTextContentType)) {
aDocType=ePlainText;
aParseMode=eDTDMode_quirks;
}
if(theModeStr) {
@ -754,7 +765,11 @@ nsresult nsParser::CreateCompatibleDTD(nsIDTD** aDTD,
nsDTDMode theDTDMode=eDTDMode_unknown;
eParserDocType theDocType=ePlainText;
DetermineParseMode(*aDocTypeStr,theDTDMode,theDocType);
if(!aMimeType) {
nsAutoString temp;
DetermineParseMode(*aDocTypeStr,theDTDMode,theDocType,temp);
}
else DetermineParseMode(*aDocTypeStr,theDTDMode,theDocType,*aMimeType);
NS_ASSERTION(aDTDMode==eDTDMode_unknown || aDTDMode==theDTDMode,"aDTDMode overrides the mode selected from the DOCTYPE ");
@ -945,7 +960,7 @@ nsresult nsParser::WillBuildModel(nsString& aFilename){
while(*theDocType) {
nsAutoString theType;
theType.AssignWithConversion(*theDocType);
DetermineParseMode(theType,theParseMode,theDocumentType);
DetermineParseMode(theType,theParseMode,theDocumentType,mParserContext->mMimeType);
theDocType++;
}
}
@ -957,7 +972,7 @@ nsresult nsParser::WillBuildModel(nsString& aFilename){
mMinorIteration=-1;
nsString& theBuffer=mParserContext->mScanner->GetBuffer();
DetermineParseMode(theBuffer,mParserContext->mDTDMode,mParserContext->mDocType);
DetermineParseMode(theBuffer,mParserContext->mDTDMode,mParserContext->mDocType,mParserContext->mMimeType);
if(PR_TRUE==FindSuitableDTD(*mParserContext,theBuffer)) {
mParserContext->mDTD->WillBuildModel( *mParserContext,mSink);

Просмотреть файл

@ -22,9 +22,10 @@
//#define ENABLE_CRC
//#define RICKG_DEBUG
#define ENABLE_RESIDUALSTYLE
//#define ALLOW_TR_AS_CHILD_OF_TABLE //by setting this to true, TR is allowable directly in TABLE.
#define ENABLE_RESIDUALSTYLE
#ifdef RICKG_DEBUG
#include <fstream.h>
#endif
@ -266,12 +267,24 @@ CNavDTD::~CNavDTD(){
/**
* Call this method if you want the DTD to construct a fresh
* instance of itself.
* @update gess7/23/98
* @update gess 25May2000
* @param
* @return
*/
nsresult CNavDTD::CreateNewInstance(nsIDTD** aInstancePtrResult){
return NS_NewNavHTMLDTD(aInstancePtrResult);
nsresult result=NS_NewNavHTMLDTD(aInstancePtrResult);
if(aInstancePtrResult) {
CNavDTD *theOtherDTD=(CNavDTD*)*aInstancePtrResult;
if(theOtherDTD) {
theOtherDTD->mDTDMode=mDTDMode;
theOtherDTD->mParserCommand=mParserCommand;
theOtherDTD->mDocType=mDocType;
}
}
return result;
}
/**
@ -827,10 +840,9 @@ nsresult CNavDTD::DidHandleStartTag(nsCParserNode& aNode,eHTMLTags aChildTag){
{
PRInt32 theCount=mBodyContext->GetCount();
eHTMLTags theGrandParentTag=mBodyContext->TagAt(theCount-2);
PRInt32 theCounter=mBodyContext->IncrementCounter(theGrandParentTag);
nsString theNumber;
theNumber.AppendInt(theCounter);
nsAutoString theNumber;
PRInt32 theCounter=mBodyContext->IncrementCounter(theGrandParentTag,aNode,theNumber);
CTextToken theToken(theNumber);
PRInt32 theLineNumber=0;
nsCParserNode theNode(&theToken,theLineNumber);
@ -838,6 +850,35 @@ nsresult CNavDTD::DidHandleStartTag(nsCParserNode& aNode,eHTMLTags aChildTag){
}
break;
case eHTMLTag_meta:
{
//we should only enable user-defined entities in debug builds...
PRInt32 theCount=aNode.GetAttributeCount();
const nsString* theNamePtr=0;
const nsString* theValuePtr=0;
if(theCount) {
PRInt32 theIndex=0;
for(theIndex=0;theIndex<theCount;theIndex++){
const nsString& theKey=aNode.GetKeyAt(theIndex);
if(theKey.EqualsWithConversion("ENTITY",PR_TRUE)) {
const nsString& theName=aNode.GetValueAt(theIndex);
theNamePtr=&theName;
}
else if(theKey.EqualsWithConversion("VALUE",PR_TRUE)) {
//store the named enity with the context...
const nsString& theValue=aNode.GetValueAt(theIndex);
theValuePtr=&theValue;
}
}
}
if(theNamePtr && theValuePtr) {
mBodyContext->RegisterEntity(*theNamePtr,*theValuePtr);
}
}
break;
default:
break;
}//switch
@ -1846,6 +1887,27 @@ nsresult CNavDTD::HandleEntityToken(CToken* aToken) {
NS_PRECONDITION(0!=aToken,kNullToken);
nsresult result=NS_OK;
nsString& theStr=aToken->GetStringValueXXX();
PRUnichar theChar=theStr.CharAt(0);
if((kHashsign!=theChar) && (-1==nsHTMLEntities::EntityToUnicode(theStr))){
//before we just toss this away as a bogus entity, let's check...
CNamedEntity *theEntity=mBodyContext->GetEntity(theStr);
CToken *theToken=0;
if(theEntity) {
theToken=new CTextToken(theEntity->mValue);
}
else {
//if you're here we have a bogus entity.
//convert it into a text token.
nsAutoString temp; temp.AssignWithConversion("&");
temp.Append(theStr);
theToken=new CTextToken(temp);
}
return HandleStartToken(theToken);
}
eHTMLTags theParentTag=mBodyContext->Last();
nsCParserNode* theNode=mNodeRecycler->CreateNode();

Просмотреть файл

@ -4,24 +4,24 @@
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
*
* Contributor(s):
*/
//#define ENABLE_CRC
//#define RICKG_DEBUG
//#define RICKG_DEBUG
#include "nsDebug.h"
@ -131,7 +131,7 @@ NS_IMPL_RELEASE(COtherDTD)
* @param
* @return
*/
COtherDTD::COtherDTD() : nsIDTD(), mMisplacedContent(0), mSkippedContent(0), mSharedNodes(0) {
COtherDTD::COtherDTD() : nsIDTD(), mSharedNodes(0) {
NS_INIT_REFCNT();
mSink = 0;
mParser=0;
@ -141,14 +141,17 @@ COtherDTD::COtherDTD() : nsIDTD(), mMisplacedContent(0), mSkippedContent(0), mSh
mHasOpenHead=0;
mHasOpenForm=PR_FALSE;
mHasOpenMap=PR_FALSE;
mHeadContext=new nsDTDContext();
mBodyContext=new nsDTDContext();
mFormContext=0;
mTokenizer=0;
mComputedCRC32=0;
mExpectedCRC32=0;
mDTDState=NS_OK;
mDocType=ePlainText;
mDocType=eHTML4Text;
mHadFrameset=PR_FALSE;
mHadBody=PR_FALSE;
mHasOpenScript=PR_FALSE;
mTokenRecycler=0;
mParserCommand=eViewNormal;
char* theEnvString = PR_GetEnv("ENABLE_STRICT");
mEnableStrict=PRBool(theEnvString!=0);
@ -280,7 +283,6 @@ const nsIID& COtherDTD::GetMostDerivedIID(void)const {
* @return
*/
COtherDTD::~COtherDTD(){
delete mHeadContext;
delete mBodyContext;
NS_IF_RELEASE(mTokenizer);
@ -336,7 +338,19 @@ NS_HTMLPARS nsresult NS_NewOtherHTMLDTD(nsIDTD** aInstancePtrResult) {
* @return
*/
nsresult COtherDTD::CreateNewInstance(nsIDTD** aInstancePtrResult){
return NS_NewOtherHTMLDTD(aInstancePtrResult);
nsresult result=NS_NewOtherHTMLDTD(aInstancePtrResult);
if(aInstancePtrResult) {
COtherDTD *theOtherDTD=(COtherDTD*)*aInstancePtrResult;
if(theOtherDTD) {
theOtherDTD->mDTDMode=mDTDMode;
theOtherDTD->mParserCommand=mParserCommand;
theOtherDTD->mDocType=mDocType;
theOtherDTD->mEnableStrict=mEnableStrict;
}
}
return result;
}
/**
@ -608,6 +622,7 @@ nsresult COtherDTD::HandleToken(CToken* aToken,nsIParser* aParser){
case eToken_start:
case eToken_whitespace:
case eToken_newline:
case eToken_doctypeDecl:
result=HandleStartToken(theToken); break;
case eToken_end:
@ -722,7 +737,7 @@ nsresult COtherDTD::WillHandleStartTag(CToken* aToken,eHTMLTags aTag,nsCParserNo
MOZ_TIMER_DEBUGLOG(("Start: Parse Time: COtherDTD::WillHandleStartTag(), this=%p\n", this));
START_TIMER()
return result;
return result;
}
@ -762,20 +777,20 @@ nsresult COtherDTD::HandleStartToken(CToken* aToken) {
if(NS_OK==result) {
mLineNumber += aToken->mNewlineCount;
PRBool theTagWasHandled=PR_FALSE;
switch(theChildTag) {
case eHTMLTag_html:
switch(theChildTag) {
case eHTMLTag_html:
if(!HasOpenContainer(theChildTag)) {
mSink->OpenHTML(*theNode);
mBodyContext->Push(theNode,0);
}
theTagWasHandled=PR_TRUE;
break;
default:
break;
default:
CElement* theElement=gElementTable->mElements[theParent];
if(theElement) {
result=theElement->HandleStartToken(theNode,theChildTag,mBodyContext,mSink);
@ -788,7 +803,7 @@ nsresult COtherDTD::HandleStartToken(CToken* aToken) {
DidHandleStartTag(*theNode,theChildTag);
}
} //if
} //if
}//if
RecycleNode(theNode);
@ -814,7 +829,7 @@ nsresult COtherDTD::HandleEndToken(CToken* aToken) {
nsresult result=NS_OK;
eHTMLTags theChildTag=(eHTMLTags)aToken->GetTypeID();
#ifdef RICKG_DEBUG
#ifdef RICKG_DEBUG
WriteTokenToLog(aToken);
#endif
@ -825,7 +840,7 @@ nsresult COtherDTD::HandleEndToken(CToken* aToken) {
break;
case eHTMLTag_script:
mHasOpenScript=PR_FALSE;
mHasOpenScript=PR_FALSE;
default:
PRInt32 theCount=mBodyContext->GetCount();
@ -838,7 +853,7 @@ nsresult COtherDTD::HandleEndToken(CToken* aToken) {
nsCParserNode theNode((CHTMLToken*)aToken,mLineNumber);
result=theElement->HandleEndToken(&theNode,theChildTag,mBodyContext,mSink);
}
break;
break;
}
return result;
@ -857,14 +872,12 @@ nsresult COtherDTD::CollectAttributes(nsCParserNode& aNode,eHTMLTags aTag,PRInt3
int attr=0;
nsresult result=NS_OK;
int theAvailTokenCount=mTokenizer->GetCount() + mSkippedContent.GetSize();
int theAvailTokenCount=mTokenizer->GetCount();
if(aCount<=theAvailTokenCount) {
CToken* theToken=0;
eHTMLTags theSkipTarget=gElementTable->mElements[aTag]->GetSkipTarget();
for(attr=0;attr<aCount;attr++){
if((eHTMLTag_unknown!=theSkipTarget) && mSkippedContent.GetSize())
theToken=(CToken*)mSkippedContent.PopFront();
else theToken=mTokenizer->PopToken();
theToken=mTokenizer->PopToken();
if(theToken) {
// Sanitize the key for it might contain some non-alpha-non-digit characters
// at its end. Ex. <OPTION SELECTED/> - This will be tokenized as "<" "OPTION",
@ -886,77 +899,6 @@ nsresult COtherDTD::CollectAttributes(nsCParserNode& aNode,eHTMLTags aTag,PRInt3
return result;
}
/**
* Causes the next skipped-content token (if any) to
* be consumed by this node.
* @update gess5/11/98
* @param node to consume skipped-content
* @param holds the number of skipped content elements encountered
* @return Error condition.
*/
nsresult COtherDTD::CollectSkippedContent(nsCParserNode& aNode,PRInt32 &aCount) {
eHTMLTags theNodeTag=(eHTMLTags)aNode.GetNodeType();
int aIndex=0;
int aMax=mSkippedContent.GetSize();
// XXX rickg This linefeed conversion stuff should be moved out of
// the parser and into the form element code
PRBool aMustConvertLinebreaks = PR_FALSE;
mScratch.SetLength(0);
aNode.SetSkippedContent(mScratch);
for(aIndex=0;aIndex<aMax;aIndex++){
CHTMLToken* theNextToken=(CHTMLToken*)mSkippedContent.PopFront();
eHTMLTokenTypes theTokenType=(eHTMLTokenTypes)theNextToken->GetTokenType();
mScratch.Truncate();
// Dont worry about attributes here because it's already stored in
// the start token as mTrailing content and will get appended in
// start token's GetSource();
if(eToken_attribute!=theTokenType) {
if (eToken_entity==theTokenType) {
if((eHTMLTag_textarea==theNodeTag) || (eHTMLTag_title==theNodeTag)) {
((CEntityToken*)theNextToken)->TranslateToUnicodeStr(mScratch);
// since this is an entity, we know that it's only one character.
// check to see if it's a CR, in which case we'll need to do line
// termination conversion at the end.
aMustConvertLinebreaks |= (mScratch[0] == kCR);
}
}
else theNextToken->GetSource(mScratch);
aNode.mSkippedContent->Append(mScratch);
}
mTokenRecycler->RecycleToken(theNextToken);
}
// if the string contained CRs (hence is either CR, or CRLF terminated)
// we need to convert line breaks
if (aMustConvertLinebreaks)
{
/*
PRInt32 offset;
while ((offset = aNode.mSkippedContent.Find("\r\n")) != kNotFound)
aNode.mSkippedContent.Cut(offset, 1); // remove the CR
// now replace remaining CRs with LFs
aNode.mSkippedContent.ReplaceChar("\r", kNewLine);
*/
#if 1
nsLinebreakConverter::ConvertStringLineBreaks(*aNode.mSkippedContent,
nsLinebreakConverter::eLinebreakAny, nsLinebreakConverter::eLinebreakContent);
#endif
}
// Let's hope that this does not hamper the PERFORMANCE!!
mLineNumber += aNode.mSkippedContent->CountChar(kNewLine);
return NS_OK;
}
/***********************************************************************************
The preceeding tables determine the set of elements each tag can contain...

Просмотреть файл

@ -340,7 +340,6 @@ CLASS_EXPORT_HTMLPARS COtherDTD : public nsIDTD {
protected:
nsresult CollectAttributes(nsCParserNode& aNode,eHTMLTags aTag,PRInt32 aCount);
nsresult CollectSkippedContent(nsCParserNode& aNode,PRInt32& aCount);
nsresult WillHandleStartTag(CToken* aToken,eHTMLTags aChildTag,nsCParserNode& aNode);
nsresult DidHandleStartTag(nsCParserNode& aNode,eHTMLTags aChildTag);
nsCParserNode* CreateNode(void);
@ -349,9 +348,7 @@ protected:
nsIHTMLContentSink* mSink;
nsDTDContext* mHeadContext;
nsDTDContext* mBodyContext;
nsDTDContext* mFormContext;
PRBool mHasOpenForm;
PRBool mHasOpenMap;
PRInt32 mHasOpenHead;
@ -364,10 +361,7 @@ protected:
nsParser* mParser;
nsITokenizer* mTokenizer;
CTokenRecycler* mTokenRecycler;
nsDeque mMisplacedContent;
nsDeque mSkippedContent;
PRBool mHasOpenScript;
PRBool mSaveBadTokens;
eHTMLTags mSkipTarget;
nsDeque mSharedNodes;
nsresult mDTDState;
@ -377,9 +371,8 @@ protected:
PRUint32 mComputedCRC32;
PRUint32 mExpectedCRC32;
nsAutoString mScratch; //used for various purposes; non-persistent
PRBool mStyleHandlingEnabled;
PRBool mEnableStrict;
eParserDocType mDocType;
PRBool mEnableStrict;
#ifdef NS_DEBUG
PRInt32 gNodeCount;

Просмотреть файл

@ -705,17 +705,19 @@ public:
case eHTMLTag_tr:
case eHTMLTag_th:
if(!aContext->HasOpenContainer(eHTMLTag_tbody)) {
nsCParserNode* theNode=new nsCParserNode();
CToken* theToken=new CStartToken(eHTMLTag_tbody);
theNode->Init(theToken,0,0); //this will likely leak...
if(aContext->mTableStates) {
if(aContext->mTableStates->CanOpenTBody()) {
nsCParserNode* theNode=new nsCParserNode();
CToken* theToken=new CStartToken(eHTMLTag_tbody);
theNode->Init(theToken,0,0); //this will likely leak...
result=HandleStartToken(theNode,eHTMLTag_tbody,aContext,aSink);
}
if(NS_SUCCEEDED(result)) {
CElement *theElement=GetElement(eHTMLTag_tbody);
if(theElement) {
result=theElement->HandleStartToken(aNode,aTag,aContext,aSink);
result=HandleStartToken(theNode,eHTMLTag_tbody,aContext,aSink);
}
if(NS_SUCCEEDED(result)) {
CElement *theElement=GetElement(eHTMLTag_tbody);
if(theElement) {
result=theElement->HandleStartToken(aNode,aTag,aContext,aSink);
}
}
}
@ -738,6 +740,7 @@ public:
case eHTMLTag_caption:
case eHTMLTag_col:
case eHTMLTag_colgroup:
case eHTMLTag_tr:
case eHTMLTag_thead:
case eHTMLTag_tfoot:
case eHTMLTag_tbody:
@ -928,23 +931,26 @@ public:
return CElement::HandleStartToken(aNode,aTag,aContext,aSink);
}
/**********************************************************
this gets called after each tag is opened in the given context
**********************************************************/
virtual nsresult OpenContainerInContext(nsIParserNode *aNode,eHTMLTags aTag,nsDTDContext *aContext,nsIHTMLContentSink *aSink) {
OpenContext(aNode,aTag,aContext,aSink);
nsresult result=OpenContainer(aNode,aTag,aContext,aSink);
if(NS_SUCCEEDED(result)) {
PRInt32 theCount=aContext->GetCount();
eHTMLTags theGrandParentTag=aContext->TagAt(theCount-2);
PRInt32 theCounter=aContext->IncrementCounter(theGrandParentTag);
nsString theNumber;
theNumber.AppendInt(theCounter);
nsCParserNode *theNode=(nsCParserNode*)aNode;
nsAutoString theNumber;
PRInt32 theCounter=aContext->IncrementCounter(theGrandParentTag,*theNode,theNumber);
CTextToken theToken(theNumber);
PRInt32 theLineNumber=0;
nsCParserNode theNode(&theToken,theLineNumber);
result=aSink->AddLeaf(theNode);
nsCParserNode theNewNode(&theToken,theLineNumber);
result=aSink->AddLeaf(theNewNode);
}
return result;
}
@ -1284,12 +1290,7 @@ public:
virtual nsresult NotifyClose(nsIParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
nsresult result=NS_OK;
if(aContext->HasOpenContainer(eHTMLTag_html)) {
aSink->OpenHead(*aNode);
result=CTextContainer::NotifyClose(aNode,aTag,aContext,aSink);
aSink->CloseHead(*aNode);
}
else {
if(aContext->HasOpenContainer(eHTMLTag_body)) {
//add the script to the body
CScriptToken theToken(mText);
PRInt32 theLineNumber=0;
@ -1297,6 +1298,12 @@ public:
theNode.SetSkippedContent(mText);
result=aSink->AddLeaf(theNode);
}
else {
//add it to the head...
aSink->OpenHead(*aNode);
result=CTextContainer::NotifyClose(aNode,aTag,aContext,aSink);
aSink->CloseHead(*aNode);
}
mText.Truncate(0);
return result;
}
@ -1628,6 +1635,28 @@ public:
CElement::Initialize(*this,aTag,CHTMLElement::GetGroup(),CHTMLElement::GetContainedGroups());
}
/**********************************************************
HTML handles the opening of it's own children
**********************************************************/
nsresult HandleDoctypeDecl( nsIParserNode* aNode,
eHTMLTags aTag,
nsDTDContext* aContext,
nsIHTMLContentSink* aSink) {
nsCParserNode *theNode=(nsCParserNode*)aNode;
nsresult result=NS_OK;
if(theNode) {
nsString theStr=theNode->mToken->GetStringValueXXX();
PRInt32 theLen=theStr.Length();
PRInt32 thePos=theStr.RFindChar(kGreaterThan);
theStr.Truncate(theLen-1);
theStr.Cut(0,2);
result = aSink->AddDocTypeDecl(*aNode,eDTDMode_strict);
}
return result;
}
/**********************************************************
HTML handles the opening of it's own children
@ -1639,6 +1668,10 @@ public:
nsresult result=NS_OK;
switch(aTag) {
case eHTMLTag_markupDecl:
result=HandleDoctypeDecl(aNode,aTag,aContext,aSink);
break;
case eHTMLTag_body:
result=aSink->OpenBody(*aNode);
result=OpenContext(aNode,aTag,aContext,aSink);
@ -1794,7 +1827,9 @@ public:
switch(aTag) {
case eHTMLTag_div:
case eHTMLTag_script:
result=OpenContext(aNode,aTag,aContext,aSink);
break;
default:
//for now, let's drop other elements onto the floor.
@ -1802,7 +1837,7 @@ public:
if(NS_SUCCEEDED(result)) {
nsCParserNode *theNode=(nsCParserNode*)aNode;
CStartToken *theToken=(CStartToken*)theNode->mToken;
if(theToken->IsEmpty()){
if(theToken->IsEmpty() && (aTag==aContext->Last())){
result=CElement::HandleEndToken(aNode,aTag,aContext,aSink);
}
}
@ -1817,7 +1852,15 @@ public:
a really convenient break point for debugging purposes.
**********************************************************/
virtual nsresult HandleEndToken(nsIParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
return CElement::HandleEndToken(aNode,aTag,aContext,aSink);
nsresult result=NS_OK;
switch(aTag) {
case eHTMLTag_script:
result=CloseContext(aNode,aTag,aContext,aSink);
break;
default:
result=CElement::HandleEndToken(aNode,aTag,aContext,aSink);
}
return result;
}
/**********************************************************

Просмотреть файл

@ -21,7 +21,7 @@
* Pierre Phaneuf <pp@ludusdesign.com>
*/
#include "nsDTDUtils.h"
#include "CNavDTD.h"
#include "nsIParserNode.h"
@ -363,7 +363,7 @@ CNodeRecycler* nsDTDContext::mNodeRecycler=0;
*
* @update gess 04.21.2000
*/
nsDTDContext::nsDTDContext() : mStack() {
nsDTDContext::nsDTDContext() : mStack(), mEntities(0){
MOZ_COUNT_CTOR(nsDTDContext);
mResidualStyleCount=0;
@ -379,6 +379,17 @@ nsDTDContext::nsDTDContext() : mStack() {
}
class CEntityDeallocator: public nsDequeFunctor{
public:
virtual void* operator()(void* anObject) {
CNamedEntity *theEntity=(CNamedEntity*)anObject;
delete theEntity;
return 0;
}
};
/**
*
* @update gess9/10/98
@ -391,9 +402,284 @@ nsDTDContext::~nsDTDContext() {
CTableState *theState=mTableStates;
mTableStates=theState->mPrevious;
delete theState;
}
}
CEntityDeallocator theDeallocator;
mEntities.ForEach(theDeallocator);
}
CNamedEntity* nsDTDContext::GetEntity(const nsString& aName)const {
PRInt32 theCount=mEntities.GetSize();
PRInt32 theIndex=0;
PRInt32 theLen=aName.Length();
PRUnichar theChar=aName.Last();
if(theLen>2) {
if(kSemicolon==theChar) {
theLen--;
}
const PRUnichar *theBuf=aName.GetUnicode();
if(kQuote==theBuf[0]) {
theBuf++;
theLen--;
}
if(kQuote==theChar) {
theLen--;
}
for(theIndex=0;theIndex<theCount;theIndex++) {
CNamedEntity *theResult=(CNamedEntity*)mEntities.ObjectAt(theIndex);
if(theResult && theResult->mName.EqualsWithConversion(theBuf,PR_TRUE,theLen)){
return theResult;
}
}
}
return 0;
}
CNamedEntity* nsDTDContext::RegisterEntity(const nsString& aName,const nsString& aValue) {
CNamedEntity *theEntity=GetEntity(aName);
if(!GetEntity(aName)){
theEntity=new CNamedEntity(aName,aValue);
mEntities.Push(theEntity);
}
return theEntity;
}
/****************************************************************
The abacus class is useful today for debug purposes, but it
will eventually serve as the implementation for css counters.
This implementation is fine for static documents, but woefully
inadequate for dynamic documents. (This about what happens if
someone inserts a new counter using the DOM? -- The other
numbers in that "group" should be renumbered.)
In order to be dynamic, we need a counter "group" manager that
is aware of layout (geometry at least) -- and that has a
mechanism for notifying markers that need to be updated, along
with the ability to cause incremental reflow to occur in a
localized context (so the counters display correctly).
****************************************************************/
class CAbacus {
public:
enum eNumFormat {eUnknown,eAlpha,eDecimal,eRoman,eSpoken,eHex,eBinary,eFootnote,eUserSeries};
CAbacus(PRInt32 aDefaultValue=0,eNumFormat aFormat=eDecimal) {
mUserSeries=0;
mFormat=aFormat;
mCase=false;
mValue=0;
mUserBase=0;
}
~CAbacus() {
}
void SetValue(int aStartValue) {mValue=aStartValue;}
void SetNumberingStyle(eNumFormat aFormat) {mFormat=aFormat;}
void SetUserSeries(const char* aSeries,int aUserBase) {mUserSeries=aSeries; mUserBase=aUserBase;}
void SetCase(PRBool alwaysUpper) {mCase=alwaysUpper;}
void GetNextValueAsString(nsString& aString) {
GetFormattedString(mFormat,mValue++,aString,mUserSeries,0,mUserBase);
}
void GetValueAsString(nsString& aString) {
GetFormattedString(mFormat,mValue,aString,mUserSeries,0,mUserBase);
}
static void GetFormattedString(eNumFormat aFormat,PRInt32 aValue, nsString& aString,const char* aCharSet, int anOffset, int aBase) {
switch (aFormat) {
case eDecimal: DecimalString(aValue,aString); break;
case eHex: HexString(aValue,aString); break;
case eBinary: BinaryString(aValue,aString); break;
case eAlpha: AlphaString(aValue,aString); break;
case eSpoken: SpokenString(aValue,aString); break;
case eRoman: RomanString(aValue,aString); break;
case eFootnote: FootnoteString(aValue,aString); break;
case eUserSeries: SeriesString(aValue,aString,aCharSet,anOffset,aBase);
}
}
static void SeriesString(PRInt32 aValue,nsString& aString,const char* aCharSet, int offset, int base) {
int ndex=0;
int root=1;
int next=base;
int expn=1;
aString.Truncate();
if(aValue<0)
aString.AppendWithConversion('-');
aValue=abs(aValue); // must be positive here...
while(next<=aValue) { // scale up in baseN; exceed current value.
root=next;
next*=base;
expn++;
}
while(expn--) {
ndex = ((root<=aValue) && (root)) ? (aValue/root): 0;
aValue%=root;
aString.AppendWithConversion(aCharSet[ndex+((root>1)*offset)]);
root/=base;
}
}
static void SpokenString(PRInt32 aValue,nsString& aString) {
static char ones[][12]= {"zero","one ","two ","three ","four ","five ","six ","seven ","eight ","nine ","ten "};
static char teens[][12]= {"ten ","eleven ","twelve ","thirteen ","fourteen ","fifteen ","sixteen ","seventeen ","eighteen ","nineteen "};
static char tens[][12]= {"","ten ","twenty ","thirty ","fourty ","fifty ","sixty ","seventy ","eighty ","ninety ","hundred "};
static char bases[][20]= {"","hundred ","thousand ","million ","billion ","trillion ","quadrillion ","quintillion ","bajillion "};
aString.Truncate();
if(aValue<0)
aString.AppendWithConversion('-');
PRInt32 root=1000000000;
PRInt32 expn=4;
PRInt32 modu=0;
PRInt32 div=0;
PRInt32 temp=0;
aValue=abs(aValue);
if(0<aValue) {
while(root && aValue) {
if(temp=aValue/root) {
if (div=temp/100) {//start with hundreds part
aString.AppendWithConversion(ones[div]);
aString.AppendWithConversion(bases[1]);
}
modu=(temp%10);
if (div=((temp%100)/10)) {
if (div<2) {
aString.AppendWithConversion(teens[modu]);
modu=0;
}
else aString.AppendWithConversion(tens[div]);
}
if (modu)
aString.AppendWithConversion(ones[modu]); //do remainder
aValue-=(temp*root);
if (expn>1)
aString.AppendWithConversion(bases[expn]);
}
expn--;
root/=1000;
}
}
else aString.AppendWithConversion(ones[0]);
}
static void DecimalString(PRInt32 aValue,nsString& aString) {
aString.Truncate();
aString.AppendInt(aValue);
}
static void BinaryString(PRInt32 aValue,nsString& aString) {
static char kBinarySet[]="01";
if (aValue<0)
aValue=65536-abs(aValue);
SeriesString(aValue,aString,kBinarySet,0,2);
}
static void HexString(PRInt32 aValue,nsString& aString) {
static char kHexSet[]="0123456789ABCDEF";
if (aValue<0)
aValue=65536-abs(aValue);
SeriesString(aValue,aString,kHexSet,0,16);
}
static void RomanString(PRInt32 aValue,nsString& aString) {
static char digitsA[] = "ixcm";
static char digitsB[] = "vld?";
aString.Truncate();
if(aValue<0)
aString.AppendWithConversion('-');
aValue=abs(aValue);
char decStr[20];
sprintf(decStr,"%d", aValue);
int len=strlen(decStr);
int romanPos=len;
int digitPos=0;
int n=0;
for(digitPos=0;digitPos<len;digitPos++) {
romanPos--;
switch(decStr[digitPos]) {
case '0': break;
case '3': aString.AppendWithConversion(digitsA[romanPos]);
case '2': aString.AppendWithConversion(digitsA[romanPos]);
case '1': aString.AppendWithConversion(digitsA[romanPos]);
break;
case '4': aString.AppendWithConversion(digitsA[romanPos]);
case '5': case '6':
case '7': case '8':
aString.AppendWithConversion(digitsB[romanPos]);
for(n=0;n<(decStr[digitPos]-'5');n++)
aString.AppendWithConversion(digitsA[romanPos]);
break;
case '9':
aString.AppendWithConversion(digitsA[romanPos]);
aString.AppendWithConversion(digitsA[romanPos]);
break;
}
}
}
static void AlphaString(PRInt32 aValue,nsString& aString) {
static const char kAlphaSet[]="abcdefghijklmnopqrstuvwxyz";
if (0<aValue)
SeriesString(aValue-1,aString,kAlphaSet,-1,26);
}
static void FootnoteString(PRInt32 aValue,nsString& aString) {
static char kFootnoteSet[]="abcdefg";
PRBool negative=(aValue<0);
int seriesLen = strlen (kFootnoteSet) - 1;
int count=0;
int repCount=0;
int modChar=0;
aString.Truncate();
aValue=abs(aValue);
repCount=((aValue-1)/seriesLen);
modChar=aValue-(repCount*seriesLen);
for(count=0;count<=repCount;count++) {
aString.AppendWithConversion(kFootnoteSet[modChar]);
}
}
protected:
const char* mUserSeries;
eNumFormat mFormat;
PRBool mCase;
PRInt32 mValue;
int mUserBase;
};
/**
*
* @update gess 11May2000
@ -402,22 +688,81 @@ void nsDTDContext::ResetCounters(void) {
memset(mCounters,0,sizeof(mCounters));
}
/**
*
* @update gess 11May2000
*/
PRInt32 nsDTDContext::IncrementCounter(eHTMLTags aTag) {
PRInt32 result=++mCounters[aTag];
/**********************************************************
@update: rickg 17May2000
Call this to handle counter attributes:
name="group"
value="nnn"
noincr="?"
format="alpha|dec|footnote|hex|roman|spoken"
returns the newly incremented value for the (determined) group.
**********************************************************/
PRInt32 nsDTDContext::IncrementCounter(eHTMLTags aTag,nsCParserNode& aNode,nsString& aResult) {
PRInt32 result=0;
PRInt32 theIndex=0;
PRInt32 theNewValue=-1; //-1 is interpreted to mean "don't reset the counter sequence.
PRInt32 theIncrValue=1; //this may get set to 0 if we see a "noincr" key.
PRInt32 theCount=aNode.GetAttributeCount();
CNamedEntity *theEntity=0;
CAbacus::eNumFormat theNumFormat=CAbacus::eDecimal;
for(theIndex=0;theIndex<theCount;theIndex++){
const nsString& theKey=aNode.GetKeyAt(theIndex);
const nsString& theValue=aNode.GetValueAt(theIndex);
if(theKey.EqualsWithConversion("name",PR_TRUE)){
theEntity=GetEntity(theValue);
if(!theEntity) {
theEntity=RegisterEntity(theValue,theValue);
theEntity->mOrdinal=0;
}
aTag=eHTMLTag_userdefined;
}
else if(theKey.EqualsWithConversion("noincr",PR_TRUE)){
theIncrValue=0;
}
else if(theKey.EqualsWithConversion("format",PR_TRUE)){
PRUnichar theChar=theValue.CharAt(0);
if('"'==theChar)
theChar=theValue.CharAt(1);
switch(theChar){
case 'A': case 'a': theNumFormat=CAbacus::eAlpha; break;
case 'B': case 'b': theNumFormat=CAbacus::eBinary; break;
case 'D': case 'd': theNumFormat=CAbacus::eDecimal; break;
case 'H': case 'h': theNumFormat=CAbacus::eHex; break;
case 'R': case 'r': theNumFormat=CAbacus::eRoman; break;
case 'S': case 's': theNumFormat=CAbacus::eSpoken; break;
default:
theNumFormat=CAbacus::eDecimal;
break;
}
//determine numbering style
}
else if(theKey.EqualsWithConversion("value",PR_TRUE)){
PRInt32 err=0;
theNewValue=theValue.ToInteger(&err);
if(!err) {
theIncrValue=0;
mCounters[aTag]=theNewValue;
}
else theNewValue=-1;
}
}
if(theEntity && (eHTMLTag_userdefined==aTag)) {
result=theEntity->mOrdinal+=theIncrValue;
}
else result=mCounters[aTag]+=theIncrValue;
CAbacus::GetFormattedString(theNumFormat,result,aResult,0,0,0);
return result;
}
/**
*
* @update gess 11May2000
*/
void nsDTDContext::ResetCounter(eHTMLTags aTag,PRInt32 aValue) {
mCounters[aTag]=aValue;
}
/**
*

Просмотреть файл

@ -155,6 +155,11 @@ public:
return result;
}
PRBool CanOpenTBody() {
PRBool result=!(mHasTBody);
return result;
}
PRBool CanOpenTHead() {
PRBool result=!(mHasTHead || mHasTFoot || mHasTBody);
return result;
@ -174,14 +179,42 @@ public:
};
//used for named entities and counters (XXX debug only)
class CNamedEntity {
public:
CNamedEntity(const nsString& aName,const nsString& aValue) : mName(), mValue() {
PRUnichar theFirst=aName.First();
PRUnichar theLast=aName.Last();
PRInt32 theLen=aName.Length();
if((2<theLen) && (theFirst==theLast) && (kQuote==theFirst)) {
aName.Mid(mName,1,theLen-2);
}
else mName=aName;
theFirst=aValue.First();
theLast=aValue.Last();
theLen=aValue.Length();
if((2<theLen) && (theFirst==theLast) && (kQuote==theFirst)) {
aValue.Mid(mValue,1,theLen-2);
}
else mValue=aValue;
}
nsAutoString mName;
nsAutoString mValue;
PRInt32 mOrdinal;
};
/************************************************************************
The dtdcontext class defines an ordered list of tags (a context).
************************************************************************/
class nsDTDContext {
public:
nsDTDContext();
~nsDTDContext();
nsDTDContext();
~nsDTDContext();
void Push(const nsIParserNode* aNode,nsEntryStack* aStyleStack=0);
nsIParserNode* Pop(nsEntryStack*& aChildStack);
@ -209,9 +242,11 @@ public:
nsresult GetNodeRecycler(CNodeRecycler*& aNodeRecycler);
static void FreeNodeRecycler(void);
CNamedEntity* RegisterEntity(const nsString& aName,const nsString& aValue);
CNamedEntity* GetEntity(const nsString& aName)const;
void ResetCounters(void);
void ResetCounter(eHTMLTags aTag,PRInt32 aNewValue);
PRInt32 IncrementCounter(eHTMLTags aTag);
PRInt32 IncrementCounter(eHTMLTags aTag,nsCParserNode& aNode,nsString& aResult);
nsEntryStack mStack; //this will hold a list of tagentries...
PRInt32 mResidualStyleCount;
@ -221,8 +256,10 @@ public:
static CNodeRecycler* mNodeRecycler;
CTableState *mTableStates;
CTableState *mTableStates;
PRInt32 mCounters[NS_HTML_TAG_MAX];
nsString mDefaultEntity;
nsDeque mEntities;
#ifdef NS_DEBUG
enum { eMaxTags = 100 };

Просмотреть файл

@ -630,7 +630,9 @@ nsresult nsHTMLTokenizer::ConsumeEntity(PRUnichar aChar,CToken*& aToken,nsScanne
return ConsumeText(temp,aToken,aScanner);
}//if
if(aToken){
#if 0
nsString& theStr=aToken->GetStringValueXXX();
if((kHashsign!=theChar) && (-1==nsHTMLEntities::EntityToUnicode(theStr))){
//if you're here we have a bogus entity.
//convert it into a text token.
@ -640,6 +642,7 @@ nsresult nsHTMLTokenizer::ConsumeEntity(PRUnichar aChar,CToken*& aToken,nsScanne
theRecycler->RecycleToken(aToken);
aToken=theToken;
}
#endif
AddToken(aToken,result,&mTokenDeque,theRecycler);
}
}//if

Просмотреть файл

@ -102,12 +102,13 @@ public:
//Note: To cut down on startup time/overhead, we defer the construction of non-html DTD's.
nsIDTD* theDTD;
NS_NewNavHTMLDTD(&theDTD); //do this as a default HTML DTD...
mDTDDeque.Push(theDTD);
#if 1
NS_NewOtherHTMLDTD(&theDTD); //do this as the default DTD for strict documents...
mDTDDeque.Push(theDTD);
#endif
mHasViewSourceDTD=PR_FALSE;
mHasRTFDTD=mHasXMLDTD=PR_FALSE;
}
@ -485,7 +486,7 @@ nsDTDMode nsParser::GetParseMode(void){
* @return parsermode (define in nsIParser.h)
*/
static
void DetermineParseMode(nsString& aBuffer,nsDTDMode& aParseMode,eParserDocType& aDocType) {
void DetermineParseMode(nsString& aBuffer,nsDTDMode& aParseMode,eParserDocType& aDocType,const nsString& aMimeType) {
const char* theModeStr= PR_GetEnv("PARSE_MODE");
aParseMode = eDTDMode_unknown;
@ -613,8 +614,18 @@ void DetermineParseMode(nsString& aBuffer,nsDTDMode& aParseMode,eParserDocType&
}
}
else if(kNotFound<(theIndex=aBuffer.Find("?XML",PR_TRUE,0,128))) {
aDocType=eXMLText;
aParseMode=eDTDMode_strict;
if(aMimeType.EqualsWithConversion(kHTMLTextContentType)) {
//this is here to prevent a crash if someone gives us an XML document,
//but necko tells us it's a text/html mimetype.
aDocType=eHTML4Text;
aParseMode=eDTDMode_strict;
}
else aDocType=eXMLText;
}
else if(aMimeType.EqualsWithConversion(kPlainTextContentType)) {
aDocType=ePlainText;
aParseMode=eDTDMode_quirks;
}
if(theModeStr) {
@ -754,7 +765,11 @@ nsresult nsParser::CreateCompatibleDTD(nsIDTD** aDTD,
nsDTDMode theDTDMode=eDTDMode_unknown;
eParserDocType theDocType=ePlainText;
DetermineParseMode(*aDocTypeStr,theDTDMode,theDocType);
if(!aMimeType) {
nsAutoString temp;
DetermineParseMode(*aDocTypeStr,theDTDMode,theDocType,temp);
}
else DetermineParseMode(*aDocTypeStr,theDTDMode,theDocType,*aMimeType);
NS_ASSERTION(aDTDMode==eDTDMode_unknown || aDTDMode==theDTDMode,"aDTDMode overrides the mode selected from the DOCTYPE ");
@ -945,7 +960,7 @@ nsresult nsParser::WillBuildModel(nsString& aFilename){
while(*theDocType) {
nsAutoString theType;
theType.AssignWithConversion(*theDocType);
DetermineParseMode(theType,theParseMode,theDocumentType);
DetermineParseMode(theType,theParseMode,theDocumentType,mParserContext->mMimeType);
theDocType++;
}
}
@ -957,7 +972,7 @@ nsresult nsParser::WillBuildModel(nsString& aFilename){
mMinorIteration=-1;
nsString& theBuffer=mParserContext->mScanner->GetBuffer();
DetermineParseMode(theBuffer,mParserContext->mDTDMode,mParserContext->mDocType);
DetermineParseMode(theBuffer,mParserContext->mDTDMode,mParserContext->mDocType,mParserContext->mMimeType);
if(PR_TRUE==FindSuitableDTD(*mParserContext,theBuffer)) {
mParserContext->mDTD->WillBuildModel( *mParserContext,mSink);