зеркало из https://github.com/mozilla/pjs.git
Cleaned up some code.
Fixed bugs 5974, 12641, and 12389.
This commit is contained in:
Родитель
1677a4153a
Коммит
bd73964c84
|
@ -1079,90 +1079,58 @@ nsresult CNavDTD::WillHandleStartTag(CToken* aToken,eHTMLTags aTag,nsCParserNode
|
|||
result=CollectSkippedContent(aNode,theAttrCount);
|
||||
}
|
||||
|
||||
/**********************************************************
|
||||
THIS WILL ULTIMATELY BECOME THE REAL OBSERVER API...
|
||||
**********************************************************/
|
||||
nsDeque* theDeque= (mParser && aTag != eHTMLTag_unknown)? (mParser->GetObserverDictionary()).GetObserversForTag(aTag):nsnull;
|
||||
if(theDeque){
|
||||
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 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;
|
||||
if(mParser) {
|
||||
nsAutoString charsetValue;
|
||||
nsCharsetSource charsetSource;
|
||||
mParser->GetDocumentCharset(charsetValue,charsetSource);
|
||||
CParserContext* pc=mParser->PeekContext();
|
||||
void* theDocID=(pc) ? pc->mKey : 0;
|
||||
result=(mParser->GetObserverService()).Notify(aTag,aNode,(PRUint32)theDocID,this,charsetValue,charsetSource);
|
||||
}
|
||||
|
||||
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);
|
||||
if(NS_SUCCEEDED(result)) {
|
||||
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
|
||||
//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;
|
||||
}
|
||||
|
||||
|
@ -1302,6 +1270,11 @@ nsresult CNavDTD::HandleStartToken(CToken* aToken) {
|
|||
result=mSink->AddLeaf(*theNode);
|
||||
break;
|
||||
|
||||
case eHTMLTag_image:
|
||||
aToken->SetTypeID(theChildTag=eHTMLTag_img);
|
||||
result=HandleDefaultStartToken(aToken,theChildTag,*theNode);
|
||||
break;
|
||||
|
||||
case eHTMLTag_userdefined:
|
||||
break; //drop them on the floor for now...
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "nsDTDUtils.h"
|
||||
#include "CNavDTD.h"
|
||||
#include "nsIParserNode.h"
|
||||
|
||||
#include "nsIObserverService.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.
|
||||
******************************************************************************/
|
||||
|
||||
CObserverDictionary::CObserverDictionary() {
|
||||
CObserverService::CObserverService() {
|
||||
|
||||
nsCRT::zero(mObservers,sizeof(mObservers));
|
||||
|
||||
|
@ -652,7 +653,7 @@ CObserverDictionary::CObserverDictionary() {
|
|||
|
||||
}
|
||||
|
||||
CObserverDictionary::~CObserverDictionary() {
|
||||
CObserverService::~CObserverService() {
|
||||
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;
|
||||
nsObserverReleaser theReleaser;
|
||||
for(theIndex=0;theIndex<=NS_HTML_TAG_MAX;theIndex++){
|
||||
if(mObservers[theIndex]){
|
||||
//nsIElementObserver* theElementObserver=0;
|
||||
mObservers[theIndex]->ForEach(theReleaser);
|
||||
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;
|
||||
nsIObserverService* theObserverService = nsnull;
|
||||
result = nsServiceManager::GetService(NS_OBSERVERSERVICE_PROGID, nsIObserverService::GetIID(),
|
||||
|
@ -703,22 +719,16 @@ void CObserverDictionary::RegisterObservers(nsString& aTopic) {
|
|||
PRUint32 theTagIndex = 0;
|
||||
theTagStr = theElementObserver->GetTagNameAt(theTagIndex);
|
||||
while (theTagStr != nsnull) {
|
||||
// XXX - HACK - Hardcoding PI for simplification. PI handling should not
|
||||
// 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));
|
||||
eHTMLTags theTag = nsHTMLTags::LookupTag(nsCAutoString(theTagStr));
|
||||
if((eHTMLTag_userdefined!=theTag) && (theTag <= NS_HTML_TAG_MAX)){
|
||||
if(mObservers[theTag] == nsnull) {
|
||||
mObservers[theTag] = new nsDeque(0);
|
||||
}
|
||||
NS_ADDREF(theElementObserver);
|
||||
mObservers[theTag]->Push(theElementObserver);
|
||||
}
|
||||
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)
|
||||
return mObservers[aTag];
|
||||
return nsnull;
|
||||
|
|
|
@ -38,6 +38,8 @@
|
|||
#include "nsString.h"
|
||||
#include "nsIElementObserver.h"
|
||||
|
||||
class nsIParserNode;
|
||||
|
||||
/***************************************************************
|
||||
Before digging into the NavDTD, we'll define a helper
|
||||
class called CTagStack.
|
||||
|
@ -242,16 +244,19 @@ struct CRCStruct {
|
|||
might be nice to use a more dynamic approach that would permit observers to
|
||||
come and go on a document basis.
|
||||
******************************************************************************/
|
||||
class CObserverDictionary {
|
||||
class CObserverService {
|
||||
public:
|
||||
CObserverDictionary();
|
||||
~CObserverDictionary();
|
||||
CObserverService();
|
||||
~CObserverService();
|
||||
|
||||
void RegisterObservers(nsString& aTopicList);
|
||||
void UnregisterObservers();
|
||||
nsDeque* GetObserversForTag(eHTMLTags aTag);
|
||||
nsresult Notify(eHTMLTags aTag,nsIParserNode& aNode,
|
||||
PRUint32 aUniqueID, nsIDTD* aDTD,
|
||||
nsAutoString& aCharsetValue,nsCharsetSource& aCharsetSource) ;
|
||||
|
||||
protected:
|
||||
void RegisterObservers(nsString& aTopicList);
|
||||
void UnregisterObservers();
|
||||
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);
|
||||
mTypeID = nsHTMLTags::LookupTag(mTextValue);
|
||||
|
||||
if(eHTMLTag_image==mTypeID){
|
||||
mTypeID=eHTMLTag_img;
|
||||
}
|
||||
|
||||
//Good. Now, let's skip whitespace after the identifier,
|
||||
//and see if the next char is ">". If so, we have a complete
|
||||
//tag without attributes.
|
||||
|
@ -507,7 +503,6 @@ nsresult CTextToken::ConsumeUntil(PRUnichar aChar,PRBool aIgnoreComments,nsScann
|
|||
//target endtag, or the start of another comment.
|
||||
|
||||
static nsAutoString theWhitespace2("\b\t ");
|
||||
static nsAutoString theTerminals("\"\'<");
|
||||
|
||||
PRInt32 termStrLen=aTerminalString.Length();
|
||||
while((!done) && (NS_OK==result)) {
|
||||
|
@ -523,9 +518,7 @@ nsresult CTextToken::ConsumeUntil(PRUnichar aChar,PRBool aIgnoreComments,nsScann
|
|||
result=theComment.Consume(aChar,aScanner);
|
||||
if(NS_OK==result) {
|
||||
//result=aScanner.SkipWhitespace();
|
||||
//temp.Append("<!");
|
||||
mTextValue.Append(theComment.GetStringValueXXX());
|
||||
//temp.Append(">");
|
||||
}
|
||||
} else {
|
||||
//read a tag...
|
||||
|
@ -534,15 +527,6 @@ nsresult CTextToken::ConsumeUntil(PRUnichar aChar,PRBool aIgnoreComments,nsScann
|
|||
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)) {
|
||||
static CWhitespaceToken theWS;
|
||||
result=theWS.Consume(aChar,aScanner);
|
||||
|
@ -552,7 +536,7 @@ nsresult CTextToken::ConsumeUntil(PRUnichar aChar,PRBool aIgnoreComments,nsScann
|
|||
}
|
||||
else {
|
||||
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
|
||||
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);
|
||||
done=PRBool(-1<rpos);
|
||||
} //while
|
||||
int len=mTextValue.Length();
|
||||
if(NS_SUCCEEDED(result)) {
|
||||
int len=mTextValue.Length();
|
||||
mTextValue.Truncate(len-(theRight.Length()-rpos));
|
||||
|
||||
// Make aTerminalString contain the name of the end tag ** as seen in **
|
||||
|
|
|
@ -287,7 +287,7 @@ friend class CTokenHandler;
|
|||
* @param
|
||||
* @return
|
||||
*/
|
||||
CObserverDictionary& GetObserverDictionary(void) { return mObserverDictionary; }
|
||||
CObserverService& GetObserverService(void) { return mObserverService; }
|
||||
|
||||
protected:
|
||||
|
||||
|
@ -379,7 +379,7 @@ protected:
|
|||
nsString mCharset;
|
||||
nsCharsetSource mCharsetSource;
|
||||
nsresult mInternalState;
|
||||
CObserverDictionary mObserverDictionary;
|
||||
CObserverService mObserverService;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -436,28 +436,6 @@ PRBool CWellFormedDTD::IsContainer(PRInt32 aTag) const{
|
|||
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;
|
||||
|
||||
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;
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -1079,90 +1079,58 @@ nsresult CNavDTD::WillHandleStartTag(CToken* aToken,eHTMLTags aTag,nsCParserNode
|
|||
result=CollectSkippedContent(aNode,theAttrCount);
|
||||
}
|
||||
|
||||
/**********************************************************
|
||||
THIS WILL ULTIMATELY BECOME THE REAL OBSERVER API...
|
||||
**********************************************************/
|
||||
nsDeque* theDeque= (mParser && aTag != eHTMLTag_unknown)? (mParser->GetObserverDictionary()).GetObserversForTag(aTag):nsnull;
|
||||
if(theDeque){
|
||||
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 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;
|
||||
if(mParser) {
|
||||
nsAutoString charsetValue;
|
||||
nsCharsetSource charsetSource;
|
||||
mParser->GetDocumentCharset(charsetValue,charsetSource);
|
||||
CParserContext* pc=mParser->PeekContext();
|
||||
void* theDocID=(pc) ? pc->mKey : 0;
|
||||
result=(mParser->GetObserverService()).Notify(aTag,aNode,(PRUint32)theDocID,this,charsetValue,charsetSource);
|
||||
}
|
||||
|
||||
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);
|
||||
if(NS_SUCCEEDED(result)) {
|
||||
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
|
||||
//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;
|
||||
}
|
||||
|
||||
|
@ -1302,6 +1270,11 @@ nsresult CNavDTD::HandleStartToken(CToken* aToken) {
|
|||
result=mSink->AddLeaf(*theNode);
|
||||
break;
|
||||
|
||||
case eHTMLTag_image:
|
||||
aToken->SetTypeID(theChildTag=eHTMLTag_img);
|
||||
result=HandleDefaultStartToken(aToken,theChildTag,*theNode);
|
||||
break;
|
||||
|
||||
case eHTMLTag_userdefined:
|
||||
break; //drop them on the floor for now...
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "nsDTDUtils.h"
|
||||
#include "CNavDTD.h"
|
||||
#include "nsIParserNode.h"
|
||||
|
||||
#include "nsIObserverService.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.
|
||||
******************************************************************************/
|
||||
|
||||
CObserverDictionary::CObserverDictionary() {
|
||||
CObserverService::CObserverService() {
|
||||
|
||||
nsCRT::zero(mObservers,sizeof(mObservers));
|
||||
|
||||
|
@ -652,7 +653,7 @@ CObserverDictionary::CObserverDictionary() {
|
|||
|
||||
}
|
||||
|
||||
CObserverDictionary::~CObserverDictionary() {
|
||||
CObserverService::~CObserverService() {
|
||||
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;
|
||||
nsObserverReleaser theReleaser;
|
||||
for(theIndex=0;theIndex<=NS_HTML_TAG_MAX;theIndex++){
|
||||
if(mObservers[theIndex]){
|
||||
//nsIElementObserver* theElementObserver=0;
|
||||
mObservers[theIndex]->ForEach(theReleaser);
|
||||
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;
|
||||
nsIObserverService* theObserverService = nsnull;
|
||||
result = nsServiceManager::GetService(NS_OBSERVERSERVICE_PROGID, nsIObserverService::GetIID(),
|
||||
|
@ -703,22 +719,16 @@ void CObserverDictionary::RegisterObservers(nsString& aTopic) {
|
|||
PRUint32 theTagIndex = 0;
|
||||
theTagStr = theElementObserver->GetTagNameAt(theTagIndex);
|
||||
while (theTagStr != nsnull) {
|
||||
// XXX - HACK - Hardcoding PI for simplification. PI handling should not
|
||||
// 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));
|
||||
eHTMLTags theTag = nsHTMLTags::LookupTag(nsCAutoString(theTagStr));
|
||||
if((eHTMLTag_userdefined!=theTag) && (theTag <= NS_HTML_TAG_MAX)){
|
||||
if(mObservers[theTag] == nsnull) {
|
||||
mObservers[theTag] = new nsDeque(0);
|
||||
}
|
||||
NS_ADDREF(theElementObserver);
|
||||
mObservers[theTag]->Push(theElementObserver);
|
||||
}
|
||||
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)
|
||||
return mObservers[aTag];
|
||||
return nsnull;
|
||||
|
|
|
@ -38,6 +38,8 @@
|
|||
#include "nsString.h"
|
||||
#include "nsIElementObserver.h"
|
||||
|
||||
class nsIParserNode;
|
||||
|
||||
/***************************************************************
|
||||
Before digging into the NavDTD, we'll define a helper
|
||||
class called CTagStack.
|
||||
|
@ -242,16 +244,19 @@ struct CRCStruct {
|
|||
might be nice to use a more dynamic approach that would permit observers to
|
||||
come and go on a document basis.
|
||||
******************************************************************************/
|
||||
class CObserverDictionary {
|
||||
class CObserverService {
|
||||
public:
|
||||
CObserverDictionary();
|
||||
~CObserverDictionary();
|
||||
CObserverService();
|
||||
~CObserverService();
|
||||
|
||||
void RegisterObservers(nsString& aTopicList);
|
||||
void UnregisterObservers();
|
||||
nsDeque* GetObserversForTag(eHTMLTags aTag);
|
||||
nsresult Notify(eHTMLTags aTag,nsIParserNode& aNode,
|
||||
PRUint32 aUniqueID, nsIDTD* aDTD,
|
||||
nsAutoString& aCharsetValue,nsCharsetSource& aCharsetSource) ;
|
||||
|
||||
protected:
|
||||
void RegisterObservers(nsString& aTopicList);
|
||||
void UnregisterObservers();
|
||||
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);
|
||||
mTypeID = nsHTMLTags::LookupTag(mTextValue);
|
||||
|
||||
if(eHTMLTag_image==mTypeID){
|
||||
mTypeID=eHTMLTag_img;
|
||||
}
|
||||
|
||||
//Good. Now, let's skip whitespace after the identifier,
|
||||
//and see if the next char is ">". If so, we have a complete
|
||||
//tag without attributes.
|
||||
|
@ -507,7 +503,6 @@ nsresult CTextToken::ConsumeUntil(PRUnichar aChar,PRBool aIgnoreComments,nsScann
|
|||
//target endtag, or the start of another comment.
|
||||
|
||||
static nsAutoString theWhitespace2("\b\t ");
|
||||
static nsAutoString theTerminals("\"\'<");
|
||||
|
||||
PRInt32 termStrLen=aTerminalString.Length();
|
||||
while((!done) && (NS_OK==result)) {
|
||||
|
@ -523,9 +518,7 @@ nsresult CTextToken::ConsumeUntil(PRUnichar aChar,PRBool aIgnoreComments,nsScann
|
|||
result=theComment.Consume(aChar,aScanner);
|
||||
if(NS_OK==result) {
|
||||
//result=aScanner.SkipWhitespace();
|
||||
//temp.Append("<!");
|
||||
mTextValue.Append(theComment.GetStringValueXXX());
|
||||
//temp.Append(">");
|
||||
}
|
||||
} else {
|
||||
//read a tag...
|
||||
|
@ -534,15 +527,6 @@ nsresult CTextToken::ConsumeUntil(PRUnichar aChar,PRBool aIgnoreComments,nsScann
|
|||
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)) {
|
||||
static CWhitespaceToken theWS;
|
||||
result=theWS.Consume(aChar,aScanner);
|
||||
|
@ -552,7 +536,7 @@ nsresult CTextToken::ConsumeUntil(PRUnichar aChar,PRBool aIgnoreComments,nsScann
|
|||
}
|
||||
else {
|
||||
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
|
||||
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);
|
||||
done=PRBool(-1<rpos);
|
||||
} //while
|
||||
int len=mTextValue.Length();
|
||||
if(NS_SUCCEEDED(result)) {
|
||||
int len=mTextValue.Length();
|
||||
mTextValue.Truncate(len-(theRight.Length()-rpos));
|
||||
|
||||
// Make aTerminalString contain the name of the end tag ** as seen in **
|
||||
|
|
|
@ -287,7 +287,7 @@ friend class CTokenHandler;
|
|||
* @param
|
||||
* @return
|
||||
*/
|
||||
CObserverDictionary& GetObserverDictionary(void) { return mObserverDictionary; }
|
||||
CObserverService& GetObserverService(void) { return mObserverService; }
|
||||
|
||||
protected:
|
||||
|
||||
|
@ -379,7 +379,7 @@ protected:
|
|||
nsString mCharset;
|
||||
nsCharsetSource mCharsetSource;
|
||||
nsresult mInternalState;
|
||||
CObserverDictionary mObserverDictionary;
|
||||
CObserverService mObserverService;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -436,28 +436,6 @@ PRBool CWellFormedDTD::IsContainer(PRInt32 aTag) const{
|
|||
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;
|
||||
|
||||
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;
|
||||
return result;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче