28965 32523 -- Setting Document key to nsISupports
34308
19575 - Fixed had by replacing PRUnichar array with nsDeque.

r=ftang
22786 - Accounting for attributes on <HTML> tag [ this got backed out before ]
r=nisheeth
This commit is contained in:
harishd%netscape.com 2000-04-04 23:58:40 +00:00
parent a8a9242fac
commit 932d797ff8
18 changed files with 140 additions and 122 deletions

View File

@ -1128,8 +1128,8 @@ nsresult CNavDTD::WillHandleStartTag(CToken* aToken,eHTMLTags aTag,nsCParserNode
if(theService) {
CParserContext* pc=mParser->PeekContext();
void* theDocID=(pc)? pc->mKey:0;
result=theService->Notify(aTag,aNode,(PRUint32)theDocID, NS_ConvertToString(kHTMLTextContentType), mParser);
result=theService->Notify(aTag,aNode,theDocID, NS_ConvertToString(kHTMLTextContentType), mParser);
}
}
@ -1334,12 +1334,12 @@ nsresult CNavDTD::HandleStartToken(CToken* aToken) {
if(nsHTMLElement::IsSectionTag(theChildTag)){
switch(theChildTag){
/*case eHTMLTag_html:
case eHTMLTag_html:
if(mBodyContext->GetCount()>0) {
result=OpenContainer(theNode,theChildTag,PR_FALSE);
isTokenHandled=PR_TRUE;
}
break;*/
break;
case eHTMLTag_body:
if(mHasOpenBody) {
result=OpenContainer(theNode,theChildTag,PR_FALSE);
@ -2561,7 +2561,7 @@ nsresult CNavDTD::OpenHTML(const nsIParserNode *aNode){
START_TIMER();
// Don't push more than one HTML tag into the stack...
//if(mBodyContext->GetCount()==0)
if(mBodyContext->GetCount()==0)
mBodyContext->Push(aNode);
return result;

View File

@ -1204,7 +1204,7 @@ nsresult COtherDTD::WillHandleStartTag(CToken* aToken,eHTMLTags aTag,nsCParserNo
CParserContext* pc=mParser->PeekContext();
void* theDocID=(pc)? pc->mKey:0;
result=theService->Notify(aTag,aNode,(PRUint32)theDocID, NS_ConvertToString(kHTMLTextContentType), mParser);
result=theService->Notify(aTag,aNode,theDocID, NS_ConvertToString(kHTMLTextContentType), mParser);
}
}

View File

@ -899,8 +899,14 @@ public:
registering tags.
**************************************************************/
nsObserverTopic::nsObserverTopic(const nsString& aTopic) : mTopic(aTopic){
nsCRT::zero(mObservers,sizeof(mObservers));
nsObserverTopic::nsObserverTopic(const nsString& aTopic) : mTopic(aTopic),
mKeys(0),
mValues(0) {
nsCRT::zero(mObservers,sizeof(mObservers));
mCharsetKey.AssignWithConversion("charset");
mSourceKey.AssignWithConversion("charsetSource");
mDTDKey.AssignWithConversion("X_COMMAND");
}
nsObserverTopic::~nsObserverTopic() {
@ -951,7 +957,7 @@ void nsObserverTopic::RegisterObserverForTag(nsIElementObserver *anObserver,eHTM
* @param aCharsetSource -
* @return if SUCCESS return NS_OK else return ERROR code.
*/
nsresult nsObserverTopic::Notify(eHTMLTags aTag,nsIParserNode& aNode,PRUint32 aUniqueID,nsIParser* aParser) {
nsresult nsObserverTopic::Notify(eHTMLTags aTag,nsIParserNode& aNode,void* aUniqueID,nsIParser* aParser) {
nsresult result=NS_OK;
nsDeque* theDeque=GetObserversForTag(aTag);
@ -964,44 +970,31 @@ nsresult nsObserverTopic::Notify(eHTMLTags aTag,nsIParserNode& aNode,PRUint32 aU
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();
mKeys.Empty();
mValues.Empty();
int index = 0;
for(index=0; index<theAttrCount; index++) {
mKeys.Push((PRUnichar*)aNode.GetKeyAt(index).GetUnicode());
mValues.Push((PRUnichar*)aNode.GetValueAt(index).GetUnicode());
}
nsAutoString theCharsetKey; theCharsetKey.AssignWithConversion("charset");
nsAutoString theSourceKey; theSourceKey.AssignWithConversion("charsetSource");
nsAutoString intValue;
// Add pseudo attribute in the end
if(index>=47) index=47; //XXX HACK HACK HACK!!!!!
//We really need to do a better job with attributes here.
mKeys.Push((PRUnichar*)mCharsetKey.GetUnicode());
mValues.Push((PRUnichar*)theCharsetValue.GetUnicode());
mKeys.Push((PRUnichar*)mSourceKey.GetUnicode());
intValue.Append(PRInt32(theCharsetSource),10);
mValues.Push((PRUnichar*)intValue.GetUnicode());
mKeys.Push((PRUnichar*)mDTDKey.GetUnicode());
mValues.Push((PRUnichar*)mTopic.GetUnicode());
if(index < 50) {
theKeys[index]=theCharsetKey.GetUnicode();
theValues[index] = theCharsetValue.GetUnicode();
index++;
}
if(index < 50) {
theKeys[index]=theSourceKey.GetUnicode();
PRInt32 sourceInt = theCharsetSource;
intValue.AppendWithConversion(sourceInt,10);
theValues[index] = intValue.GetUnicode();
index++;
}
nsAutoString theDTDKey; theDTDKey.AssignWithConversion("X_COMMAND");
// nsAutoString theDTDValue(aCommand);
if(index < 50) {
theKeys[index]=theDTDKey.GetUnicode();
theValues[index]=mTopic.GetUnicode();
index++;
}
nsAutoString theTagStr(nsHTMLTags::GetStringValue(aTag));
nsObserverNotifier theNotifier(theTagStr.GetUnicode(),aUniqueID,index,theKeys,theValues);
nsObserverNotifier theNotifier(theTagStr.GetUnicode(),(nsISupports*)aUniqueID,&mKeys,&mValues);
theDeque->FirstThat(theNotifier);
result=theNotifier.mResult;
}//if
@ -1145,7 +1138,7 @@ void CObserverService::UnregisterObservers(const nsString& aTopic) {
*/
nsresult CObserverService::Notify( eHTMLTags aTag,
nsIParserNode& aNode,
PRUint32 aUniqueID,
void* aUniqueID,
const nsString& aTopic,
nsIParser* aParser) {
nsresult result=NS_OK;

View File

@ -301,9 +301,14 @@ public:
PRBool Matches(const nsString& aTopic);
void RegisterObserverForTag(nsIElementObserver *anObserver,eHTMLTags aTag);
nsDeque* GetObserversForTag(eHTMLTags aTag);
nsresult Notify(eHTMLTags aTag,nsIParserNode& aNode,PRUint32 aUniqueID,nsIParser* aParser);
nsresult Notify(eHTMLTags aTag,nsIParserNode& aNode,void* aUniqueID,nsIParser* aParser);
nsString mTopic;
nsDeque mKeys;
nsDeque mValues;
nsString mCharsetKey;
nsString mSourceKey;
nsString mDTDKey;
nsDeque* mObservers[NS_HTML_TAG_MAX + 1];
};
@ -322,7 +327,7 @@ public:
nsDeque* GetObserversForTagInTopic(eHTMLTags aTag,const nsString& aTopic);
nsresult Notify( eHTMLTags aTag,
nsIParserNode& aNode,
PRUint32 aUniqueID,
void* aUniqueID,
const nsString& aTopic,
nsIParser* aParser);
nsObserverTopic* GetTopic(const nsString& aTopic);
@ -339,9 +344,8 @@ protected:
**************************************************************/
class nsObserverNotifier: public nsDequeFunctor{
public:
nsObserverNotifier(const PRUnichar* aTagName,PRUint32 aUniqueKey,PRUint32 aCount=0,
const PRUnichar** aKeys=nsnull,const PRUnichar** aValues=nsnull){
mCount=aCount;
nsObserverNotifier(const PRUnichar* aTagName,nsISupports* aUniqueKey,
const nsDeque* aKeys=0,const nsDeque* aValues=0){
mKeys=aKeys;
mValues=aValues;
mUniqueKey=aUniqueKey;
@ -351,19 +355,18 @@ public:
virtual void* operator()(void* anObject) {
nsIElementObserver* theObserver= (nsIElementObserver*)anObject;
if(theObserver) {
mResult = theObserver->Notify(mUniqueKey,mTagName,mCount,mKeys,mValues);
mResult = theObserver->Notify(mUniqueKey,mTagName,mKeys,mValues);
}
if(NS_OK==mResult)
return 0;
return anObject;
}
const PRUnichar** mKeys;
const PRUnichar** mValues;
PRUint32 mCount;
PRUint32 mUniqueKey;
nsresult mResult;
const nsDeque* mKeys;
const nsDeque* mValues;
const PRUnichar* mTagName;
nsISupports* mUniqueKey;
nsresult mResult;
};

View File

@ -128,6 +128,7 @@ nsHTMLContentSinkStream::nsHTMLContentSinkStream()
mBufferSize = 0;
mBufferLength = 0;
mFlags = 0;
mHasOpenHtmlTag=PR_FALSE;
}
NS_IMETHODIMP
@ -512,14 +513,21 @@ nsHTMLContentSinkStream::OpenHTML(const nsIParserNode& aNode)
eHTMLTags tag = (eHTMLTags)aNode.GetNodeType();
if (tag == eHTMLTag_html)
{
// See bug 20246: the html tag doesn't have "html" in its text,
// so AddStartTag will do the wrong thing
Write(kLessThan);
nsString temp; temp.AssignWithConversion(nsHTMLTags::GetStringValue(tag));
nsAutoCString tagname(temp);
Write(tagname);
Write(kGreaterThan);
if(!mHasOpenHtmlTag) {
AddStartTag(aNode);
mHasOpenHtmlTag=PR_TRUE;
}
else {
PRInt32 ac=aNode.GetAttributeCount();
if(ac>0) {
Write(kLessThan);
nsAutoString tagname;
tagname.AssignWithConversion(nsHTMLTags::GetStringValue(tag));
Write(tagname);
WriteAttributes(aNode);
Write(kGreaterThan);
}
}
}
return NS_OK;
}

View File

@ -191,6 +191,7 @@ protected:
PRBool mDoFormat;
PRBool mDoHeader;
PRBool mBodyOnly;
PRBool mHasOpenHtmlTag;
PRInt32 mMaxColumn;

View File

@ -33,6 +33,7 @@
#include "nsISupports.h"
#include "prtypes.h"
#include "nsHTMLTokens.h"
#include "nsDeque.h"
// {4672AA04-F6AE-11d2-B3B7-00805F8A6670}
@ -64,6 +65,9 @@ public:
NS_IMETHOD Notify(PRUint32 aDocumentID, const PRUnichar* aTag,
PRUint32 numOfAttributes, const PRUnichar* nameArray[],
const PRUnichar* valueArray[]) = 0;
NS_IMETHOD Notify(nsISupports* aDocumentID, const PRUnichar* aTag,
const nsDeque* aKeys, const nsDeque* aValues) = 0;
};

View File

@ -997,7 +997,7 @@ aMimeType,PRBool aVerifyEnabled,PRBool aLastCall,eParseMode aMode){
NS_RELEASE(me);
return NS_ERROR_OUT_OF_MEMORY;
}
NS_IF_RELEASE(theDTD);
}
else {
mParserContext->mScanner->Append(aSourceBuffer);

View File

@ -902,7 +902,7 @@ NS_IMETHODIMP CViewSourceHTML::HandleToken(CToken* aToken,nsIParser* aParser) {
void* theDocID=(pc)? pc->mKey:0;
eHTMLTags theTag=(eHTMLTags)theToken->GetTypeID();
result=theService->Notify(theTag,theContext.mTokenNode,(PRUint32)theDocID, NS_ConvertToString(kViewSourceCommand), mParser);
result=theService->Notify(theTag,theContext.mTokenNode,theDocID, NS_ConvertToString(kViewSourceCommand), mParser);
}
}
theContext.mTokenNode.Init(0,0,gTokenRecycler); //now recycle.

View File

@ -1128,8 +1128,8 @@ nsresult CNavDTD::WillHandleStartTag(CToken* aToken,eHTMLTags aTag,nsCParserNode
if(theService) {
CParserContext* pc=mParser->PeekContext();
void* theDocID=(pc)? pc->mKey:0;
result=theService->Notify(aTag,aNode,(PRUint32)theDocID, NS_ConvertToString(kHTMLTextContentType), mParser);
result=theService->Notify(aTag,aNode,theDocID, NS_ConvertToString(kHTMLTextContentType), mParser);
}
}
@ -1334,12 +1334,12 @@ nsresult CNavDTD::HandleStartToken(CToken* aToken) {
if(nsHTMLElement::IsSectionTag(theChildTag)){
switch(theChildTag){
/*case eHTMLTag_html:
case eHTMLTag_html:
if(mBodyContext->GetCount()>0) {
result=OpenContainer(theNode,theChildTag,PR_FALSE);
isTokenHandled=PR_TRUE;
}
break;*/
break;
case eHTMLTag_body:
if(mHasOpenBody) {
result=OpenContainer(theNode,theChildTag,PR_FALSE);
@ -2561,7 +2561,7 @@ nsresult CNavDTD::OpenHTML(const nsIParserNode *aNode){
START_TIMER();
// Don't push more than one HTML tag into the stack...
//if(mBodyContext->GetCount()==0)
if(mBodyContext->GetCount()==0)
mBodyContext->Push(aNode);
return result;

View File

@ -1204,7 +1204,7 @@ nsresult COtherDTD::WillHandleStartTag(CToken* aToken,eHTMLTags aTag,nsCParserNo
CParserContext* pc=mParser->PeekContext();
void* theDocID=(pc)? pc->mKey:0;
result=theService->Notify(aTag,aNode,(PRUint32)theDocID, NS_ConvertToString(kHTMLTextContentType), mParser);
result=theService->Notify(aTag,aNode,theDocID, NS_ConvertToString(kHTMLTextContentType), mParser);
}
}

View File

@ -899,8 +899,14 @@ public:
registering tags.
**************************************************************/
nsObserverTopic::nsObserverTopic(const nsString& aTopic) : mTopic(aTopic){
nsCRT::zero(mObservers,sizeof(mObservers));
nsObserverTopic::nsObserverTopic(const nsString& aTopic) : mTopic(aTopic),
mKeys(0),
mValues(0) {
nsCRT::zero(mObservers,sizeof(mObservers));
mCharsetKey.AssignWithConversion("charset");
mSourceKey.AssignWithConversion("charsetSource");
mDTDKey.AssignWithConversion("X_COMMAND");
}
nsObserverTopic::~nsObserverTopic() {
@ -951,7 +957,7 @@ void nsObserverTopic::RegisterObserverForTag(nsIElementObserver *anObserver,eHTM
* @param aCharsetSource -
* @return if SUCCESS return NS_OK else return ERROR code.
*/
nsresult nsObserverTopic::Notify(eHTMLTags aTag,nsIParserNode& aNode,PRUint32 aUniqueID,nsIParser* aParser) {
nsresult nsObserverTopic::Notify(eHTMLTags aTag,nsIParserNode& aNode,void* aUniqueID,nsIParser* aParser) {
nsresult result=NS_OK;
nsDeque* theDeque=GetObserversForTag(aTag);
@ -964,44 +970,31 @@ nsresult nsObserverTopic::Notify(eHTMLTags aTag,nsIParserNode& aNode,PRUint32 aU
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();
mKeys.Empty();
mValues.Empty();
int index = 0;
for(index=0; index<theAttrCount; index++) {
mKeys.Push((PRUnichar*)aNode.GetKeyAt(index).GetUnicode());
mValues.Push((PRUnichar*)aNode.GetValueAt(index).GetUnicode());
}
nsAutoString theCharsetKey; theCharsetKey.AssignWithConversion("charset");
nsAutoString theSourceKey; theSourceKey.AssignWithConversion("charsetSource");
nsAutoString intValue;
// Add pseudo attribute in the end
if(index>=47) index=47; //XXX HACK HACK HACK!!!!!
//We really need to do a better job with attributes here.
mKeys.Push((PRUnichar*)mCharsetKey.GetUnicode());
mValues.Push((PRUnichar*)theCharsetValue.GetUnicode());
mKeys.Push((PRUnichar*)mSourceKey.GetUnicode());
intValue.Append(PRInt32(theCharsetSource),10);
mValues.Push((PRUnichar*)intValue.GetUnicode());
mKeys.Push((PRUnichar*)mDTDKey.GetUnicode());
mValues.Push((PRUnichar*)mTopic.GetUnicode());
if(index < 50) {
theKeys[index]=theCharsetKey.GetUnicode();
theValues[index] = theCharsetValue.GetUnicode();
index++;
}
if(index < 50) {
theKeys[index]=theSourceKey.GetUnicode();
PRInt32 sourceInt = theCharsetSource;
intValue.AppendWithConversion(sourceInt,10);
theValues[index] = intValue.GetUnicode();
index++;
}
nsAutoString theDTDKey; theDTDKey.AssignWithConversion("X_COMMAND");
// nsAutoString theDTDValue(aCommand);
if(index < 50) {
theKeys[index]=theDTDKey.GetUnicode();
theValues[index]=mTopic.GetUnicode();
index++;
}
nsAutoString theTagStr(nsHTMLTags::GetStringValue(aTag));
nsObserverNotifier theNotifier(theTagStr.GetUnicode(),aUniqueID,index,theKeys,theValues);
nsObserverNotifier theNotifier(theTagStr.GetUnicode(),(nsISupports*)aUniqueID,&mKeys,&mValues);
theDeque->FirstThat(theNotifier);
result=theNotifier.mResult;
}//if
@ -1145,7 +1138,7 @@ void CObserverService::UnregisterObservers(const nsString& aTopic) {
*/
nsresult CObserverService::Notify( eHTMLTags aTag,
nsIParserNode& aNode,
PRUint32 aUniqueID,
void* aUniqueID,
const nsString& aTopic,
nsIParser* aParser) {
nsresult result=NS_OK;

View File

@ -301,9 +301,14 @@ public:
PRBool Matches(const nsString& aTopic);
void RegisterObserverForTag(nsIElementObserver *anObserver,eHTMLTags aTag);
nsDeque* GetObserversForTag(eHTMLTags aTag);
nsresult Notify(eHTMLTags aTag,nsIParserNode& aNode,PRUint32 aUniqueID,nsIParser* aParser);
nsresult Notify(eHTMLTags aTag,nsIParserNode& aNode,void* aUniqueID,nsIParser* aParser);
nsString mTopic;
nsDeque mKeys;
nsDeque mValues;
nsString mCharsetKey;
nsString mSourceKey;
nsString mDTDKey;
nsDeque* mObservers[NS_HTML_TAG_MAX + 1];
};
@ -322,7 +327,7 @@ public:
nsDeque* GetObserversForTagInTopic(eHTMLTags aTag,const nsString& aTopic);
nsresult Notify( eHTMLTags aTag,
nsIParserNode& aNode,
PRUint32 aUniqueID,
void* aUniqueID,
const nsString& aTopic,
nsIParser* aParser);
nsObserverTopic* GetTopic(const nsString& aTopic);
@ -339,9 +344,8 @@ protected:
**************************************************************/
class nsObserverNotifier: public nsDequeFunctor{
public:
nsObserverNotifier(const PRUnichar* aTagName,PRUint32 aUniqueKey,PRUint32 aCount=0,
const PRUnichar** aKeys=nsnull,const PRUnichar** aValues=nsnull){
mCount=aCount;
nsObserverNotifier(const PRUnichar* aTagName,nsISupports* aUniqueKey,
const nsDeque* aKeys=0,const nsDeque* aValues=0){
mKeys=aKeys;
mValues=aValues;
mUniqueKey=aUniqueKey;
@ -351,19 +355,18 @@ public:
virtual void* operator()(void* anObject) {
nsIElementObserver* theObserver= (nsIElementObserver*)anObject;
if(theObserver) {
mResult = theObserver->Notify(mUniqueKey,mTagName,mCount,mKeys,mValues);
mResult = theObserver->Notify(mUniqueKey,mTagName,mKeys,mValues);
}
if(NS_OK==mResult)
return 0;
return anObject;
}
const PRUnichar** mKeys;
const PRUnichar** mValues;
PRUint32 mCount;
PRUint32 mUniqueKey;
nsresult mResult;
const nsDeque* mKeys;
const nsDeque* mValues;
const PRUnichar* mTagName;
nsISupports* mUniqueKey;
nsresult mResult;
};

View File

@ -128,6 +128,7 @@ nsHTMLContentSinkStream::nsHTMLContentSinkStream()
mBufferSize = 0;
mBufferLength = 0;
mFlags = 0;
mHasOpenHtmlTag=PR_FALSE;
}
NS_IMETHODIMP
@ -512,14 +513,21 @@ nsHTMLContentSinkStream::OpenHTML(const nsIParserNode& aNode)
eHTMLTags tag = (eHTMLTags)aNode.GetNodeType();
if (tag == eHTMLTag_html)
{
// See bug 20246: the html tag doesn't have "html" in its text,
// so AddStartTag will do the wrong thing
Write(kLessThan);
nsString temp; temp.AssignWithConversion(nsHTMLTags::GetStringValue(tag));
nsAutoCString tagname(temp);
Write(tagname);
Write(kGreaterThan);
if(!mHasOpenHtmlTag) {
AddStartTag(aNode);
mHasOpenHtmlTag=PR_TRUE;
}
else {
PRInt32 ac=aNode.GetAttributeCount();
if(ac>0) {
Write(kLessThan);
nsAutoString tagname;
tagname.AssignWithConversion(nsHTMLTags::GetStringValue(tag));
Write(tagname);
WriteAttributes(aNode);
Write(kGreaterThan);
}
}
}
return NS_OK;
}

View File

@ -191,6 +191,7 @@ protected:
PRBool mDoFormat;
PRBool mDoHeader;
PRBool mBodyOnly;
PRBool mHasOpenHtmlTag;
PRInt32 mMaxColumn;

View File

@ -33,6 +33,7 @@
#include "nsISupports.h"
#include "prtypes.h"
#include "nsHTMLTokens.h"
#include "nsDeque.h"
// {4672AA04-F6AE-11d2-B3B7-00805F8A6670}
@ -64,6 +65,9 @@ public:
NS_IMETHOD Notify(PRUint32 aDocumentID, const PRUnichar* aTag,
PRUint32 numOfAttributes, const PRUnichar* nameArray[],
const PRUnichar* valueArray[]) = 0;
NS_IMETHOD Notify(nsISupports* aDocumentID, const PRUnichar* aTag,
const nsDeque* aKeys, const nsDeque* aValues) = 0;
};

View File

@ -997,7 +997,7 @@ aMimeType,PRBool aVerifyEnabled,PRBool aLastCall,eParseMode aMode){
NS_RELEASE(me);
return NS_ERROR_OUT_OF_MEMORY;
}
NS_IF_RELEASE(theDTD);
}
else {
mParserContext->mScanner->Append(aSourceBuffer);

View File

@ -902,7 +902,7 @@ NS_IMETHODIMP CViewSourceHTML::HandleToken(CToken* aToken,nsIParser* aParser) {
void* theDocID=(pc)? pc->mKey:0;
eHTMLTags theTag=(eHTMLTags)theToken->GetTypeID();
result=theService->Notify(theTag,theContext.mTokenNode,(PRUint32)theDocID, NS_ConvertToString(kViewSourceCommand), mParser);
result=theService->Notify(theTag,theContext.mTokenNode,theDocID, NS_ConvertToString(kViewSourceCommand), mParser);
}
}
theContext.mTokenNode.Init(0,0,gTokenRecycler); //now recycle.