/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* * The contents of this file are subject to the Netscape Public License * Version 1.0 (the "NPL"); you may not use this file except in * compliance with the NPL. You may obtain a copy of the NPL at * http://www.mozilla.org/NPL/ * * Software distributed under the NPL is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL * for the specific language governing rights and limitations under the * NPL. * * The Initial Developer of this code under the NPL is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All Rights * Reserved. */ #include "nsDTDUtils.h" #include "CNavDTD.h" /*************************************************************** First, define the tagstack class ***************************************************************/ /** * Default constructor * @update harishd 04/04/99 * @update gess 04/22/99 */ nsTagStack::nsTagStack() { mCapacity=0; mCount=0; mEntries=0; } /** * Default destructor * @update harishd 04/04/99 * @update gess 04/22/99 */ nsTagStack::~nsTagStack() { if(mEntries) delete [] mEntries; } /** * Resets state of stack to be empty. * @update harishd 04/04/99 */ void nsTagStack::Empty(void) { mCount=0; } /** * * @update gess 04/22/99 */ void nsTagStack::Push(eHTMLTags aTag) { if(mCount==mCapacity){ nsTagEntry* temp=new nsTagEntry[mCapacity+50]; if(mCapacity){ PRUint32 index=0; for(index=0;index=0;theIndex--){ if(aTag==TagAt(theIndex)) return theIndex; } return kNotFound; } /*************************************************************** Now define the dtdcontext class ***************************************************************/ /** * * @update gess9/10/98 */ nsDTDContext::nsDTDContext() : mStack(), mSkipped(0), mStyles(0) { #ifdef NS_DEBUG nsCRT::zero(mTags,sizeof(mTags)); #endif } /** * * @update gess9/10/98 */ nsDTDContext::~nsDTDContext() { } /** * * @update gess7/9/98, harishd 04/04/99 */ PRInt32 nsDTDContext::GetCount(void) { return mStack.GetSize(); } /** * * @update gess7/9/98, harishd 04/04/99 */ void nsDTDContext::Push(eHTMLTags aTag) { #ifdef NS_DEBUG if(mStack.mCount0) mTags[mStack.mCount-1]=eHTMLTag_unknown; #endif eHTMLTags result=mStack.Pop(); return result; } /** * * @update gess7/9/98 */ eHTMLTags nsDTDContext::First() const { return mStack.First(); } /** * * @update gess7/9/98 */ eHTMLTags nsDTDContext::TagAt(PRInt32 anIndex) const { return mStack.TagAt(anIndex); } /** * * @update gess7/9/98 */ eHTMLTags nsDTDContext::operator[](PRInt32 anIndex) const { return mStack[anIndex]; } /** * * @update gess7/9/98 */ eHTMLTags nsDTDContext::Last() const { return mStack.Last(); } /** * * @update gess7/9/98 */ nsTagStack* nsDTDContext::GetStyles(void) const { PRInt32 theIndex=mStack.mEntries[mStack.mCount-1].mStyleIndex; nsTagStack* result=0; if(-1 -1,"Out of bounds"); if(aToken) { nsTagEntry& theEntry=mStack.EntryAt(aID); //ok, now go get the right tokenbank deque... nsDeque* theDeque=0; if(-1Push(aToken); } } /** * * @update harishd 04/04/99 * @update gess 04/21/99 */ CToken* nsDTDContext::RestoreTokenFrom(PRInt32 aID) { NS_PRECONDITION(aID <= mStack.GetSize() && aID > -1,"Out of bounds"); CToken* result=0; if(0PopFront(); } } return result; } /** * * @update harishd 04/04/99 * @update gess 04/21/99 */ PRInt32 nsDTDContext::TokenCountAt(PRInt32 aID) { NS_PRECONDITION(aID <= mStack.GetSize(),"Out of bounds"); nsTagEntry theEntry=mStack.EntryAt(aID); nsDeque* theDeque=(nsDeque*)mSkipped.ObjectAt(theEntry.mBankIndex); if(theDeque){ return theDeque->GetSize(); } return kNotFound; } /************************************************************** Now define the tokenrecycler class... **************************************************************/ /** * * @update gess7/25/98 * @param */ CTokenRecycler::CTokenRecycler() : nsITokenRecycler() { int i=0; for(i=0;iGetTokenType(); CTokenFinder finder(aToken); CToken* theMatch=(CToken*)mTokenCache[theType-1]->FirstThat(finder); if(theMatch) { int x=5; } mTokenCache[theType-1]->Push(aToken); } } /** * * @update vidur 11/12/98 * @param * @return */ CToken* CTokenRecycler::CreateTokenOfType(eHTMLTokenTypes aType,eHTMLTags aTag, const nsString& aString) { CToken* result=(CToken*)mTokenCache[aType-1]->Pop(); if(result) { result->Reinitialize(aTag,aString); } else { #ifdef NS_DEBUG mTotals[aType-1]++; #endif switch(aType){ case eToken_start: result=new CStartToken(aTag); break; case eToken_end: result=new CEndToken(aTag); break; case eToken_comment: result=new CCommentToken(); break; case eToken_entity: result=new CEntityToken(); break; case eToken_whitespace: result=new CWhitespaceToken(); break; case eToken_newline: result=new CNewlineToken(); break; case eToken_text: result=new CTextToken(aString); break; case eToken_attribute: result=new CAttributeToken(); break; case eToken_script: result=new CScriptToken(); break; case eToken_style: result=new CStyleToken(); break; case eToken_skippedcontent: result=new CSkippedContentToken(aString); break; case eToken_instruction:result=new CInstructionToken(); break; case eToken_cdatasection:result=new CCDATASectionToken(); break; default: break; } } return result; } /** * * @update vidur 11/12/98 * @param * @return */ CToken* CTokenRecycler::CreateTokenOfType(eHTMLTokenTypes aType,eHTMLTags aTag) { CToken* result=(CToken*)mTokenCache[aType-1]->Pop(); static nsAutoString theEmpty; if(result) { result->Reinitialize(aTag,theEmpty); } else { #ifdef NS_DEBUG mTotals[aType-1]++; #endif switch(aType){ case eToken_start: result=new CStartToken(aTag); break; case eToken_end: result=new CEndToken(aTag); break; case eToken_comment: result=new CCommentToken(); break; case eToken_attribute: result=new CAttributeToken(); break; case eToken_entity: result=new CEntityToken(); break; case eToken_whitespace: result=new CWhitespaceToken(); break; case eToken_newline: result=new CNewlineToken(); break; case eToken_text: result=new CTextToken(theEmpty); break; case eToken_script: result=new CScriptToken(); break; case eToken_style: result=new CStyleToken(); break; case eToken_skippedcontent: result=new CSkippedContentToken(theEmpty); break; case eToken_instruction: result=new CInstructionToken(); break; case eToken_cdatasection: result=new CCDATASectionToken(); break; case eToken_error: result=new CErrorToken(); break; default: break; } } return result; } void DebugDumpContainmentRules(nsIDTD& theDTD,const char* aFilename,const char* aTitle) { const char* prefix=" "; fstream out(aFilename,ios::out); out << "==================================================" << endl; out << aTitle << endl; out << "=================================================="; int i,j=0; int written; for(i=1;i" << endl; out << prefix; written=0; if(theDTD.IsContainer(i)) { for(j=1;j> 24) ^ *data_blk_ptr++ ) & 0xff; crc_accum = ( crc_accum << 8 ) ^ crc_table[i]; } return crc_accum; } /****************************************************************************** This class is used to store ref's to tag observers during the parse phase. Note that for simplicity, this is a singleton that is constructed in the CNavDTD and shared for the duration of the application session. Later on it might be nice to use a more dynamic approach that would permit observers to come and go on a document basis. ******************************************************************************/ CObserverDictionary::CObserverDictionary() { nsCRT::zero(mObservers,sizeof(mObservers)); RegisterObservers(); } CObserverDictionary::~CObserverDictionary() { UnregisterObservers(); } void CObserverDictionary::UnregisterObservers() { int theIndex=0; for(theIndex=0;theIndexPop()){ NS_RELEASE(theObserver); } */ } } } void CObserverDictionary::RegisterObservers() { /* nsIObserverService* theObserverService=GetService("observer"); //or whatever the call is here... if(theObserverService){ nsIObserverEnumerator* theEnum=theObserverService->GetObserversForTopic("htmlparser"); //again, put the real call here! if(theEnum){ nsIObserver* theObserver=theEnum->First(); while(theObserver){ const char* theTagStr=theObserver->GetTag(); if(theTagStr){ eHTMLTags theTag=NS_TagToEnum(theTagStr); if(eHTMLTag_userdefined!=theTag){ nsDeque* theDeque=mObservers[theTag]; if(theDeque){ NS_ADDREF(theObserver); theDeque->Push(theObserver); } } } theObserver=theEnum->Next(); } } } */ } nsDeque* CObserverDictionary::GetObserversForTag(eHTMLTags aTag) { nsDeque* result=mObservers[aTag]; return result; }