Fixed  bugs 5974, 12641, and 12389.
This commit is contained in:
harishd%netscape.com 1999-09-01 01:01:21 +00:00
Родитель 1677a4153a
Коммит bd73964c84
12 изменённых файлов: 298 добавлений и 306 удалений

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

@ -1079,90 +1079,58 @@ nsresult CNavDTD::WillHandleStartTag(CToken* aToken,eHTMLTags aTag,nsCParserNode
result=CollectSkippedContent(aNode,theAttrCount); result=CollectSkippedContent(aNode,theAttrCount);
} }
/********************************************************** if(mParser) {
THIS WILL ULTIMATELY BECOME THE REAL OBSERVER API... nsAutoString charsetValue;
**********************************************************/ nsCharsetSource charsetSource;
nsDeque* theDeque= (mParser && aTag != eHTMLTag_unknown)? (mParser->GetObserverDictionary()).GetObserversForTag(aTag):nsnull; mParser->GetDocumentCharset(charsetValue,charsetSource);
if(theDeque){ CParserContext* pc=mParser->PeekContext();
PRUint32 theDequeSize=theDeque->GetSize(); void* theDocID=(pc) ? pc->mKey : 0;
if(0<theDequeSize){ result=(mParser->GetObserverService()).Notify(aTag,aNode,(PRUint32)theDocID,this,charsetValue,charsetSource);
PRInt32 index = 0;
const PRUnichar* theKeys[50] = {0,0,0,0,0}; // XXX - should be dynamic
const PRUnichar* theValues[50]= {0,0,0,0,0}; // XXX - should be dynamic
for(index=0; index<theAttrCount && index < 50; index++) {
theKeys[index] = aNode.GetKeyAt(index).GetUnicode();
theValues[index] = aNode.GetValueAt(index).GetUnicode();
}
nsAutoString charsetValue;
nsCharsetSource charsetSource;
nsAutoString theCharsetKey("charset");
nsAutoString theSourceKey("charsetSource");
nsAutoString intValue;
mParser->GetDocumentCharset(charsetValue, charsetSource);
// Add pseudo attribute in the end
if(index < 50) {
theKeys[index]=theCharsetKey.GetUnicode();
theValues[index] = charsetValue.GetUnicode();
index++;
}
if(index < 50) {
theKeys[index]=theSourceKey.GetUnicode();
PRInt32 sourceInt = charsetSource;
intValue.Append(sourceInt,10);
theValues[index] = intValue.GetUnicode();
index++;
}
nsAutoString theTagStr(nsHTMLTags::GetStringValue(aTag));
CParserContext* pc=mParser->PeekContext();
void* theDocID=(pc) ? pc-> mKey : 0;
nsObserverNotifier theNotifier(theTagStr.GetUnicode(),(PRUint32)theDocID,index,theKeys,theValues);
theDeque->FirstThat(theNotifier);
result=theNotifier.mResult;
}//if
}
if(eHTMLTag_meta==aTag) {
PRInt32 theCount=aNode.GetAttributeCount();
if(1<theCount){
const nsString& theKey=aNode.GetKeyAt(0);
if(theKey.EqualsIgnoreCase("NAME")) {
const nsString& theValue1=aNode.GetValueAt(0);
if(theValue1.EqualsIgnoreCase("\"CRC\"")) {
const nsString& theKey2=aNode.GetKeyAt(1);
if(theKey2.EqualsIgnoreCase("CONTENT")) {
const nsString& theValue2=aNode.GetValueAt(1);
PRInt32 err=0;
mExpectedCRC32=theValue2.ToInteger(&err);
} //if
} //if
} //else
} //if
}//if
if(NS_OK==result) {
result=gHTMLElements[aTag].HasSpecialProperty(kDiscardTag) ? 1 : NS_OK;
} }
PRBool isHeadChild=gHTMLElements[eHTMLTag_head].IsChildOfHead(aTag);
//this code is here to make sure the head is closed before we deal if(NS_SUCCEEDED(result)) {
//with any tags that don't belong in the head. if(eHTMLTag_meta==aTag) {
if(NS_OK==result) { PRInt32 theCount=aNode.GetAttributeCount();
if(mHasOpenHead){ if(1<theCount){
static eHTMLTags skip2[]={eHTMLTag_newline,eHTMLTag_whitespace};
if(!FindTagInSet(aTag,skip2,sizeof(skip2)/sizeof(eHTMLTag_unknown))){ const nsString& theKey=aNode.GetKeyAt(0);
if(!isHeadChild){ if(theKey.EqualsIgnoreCase("NAME")) {
CEndToken theToken(eHTMLTag_head); const nsString& theValue1=aNode.GetValueAt(0);
nsCParserNode theNode(&theToken,mLineNumber); if(theValue1.EqualsIgnoreCase("\"CRC\"")) {
result=CloseHead(theNode); const nsString& theKey2=aNode.GetKeyAt(1);
if(theKey2.EqualsIgnoreCase("CONTENT")) {
const nsString& theValue2=aNode.GetValueAt(1);
PRInt32 err=0;
mExpectedCRC32=theValue2.ToInteger(&err);
} //if
} //if
} //else
} //if
}//if
if(NS_OK==result) {
result=gHTMLElements[aTag].HasSpecialProperty(kDiscardTag) ? 1 : NS_OK;
}
PRBool isHeadChild=gHTMLElements[eHTMLTag_head].IsChildOfHead(aTag);
//this code is here to make sure the head is closed before we deal
//with any tags that don't belong in the head.
if(NS_OK==result) {
if(mHasOpenHead){
static eHTMLTags skip2[]={eHTMLTag_newline,eHTMLTag_whitespace};
if(!FindTagInSet(aTag,skip2,sizeof(skip2)/sizeof(eHTMLTag_unknown))){
if(!isHeadChild){
CEndToken theToken(eHTMLTag_head);
nsCParserNode theNode(&theToken,mLineNumber);
result=CloseHead(theNode);
}
} }
} }
} }
} }
return result; return result;
} }
@ -1302,6 +1270,11 @@ nsresult CNavDTD::HandleStartToken(CToken* aToken) {
result=mSink->AddLeaf(*theNode); result=mSink->AddLeaf(*theNode);
break; break;
case eHTMLTag_image:
aToken->SetTypeID(theChildTag=eHTMLTag_img);
result=HandleDefaultStartToken(aToken,theChildTag,*theNode);
break;
case eHTMLTag_userdefined: case eHTMLTag_userdefined:
break; //drop them on the floor for now... break; //drop them on the floor for now...

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

@ -19,6 +19,7 @@
#include "nsDTDUtils.h" #include "nsDTDUtils.h"
#include "CNavDTD.h" #include "CNavDTD.h"
#include "nsIParserNode.h"
#include "nsIObserverService.h" #include "nsIObserverService.h"
#include "nsIServiceManager.h" #include "nsIServiceManager.h"
@ -640,7 +641,7 @@ PRUint32 AccumulateCRC(PRUint32 crc_accum, char *data_blk_ptr, int data_blk_size
come and go on a document basis. come and go on a document basis.
******************************************************************************/ ******************************************************************************/
CObserverDictionary::CObserverDictionary() { CObserverService::CObserverService() {
nsCRT::zero(mObservers,sizeof(mObservers)); nsCRT::zero(mObservers,sizeof(mObservers));
@ -652,7 +653,7 @@ CObserverDictionary::CObserverDictionary() {
} }
CObserverDictionary::~CObserverDictionary() { CObserverService::~CObserverService() {
UnregisterObservers(); UnregisterObservers();
} }
@ -668,19 +669,34 @@ public:
} }
}; };
void CObserverDictionary::UnregisterObservers() { /**
* Release observers and empty the observer array.
*
* @update harishd 08/29/99
* @param
* @return
*/
void CObserverService::UnregisterObservers() {
int theIndex=0; int theIndex=0;
nsObserverReleaser theReleaser; nsObserverReleaser theReleaser;
for(theIndex=0;theIndex<=NS_HTML_TAG_MAX;theIndex++){ for(theIndex=0;theIndex<=NS_HTML_TAG_MAX;theIndex++){
if(mObservers[theIndex]){ if(mObservers[theIndex]){
//nsIElementObserver* theElementObserver=0;
mObservers[theIndex]->ForEach(theReleaser); mObservers[theIndex]->ForEach(theReleaser);
delete mObservers[theIndex]; delete mObservers[theIndex];
} }
} }
} }
void CObserverDictionary::RegisterObservers(nsString& aTopic) { /**
* This method will maintain lists of observers registered for specific tags.
*
* @update harishd 08/29/99
* @param aTopic - The topic under which observers register for.
* @return if SUCCESS return NS_OK else return ERROR code.
*/
void CObserverService::RegisterObservers(nsString& aTopic) {
nsresult result = NS_OK; nsresult result = NS_OK;
nsIObserverService* theObserverService = nsnull; nsIObserverService* theObserverService = nsnull;
result = nsServiceManager::GetService(NS_OBSERVERSERVICE_PROGID, nsIObserverService::GetIID(), result = nsServiceManager::GetService(NS_OBSERVERSERVICE_PROGID, nsIObserverService::GetIID(),
@ -703,22 +719,16 @@ void CObserverDictionary::RegisterObservers(nsString& aTopic) {
PRUint32 theTagIndex = 0; PRUint32 theTagIndex = 0;
theTagStr = theElementObserver->GetTagNameAt(theTagIndex); theTagStr = theElementObserver->GetTagNameAt(theTagIndex);
while (theTagStr != nsnull) { while (theTagStr != nsnull) {
// XXX - HACK - Hardcoding PI for simplification. PI handling should not eHTMLTags theTag = nsHTMLTags::LookupTag(nsCAutoString(theTagStr));
// happen along with ** tags **. For now the specific PI, ?xml, is treated
// as an unknown tag in the dictionary!!!!
eHTMLTags theTag = (nsCRT::strcmp(theTagStr,"?xml") == 0) ? eHTMLTag_unknown :
nsHTMLTags::LookupTag(nsCAutoString(theTagStr));
if((eHTMLTag_userdefined!=theTag) && (theTag <= NS_HTML_TAG_MAX)){ if((eHTMLTag_userdefined!=theTag) && (theTag <= NS_HTML_TAG_MAX)){
if(mObservers[theTag] == nsnull) { if(mObservers[theTag] == nsnull) {
mObservers[theTag] = new nsDeque(0); mObservers[theTag] = new nsDeque(0);
} }
NS_ADDREF(theElementObserver);
mObservers[theTag]->Push(theElementObserver); mObservers[theTag]->Push(theElementObserver);
} }
theTagIndex++; theTagIndex++;
theTagStr = theElementObserver->GetTagNameAt(theTagIndex); theTagStr = theElementObserver->GetTagNameAt(theTagIndex);
} }
NS_RELEASE(theElementObserver);
} }
} }
} }
@ -726,7 +736,69 @@ void CObserverDictionary::RegisterObservers(nsString& aTopic) {
} }
} }
nsDeque* CObserverDictionary::GetObserversForTag(eHTMLTags aTag) { /**
* This method will notify observers registered for specific tags.
*
* @update harishd 08/29/99
* @param aTag - The tag for which observers could be waiting for.
* @param aNode -
* @param aUniqueID - The document ID.
* @param aDTD - The current DTD.
* @param aCharsetValue -
* @param aCharsetSource -
* @return if SUCCESS return NS_OK else return ERROR code.
*/
nsresult CObserverService::Notify(eHTMLTags aTag,nsIParserNode& aNode,PRUint32 aUniqueID, nsIDTD* aDTD,
nsAutoString& aCharsetValue,nsCharsetSource& aCharsetSource) {
nsresult result=NS_OK;
nsDeque* theDeque=GetObserversForTag(aTag);
if(theDeque){
PRInt32 theAttrCount =aNode.GetAttributeCount();
PRUint32 theDequeSize=theDeque->GetSize();
if(0<theDequeSize){
PRInt32 index = 0;
const PRUnichar* theKeys[50] = {0,0,0,0,0}; // XXX - should be dynamic
const PRUnichar* theValues[50]= {0,0,0,0,0}; // XXX - should be dynamic
for(index=0; index<theAttrCount && index < 50; index++) {
theKeys[index] = aNode.GetKeyAt(index).GetUnicode();
theValues[index] = aNode.GetValueAt(index).GetUnicode();
}
nsAutoString theCharsetKey("charset");
nsAutoString theSourceKey("charsetSource");
nsAutoString intValue;
// Add pseudo attribute in the end
if(index < 50) {
theKeys[index]=theCharsetKey.GetUnicode();
theValues[index] = aCharsetValue.GetUnicode();
index++;
}
if(index < 50) {
theKeys[index]=theSourceKey.GetUnicode();
PRInt32 sourceInt = aCharsetSource;
intValue.Append(sourceInt,10);
theValues[index] = intValue.GetUnicode();
index++;
}
nsAutoString theTagStr(nsHTMLTags::GetStringValue(aTag));
nsObserverNotifier theNotifier(theTagStr.GetUnicode(),aUniqueID,index,theKeys,theValues);
theDeque->FirstThat(theNotifier);
result=theNotifier.mResult;
}//if
}
return result;
}
/**
* This method will look for the list of observers registered for
* a specific tag.
*
* @update harishd 08/29/99
* @param aTag - The tag for which observers could be waiting for.
* @return if FOUND return "observer list" else return nsnull;
*
*/
nsDeque* CObserverService::GetObserversForTag(eHTMLTags aTag) {
if(aTag <= NS_HTML_TAG_MAX) if(aTag <= NS_HTML_TAG_MAX)
return mObservers[aTag]; return mObservers[aTag];
return nsnull; return nsnull;

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

@ -38,6 +38,8 @@
#include "nsString.h" #include "nsString.h"
#include "nsIElementObserver.h" #include "nsIElementObserver.h"
class nsIParserNode;
/*************************************************************** /***************************************************************
Before digging into the NavDTD, we'll define a helper Before digging into the NavDTD, we'll define a helper
class called CTagStack. class called CTagStack.
@ -242,16 +244,19 @@ struct CRCStruct {
might be nice to use a more dynamic approach that would permit observers to might be nice to use a more dynamic approach that would permit observers to
come and go on a document basis. come and go on a document basis.
******************************************************************************/ ******************************************************************************/
class CObserverDictionary { class CObserverService {
public: public:
CObserverDictionary(); CObserverService();
~CObserverDictionary(); ~CObserverService();
void RegisterObservers(nsString& aTopicList);
void UnregisterObservers();
nsDeque* GetObserversForTag(eHTMLTags aTag); nsDeque* GetObserversForTag(eHTMLTags aTag);
nsresult Notify(eHTMLTags aTag,nsIParserNode& aNode,
PRUint32 aUniqueID, nsIDTD* aDTD,
nsAutoString& aCharsetValue,nsCharsetSource& aCharsetSource) ;
protected: protected:
void RegisterObservers(nsString& aTopicList);
void UnregisterObservers();
nsDeque* mObservers[NS_HTML_TAG_MAX + 1]; nsDeque* mObservers[NS_HTML_TAG_MAX + 1];
}; };

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

@ -223,10 +223,6 @@ nsresult CStartToken::Consume(PRUnichar aChar, nsScanner& aScanner) {
nsresult result=aScanner.ReadWhile(mTextValue,GetIdentChars(),PR_TRUE,PR_FALSE); nsresult result=aScanner.ReadWhile(mTextValue,GetIdentChars(),PR_TRUE,PR_FALSE);
mTypeID = nsHTMLTags::LookupTag(mTextValue); mTypeID = nsHTMLTags::LookupTag(mTextValue);
if(eHTMLTag_image==mTypeID){
mTypeID=eHTMLTag_img;
}
//Good. Now, let's skip whitespace after the identifier, //Good. Now, let's skip whitespace after the identifier,
//and see if the next char is ">". If so, we have a complete //and see if the next char is ">". If so, we have a complete
//tag without attributes. //tag without attributes.
@ -507,7 +503,6 @@ nsresult CTextToken::ConsumeUntil(PRUnichar aChar,PRBool aIgnoreComments,nsScann
//target endtag, or the start of another comment. //target endtag, or the start of another comment.
static nsAutoString theWhitespace2("\b\t "); static nsAutoString theWhitespace2("\b\t ");
static nsAutoString theTerminals("\"\'<");
PRInt32 termStrLen=aTerminalString.Length(); PRInt32 termStrLen=aTerminalString.Length();
while((!done) && (NS_OK==result)) { while((!done) && (NS_OK==result)) {
@ -523,9 +518,7 @@ nsresult CTextToken::ConsumeUntil(PRUnichar aChar,PRBool aIgnoreComments,nsScann
result=theComment.Consume(aChar,aScanner); result=theComment.Consume(aChar,aScanner);
if(NS_OK==result) { if(NS_OK==result) {
//result=aScanner.SkipWhitespace(); //result=aScanner.SkipWhitespace();
//temp.Append("<!");
mTextValue.Append(theComment.GetStringValueXXX()); mTextValue.Append(theComment.GetStringValueXXX());
//temp.Append(">");
} }
} else { } else {
//read a tag... //read a tag...
@ -534,15 +527,6 @@ nsresult CTextToken::ConsumeUntil(PRUnichar aChar,PRBool aIgnoreComments,nsScann
result=aScanner.ReadUntil(mTextValue,kGreaterThan,PR_TRUE); result=aScanner.ReadUntil(mTextValue,kGreaterThan,PR_TRUE);
} }
} }
else if((NS_OK==result) && ((kQuote==aChar) || kApostrophe==aChar)) {
static nsAutoString theEndings("\n\"\'");
mTextValue += aChar;
result=aScanner.ReadUntil(mTextValue,theEndings,PR_TRUE,PR_FALSE);
if(result==NS_OK) {
result=aScanner.GetChar(aChar);
if(result==NS_OK) mTextValue += aChar; // consume the character that stopped the scan
}
}
else if(0<=theWhitespace2.BinarySearch(aChar)) { else if(0<=theWhitespace2.BinarySearch(aChar)) {
static CWhitespaceToken theWS; static CWhitespaceToken theWS;
result=theWS.Consume(aChar,aScanner); result=theWS.Consume(aChar,aScanner);
@ -552,7 +536,7 @@ nsresult CTextToken::ConsumeUntil(PRUnichar aChar,PRBool aIgnoreComments,nsScann
} }
else { else {
mTextValue+=aChar; mTextValue+=aChar;
result=aScanner.ReadUntil(mTextValue,theTerminals,PR_TRUE,PR_FALSE); result=aScanner.ReadUntil(mTextValue,kLessThan,PR_FALSE);
} }
mTextValue.Right(theRight,termStrLen+10); //first, get a wad of chars from the temp string mTextValue.Right(theRight,termStrLen+10); //first, get a wad of chars from the temp string
rpos=theRight.RFindChar('<'); //now scan for the '<' rpos=theRight.RFindChar('<'); //now scan for the '<'
@ -560,8 +544,8 @@ nsresult CTextToken::ConsumeUntil(PRUnichar aChar,PRBool aIgnoreComments,nsScann
rpos=theRight.RFind(aTerminalString,PR_TRUE); rpos=theRight.RFind(aTerminalString,PR_TRUE);
done=PRBool(-1<rpos); done=PRBool(-1<rpos);
} //while } //while
int len=mTextValue.Length();
if(NS_SUCCEEDED(result)) { if(NS_SUCCEEDED(result)) {
int len=mTextValue.Length();
mTextValue.Truncate(len-(theRight.Length()-rpos)); mTextValue.Truncate(len-(theRight.Length()-rpos));
// Make aTerminalString contain the name of the end tag ** as seen in ** // Make aTerminalString contain the name of the end tag ** as seen in **

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

@ -287,7 +287,7 @@ friend class CTokenHandler;
* @param * @param
* @return * @return
*/ */
CObserverDictionary& GetObserverDictionary(void) { return mObserverDictionary; } CObserverService& GetObserverService(void) { return mObserverService; }
protected: protected:
@ -379,7 +379,7 @@ protected:
nsString mCharset; nsString mCharset;
nsCharsetSource mCharsetSource; nsCharsetSource mCharsetSource;
nsresult mInternalState; nsresult mInternalState;
CObserverDictionary mObserverDictionary; CObserverService mObserverService;
}; };

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

@ -436,28 +436,6 @@ PRBool CWellFormedDTD::IsContainer(PRInt32 aTag) const{
return result; return result;
} }
/**
* Helper method that filters out the PI from a given string.
*
*
* @update harishd 06/27/99
* @param aPIString -- string that contains the PI.
* @param aPI -- PI that's filtered out from aPIString.
* @return
*/
void GetProcessingInstruction(const nsString& aPIString, char* a_PI)
{
static nsAutoString theWS2("\b\t\n ");
if(aPIString.Length() > 0) {
nsString temp;
PRInt32 theOffset = aPIString.FindCharInSet(theWS2,1);
aPIString.Mid(temp,1,theOffset);
temp.ToCString(a_PI,30);
}
return;
}
/** /**
* *
@ -574,22 +552,6 @@ nsresult CWellFormedDTD::HandleProcessingInstructionToken(CToken* aToken) {
nsresult result=NS_OK; nsresult result=NS_OK;
nsCParserNode theNode((CHTMLToken*)aToken,mLineNumber,mTokenizer->GetTokenRecycler()); nsCParserNode theNode((CHTMLToken*)aToken,mLineNumber,mTokenizer->GetTokenRecycler());
char thePI[30]={0};
nsString& thePIString = aToken->GetStringValueXXX();
GetProcessingInstruction(thePIString,thePI);
// XXX - HACK - The current observer dictionary is tag based. Converting it to be string based
// might cause some overhead. Until we figure out a better solution, in handling PIs and tags, I'm hardcoding
// a specific PI observer-list to be notified.
eHTMLTags theTag = (nsCRT::strcasecmp(thePI,"?xml") == 0)? eHTMLTag_unknown:eHTMLTag_userdefined;
nsDeque* theDeque= (mParser)? (mParser->GetObserverDictionary()).GetObserversForTag(theTag):nsnull;
if(theDeque) {
CParserContext* pc=mParser->PeekContext();
void* theDocID=(pc) ? pc-> mKey : 0;
nsObserverNotifier theNotifier(thePIString.GetUnicode(),(PRUint32)theDocID);
theDeque->FirstThat(theNotifier);
}
result=(mSink)? mSink->AddProcessingInstruction(theNode):NS_OK; result=(mSink)? mSink->AddProcessingInstruction(theNode):NS_OK;
return result; return result;
} }

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

@ -1079,90 +1079,58 @@ nsresult CNavDTD::WillHandleStartTag(CToken* aToken,eHTMLTags aTag,nsCParserNode
result=CollectSkippedContent(aNode,theAttrCount); result=CollectSkippedContent(aNode,theAttrCount);
} }
/********************************************************** if(mParser) {
THIS WILL ULTIMATELY BECOME THE REAL OBSERVER API... nsAutoString charsetValue;
**********************************************************/ nsCharsetSource charsetSource;
nsDeque* theDeque= (mParser && aTag != eHTMLTag_unknown)? (mParser->GetObserverDictionary()).GetObserversForTag(aTag):nsnull; mParser->GetDocumentCharset(charsetValue,charsetSource);
if(theDeque){ CParserContext* pc=mParser->PeekContext();
PRUint32 theDequeSize=theDeque->GetSize(); void* theDocID=(pc) ? pc->mKey : 0;
if(0<theDequeSize){ result=(mParser->GetObserverService()).Notify(aTag,aNode,(PRUint32)theDocID,this,charsetValue,charsetSource);
PRInt32 index = 0;
const PRUnichar* theKeys[50] = {0,0,0,0,0}; // XXX - should be dynamic
const PRUnichar* theValues[50]= {0,0,0,0,0}; // XXX - should be dynamic
for(index=0; index<theAttrCount && index < 50; index++) {
theKeys[index] = aNode.GetKeyAt(index).GetUnicode();
theValues[index] = aNode.GetValueAt(index).GetUnicode();
}
nsAutoString charsetValue;
nsCharsetSource charsetSource;
nsAutoString theCharsetKey("charset");
nsAutoString theSourceKey("charsetSource");
nsAutoString intValue;
mParser->GetDocumentCharset(charsetValue, charsetSource);
// Add pseudo attribute in the end
if(index < 50) {
theKeys[index]=theCharsetKey.GetUnicode();
theValues[index] = charsetValue.GetUnicode();
index++;
}
if(index < 50) {
theKeys[index]=theSourceKey.GetUnicode();
PRInt32 sourceInt = charsetSource;
intValue.Append(sourceInt,10);
theValues[index] = intValue.GetUnicode();
index++;
}
nsAutoString theTagStr(nsHTMLTags::GetStringValue(aTag));
CParserContext* pc=mParser->PeekContext();
void* theDocID=(pc) ? pc-> mKey : 0;
nsObserverNotifier theNotifier(theTagStr.GetUnicode(),(PRUint32)theDocID,index,theKeys,theValues);
theDeque->FirstThat(theNotifier);
result=theNotifier.mResult;
}//if
}
if(eHTMLTag_meta==aTag) {
PRInt32 theCount=aNode.GetAttributeCount();
if(1<theCount){
const nsString& theKey=aNode.GetKeyAt(0);
if(theKey.EqualsIgnoreCase("NAME")) {
const nsString& theValue1=aNode.GetValueAt(0);
if(theValue1.EqualsIgnoreCase("\"CRC\"")) {
const nsString& theKey2=aNode.GetKeyAt(1);
if(theKey2.EqualsIgnoreCase("CONTENT")) {
const nsString& theValue2=aNode.GetValueAt(1);
PRInt32 err=0;
mExpectedCRC32=theValue2.ToInteger(&err);
} //if
} //if
} //else
} //if
}//if
if(NS_OK==result) {
result=gHTMLElements[aTag].HasSpecialProperty(kDiscardTag) ? 1 : NS_OK;
} }
PRBool isHeadChild=gHTMLElements[eHTMLTag_head].IsChildOfHead(aTag);
//this code is here to make sure the head is closed before we deal if(NS_SUCCEEDED(result)) {
//with any tags that don't belong in the head. if(eHTMLTag_meta==aTag) {
if(NS_OK==result) { PRInt32 theCount=aNode.GetAttributeCount();
if(mHasOpenHead){ if(1<theCount){
static eHTMLTags skip2[]={eHTMLTag_newline,eHTMLTag_whitespace};
if(!FindTagInSet(aTag,skip2,sizeof(skip2)/sizeof(eHTMLTag_unknown))){ const nsString& theKey=aNode.GetKeyAt(0);
if(!isHeadChild){ if(theKey.EqualsIgnoreCase("NAME")) {
CEndToken theToken(eHTMLTag_head); const nsString& theValue1=aNode.GetValueAt(0);
nsCParserNode theNode(&theToken,mLineNumber); if(theValue1.EqualsIgnoreCase("\"CRC\"")) {
result=CloseHead(theNode); const nsString& theKey2=aNode.GetKeyAt(1);
if(theKey2.EqualsIgnoreCase("CONTENT")) {
const nsString& theValue2=aNode.GetValueAt(1);
PRInt32 err=0;
mExpectedCRC32=theValue2.ToInteger(&err);
} //if
} //if
} //else
} //if
}//if
if(NS_OK==result) {
result=gHTMLElements[aTag].HasSpecialProperty(kDiscardTag) ? 1 : NS_OK;
}
PRBool isHeadChild=gHTMLElements[eHTMLTag_head].IsChildOfHead(aTag);
//this code is here to make sure the head is closed before we deal
//with any tags that don't belong in the head.
if(NS_OK==result) {
if(mHasOpenHead){
static eHTMLTags skip2[]={eHTMLTag_newline,eHTMLTag_whitespace};
if(!FindTagInSet(aTag,skip2,sizeof(skip2)/sizeof(eHTMLTag_unknown))){
if(!isHeadChild){
CEndToken theToken(eHTMLTag_head);
nsCParserNode theNode(&theToken,mLineNumber);
result=CloseHead(theNode);
}
} }
} }
} }
} }
return result; return result;
} }
@ -1302,6 +1270,11 @@ nsresult CNavDTD::HandleStartToken(CToken* aToken) {
result=mSink->AddLeaf(*theNode); result=mSink->AddLeaf(*theNode);
break; break;
case eHTMLTag_image:
aToken->SetTypeID(theChildTag=eHTMLTag_img);
result=HandleDefaultStartToken(aToken,theChildTag,*theNode);
break;
case eHTMLTag_userdefined: case eHTMLTag_userdefined:
break; //drop them on the floor for now... break; //drop them on the floor for now...

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

@ -19,6 +19,7 @@
#include "nsDTDUtils.h" #include "nsDTDUtils.h"
#include "CNavDTD.h" #include "CNavDTD.h"
#include "nsIParserNode.h"
#include "nsIObserverService.h" #include "nsIObserverService.h"
#include "nsIServiceManager.h" #include "nsIServiceManager.h"
@ -640,7 +641,7 @@ PRUint32 AccumulateCRC(PRUint32 crc_accum, char *data_blk_ptr, int data_blk_size
come and go on a document basis. come and go on a document basis.
******************************************************************************/ ******************************************************************************/
CObserverDictionary::CObserverDictionary() { CObserverService::CObserverService() {
nsCRT::zero(mObservers,sizeof(mObservers)); nsCRT::zero(mObservers,sizeof(mObservers));
@ -652,7 +653,7 @@ CObserverDictionary::CObserverDictionary() {
} }
CObserverDictionary::~CObserverDictionary() { CObserverService::~CObserverService() {
UnregisterObservers(); UnregisterObservers();
} }
@ -668,19 +669,34 @@ public:
} }
}; };
void CObserverDictionary::UnregisterObservers() { /**
* Release observers and empty the observer array.
*
* @update harishd 08/29/99
* @param
* @return
*/
void CObserverService::UnregisterObservers() {
int theIndex=0; int theIndex=0;
nsObserverReleaser theReleaser; nsObserverReleaser theReleaser;
for(theIndex=0;theIndex<=NS_HTML_TAG_MAX;theIndex++){ for(theIndex=0;theIndex<=NS_HTML_TAG_MAX;theIndex++){
if(mObservers[theIndex]){ if(mObservers[theIndex]){
//nsIElementObserver* theElementObserver=0;
mObservers[theIndex]->ForEach(theReleaser); mObservers[theIndex]->ForEach(theReleaser);
delete mObservers[theIndex]; delete mObservers[theIndex];
} }
} }
} }
void CObserverDictionary::RegisterObservers(nsString& aTopic) { /**
* This method will maintain lists of observers registered for specific tags.
*
* @update harishd 08/29/99
* @param aTopic - The topic under which observers register for.
* @return if SUCCESS return NS_OK else return ERROR code.
*/
void CObserverService::RegisterObservers(nsString& aTopic) {
nsresult result = NS_OK; nsresult result = NS_OK;
nsIObserverService* theObserverService = nsnull; nsIObserverService* theObserverService = nsnull;
result = nsServiceManager::GetService(NS_OBSERVERSERVICE_PROGID, nsIObserverService::GetIID(), result = nsServiceManager::GetService(NS_OBSERVERSERVICE_PROGID, nsIObserverService::GetIID(),
@ -703,22 +719,16 @@ void CObserverDictionary::RegisterObservers(nsString& aTopic) {
PRUint32 theTagIndex = 0; PRUint32 theTagIndex = 0;
theTagStr = theElementObserver->GetTagNameAt(theTagIndex); theTagStr = theElementObserver->GetTagNameAt(theTagIndex);
while (theTagStr != nsnull) { while (theTagStr != nsnull) {
// XXX - HACK - Hardcoding PI for simplification. PI handling should not eHTMLTags theTag = nsHTMLTags::LookupTag(nsCAutoString(theTagStr));
// happen along with ** tags **. For now the specific PI, ?xml, is treated
// as an unknown tag in the dictionary!!!!
eHTMLTags theTag = (nsCRT::strcmp(theTagStr,"?xml") == 0) ? eHTMLTag_unknown :
nsHTMLTags::LookupTag(nsCAutoString(theTagStr));
if((eHTMLTag_userdefined!=theTag) && (theTag <= NS_HTML_TAG_MAX)){ if((eHTMLTag_userdefined!=theTag) && (theTag <= NS_HTML_TAG_MAX)){
if(mObservers[theTag] == nsnull) { if(mObservers[theTag] == nsnull) {
mObservers[theTag] = new nsDeque(0); mObservers[theTag] = new nsDeque(0);
} }
NS_ADDREF(theElementObserver);
mObservers[theTag]->Push(theElementObserver); mObservers[theTag]->Push(theElementObserver);
} }
theTagIndex++; theTagIndex++;
theTagStr = theElementObserver->GetTagNameAt(theTagIndex); theTagStr = theElementObserver->GetTagNameAt(theTagIndex);
} }
NS_RELEASE(theElementObserver);
} }
} }
} }
@ -726,7 +736,69 @@ void CObserverDictionary::RegisterObservers(nsString& aTopic) {
} }
} }
nsDeque* CObserverDictionary::GetObserversForTag(eHTMLTags aTag) { /**
* This method will notify observers registered for specific tags.
*
* @update harishd 08/29/99
* @param aTag - The tag for which observers could be waiting for.
* @param aNode -
* @param aUniqueID - The document ID.
* @param aDTD - The current DTD.
* @param aCharsetValue -
* @param aCharsetSource -
* @return if SUCCESS return NS_OK else return ERROR code.
*/
nsresult CObserverService::Notify(eHTMLTags aTag,nsIParserNode& aNode,PRUint32 aUniqueID, nsIDTD* aDTD,
nsAutoString& aCharsetValue,nsCharsetSource& aCharsetSource) {
nsresult result=NS_OK;
nsDeque* theDeque=GetObserversForTag(aTag);
if(theDeque){
PRInt32 theAttrCount =aNode.GetAttributeCount();
PRUint32 theDequeSize=theDeque->GetSize();
if(0<theDequeSize){
PRInt32 index = 0;
const PRUnichar* theKeys[50] = {0,0,0,0,0}; // XXX - should be dynamic
const PRUnichar* theValues[50]= {0,0,0,0,0}; // XXX - should be dynamic
for(index=0; index<theAttrCount && index < 50; index++) {
theKeys[index] = aNode.GetKeyAt(index).GetUnicode();
theValues[index] = aNode.GetValueAt(index).GetUnicode();
}
nsAutoString theCharsetKey("charset");
nsAutoString theSourceKey("charsetSource");
nsAutoString intValue;
// Add pseudo attribute in the end
if(index < 50) {
theKeys[index]=theCharsetKey.GetUnicode();
theValues[index] = aCharsetValue.GetUnicode();
index++;
}
if(index < 50) {
theKeys[index]=theSourceKey.GetUnicode();
PRInt32 sourceInt = aCharsetSource;
intValue.Append(sourceInt,10);
theValues[index] = intValue.GetUnicode();
index++;
}
nsAutoString theTagStr(nsHTMLTags::GetStringValue(aTag));
nsObserverNotifier theNotifier(theTagStr.GetUnicode(),aUniqueID,index,theKeys,theValues);
theDeque->FirstThat(theNotifier);
result=theNotifier.mResult;
}//if
}
return result;
}
/**
* This method will look for the list of observers registered for
* a specific tag.
*
* @update harishd 08/29/99
* @param aTag - The tag for which observers could be waiting for.
* @return if FOUND return "observer list" else return nsnull;
*
*/
nsDeque* CObserverService::GetObserversForTag(eHTMLTags aTag) {
if(aTag <= NS_HTML_TAG_MAX) if(aTag <= NS_HTML_TAG_MAX)
return mObservers[aTag]; return mObservers[aTag];
return nsnull; return nsnull;

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

@ -38,6 +38,8 @@
#include "nsString.h" #include "nsString.h"
#include "nsIElementObserver.h" #include "nsIElementObserver.h"
class nsIParserNode;
/*************************************************************** /***************************************************************
Before digging into the NavDTD, we'll define a helper Before digging into the NavDTD, we'll define a helper
class called CTagStack. class called CTagStack.
@ -242,16 +244,19 @@ struct CRCStruct {
might be nice to use a more dynamic approach that would permit observers to might be nice to use a more dynamic approach that would permit observers to
come and go on a document basis. come and go on a document basis.
******************************************************************************/ ******************************************************************************/
class CObserverDictionary { class CObserverService {
public: public:
CObserverDictionary(); CObserverService();
~CObserverDictionary(); ~CObserverService();
void RegisterObservers(nsString& aTopicList);
void UnregisterObservers();
nsDeque* GetObserversForTag(eHTMLTags aTag); nsDeque* GetObserversForTag(eHTMLTags aTag);
nsresult Notify(eHTMLTags aTag,nsIParserNode& aNode,
PRUint32 aUniqueID, nsIDTD* aDTD,
nsAutoString& aCharsetValue,nsCharsetSource& aCharsetSource) ;
protected: protected:
void RegisterObservers(nsString& aTopicList);
void UnregisterObservers();
nsDeque* mObservers[NS_HTML_TAG_MAX + 1]; nsDeque* mObservers[NS_HTML_TAG_MAX + 1];
}; };

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

@ -223,10 +223,6 @@ nsresult CStartToken::Consume(PRUnichar aChar, nsScanner& aScanner) {
nsresult result=aScanner.ReadWhile(mTextValue,GetIdentChars(),PR_TRUE,PR_FALSE); nsresult result=aScanner.ReadWhile(mTextValue,GetIdentChars(),PR_TRUE,PR_FALSE);
mTypeID = nsHTMLTags::LookupTag(mTextValue); mTypeID = nsHTMLTags::LookupTag(mTextValue);
if(eHTMLTag_image==mTypeID){
mTypeID=eHTMLTag_img;
}
//Good. Now, let's skip whitespace after the identifier, //Good. Now, let's skip whitespace after the identifier,
//and see if the next char is ">". If so, we have a complete //and see if the next char is ">". If so, we have a complete
//tag without attributes. //tag without attributes.
@ -507,7 +503,6 @@ nsresult CTextToken::ConsumeUntil(PRUnichar aChar,PRBool aIgnoreComments,nsScann
//target endtag, or the start of another comment. //target endtag, or the start of another comment.
static nsAutoString theWhitespace2("\b\t "); static nsAutoString theWhitespace2("\b\t ");
static nsAutoString theTerminals("\"\'<");
PRInt32 termStrLen=aTerminalString.Length(); PRInt32 termStrLen=aTerminalString.Length();
while((!done) && (NS_OK==result)) { while((!done) && (NS_OK==result)) {
@ -523,9 +518,7 @@ nsresult CTextToken::ConsumeUntil(PRUnichar aChar,PRBool aIgnoreComments,nsScann
result=theComment.Consume(aChar,aScanner); result=theComment.Consume(aChar,aScanner);
if(NS_OK==result) { if(NS_OK==result) {
//result=aScanner.SkipWhitespace(); //result=aScanner.SkipWhitespace();
//temp.Append("<!");
mTextValue.Append(theComment.GetStringValueXXX()); mTextValue.Append(theComment.GetStringValueXXX());
//temp.Append(">");
} }
} else { } else {
//read a tag... //read a tag...
@ -534,15 +527,6 @@ nsresult CTextToken::ConsumeUntil(PRUnichar aChar,PRBool aIgnoreComments,nsScann
result=aScanner.ReadUntil(mTextValue,kGreaterThan,PR_TRUE); result=aScanner.ReadUntil(mTextValue,kGreaterThan,PR_TRUE);
} }
} }
else if((NS_OK==result) && ((kQuote==aChar) || kApostrophe==aChar)) {
static nsAutoString theEndings("\n\"\'");
mTextValue += aChar;
result=aScanner.ReadUntil(mTextValue,theEndings,PR_TRUE,PR_FALSE);
if(result==NS_OK) {
result=aScanner.GetChar(aChar);
if(result==NS_OK) mTextValue += aChar; // consume the character that stopped the scan
}
}
else if(0<=theWhitespace2.BinarySearch(aChar)) { else if(0<=theWhitespace2.BinarySearch(aChar)) {
static CWhitespaceToken theWS; static CWhitespaceToken theWS;
result=theWS.Consume(aChar,aScanner); result=theWS.Consume(aChar,aScanner);
@ -552,7 +536,7 @@ nsresult CTextToken::ConsumeUntil(PRUnichar aChar,PRBool aIgnoreComments,nsScann
} }
else { else {
mTextValue+=aChar; mTextValue+=aChar;
result=aScanner.ReadUntil(mTextValue,theTerminals,PR_TRUE,PR_FALSE); result=aScanner.ReadUntil(mTextValue,kLessThan,PR_FALSE);
} }
mTextValue.Right(theRight,termStrLen+10); //first, get a wad of chars from the temp string mTextValue.Right(theRight,termStrLen+10); //first, get a wad of chars from the temp string
rpos=theRight.RFindChar('<'); //now scan for the '<' rpos=theRight.RFindChar('<'); //now scan for the '<'
@ -560,8 +544,8 @@ nsresult CTextToken::ConsumeUntil(PRUnichar aChar,PRBool aIgnoreComments,nsScann
rpos=theRight.RFind(aTerminalString,PR_TRUE); rpos=theRight.RFind(aTerminalString,PR_TRUE);
done=PRBool(-1<rpos); done=PRBool(-1<rpos);
} //while } //while
int len=mTextValue.Length();
if(NS_SUCCEEDED(result)) { if(NS_SUCCEEDED(result)) {
int len=mTextValue.Length();
mTextValue.Truncate(len-(theRight.Length()-rpos)); mTextValue.Truncate(len-(theRight.Length()-rpos));
// Make aTerminalString contain the name of the end tag ** as seen in ** // Make aTerminalString contain the name of the end tag ** as seen in **

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

@ -287,7 +287,7 @@ friend class CTokenHandler;
* @param * @param
* @return * @return
*/ */
CObserverDictionary& GetObserverDictionary(void) { return mObserverDictionary; } CObserverService& GetObserverService(void) { return mObserverService; }
protected: protected:
@ -379,7 +379,7 @@ protected:
nsString mCharset; nsString mCharset;
nsCharsetSource mCharsetSource; nsCharsetSource mCharsetSource;
nsresult mInternalState; nsresult mInternalState;
CObserverDictionary mObserverDictionary; CObserverService mObserverService;
}; };

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

@ -436,28 +436,6 @@ PRBool CWellFormedDTD::IsContainer(PRInt32 aTag) const{
return result; return result;
} }
/**
* Helper method that filters out the PI from a given string.
*
*
* @update harishd 06/27/99
* @param aPIString -- string that contains the PI.
* @param aPI -- PI that's filtered out from aPIString.
* @return
*/
void GetProcessingInstruction(const nsString& aPIString, char* a_PI)
{
static nsAutoString theWS2("\b\t\n ");
if(aPIString.Length() > 0) {
nsString temp;
PRInt32 theOffset = aPIString.FindCharInSet(theWS2,1);
aPIString.Mid(temp,1,theOffset);
temp.ToCString(a_PI,30);
}
return;
}
/** /**
* *
@ -574,22 +552,6 @@ nsresult CWellFormedDTD::HandleProcessingInstructionToken(CToken* aToken) {
nsresult result=NS_OK; nsresult result=NS_OK;
nsCParserNode theNode((CHTMLToken*)aToken,mLineNumber,mTokenizer->GetTokenRecycler()); nsCParserNode theNode((CHTMLToken*)aToken,mLineNumber,mTokenizer->GetTokenRecycler());
char thePI[30]={0};
nsString& thePIString = aToken->GetStringValueXXX();
GetProcessingInstruction(thePIString,thePI);
// XXX - HACK - The current observer dictionary is tag based. Converting it to be string based
// might cause some overhead. Until we figure out a better solution, in handling PIs and tags, I'm hardcoding
// a specific PI observer-list to be notified.
eHTMLTags theTag = (nsCRT::strcasecmp(thePI,"?xml") == 0)? eHTMLTag_unknown:eHTMLTag_userdefined;
nsDeque* theDeque= (mParser)? (mParser->GetObserverDictionary()).GetObserversForTag(theTag):nsnull;
if(theDeque) {
CParserContext* pc=mParser->PeekContext();
void* theDocID=(pc) ? pc-> mKey : 0;
nsObserverNotifier theNotifier(thePIString.GetUnicode(),(PRUint32)theDocID);
theDeque->FirstThat(theNotifier);
}
result=(mSink)? mSink->AddProcessingInstruction(theNode):NS_OK; result=(mSink)? mSink->AddProcessingInstruction(theNode):NS_OK;
return result; return result;
} }