fixed several nsbeta2+ bugs; r=harish, buster; a=pdt

This commit is contained in:
rickg%netscape.com 2000-06-10 02:53:04 +00:00
Родитель c12a990ef8
Коммит a52435dd9f
52 изменённых файлов: 1838 добавлений и 1154 удалений

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

@ -327,7 +327,7 @@ PRBool CNavDTD::Verify(nsString& aURLRef,nsIParser* aParser){
* @update gess 02/24/00
* @param
* @return TRUE if this DTD can satisfy the request; FALSE otherwise.
*/
*/
eAutoDetectResult CNavDTD::CanParse(CParserContext& aParserContext,nsString& aBuffer, PRInt32 aVersion) {
eAutoDetectResult result=eUnknownDetect;
@ -338,14 +338,22 @@ eAutoDetectResult CNavDTD::CanParse(CParserContext& aParserContext,nsString& aBu
else if(aParserContext.mMimeType.EqualsWithConversion(kRTFTextContentType)){
result=ePrimaryDetect;
}
}
}
else {
if(PR_TRUE==aParserContext.mMimeType.EqualsWithConversion(kHTMLTextContentType)) {
result=(eDTDMode_strict==aParserContext.mDTDMode) ? eValidDetect : ePrimaryDetect;
switch(aParserContext.mDTDMode) {
case eDTDMode_strict:
case eDTDMode_transitional:
result=eValidDetect;
break;
default:
result=ePrimaryDetect;
break;
}
}
else if(PR_TRUE==aParserContext.mMimeType.EqualsWithConversion(kPlainTextContentType)) {
result=ePrimaryDetect;
}
}
else {
//otherwise, look into the buffer to see if you recognize anything...
PRBool theBufHasXML=PR_FALSE;
@ -354,12 +362,20 @@ eAutoDetectResult CNavDTD::CanParse(CParserContext& aParserContext,nsString& aBu
if(0==aParserContext.mMimeType.Length()) {
aParserContext.SetMimeType(NS_ConvertToString(kHTMLTextContentType));
if(!theBufHasXML) {
result=(eDTDMode_strict==aParserContext.mDTDMode) ? eValidDetect : ePrimaryDetect;
switch(aParserContext.mDTDMode) {
case eDTDMode_strict:
case eDTDMode_transitional:
result=eValidDetect;
break;
default:
result=ePrimaryDetect;
break;
}
}
else result=eValidDetect;
}
}
}
}
}
return result;
}
@ -816,6 +832,12 @@ nsresult CNavDTD::HandleToken(CToken* aToken,nsIParser* aParser){
nsresult CNavDTD::DidHandleStartTag(nsCParserNode& aNode,eHTMLTags aChildTag){
nsresult result=NS_OK;
#if 0
// XXX --- Ignore this: it's just rickg debug testing...
nsAutoString theStr;
aNode.GetSource(theStr);
#endif
switch(aChildTag){
case eHTMLTag_pre:
@ -2097,7 +2119,22 @@ nsresult CNavDTD::HandleDocTypeDeclToken(CToken* aToken){
STOP_TIMER();
MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::HandleDocTypeDeclToken(), this=%p\n", this));
result = (mSink)? mSink->AddDocTypeDecl(*theNode,mDTDMode):NS_OK;
/*************************************************************
While the parser is happy to deal with various modes, the
rest of layout prefers only 2: strict vs. quirks. So we'll
constrain the modes when reporting to layout.
*************************************************************/
nsDTDMode theMode=mDTDMode;
switch(mDTDMode) {
case eDTDMode_transitional:
case eDTDMode_strict:
theMode=eDTDMode_strict;
break;
default:
theMode=eDTDMode_quirks;
}
result = (mSink)? mSink->AddDocTypeDecl(*theNode,theMode):NS_OK;
mNodeRecycler->RecycleNode(theNode,mTokenRecycler);
@ -2270,6 +2307,47 @@ NS_IMETHODIMP CNavDTD::ConvertEntityToUnicode(const nsString& aEntity, PRInt32*
return NS_OK;
}
/**
* This method is called to determine whether or not
* the given childtag is a block element.
*
* @update gess 6June2000
* @param aChildID -- tag id of child
* @param aParentID -- tag id of parent (or eHTMLTag_unknown)
* @return PR_TRUE if this tag is a block tag
*/
PRBool CNavDTD::IsBlockElement(PRInt32 aTagID,PRInt32 aParentID) const {
PRBool result=PR_FALSE;
eHTMLTags theTag=(eHTMLTags)aTagID;
if((theTag>eHTMLTag_unknown) && (theTag<eHTMLTag_userdefined)) {
result=gHTMLElements[theTag].IsBlockEntity();
}
return result;
}
/**
* This method is called to determine whether or not
* the given childtag is an inline element.
*
* @update gess 6June2000
* @param aChildID -- tag id of child
* @param aParentID -- tag id of parent (or eHTMLTag_unknown)
* @return PR_TRUE if this tag is an inline tag
*/
PRBool CNavDTD::IsInlineElement(PRInt32 aTagID,PRInt32 aParentID) const {
PRBool result=PR_FALSE;
eHTMLTags theTag=(eHTMLTags)aTagID;
if((theTag>eHTMLTag_unknown) && (theTag<eHTMLTag_userdefined)) {
result=nsHTMLElement::IsInlineEntity(theTag);
}
return result;
}
/**
* This method is called to determine whether or not
* the necessary intermediate tags should be propagated
@ -3064,6 +3142,9 @@ CNavDTD::OpenContainer(const nsIParserNode *aNode,eHTMLTags aTag,PRBool aClosedB
}
break;
case eHTMLTag_counter: //drop it on the floor.
break;
case eHTMLTag_style:
case eHTMLTag_title:
break;
@ -3336,34 +3417,6 @@ nsresult CNavDTD::CloseContainersTo(PRInt32 anIndex,eHTMLTags aTarget, PRBool aC
mNodeRecycler->RecycleNode(theNode,mTokenRecycler);
}
if(eDTDMode_quirks==mDTDMode) {
#if 0
//This code takes any nodes in style stack for at this level and reopens
//then where they were originally.
if(!aClosedByStartTag) {
nsEntryStack* theStack=mBodyContext->GetStylesAt(anIndex-1);
if(theStack){
PRUint32 scount=theStack->mCount;
PRUint32 sindex=0;
for(sindex=0;sindex<scount;sindex++){
nsIParserNode* theNode=theStack->NodeAt(sindex);
if(theNode) {
((nsCParserNode*)theNode)->mUseCount--;
result=OpenContainer(theNode,(eHTMLTags)theNode->GetNodeType(),PR_FALSE);
}
}
theStack->mCount=0;
} //if
} //if
#endif
}//if
} //if
return result;
}

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

@ -389,6 +389,9 @@ CLASS_EXPORT_HTMLPARS CNavDTD : public nsIDTD {
NS_IMETHOD ConvertEntityToUnicode(const nsString& aEntity, PRInt32* aUnicode) const;
virtual PRBool IsBlockElement(PRInt32 aTagID,PRInt32 aParentID) const;
virtual PRBool IsInlineElement(PRInt32 aTagID,PRInt32 aParentID) const;
/**
* The following set of methods are used to partially construct
* the content model (via the sink) according to the type of token.

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

@ -10,22 +10,22 @@
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Contributor(s): rickg@netscape.com
*/
//#define ENABLE_CRC
//#define RICKG_DEBUG
//#define ENABLE_CRC
//#define RICKG_DEBUG
#include "nsDebug.h"
#include "nsIDTDDebug.h"
#include "nsIDTDDebug.h"
#include "COtherDTD.h"
#include "nsHTMLTokens.h"
#include "nsCRT.h"
@ -56,8 +56,6 @@ static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static NS_DEFINE_IID(kIDTDIID, NS_IDTD_IID);
static NS_DEFINE_IID(kClassIID, NS_IOTHERHTML_DTD_IID);
static const char* kNullToken = "Error: Null token given";
static const char* kInvalidTagStackPos = "Error: invalid tag stack position";
static char* kVerificationDir = "c:/temp";
@ -153,8 +151,12 @@ COtherDTD::COtherDTD() : nsIDTD(), mSharedNodes(0) {
mTokenRecycler=0;
mParserCommand=eViewNormal;
#if 0 //set this to 1 if you want strictDTD to be based on the environment setting.
char* theEnvString = PR_GetEnv("ENABLE_STRICT");
mEnableStrict=PRBool(theEnvString!=0);
else
mEnableStrict=PR_TRUE;
#endif
if(!gElementTable) {
gElementTable = new CElementTable();
@ -391,7 +393,7 @@ PRBool COtherDTD::Verify(nsString& aURLRef,nsIParser* aParser){
* NOTE: Parsing always assumes that the end result will involve
* storing the result in the main content model.
* @update gess6/24/98
* @param
* @param
* @return TRUE if this DTD can satisfy the request; FALSE otherwise.
*/
eAutoDetectResult COtherDTD::CanParse(CParserContext& aParserContext,nsString& aBuffer, PRInt32 aVersion) {
@ -407,12 +409,20 @@ eAutoDetectResult COtherDTD::CanParse(CParserContext& aParserContext,nsString& a
}
}
else {
if(PR_TRUE==aParserContext.mMimeType.EqualsWithConversion(kHTMLTextContentType)) {
result=(eDTDMode_strict==aParserContext.mDTDMode) ? ePrimaryDetect : eValidDetect;
}
else if(PR_TRUE==aParserContext.mMimeType.EqualsWithConversion(kPlainTextContentType)) {
if(PR_TRUE==aParserContext.mMimeType.EqualsWithConversion(kPlainTextContentType)) {
result=eValidDetect;
}
else if(PR_TRUE==aParserContext.mMimeType.EqualsWithConversion(kHTMLTextContentType)) {
switch(aParserContext.mDTDMode) {
case eDTDMode_strict:
case eDTDMode_transitional:
result=ePrimaryDetect;
break;
default:
result=eValidDetect;
break;
}
}
else {
//otherwise, look into the buffer to see if you recognize anything...
PRBool theBufHasXML=PR_FALSE;
@ -421,14 +431,21 @@ eAutoDetectResult COtherDTD::CanParse(CParserContext& aParserContext,nsString& a
if(0==aParserContext.mMimeType.Length()) {
aParserContext.SetMimeType(NS_ConvertToString(kHTMLTextContentType));
if(!theBufHasXML) {
result=(eDTDMode_strict==aParserContext.mDTDMode) ? ePrimaryDetect : eValidDetect;
switch(aParserContext.mDTDMode) {
case eDTDMode_strict:
case eDTDMode_transitional:
result=ePrimaryDetect;
break;
default:
result=eValidDetect;
break;
}
}
else result=eValidDetect;
}
}
}
}
return result;
}
return result;
}
@ -462,6 +479,7 @@ nsresult COtherDTD::WillBuildModel( const CParserContext& aParserContext,nsICon
mTokenRecycler=0;
mDocType=aParserContext.mDocType;
mBodyContext->mTransitional=PRBool(aParserContext.mDTDMode==eDTDMode_transitional);
if(aSink && (!mSink)) {
result=aSink->QueryInterface(kIHTMLContentSinkIID, (void **)&mSink);
}
@ -609,12 +627,9 @@ nsresult COtherDTD::HandleToken(CToken* aToken,nsIParser* aParser){
if(aToken) {
CHTMLToken* theToken= (CHTMLToken*)(aToken);
eHTMLTokenTypes theType=eHTMLTokenTypes(theToken->GetTokenType());
// eHTMLTags theTag=(eHTMLTags)theToken->GetTypeID();
// PRBool execSkipContent=PR_FALSE;
theToken->mUseCount=0; //assume every token coming into this system needs recycling.
mParser=(nsParser*)aParser;
switch(theType) {
@ -625,6 +640,9 @@ nsresult COtherDTD::HandleToken(CToken* aToken,nsIParser* aParser){
case eToken_doctypeDecl:
result=HandleStartToken(theToken); break;
case eToken_entity:
result=HandleEntityToken(theToken); break;
case eToken_end:
result=HandleEndToken(theToken); break;
@ -676,6 +694,35 @@ nsresult COtherDTD::DidHandleStartTag(nsCParserNode& aNode,eHTMLTags aChildTag){
}
break;
case eHTMLTag_meta:
{
//we should only enable user-defined entities in debug builds...
PRInt32 theCount=aNode.GetAttributeCount();
const nsString* theNamePtr=0;
const nsString* theValuePtr=0;
if(theCount) {
PRInt32 theIndex=0;
for(theIndex=0;theIndex<theCount;theIndex++){
const nsString& theKey=aNode.GetKeyAt(theIndex);
if(theKey.EqualsWithConversion("ENTITY",PR_TRUE)) {
const nsString& theName=aNode.GetValueAt(theIndex);
theNamePtr=&theName;
}
else if(theKey.EqualsWithConversion("VALUE",PR_TRUE)) {
//store the named enity with the context...
const nsString& theValue=aNode.GetValueAt(theIndex);
theValuePtr=&theValue;
}
}
}
if(theNamePtr && theValuePtr) {
mBodyContext->RegisterEntity(*theNamePtr,*theValuePtr);
}
}
break;
default:
break;
}//switch
@ -755,9 +802,7 @@ nsresult COtherDTD::WillHandleStartTag(CToken* aToken,eHTMLTags aTag,nsCParserNo
* @param aNode -- CParserNode representing this start token
* @return PR_TRUE if all went well; PR_FALSE if error occured
*/
nsresult COtherDTD::HandleStartToken(CToken* aToken) {
NS_PRECONDITION(0!=aToken,kNullToken);
nsresult COtherDTD::HandleStartToken(CToken* aToken) {
#ifdef RICKG_DEBUG
WriteTokenToLog(aToken);
#endif
@ -781,15 +826,15 @@ nsresult COtherDTD::HandleStartToken(CToken* aToken) {
PRBool theTagWasHandled=PR_FALSE;
switch(theChildTag) {
case eHTMLTag_html:
if(!HasOpenContainer(theChildTag)) {
if(!mBodyContext->HasOpenContainer(theChildTag)){
mSink->OpenHTML(*theNode);
mBodyContext->Push(theNode,0);
}
theTagWasHandled=PR_TRUE;
break;
default:
CElement* theElement=gElementTable->mElements[theParent];
if(theElement) {
@ -798,7 +843,7 @@ nsresult COtherDTD::HandleStartToken(CToken* aToken) {
}
break;
}//switch
if(theTagWasHandled) {
DidHandleStartTag(*theNode,theChildTag);
}
@ -823,9 +868,7 @@ nsresult COtherDTD::HandleStartToken(CToken* aToken) {
* @param aToken -- next (start) token to be handled
* @return PR_TRUE if all went well; PR_FALSE if error occured
*/
nsresult COtherDTD::HandleEndToken(CToken* aToken) {
NS_PRECONDITION(0!=aToken,kNullToken);
nsresult COtherDTD::HandleEndToken(CToken* aToken) {
nsresult result=NS_OK;
eHTMLTags theChildTag=(eHTMLTags)aToken->GetTypeID();
@ -840,7 +883,7 @@ nsresult COtherDTD::HandleEndToken(CToken* aToken) {
break;
case eHTMLTag_script:
mHasOpenScript=PR_FALSE;
mHasOpenScript=PR_FALSE;
default:
PRInt32 theCount=mBodyContext->GetCount();
@ -899,6 +942,38 @@ nsresult COtherDTD::CollectAttributes(nsCParserNode& aNode,eHTMLTags aTag,PRInt3
return result;
}
/**
* This method gets called when an entity token has been
* encountered in the parse process.
*
* @update gess 3/25/98
* @param aToken -- next (start) token to be handled
* @return PR_TRUE if all went well; PR_FALSE if error occured
*/
nsresult COtherDTD::HandleEntityToken(CToken* aToken) {
nsresult result=NS_OK;
nsString& theStr=aToken->GetStringValueXXX();
PRUnichar theChar=theStr.CharAt(0);
if((kHashsign!=theChar) && (-1==nsHTMLEntities::EntityToUnicode(theStr))){
//before we just toss this away as a bogus entity, let's check...
CNamedEntity *theEntity=mBodyContext->GetEntity(theStr);
CToken *theToken=0;
if(theEntity) {
theToken=new CTextToken(theEntity->mValue);
}
else {
//if you're here we have a bogus entity.
//convert it into a text token.
nsAutoString temp; temp.AssignWithConversion("&");
temp.Append(theStr);
theToken=new CTextToken(temp);
}
result=HandleStartToken(theToken);
}
return result;
}
/***********************************************************************************
The preceeding tables determine the set of elements each tag can contain...
@ -914,9 +989,14 @@ nsresult COtherDTD::CollectAttributes(nsCParserNode& aNode,eHTMLTags aTag,PRInt3
* @return PR_TRUE if parent can contain child
*/
PRBool COtherDTD::CanContain(PRInt32 aParent,PRInt32 aChild) const {
PRBool result=PR_FALSE;
//result=gHTMLElements[aParent].CanContain((eHTMLTags)aChild);
return result;
CElement *theParent=gElementTable->mElements[eHTMLTags(aParent)];
if(theParent) {
CElement *theChild=gElementTable->mElements[eHTMLTags(aChild)];
if(aChild) {
return theParent->CanContain(theChild,mBodyContext);
}
}
return PR_FALSE;
}
/**
@ -938,10 +1018,47 @@ NS_IMETHODIMP COtherDTD::ConvertEntityToUnicode(const nsString& aEntity, PRInt32
return NS_OK;
}
/**
* This method is called to determine whether or not
* the given childtag is a block element.
*
* @update gess 6June2000
* @param aChildID -- tag id of child
* @param aParentID -- tag id of parent (or eHTMLTag_unknown)
* @return PR_TRUE if this tag is a block tag
*/
PRBool COtherDTD::IsBlockElement(PRInt32 aChildID,PRInt32 aParentID) const {
PRBool result=PR_FALSE;
if(gElementTable) {
CElement *theElement=gElementTable->GetElement((eHTMLTags)aChildID);
result = (theElement) ? theElement->IsBlockElement((eHTMLTags)aParentID) : PR_FALSE;
}
return result;
}
/**
* This method is called to determine whether or not
* the given childtag is an inline element.
*
* @update gess 6June2000
* @param aChildID -- tag id of child
* @param aParentID -- tag id of parent (or eHTMLTag_unknown)
* @return PR_TRUE if this tag is an inline element
*/
PRBool COtherDTD::IsInlineElement(PRInt32 aChildID,PRInt32 aParentID) const {
PRBool result=PR_FALSE;
if(gElementTable) {
CElement *theElement=gElementTable->GetElement((eHTMLTags)aChildID);
result = (theElement) ? theElement->IsInlineElement((eHTMLTags)aParentID) : PR_FALSE;
}
return result;
}
/**
* This method gets called to determine whether a given
* tag is itself a container
* tag is itself a container
*
* @update gess 4/8/98
* @param aTag -- tag to test as a container
@ -951,155 +1068,6 @@ PRBool COtherDTD::IsContainer(PRInt32 aTag) const {
return gElementTable->mElements[eHTMLTags(aTag)]->IsContainer();
}
/**
* This method allows the caller to determine if a given container
* is currently open
*
* @update gess 11/9/98
* @param
* @return
*/
PRBool COtherDTD::HasOpenContainer(eHTMLTags aContainer) const {
PRBool result=PR_FALSE;
switch(aContainer) {
case eHTMLTag_form:
result=mHasOpenForm; break;
case eHTMLTag_map:
result=mHasOpenMap; break;
default:
result=mBodyContext->HasOpenContainer(aContainer);
break;
}
return result;
}
/**
* This method allows the caller to determine if a any member
* in a set of tags is currently open
*
* @update gess 11/9/98
* @param
* @return
*/
PRBool COtherDTD::HasOpenContainer(const eHTMLTags aTagSet[],PRInt32 aCount) const {
int theIndex;
int theTopIndex=mBodyContext->GetCount()-1;
for(theIndex=theTopIndex;theIndex>0;theIndex--){
if(FindTagInSet((*mBodyContext)[theIndex],aTagSet,aCount))
return PR_TRUE;
}
return PR_FALSE;
}
/**
* This method does two things: 1st, help construct
* our own internal model of the content-stack; and
* 2nd, pass this message on to the sink.
* @update gess4/6/98
* @param aNode -- next node to be removed from our model
* @param aTag -- id of tag to be closed
* @param aClosedByStartTag -- ONLY TRUE if the container is being closed by opening of another container.
* @return TRUE if ok, FALSE if error
*/
nsresult
COtherDTD::CloseContainer(const nsIParserNode *aNode,eHTMLTags aTarget,PRBool aClosedByStartTag){
nsresult result=NS_OK;
eHTMLTags nodeType=(eHTMLTags)aNode->GetNodeType();
#ifdef ENABLE_CRC
#define K_CLOSEOP 200
CRCStruct theStruct(nodeType,K_CLOSEOP);
mComputedCRC32=AccumulateCRC(mComputedCRC32,(char*)&theStruct,sizeof(theStruct));
#endif
switch(nodeType) {
case eHTMLTag_html:
// result=CloseHTML(aNode); break;
case eHTMLTag_map:
// result=CloseMap(aNode);
break;
case eHTMLTag_form:
// result=CloseForm(aNode);
break;
case eHTMLTag_frameset:
// result=CloseFrameset(aNode);
break;
case eHTMLTag_title:
default:
STOP_TIMER();
MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: COtherDTD::CloseContainer(), this=%p\n", this));
result=(mSink) ? mSink->CloseContainer(*aNode) : NS_OK;
MOZ_TIMER_DEBUGLOG(("Start: Parse Time: COtherDTD::CloseContainer(), this=%p\n", this));
START_TIMER();
break;
}
return result;
}
/**
* This method does two things: 1st, help construct
* our own internal model of the content-stack; and
* 2nd, pass this message on to the sink.
* @update gess4/6/98
* @param anIndex
* @param aTag
* @param aClosedByStartTag -- if TRUE, then we're closing something because a start tag caused it
* @return TRUE if ok, FALSE if error
*/
nsresult COtherDTD::CloseContainersTo(PRInt32 anIndex,eHTMLTags aTarget, PRBool aClosedByStartTag){
NS_PRECONDITION(mBodyContext->GetCount() > 0, kInvalidTagStackPos);
nsresult result=NS_OK;
if((anIndex<mBodyContext->GetCount()) && (anIndex>=0)) {
while(mBodyContext->GetCount()>anIndex) {
// eHTMLTags theTag=mBodyContext->Last();
nsEntryStack *theChildStyleStack=0;
nsCParserNode *theNode=(nsCParserNode*)mBodyContext->Pop(theChildStyleStack);
if(theNode) {
result=CloseContainer(theNode,aTarget,aClosedByStartTag);
}//if anode
RecycleNode(theNode);
}
} //if
return result;
}
/**
* This method does two things: 1st, help construct
* our own internal model of the content-stack; and
* 2nd, pass this message on to the sink.
* @update gess4/6/98
* @param aTag --
* @param aClosedByStartTag -- ONLY TRUE if the container is being closed by opening of another container.
* @return TRUE if ok, FALSE if error
*/
nsresult COtherDTD::CloseContainersTo(eHTMLTags aTarget,PRBool aClosedByStartTag){
NS_PRECONDITION(mBodyContext->GetCount() > 0, kInvalidTagStackPos);
nsresult result=NS_OK;
return result;
}
/**
* Retrieve the preferred tokenizer for use by this DTD.

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

@ -269,23 +269,6 @@ CLASS_EXPORT_HTMLPARS COtherDTD : public nsIDTD {
*/
virtual PRBool IsContainer(PRInt32 aTag) const;
/**
* Ask parser if a given container is open ANYWHERE on stack
* @update gess5/11/98
* @param id of container you want to test for
* @return TRUE if the given container type is open -- otherwise FALSE
*/
virtual PRBool HasOpenContainer(eHTMLTags aContainer) const;
/**
* Ask parser if a given container is open ANYWHERE on stack
* @update gess5/11/98
* @param id of container you want to test for
* @return TRUE if the given container type is open -- otherwise FALSE
*/
virtual PRBool HasOpenContainer(const eHTMLTags aTagSet[],PRInt32 aCount) const;
/**
* Use this id you want to stop the building content model
* --------------[ Sets DTD to STOP mode ]----------------
@ -308,6 +291,9 @@ CLASS_EXPORT_HTMLPARS COtherDTD : public nsIDTD {
NS_IMETHOD ConvertEntityToUnicode(const nsString& aEntity, PRInt32* aUnicode) const;
virtual PRBool IsBlockElement(PRInt32 aTagID,PRInt32 aParentID) const;
virtual PRBool IsInlineElement(PRInt32 aTagID,PRInt32 aParentID) const;
/**
* The following set of methods are used to partially construct
* the content model (via the sink) according to the type of token.
@ -317,24 +303,13 @@ CLASS_EXPORT_HTMLPARS COtherDTD : public nsIDTD {
*/
nsresult HandleStartToken(CToken* aToken);
nsresult HandleEndToken(CToken* aToken);
nsresult HandleDocTypeDeclToken(CToken* aToken);
nsresult HandleEntityToken(CToken* aToken);
//*************************************************
//these cover methods mimic the sink, and are used
//by the parser to manage its context-stack.
//*************************************************
/**
* The special purpose methods automatically close
* one or more open containers.
* @update gess5/11/98
* @return error code - 0 if all went well.
*/
nsresult CloseContainer(const nsIParserNode *aNode,eHTMLTags aTarget,PRBool aClosedByStartTag);
nsresult CloseContainersTo(eHTMLTags aTag,PRBool aClosedByStartTag);
nsresult CloseContainersTo(PRInt32 anIndex,eHTMLTags aTag,PRBool aClosedByStartTag);
static void ReleaseTable(void);
protected:

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

@ -17,7 +17,7 @@
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Contributor(s): rickg@netscape.com
*/
/************************************************************************
@ -29,12 +29,10 @@
*
*
************************************************************************/
#ifndef _COTHERELEMENTS_
#define _COTHERELEMENTS_
#undef TRANSITIONAL
/************************************************************************
This union is a bitfield which describes the group membership
************************************************************************/
@ -75,7 +73,7 @@ union CGroupMembers {
inline PRBool ContainsGroup(CGroupMembers& aGroupSet,CGroupMembers& aGroup) {
PRBool result=PR_FALSE;
if(aGroup.mAllBits) {
result=PRBool(aGroupSet.mAllBits & aGroup.mAllBits);
result=(aGroupSet.mAllBits & aGroup.mAllBits) ? PR_TRUE : PR_FALSE;
}
return result;
}
@ -104,7 +102,7 @@ public:
struct CFlags {
PRUint32 mOmitEndTag:1;
PRUint32 mIsContainer:1;
PRUint32 mPropagateDepth:4;
PRUint32 mIsSinkContainer:1;
PRUint32 mDeprecated:1;
PRUint32 mOmitWS:1;
};
@ -139,6 +137,7 @@ public:
static void Initialize(CElement& anElement,eHTMLTags aTag){
anElement.mProperties.mIsContainer=0;
anElement.mProperties.mIsSinkContainer=0;
anElement.mTag=aTag;
anElement.mGroup.mAllBits=0;;
anElement.mContainsGroups.mAllBits=0;
@ -146,6 +145,7 @@ public:
static void InitializeLeaf(CElement& anElement,eHTMLTags aTag,CGroupMembers& aGroup,CGroupMembers& aContainsGroups) {
anElement.mProperties.mIsContainer=PR_FALSE;
anElement.mProperties.mIsSinkContainer=PR_FALSE;
anElement.mTag=aTag;
anElement.mGroup.mAllBits=aGroup.mAllBits;
anElement.mContainsGroups.mAllBits=aContainsGroups.mAllBits;
@ -153,6 +153,7 @@ public:
static void Initialize(CElement& anElement,eHTMLTags aTag,CGroupMembers& aGroup,CGroupMembers& aContainsGroups) {
anElement.mProperties.mIsContainer=PR_TRUE;
anElement.mProperties.mIsSinkContainer=PR_TRUE;
anElement.mTag=aTag;
anElement.mGroup.mAllBits=aGroup.mAllBits;
anElement.mContainsGroups.mAllBits=aContainsGroups.mAllBits;
@ -176,7 +177,19 @@ public:
virtual PRBool CanBeClosedByStartTag(CElement* anElement,nsDTDContext* aContext);
virtual PRBool CanBeClosedByEndTag(CElement* anElement,nsDTDContext* aContext);
virtual PRBool IsContainer(void) {return mProperties.mIsContainer;}
//this tells us whether this tag is a block tag within the given parent
virtual PRBool IsBlockElement(eHTMLTags aParentID);
//this tells us whether this tag is an inline tag within the given parent
//NOTE: aParentID is currently ignored, but shouldn't be.
virtual PRBool IsInlineElement(eHTMLTags aParentID);
//this tells us whether the tag is a container as defined by HTML
//NOTE: aParentID is currently ignored, but shouldn't be.
virtual PRBool IsContainer(void) {return mProperties.mIsContainer; }
//this tells us whether the tag should be opened as a container in the sink (script doesn't, for example).
virtual PRBool IsSinkContainer(void) { return mProperties.mIsSinkContainer; }
virtual eHTMLTags GetSkipTarget(void) {return eHTMLTag_unknown;}
@ -919,6 +932,7 @@ public:
CCounterElement(eHTMLTags aTag=eHTMLTag_counter) : CInlineElement(aTag) {
CInlineElement::Initialize(*this,aTag);
mProperties.mIsSinkContainer=PR_FALSE;
}
/**********************************************************
@ -935,23 +949,21 @@ public:
/**********************************************************
this gets called after each tag is opened in the given context
**********************************************************/
virtual nsresult OpenContainerInContext(nsIParserNode *aNode,eHTMLTags aTag,nsDTDContext *aContext,nsIHTMLContentSink *aSink) {
OpenContext(aNode,aTag,aContext,aSink);
virtual nsresult OpenContext(nsIParserNode *aNode,eHTMLTags aTag,nsDTDContext *aContext,nsIHTMLContentSink *aSink) {
CElement::OpenContext(aNode,aTag,aContext,aSink);
nsresult result=OpenContainer(aNode,aTag,aContext,aSink);
if(NS_SUCCEEDED(result)) {
PRInt32 theCount=aContext->GetCount();
eHTMLTags theGrandParentTag=aContext->TagAt(theCount-2);
nsresult result=NS_OK;
PRInt32 theCount=aContext->GetCount();
eHTMLTags theGrandParentTag=aContext->TagAt(theCount-2);
nsCParserNode *theNode=(nsCParserNode*)aNode;
nsAutoString theNumber;
PRInt32 theCounter=aContext->IncrementCounter(theGrandParentTag,*theNode,theNumber);
nsCParserNode *theNode=(nsCParserNode*)aNode;
nsAutoString theNumber;
PRInt32 theCounter=aContext->IncrementCounter(theGrandParentTag,*theNode,theNumber);
CTextToken theToken(theNumber);
PRInt32 theLineNumber=0;
nsCParserNode theNewNode(&theToken,theLineNumber);
result=aSink->AddLeaf(theNewNode);
}
CTextToken theToken(theNumber);
PRInt32 theLineNumber=0;
nsCParserNode theNewNode(&theToken,theLineNumber);
result=aSink->AddLeaf(theNewNode);
return result;
}
@ -1269,11 +1281,13 @@ public:
static void Initialize(CElement& anElement,eHTMLTags aTag){
CTextContainer::Initialize(anElement,aTag);
anElement.mProperties.mIsSinkContainer=PR_FALSE;
}
CScriptElement() : CTextContainer(eHTMLTag_script) {
mGroup.mBits.mHeadMisc=1;
mGroup.mBits.mBlock=1;
mProperties.mIsSinkContainer=PR_FALSE;
}
/**********************************************************
@ -1791,19 +1805,22 @@ public:
CBodyElement(eHTMLTags aTag=eHTMLTag_body) : CElement(aTag) {
CGroupMembers theGroups=CBlockElement::GetBlockGroupMembers();
#ifdef TRANSITIONAL
theGroups.mBits.mComment=1;
theGroups.mBits.mSpecial=1;
theGroups.mBits.mPhrase=1;
theGroups.mBits.mFontStyle=1;
theGroups.mBits.mFormControl=1;
theGroups.mBits.mLeaf=1;
#endif
CElement::Initialize(*this,aTag,CBodyElement::GetGroup(),theGroups);
mIncludeKids=gBodyKids;
mExcludeKids=gBodyExcludeKids;
}
virtual PRBool CanContain(CElement* anElement,nsDTDContext* aContext) {
PRBool result=CElement::CanContain(anElement,aContext);
if((!result) && (aContext->mTransitional)) {
//let's try so additions that are specific to the body tag,
//and only work in transitional mode...
CGroupMembers& theFlowGroup=CFlowElement::GetContainedGroups();
result=ContainsGroup(theFlowGroup,anElement->mGroup);
}
return result;
}
//this gets called after each tag is opened in the given context
virtual nsresult OpenContainer(nsIParserNode *aNode,eHTMLTags aTag,nsDTDContext *aContext,nsIHTMLContentSink *aSink) {
@ -1823,26 +1840,15 @@ public:
eHTMLTags aTag,
nsDTDContext* aContext,
nsIHTMLContentSink* aSink) {
nsresult result=NS_OK;
switch(aTag) {
case eHTMLTag_script:
result=OpenContext(aNode,aTag,aContext,aSink);
break;
default:
//for now, let's drop other elements onto the floor.
result=CElement::HandleStartToken(aNode,aTag,aContext,aSink);
if(NS_SUCCEEDED(result)) {
nsCParserNode *theNode=(nsCParserNode*)aNode;
CStartToken *theToken=(CStartToken*)theNode->mToken;
if(theToken->IsEmpty() && (aTag==aContext->Last())){
result=CElement::HandleEndToken(aNode,aTag,aContext,aSink);
}
}
break;
}//switch
//for now, let's drop other elements onto the floor.
nsresult result=CElement::HandleStartToken(aNode,aTag,aContext,aSink);
if(NS_SUCCEEDED(result)) {
nsCParserNode *theNode=(nsCParserNode*)aNode;
CStartToken *theToken=(CStartToken*)theNode->mToken;
if(theToken->IsEmpty() && (aTag==aContext->Last())){
result=CElement::HandleEndToken(aNode,aTag,aContext,aSink);
}
}
return result;
}
@ -1902,15 +1908,31 @@ public:
{
memset(mElements,0,sizeof(mElements));
InitializeElements();
//DebugDumpBlockElements();
//DebugDumpInlineElements();
//DebugDumpContainment("all elements");
}
//call this to get a ptr to an element prototype...
CElement* GetElement(eHTMLTags aTagID) {
if(aTagID>eHTMLTag_unknown) {
if(aTagID<eHTMLTag_userdefined) {
return mElements[aTagID];
}
}
return 0;
}
void InitializeElements();
void DebugDumpGroups(CElement* aParent);
void DebugDumpContainment(const char* aTitle);
void DebugDumpContainment(CElement* aParent);
void DebugDumpInlineElements(const char* aTitle);
void DebugDumpBlockElements(const char* aTitle);
CElement* mElements[150]; //add one here for special handling of a given element
CElement mDfltElements[150];
@ -1953,6 +1975,7 @@ static eHTMLTags kBlockQuoteKids[]={eHTMLTag_script,eHTMLTag_unknown};
static eHTMLTags kFramesetKids[]={eHTMLTag_noframes,eHTMLTag_unknown};
static eHTMLTags kObjectKids[]={eHTMLTag_param,eHTMLTag_unknown};
static eHTMLTags kTBodyKids[]={eHTMLTag_tr,eHTMLTag_unknown};
static eHTMLTags kUnknownKids[]={eHTMLTag_html,eHTMLTag_unknown};
inline CElement* CElement::GetElement(eHTMLTags aTag) {
@ -2004,6 +2027,8 @@ void CElementTable::InitializeElements() {
CElement::Initialize( mDfltElements[eHTMLTag_caption], eHTMLTag_caption, CTableElement::GetGroup(), CSpecialElement::GetContainedGroups());
mDfltElements[eHTMLTag_tr].mContainsGroups.mBits.mSelf=0;
CElement::Initialize( mDfltElements[eHTMLTag_center], eHTMLTag_center, CBlockElement::GetGroup(), CFlowElement::GetContainedGroups());
CPhraseElement::Initialize( mDfltElements[eHTMLTag_cite], eHTMLTag_cite);
@ -2169,17 +2194,22 @@ void CElementTable::InitializeElements() {
mDfltElements[eHTMLTag_tbody].mIncludeKids=kTBodyKids;
CElement::Initialize( mDfltElements[eHTMLTag_td], eHTMLTag_td, CElement::GetEmptyGroup(), CFlowElement::GetContainedGroups());
mDfltElements[eHTMLTag_td].mContainsGroups.mBits.mSelf=0;
CElement::Initialize( mDfltElements[eHTMLTag_textarea], eHTMLTag_textarea);
CElement::Initialize( mDfltElements[eHTMLTag_tfoot], eHTMLTag_tfoot, CTableElement::GetGroup(), CLeafElement::GetContainedGroups());
mDfltElements[eHTMLTag_tfoot].mIncludeKids=kTBodyKids;
mDfltElements[eHTMLTag_tfoot].mContainsGroups.mBits.mSelf=0;
CTableRowElement::Initialize( mDfltElements[eHTMLTag_th], eHTMLTag_th);
mDfltElements[eHTMLTag_th].mContainsGroups.mBits.mSelf=0;
CElement::Initialize( mDfltElements[eHTMLTag_thead], eHTMLTag_thead, CTableElement::GetGroup(), CLeafElement::GetContainedGroups());
mDfltElements[eHTMLTag_thead].mIncludeKids=kTBodyKids;
CTableRowElement::Initialize( mDfltElements[eHTMLTag_tr], eHTMLTag_tr);
mDfltElements[eHTMLTag_tr].mContainsGroups.mBits.mSelf=0;
CElement::Initialize( mDfltElements[eHTMLTag_title], eHTMLTag_title);
@ -2199,6 +2229,7 @@ void CElementTable::InitializeElements() {
CLeafElement::Initialize( mDfltElements[eHTMLTag_newline], eHTMLTag_newline);
CLeafElement::Initialize( mDfltElements[eHTMLTag_whitespace],eHTMLTag_whitespace);
CLeafElement::Initialize( mDfltElements[eHTMLTag_unknown], eHTMLTag_unknown);
mDfltElements[eHTMLTag_unknown].mIncludeKids=kUnknownKids;
/************************************************************
@ -2325,6 +2356,42 @@ void CElementTable::DebugDumpContainment(CElement* anElement){
}
}
void CElementTable::DebugDumpInlineElements(const char* aTitle) {
PRInt32 theTagID=eHTMLTag_unknown;
PRBool result=PR_FALSE;
printf("Inline Elements -- %s: \n",aTitle);
while(theTagID<=eHTMLTag_userdefined) {
CElement *theTag=GetElement((eHTMLTags)theTagID);
if(theTag) {
result=theTag->IsInlineElement(eHTMLTag_unknown);
if(result) {
const char* theName=nsHTMLTags::GetCStringValue(theTag->mTag);
printf(" %s\n",theName);
}
}
theTagID++;
}
}
void CElementTable::DebugDumpBlockElements(const char* aTitle) {
PRInt32 theTagID=eHTMLTag_unknown;
PRBool result=PR_FALSE;
printf("Block Elements -- %s: \n");
while(theTagID<=eHTMLTag_userdefined) {
CElement *theTag=GetElement((eHTMLTags)theTagID);
if(theTag) {
result=theTag->IsBlockElement(eHTMLTag_unknown);
if(result) {
const char* theName=nsHTMLTags::GetCStringValue(theTag->mTag);
printf(" %s\n",theName);
}
}
theTagID++;
}
}
void CElementTable::DebugDumpContainment(const char* aTitle){
#if 0
DebugDumpContainment(mElements[eHTMLTag_head]);
@ -2423,6 +2490,37 @@ PRBool CElement::CanContain(CElement* anElement,nsDTDContext* aContext) {
}
else result=mContainsGroups.mBits.mSelf;
}
/***************************************************
This is a (cheesy) exception table, that allows
us to override containment for transitional
documents. A better implementation would be to
create unique classes for each of the tags in
this table, and to override CanContain() there.
***************************************************/
if((!result) && (aContext->mTransitional)) {
switch(anElement->mTag) {
case eHTMLTag_address:
if(eHTMLTag_p==anElement->mTag)
result=PR_TRUE;
break;
case eHTMLTag_blockquote:
case eHTMLTag_form:
case eHTMLTag_iframe:
result=ContainsGroup(CFlowElement::GetContainedGroups(),anElement->mGroup);
break;
case eHTMLTag_button:
if((eHTMLTag_iframe==anElement->mTag) || (eHTMLTag_isindex==anElement->mTag))
result=PR_TRUE;
break;
default:
break;
}
}
}
return result;
}
@ -2452,12 +2550,18 @@ nsresult CElement::HandleStartToken( nsIParserNode* aNode,
}
else
#endif
{
if(theElement) {
if(CanContain(theElement,aContext)) {
if(theElement->IsContainer()) {
result=theElement->OpenContainerInContext(aNode,aTag,aContext,aSink);
if(theElement->IsSinkContainer()) {
result=theElement->OpenContainerInContext(aNode,aTag,aContext,aSink);
}
else {
result=theElement->OpenContext(aNode,aTag,aContext,aSink);
}
}
else {
result=aSink->AddLeaf(*aNode);
@ -2467,7 +2571,7 @@ nsresult CElement::HandleStartToken( nsIParserNode* aNode,
//Ok, so we have a start token that is misplaced. Before handing this off
//to a default container (parent), let's check the autoclose condition.
if(ListContainsTag(mAutoClose,theElement->mTag)) {
if(ListContainsTag(mAutoClose,theElement->mTag) || (aTag==mTag)) {
if(HasOptionalEndTag(theElement)) {
//aha! We have a case where this tag is autoclosed by anElement.
//Let's close this container, then try to open theElement.
@ -2498,7 +2602,7 @@ nsresult CElement::HandleStartToken( nsIParserNode* aNode,
if(mTag!=aTag) {
PRInt32 theLastPos=aContext->LastOf(aTag); //see if it's already open...
if(-1<theLastPos) {
if(-1!=theLastPos) {
PRInt32 theCount=aContext->GetCount();
result=HandleEndToken(aNode,aTag,aContext,aSink);
theElementCanOpen=PRBool(aContext->GetCount()<theCount);
@ -2530,7 +2634,14 @@ nsresult CElement::HandleEndToken(nsIParserNode* aNode,eHTMLTags aTag,nsDTDConte
nsresult result=NS_OK;
if(aContext->Last()==aTag) {
return CloseContainerInContext(aNode,aTag,aContext,aSink);
CElement* theElement=gElementTable->mElements[aTag];
if(theElement) {
if(theElement->IsSinkContainer()) {
CloseContainerInContext(aNode,aTag,aContext,aSink);
}
else CloseContext(aNode,aTag,aContext,aSink);
return result;
}
}
PRInt32 theCount=aContext->GetCount();
@ -2548,39 +2659,6 @@ nsresult CElement::HandleEndToken(nsIParserNode* aNode,eHTMLTags aTag,nsDTDConte
}
return result;
}
/* This junk is intentionally commented out...
PRInt32 theLastOptionalTag=-1;
PRBool done=PR_FALSE;
theIndex=0;
if(!done) {
for(theIndex=theCount-1;theIndex>=0;theIndex--) {
eHTMLTags theTag=aContext->TagAt(theIndex);
CElement* theElement=gElementTable->mElements[theTag];
if(HasOptionalEndTag(theElement)){
theLastOptionalTag=theIndex;
}
else break;
}
if(-1<theLastOptionalTag) {
PRInt32 theLastInstance=aContext->LastOf(aTag);
if(-1<theLastInstance) {
if(theLastOptionalTag-1==theLastInstance) {
for(theIndex=theCount-1;theIndex>=theLastInstance;theIndex--){
CloseContainerInContext(aNode,aTag,aContext,aSink);
}
}
}
//there's nothing to do...
}
//there's nothing to do...
}
*/
return result;
}
@ -2610,5 +2688,21 @@ inline CElement* CElement::GetDefaultContainerFor(CElement* anElement) {
}
//this tells us whether this tag is a block tag within the given parent
//NOTE: aParentID is currently ignored, but shouldn't be.
PRBool CElement::IsBlockElement(eHTMLTags aParentID) {
CGroupMembers& theBlockGroup=CBlockElement::GetBlockGroupMembers();
PRBool result=ContainsGroup(theBlockGroup,mGroup);
return result;
}
//this tells us whether this tag is an inline tag within the given parent
//NOTE: aParentID is currently ignored, but shouldn't be.
PRBool CElement::IsInlineElement(eHTMLTags aParentID) {
CGroupMembers& theInlineGroup=CInlineElement::GetContainedGroups();
PRBool result=ContainsGroup(theInlineGroup,mGroup);
return result;
}
#endif

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

@ -63,6 +63,7 @@ CParserContext::CParserContext(nsScanner* aScanner,
mCopyUnused=aCopyUnused;
mParserCommand=aCommand;
mChannel=0;
mValidator=0;
}
/**

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

@ -76,6 +76,7 @@ public:
nsScanner* mScanner;
nsIDTD* mDTD;
nsIDTD* mValidator;
char* mTransferBuffer;
nsIStreamObserver* mListener;

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

@ -974,11 +974,6 @@ nsresult CRTFContent::Consume(PRUnichar aChar,nsScanner& aScanner,PRInt32 aMode)
***************************************************************/
/************************************************************************
And now for the main class -- nsRTFTokenizer...
************************************************************************/
/**
* This method gets called as part of our COM-like interfaces.
* Its purpose is to create an interface to parser object
@ -1013,6 +1008,7 @@ nsresult nsRTFTokenizer::QueryInterface(const nsIID& aIID, void** aInstancePtr)
}
nsRTFTokenizer::nsRTFTokenizer() : mTokenDeque(0) {
NS_INIT_REFCNT();
}
/**

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

@ -327,6 +327,9 @@ class CRtfDTD : public nsIDTD {
NS_IMETHOD ConvertEntityToUnicode(const nsString& aEntity, PRInt32* aUnicode) const;
virtual PRBool IsBlockElement(PRInt32 aTagID,PRInt32 aParentID) const {return PR_FALSE;}
virtual PRBool IsInlineElement(PRInt32 aTagID,PRInt32 aParentID) const {return PR_FALSE;}
protected:

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

@ -16,13 +16,13 @@
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
*
* Contributor(s):
* Pierre Phaneuf <pp@ludusdesign.com>
*/
#include "nsDTDUtils.h"
*/
#include "nsDTDUtils.h"
#include "CNavDTD.h"
#include "nsIParserNode.h"
#include "nsParserNode.h"
@ -371,8 +371,9 @@ nsDTDContext::nsDTDContext() : mStack(), mEntities(0){
mTableStates=0;
mHadBody=PR_FALSE;
mHadFrameset=PR_TRUE;
mHadDocTypeDecl=PR_FALSE;
mTransitional=PR_FALSE;
ResetCounters();
mHadDocTypeDecl=PR_FALSE;
#ifdef NS_DEBUG
memset(mXTags,0,sizeof(mXTags));
@ -471,7 +472,7 @@ CNamedEntity* nsDTDContext::RegisterEntity(const nsString& aName,const nsString
class CAbacus {
public:
enum eNumFormat {eUnknown,eAlpha,eDecimal,eRoman,eSpoken,eHex,eBinary,eFootnote,eUserSeries};
enum eNumFormat {eUnknown,eAlpha,eDecimal,eRoman,eSpelled,eHex,eBinary,eFootnote,eUserSeries};
CAbacus(PRInt32 aDefaultValue=0,eNumFormat aFormat=eDecimal) {
mUserSeries=0;
@ -504,7 +505,7 @@ public:
case eHex: HexString(aValue,aString); break;
case eBinary: BinaryString(aValue,aString); break;
case eAlpha: AlphaString(aValue,aString); break;
case eSpoken: SpokenString(aValue,aString); break;
case eSpelled: SpelledString(aValue,aString); break;
case eRoman: RomanString(aValue,aString); break;
case eFootnote: FootnoteString(aValue,aString); break;
case eUserSeries: SeriesString(aValue,aString,aCharSet,anOffset,aBase);
@ -536,7 +537,7 @@ public:
}
}
static void SpokenString(PRInt32 aValue,nsString& aString) {
static void SpelledString(PRInt32 aValue,nsString& aString) {
static char ones[][12]= {"zero","one ","two ","three ","four ","five ","six ","seven ","eight ","nine ","ten "};
static char teens[][12]= {"ten ","eleven ","twelve ","thirteen ","fourteen ","fifteen ","sixteen ","seventeen ","eighteen ","nineteen "};
@ -696,7 +697,7 @@ void nsDTDContext::ResetCounters(void) {
name="group"
value="nnn"
noincr="?"
format="alpha|dec|footnote|hex|roman|spoken"
format="alpha|dec|footnote|hex|roman|spelled|talk"
returns the newly incremented value for the (determined) group.
**********************************************************/
@ -737,7 +738,7 @@ PRInt32 nsDTDContext::IncrementCounter(eHTMLTags aTag,nsCParserNode& aNode,nsStr
case 'D': case 'd': theNumFormat=CAbacus::eDecimal; break;
case 'H': case 'h': theNumFormat=CAbacus::eHex; break;
case 'R': case 'r': theNumFormat=CAbacus::eRoman; break;
case 'S': case 's': theNumFormat=CAbacus::eSpoken; break;
case 'S': case 's': theNumFormat=CAbacus::eSpelled; break;
default:
theNumFormat=CAbacus::eDecimal;
break;

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

@ -253,6 +253,7 @@ public:
PRInt32 mContextTopIndex;
PRBool mHadBody;
PRBool mHadFrameset;
PRBool mTransitional;
PRBool mHadDocTypeDecl;
static CNodeRecycler* mNodeRecycler;
@ -383,20 +384,54 @@ inline PRBool FindTagInSet(PRInt32 aTag,const eHTMLTags *aTagSet,PRInt32 aCount)
/**
* Called from various DTD's to determine the type of data in the buffer...
* @update gess11/20/98
* @param
* @return
* @update gess 06Jun2000
* @param aBuffer: contains a string with first block of html from source document
* @param aHasXMLFragment: tells us whether we detect XML in the buffer (based on PI)
* @return TRUE if we find HTML
*/
inline PRBool BufferContainsHTML(nsString& aBuffer,PRBool& aHasXMLFragment){
PRBool result=PR_FALSE;
nsString temp;
aBuffer.Left(temp,200);
temp.ToLowerCase();
aHasXMLFragment=PRBool(-1<temp.Find("<?xml"));
if((-1<temp.Find("<html ") || (-1<temp.Find("!doctype html public")))) {
result=PR_TRUE;
aHasXMLFragment=PRBool(-1!=aBuffer.Find("<?XML",PR_TRUE,100));
PRInt32 theDocTypePos=aBuffer.Find("DOCTYPE",PR_TRUE,0,200);
if(-1!=theDocTypePos) {
PRInt32 theHTMLPos=aBuffer.Find("HTML",PR_TRUE,theDocTypePos+8,200);
if(-1==theHTMLPos) {
theHTMLPos=aBuffer.Find("ISO/IEC 15445",PR_TRUE,theDocTypePos+8,200);
if(-1==theHTMLPos) {
theHTMLPos=aBuffer.Find("HYPERTEXT MARKUP",PR_TRUE,theDocTypePos+8,200);
}
}
result=PRBool(-1!=theHTMLPos);
}
else {
//worst case scenario: let's look for a few HTML tags...
PRInt32 theCount=0;
PRInt32 theLTPos=0;
PRInt32 theStartPos=0;
nsAutoString theTagName;
PRInt32 theTagCount=0;
for(theCount=0;theCount<5;theCount++) {
theLTPos=aBuffer.Find("<",PR_TRUE,theStartPos,200);
if(-1!=theLTPos) {
//we found what may be a start tag...
PRInt32 theTagEnd=aBuffer.FindCharInSet(" >\"",theLTPos);
aBuffer.Mid(theTagName,theLTPos+1,theTagEnd-theLTPos-1);
nsHTMLTag theTag=nsHTMLTags::LookupTag(theTagName);
if(eHTMLTag_userdefined!=theTag) {
theTagCount++;
}
//now let's see if it's a tag or not...
theStartPos=theTagEnd+1;
}
else break;
}
result=PRBool(2<=theTagCount); //claim HTML if we find at least 2 real html tags...
}
return result;
}

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

@ -229,6 +229,9 @@ class nsExpatDTD : public nsIDTD {
NS_IMETHOD ConvertEntityToUnicode(const nsString& aEntity, PRInt32* aUnicode) const;
virtual PRBool IsBlockElement(PRInt32 aTagID,PRInt32 aParentID) const {return PR_FALSE;}
virtual PRBool IsInlineElement(PRInt32 aTagID,PRInt32 aParentID) const {return PR_FALSE;}
/**
* Retrieve a ptr to the global token recycler...
* @update gess8/4/98

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

@ -124,7 +124,7 @@ NS_IMPL_RELEASE(nsHTMLTokenizer)
nsITokenizer(), mTokenDeque(0), mParseMode(aParseMode)
{
NS_INIT_REFCNT();
mDoXMLEmptyTags=(eDTDMode_strict==aParseMode);
mDoXMLEmptyTags=((eDTDMode_strict==aParseMode) || (eDTDMode_transitional==aParseMode));
mDocType=aDocType;
mRecordTrailingContent=PR_FALSE;
mParserCommand=aCommand;

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

@ -615,7 +615,7 @@ nsresult CTextToken::ConsumeUntil(PRUnichar aChar,PRBool aIgnoreComments,nsScann
}
//theTermStrPos=theBuffer.Find(aTerminalString,PR_TRUE,theCurrOffset);
if(theTermStrPos>kNotFound) {
if(aMode!=eDTDMode_strict && !theLastIteration) {
if((aMode!=eDTDMode_strict) && (aMode!=eDTDMode_transitional) && !theLastIteration) {
if(!aIgnoreComments) {
theCurrOffset=theBuffer.Find("<!--",PR_TRUE,theCurrOffset,5);
if(theStartCommentPos==kNotFound && theCurrOffset>kNotFound) {
@ -944,6 +944,7 @@ nsresult ConsumeComment(PRUnichar aChar, nsScanner& aScanner,nsString& aString)
if(NS_OK==result) {
//Read up to the closing '>', unless you already did! (such as <!>).
if(kGreaterThan!=aChar) {
aString.AppendWithConversion("<!- ");
result=aScanner.ReadUntil(aString,kGreaterThan,PR_TRUE);
}
}
@ -960,19 +961,18 @@ nsresult ConsumeComment(PRUnichar aChar, nsScanner& aScanner,nsString& aString)
* @return error result
*/
nsresult CCommentToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aMode) {
nsresult result=(aMode==eDTDMode_strict) ? ConsumeStrictComment(aChar,aScanner,mTextValue) : ConsumeComment(aChar,aScanner,mTextValue);
nsresult result=PR_TRUE;
switch(aMode) {
case eDTDMode_strict:
ConsumeStrictComment(aChar,aScanner,mTextValue);
break;
case eDTDMode_transitional:
default:
ConsumeComment(aChar,aScanner,mTextValue);
break;
} //switch
#if 0
if(NS_OK==result) {
//ok then, all is well so strip off the delimiters...
nsAutoString theLeft("");
mTextValue.Left(theLeft,2);
if(theLeft=="<!")
mTextValue.Cut(0,2);
if('>'==mTextValue.Last())
mTextValue.Truncate(mTextValue.Length()-1);
}
#endif
return result;
}
@ -1220,29 +1220,28 @@ void CAttributeToken::DebugDumpToken(nsOutputStream& out) {
/*
*
*
* @update gess 3/25/98
* @update rickg 6June2000
* @param anOutputString will recieve the result
* @return nada
*/
void CAttributeToken::GetSource(nsString& anOutputString){
anOutputString=mTextKey;
anOutputString.AppendWithConversion("=");
anOutputString+=mTextValue;
anOutputString.AppendWithConversion(";");
anOutputString.Truncate();
AppendSource(anOutputString);
}
/*
*
*
* @update harishd 03/23/00
* @update rickg 6June2000
* @param result appended to the output string.
* @return nada
*/
void CAttributeToken::AppendSource(nsString& anOutputString){
anOutputString+=mTextKey;
anOutputString.AppendWithConversion("=");
if(mTextValue.Length() || mHasEqualWithoutValue)
anOutputString.AppendWithConversion("=");
anOutputString+=mTextValue;
anOutputString.AppendWithConversion(";");
// anOutputString.AppendWithConversion(";");
}
/*

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

@ -52,8 +52,8 @@ enum eAutoDetectResult {
enum nsDTDMode {
eDTDMode_unknown=0,
eDTDMode_quirks, //pre 5.0 versions
eDTDMode_noquirks, //raptor versions...)
eDTDMode_quirks, //pre 4.0 versions
eDTDMode_transitional,
eDTDMode_strict,
eDTDMode_autodetect
};
@ -214,6 +214,10 @@ class nsIDTD : public nsISupports {
NS_IMETHOD IntTagToStringTag(PRInt32 aIntTag, nsString& aTag) const =0;
NS_IMETHOD ConvertEntityToUnicode(const nsString& aEntity, PRInt32* aUnicode) const =0;
virtual PRBool IsBlockElement(PRInt32 aTagID,PRInt32 aParentID) const=0;
virtual PRBool IsInlineElement(PRInt32 aTagID,PRInt32 aParentID) const=0;
};

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

@ -149,6 +149,12 @@ class nsIParserNode : public nsISupports {
virtual PRBool GetGenericState(void) const =0;
virtual void SetGenericState(PRBool aState) =0;
/** Retrieve a string containing the tag and its attributes in "source" form
* @update rickg 06June2000
* @return void
*/
virtual void GetSource(nsString& aString)=0;
};
#endif

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

@ -23,6 +23,7 @@
#define DEBUG_XMLENCODING
#define XMLENCODING_PEEKBYTES 64
//#define TEST_DOCTYPES
#include "nsParser.h"
#include "nsIContentSink.h"
@ -103,11 +104,13 @@ public:
nsIDTD* theDTD;
#if 1
NS_NewNavHTMLDTD(&theDTD); //do this as a default HTML DTD...
mDTDDeque.Push(theDTD);
#endif
NS_NewOtherHTMLDTD(&theDTD); //do this as the default DTD for strict documents...
mDTDDeque.Push(theDTD);
NS_NewOtherHTMLDTD(&mOtherDTD); //do this as the default DTD for strict documents...
mDTDDeque.Push(mOtherDTD);
mHasViewSourceDTD=PR_FALSE;
mHasRTFDTD=mHasXMLDTD=PR_FALSE;
@ -135,6 +138,7 @@ public:
PRBool mHasViewSourceDTD; //this allows us to defer construction of this object.
PRBool mHasXMLDTD; //also defer XML dtd construction
PRBool mHasRTFDTD; //also defer RTF dtd construction
nsIDTD *mOtherDTD; //it's ok to leak this; the deque contains a copy too.
};
static CSharedParserObjects* gSharedParserObjects=0;
@ -515,7 +519,7 @@ void DetermineParseMode(nsString& aBuffer,nsDTDMode& aParseMode,eParserDocType&
aParseMode = eDTDMode_unknown;
PRInt32 theIndex=aBuffer.Find("DOCTYPE",PR_TRUE,0,10);
PRInt32 theIndex=aBuffer.Find("DOCTYPE",PR_TRUE,0,100);
if(kNotFound<theIndex) {
//good, we found "DOCTYPE" -- now go find it's end delimiter '>'
@ -527,102 +531,99 @@ void DetermineParseMode(nsString& aBuffer,nsDTDMode& aParseMode,eParserDocType&
//note that if we don't find '>', then we just scan the first 512 bytes.
if(0<=theSubIndex) {
if(kNotFound!=theSubIndex) {
//if you're here then we found the //DTD identifier type...
PRInt32 theStartPos=theSubIndex+5;
PRInt32 theCount=theEnd-theStartPos;
if(kNotFound<theSubIndex) {
theSubIndex=aBuffer.Find("XHTML",PR_TRUE,theStartPos,theCount);
if(0<=theSubIndex) {
aDocType=eXHTMLText;
aParseMode=eDTDMode_strict;
return;
}
else {
theSubIndex=aBuffer.Find("ISO/IEC 15445:",PR_TRUE,theIndex+8,theEnd-(theIndex+8));
if(0<=theSubIndex) {
aDocType=eHTML4Text;
aParseMode=eDTDMode_strict;
theMajorVersion=4;
theSubIndex+=15;
return;
}
else {
theSubIndex=aBuffer.Find("HTML",PR_TRUE,theStartPos,theCount);
if(0<=theSubIndex) {
aDocType=eHTML4Text;
aParseMode=eDTDMode_strict;
theMajorVersion=3;
}
else {
theSubIndex=aBuffer.Find("HYPERTEXT MARKUP",PR_TRUE,theStartPos,theCount);
if(0<=theSubIndex) {
aDocType=eHTML3Text;
aParseMode=eDTDMode_quirks;
theSubIndex+=20;
}
}
}
}
}
theStartPos=theSubIndex+5;
theCount=theEnd-theStartPos;
nsAutoString theNum;
//get the next substring from the buffer, which should be a number.
//now see what the version number is...
theStartPos=aBuffer.FindCharInSet("123456789",theStartPos);
if(0<=theStartPos) {
PRInt32 theTerminal=aBuffer.FindCharInSet(" />",theStartPos+1);
if(theTerminal) {
aBuffer.Mid(theNum,theStartPos,theTerminal-theStartPos);
}
else aBuffer.Mid(theNum,theStartPos,3);
theMajorVersion=theNum.ToInteger(&theErr);
}
//now see what the
theStartPos+=theNum.Length();
theCount=theEnd-theStartPos;
if((aBuffer.Find("TRANSITIONAL",PR_TRUE,theStartPos,theCount)>kNotFound)||
(aBuffer.Find("LOOSE",PR_TRUE,theStartPos,theCount)>kNotFound) ||
(aBuffer.Find("FRAMESET",PR_TRUE,theStartPos,theCount)>kNotFound) ||
(aBuffer.Find("LATIN1", PR_TRUE,theStartPos,theCount) >kNotFound) ||
(aBuffer.Find("SYMBOLS",PR_TRUE,theStartPos,theCount) >kNotFound) ||
(aBuffer.Find("SPECIAL",PR_TRUE,theStartPos,theCount) >kNotFound)) {
aParseMode=eDTDMode_quirks;
}
//one last thing: look for a URI that specifies the strict.dtd
theStartPos+=6;
theCount=theEnd-theStartPos;
theSubIndex=aBuffer.Find("STRICT.DTD",PR_TRUE,theStartPos,theCount);
if(0<theSubIndex) {
//Since we found it, regardless of what's in the descr-text, kick into strict mode.
if(kNotFound!=aBuffer.Find("ISO/IEC 15445:1999",PR_TRUE,theIndex,theEnd-theIndex)) {
//per spec, this DTD is always strict...
aParseMode=eDTDMode_strict;
aDocType=eHTML4Text;
theMajorVersion=4;
return;
}
if (kNotFound!=aBuffer.Find("XHTML",PR_TRUE,theStartPos,theCount)) {
aDocType=eXHTMLText;
aParseMode=eDTDMode_strict;
return;
}
if (0==theErr){
switch(theMajorVersion) {
case 0: case 1: case 2: case 3:
if(aDocType!=eXHTMLText){
aParseMode=eDTDMode_quirks; //be as backward compatible as possible
aDocType=eHTML3Text;
if(kNotFound<theSubIndex) {
PRInt32 theHTMLTagPos=aBuffer.Find("HTML",PR_TRUE,theStartPos,theCount);
if(kNotFound==theHTMLTagPos) {
theHTMLTagPos=aBuffer.Find("HYPERTEXT MARKUP",PR_TRUE,theStartPos,theCount);
}
if(kNotFound!=theHTMLTagPos) {
//get the next substring from the buffer, which should be a number.
//now see what the version number is...
PRInt32 theVersionPos=aBuffer.FindCharInSet("1234567890",theHTMLTagPos);
if((0<=theVersionPos) && (theVersionPos<theEnd)) {
nsAutoString theNum;
PRInt32 theTerminal=aBuffer.FindCharInSet(" />",theVersionPos+1);
if(theTerminal) {
aBuffer.Mid(theNum,theVersionPos,theTerminal-theVersionPos);
}
break;
default:
//XXX hack -- someday, the next line of code will be criticized
//for it's lack of vision...
if(theMajorVersion>20) {
else aBuffer.Mid(theNum,theVersionPos,3);
theMajorVersion=theNum.ToInteger(&theErr);
if(theMajorVersion>10) {
theMajorVersion=3; //assume that's an error for now.
}
}
//now let's see if we have descriptive text (providing strictness id)...
theStartPos=theVersionPos+2;
theCount=theEnd-theStartPos;
if((aBuffer.Find("TRANSITIONAL",PR_TRUE,theVersionPos+2,theCount)>kNotFound)||
(aBuffer.Find("LOOSE",PR_TRUE,theStartPos,theCount)>kNotFound) ||
(aBuffer.Find("FRAMESET",PR_TRUE,theStartPos,theCount)>kNotFound) ||
(aBuffer.Find("LATIN1", PR_TRUE,theStartPos,theCount) >kNotFound) ||
(aBuffer.Find("SYMBOLS",PR_TRUE,theStartPos,theCount) >kNotFound) ||
(aBuffer.Find("SPECIAL",PR_TRUE,theStartPos,theCount) >kNotFound)) {
//for now TRANSITIONAL 4.0 documents are handled in the compatibility DTD.
//Soon, they'll be handled in the strictDTD in transitional mode.
aParseMode=eDTDMode_transitional;
}
else {
//since we didn't find descriptive text, let's check out the URI...
//to see whether that specifies the strict.dtd...
theStartPos+=6;
theCount=theEnd-theStartPos;
theSubIndex=aBuffer.Find("STRICT.DTD",PR_TRUE,theStartPos,theCount);
if(0<theSubIndex) {
//Since we found it, regardless of what's in the descr-text, kick into strict mode.
aParseMode=eDTDMode_strict;
aDocType=eHTML4Text;
}
break;
} //switch
}
switch(theMajorVersion) {
case 1:
case 2:
case 3:
aParseMode=eDTDMode_quirks;
aDocType=eHTML4Text;
break;
default:
if(eDTDMode_unknown==aParseMode) {
aParseMode=eDTDMode_strict;
}
break;
}
}
}
} //if
@ -651,6 +652,10 @@ void DetermineParseMode(nsString& aBuffer,nsDTDMode& aParseMode,eParserDocType&
aDocType=ePlainText;
aParseMode=eDTDMode_quirks;
}
else if(aMimeType.EqualsWithConversion(kRTFTextContentType)) {
aDocType=ePlainText;
aParseMode=eDTDMode_quirks;
}
if(theModeStr) {
if(0==nsCRT::strcasecmp(theModeStr,"strict"))
@ -680,7 +685,7 @@ PRBool FindSuitableDTD( CParserContext& aParserContext,nsString& aBuffer) {
return PR_TRUE;
CSharedParserObjects& gSharedObjects=GetSharedObjects();
aParserContext.mValidator=gSharedObjects.mOtherDTD;
aParserContext.mAutoDetectStatus=eUnknownDetect;
PRInt32 theDTDIndex=0;
@ -800,7 +805,7 @@ nsresult nsParser::CreateCompatibleDTD(nsIDTD** aDTD,
switch(theDocType) {
case eHTML4Text:
if(theDTDMode==eDTDMode_strict) {
if((theDTDMode==eDTDMode_strict) || (theDTDMode==eDTDMode_transitional)) {
theDTDClassID=&kCOtherDTDCID;
break;
}
@ -821,7 +826,7 @@ nsresult nsParser::CreateCompatibleDTD(nsIDTD** aDTD,
NS_ASSERTION(aDTDMode!=eDTDMode_unknown,"DTD selection might require a parsemode");
if(aMimeType->EqualsWithConversion(kHTMLTextContentType)) {
if(aDTDMode==eDTDMode_strict) {
if((aDTDMode==eDTDMode_strict) || (aDTDMode==eDTDMode_transitional)) {
theDTDClassID=&kCOtherDTDCID;
}
else {
@ -856,37 +861,60 @@ nsresult nsParser::CreateCompatibleDTD(nsIDTD** aDTD,
}
#ifdef TEST_DOCTYPES
static const char* doctypes[] = {
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">",
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">",
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Frameset//EN\" \"http://www.w3.org/TR/html4/frameset.dtd\">",
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\">",
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" >",
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Frameset//EN\">",
//here are a few HTML doctypes we'll treat as strict...
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\">",
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">",
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">",
"<!DOCTYPE HTML PUBLIC PublicID SystemID>",
"<!DOCTYPE HTML SYSTEM SystemID>",
"<!DOCTYPE \"-//W3C//DTD HTML 4.0//EN\">",
"<!DOCTYPE \"-//W3C//DTD HTML 4.01//EN\">",
"<!DOCTYPE \"-//W3C//DTD HTML 4.0 STRICT//EN\">",
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\">",
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">",
"<!DOCTYPE \"ISO/IEC 15445:1999//DTD HyperText Markup Language//EN\">",
"<!DOCTYPE \"ISO/IEC 15445:1999//DTD HTML//EN\">",
"<!DOCTYPE \"-//SoftQuad Software//DTD HoTMetaL PRO 6.::19990601::extensions to HTML 4.//EN\">",
"<!DOCTYPE \"-//W3C//DTD HTML 5.0//EN\">",
"<!DOCTYPE \"-//W3C//DTD HTML 6.01 Transitional//EN\">",
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 6.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">",
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">",
"<!DOCTYPE \"-//W3C//DTD HTML 4.0 STRICT//EN\">",
"<!DOCTYPE \"-//W3C//DTD HTML 4.01//EN\">",
"<!DOCTYPE \"-//W3C//DTD HTML 4.0//EN\">",
"<!DOCTYPE \"ISO/IEC 15445:1999//DTD HyperText Markup Language//EN\">",
"<!DOCTYPE \"ISO/IEC 15445:1999//DTD HTML//EN\">",
"<!DOCTYPE \"-//SoftQuad Software//DTD HoTMetaL PRO 6.::19990601::extensions to HTML 4.//EN\">",
//here are the XHTML doctypes we'll treat as strict...
"<!DOCTYPE \"-//W3C//DTD XHTML 1.0 Strict//EN\">",
"<!DOCTYPE \"-//W3C//DTD XHTML 1.0 Transitional//EN\">",
"<!DOCTYPE \"-//W3C//DTD XHTML 1.0 Frameset//EN\">",
//these we treat as standard (no quirks)...
//these we treat as compatible (no quirks if possible)...
"<!DOCTYPE \"-//W3C//DTD HTML Experimental 19960712//EN\">",
"<!DOCTYPE \"-//W3C//DTD HTML 4.01 Transitional//EN\">",
"<!DOCTYPE \"-//W3C//DTD HTML 4.1 Frameset//EN\">",
"<!DOCTYPE \"-//W3C//DTD HTML 4.0 Transitional//EN\">",
"<!DOCTYPE \"-//W3C//DTD HTML 4.0 Frameset//EN\">",
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">",
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Frameset//EN\">",
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Frameset//EN\" \"http://www.w3.org/TR/html4/frameset.dtd\">",
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">",
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Frameset//EN\">",
//these we treat as quirks... (along with any other we encounter)...
//these we treat as compatible with quirks... (along with any other we encounter)...
"<!DOCTYPE \"-//W3O//DTD W3 HTML 3.0//EN//\">",
"<!DOCTYPE \"-//IETF//DTD HTML//EN//3.\">",
"<!DOCTYPE \"-//W3C//DTD W3 HTML 3.0//EN//\">",
@ -902,6 +930,7 @@ static const char* doctypes[] = {
"<!DOCTYPE \"-//W3C//DTD W3 HTML Strict 3//EN//\">",
"<!DOCTYPE \"-//IETF//DTD HTML Strict Level 3//EN\">",
"<!DOCTYPE \"-//IETF//DTD HTML Strict Level 3//EN//3.0\">",
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">",
"<!DOCTYPE \"HTML\">",
"<!DOCTYPE \"-//IETF//DTD HTML//EN\">",
@ -970,20 +999,20 @@ nsresult nsParser::WillBuildModel(nsString& aFilename){
nsresult result=NS_OK;
#if TEST_DOCTYPES
#ifdef TEST_DOCTYPES
static PRBool tested=PR_FALSE;
const char** theDocType=doctypes;
if(!tested) {
tested=PR_TRUE;
eParseMode theParseMode=eDTDMode_unknown;
eParserDocType theDocumentType=ePlainText;
nsDTDMode theMode=eDTDMode_unknown;
eParserDocType theDocumentType=ePlainText;
while(*theDocType) {
nsAutoString theType;
theType.AssignWithConversion(*theDocType);
DetermineParseMode(theType,theParseMode,theDocumentType,mParserContext->mMimeType);
DetermineParseMode(theType,theMode,theDocumentType,mParserContext->mMimeType);
theDocType++;
}
}

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

@ -352,4 +352,31 @@ CToken* nsCParserNode::PopAttributeToken() {
return result;
}
/** Retrieve a string containing the tag and its attributes in "source" form
* @update rickg 06June2000
* @return void
*/
void nsCParserNode::GetSource(nsString& aString) {
aString.Truncate();
eHTMLTags theTag=(eHTMLTags)mToken->GetTypeID();
aString.AppendWithConversion("<");
const char* theTagName=nsHTMLTags::GetCStringValue(theTag);
if(theTagName) {
aString.AppendWithConversion(theTagName);
}
if(mAttributes) {
nsAutoString theAttrStr;
int index=0;
for(index=0;index<mAttributes->GetSize();index++) {
CAttributeToken *theToken=(CAttributeToken*)mAttributes->ObjectAt(index);
if(theToken) {
theToken->AppendSource(theAttrStr);
aString.AppendWithConversion(" "); //this will get removed...
}
}
aString.Append(theAttrStr);
}
aString.AppendWithConversion(">");
}

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

@ -174,6 +174,12 @@ class nsCParserNode : public nsIParserNode {
*/
virtual CToken* PopAttributeToken();
/** Retrieve a string containing the tag and its attributes in "source" form
* @update rickg 06June2000
* @return void
*/
virtual void GetSource(nsString& aString);
/**
* This pair of methods allows us to set a generic bit (for arbitrary use)
* on each node stored in the context.

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

@ -240,6 +240,9 @@ class CValidDTD : public nsIDTD {
NS_IMETHOD ConvertEntityToUnicode(const nsString& aEntity, PRInt32* aUnicode) const;
virtual PRBool IsBlockElement(PRInt32 aTagID,PRInt32 aParentID) const {return PR_FALSE;}
virtual PRBool IsInlineElement(PRInt32 aTagID,PRInt32 aParentID) const {return PR_FALSE;}
protected:

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

@ -28,6 +28,9 @@
*/
#define ENABLE_ERROR_OUTPUT //debug only for now...
#ifdef RAPTOR_PERF_METRICS
# define START_TIMER() \
if(mParser) mParser->mParseTime.Start(PR_FALSE); \
@ -54,7 +57,7 @@
#include "nsIContentSink.h"
#include "nsIHTMLContentSink.h"
#include "nsHTMLTokenizer.h"
#include "COtherDTD.h"
#include "prenv.h" //this is here for debug reasons...
#include "prtypes.h" //this is here for debug reasons...
@ -73,6 +76,7 @@ Stopwatch vsTimer;
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static NS_DEFINE_IID(kIDTDIID, NS_IDTD_IID);
static NS_DEFINE_IID(kClassIID, NS_VIEWSOURCE_HTML_IID);
static int gErrorThreshold = 10;
static CTokenRecycler* gTokenRecycler=0;
@ -171,9 +175,11 @@ public:
mEndNode(),
mStartNode(),
mTokenNode(),
mErrorNode(),
mITextToken(),
mITextNode(&mITextToken),
mTextToken(),
mErrorToken("error"),
mTextNode(&mTextToken){
}
@ -188,9 +194,11 @@ public:
nsCParserNode mEndNode;
nsCParserNode mStartNode;
nsCParserNode mTokenNode;
nsCParserNode mErrorNode;
CIndirectTextToken mITextToken;
nsCParserNode mITextNode;
CTextToken mTextToken;
CToken mErrorToken;
nsCParserNode mTextNode;
};
@ -202,8 +210,7 @@ public:
* @param
* @return
*/
CViewSourceHTML::CViewSourceHTML()
{
CViewSourceHTML::CViewSourceHTML() : mTags(), mErrors() {
NS_INIT_REFCNT();
mStartTag.AssignWithConversion("start");
@ -216,12 +223,15 @@ CViewSourceHTML::CViewSourceHTML()
mText.AssignWithConversion("txt");
mKey.AssignWithConversion("key");
mValue.AssignWithConversion("val");
mSummaryTag.AssignWithConversion("summary");
mPopupTag.AssignWithConversion("popup");
mParser=0;
mSink=0;
mLineNumber=0;
mTokenizer=0;
mDocType=eHTML3Text;
mValidator=0;
#ifdef rickgdebug
gDumpFile = new fstream("c:/temp/viewsource.xml",ios::trunc);
@ -317,10 +327,16 @@ nsresult CViewSourceHTML::WillBuildModel( const CParserContext& aParserContext,
if((!aParserContext.mPrevContext) && (mSink)) {
mTags.Truncate();
mErrors.AssignWithConversion(" HTML 4.0 Strict-DTD validation (enabled); [Should use Transitional?].\n");
mValidator=aParserContext.mValidator;
mDocType=aParserContext.mDocType;
mMimeType=aParserContext.mMimeType;
mDTDMode=aParserContext.mDTDMode;
mParserCommand=aParserContext.mParserCommand;
mErrorCount=0;
mTagCount=0;
static const char* theHeader="<?xml version=\"1.0\"?>";
CToken ssToken(theHeader);
@ -394,6 +410,29 @@ NS_IMETHODIMP CViewSourceHTML::BuildModel(nsIParser* aParser,nsITokenizer* aToke
return result;
}
/**
* Call this to display an error summary regarding the page.
*
* @update rickg 6June2000
* @return nsresult
*/
nsresult CViewSourceHTML::GenerateSummary() {
nsresult result=NS_OK;
if(mErrorCount && mTagCount) {
mErrors.AppendWithConversion("\n\n ");
mErrors.AppendInt(mErrorCount);
mErrors.AppendWithConversion(" error(s) detected -- see highlighted portions.\n");
result=WriteTag(mSummaryTag,mErrors,0,PR_FALSE);
}
return result;
}
/**
*
* @update gess5/18/98
@ -424,6 +463,9 @@ NS_IMETHODIMP CViewSourceHTML::DidBuildModel(nsresult anErrorCode,PRBool aNotify
if(ePlainText!=mDocType) {
//now let's automatically close the root container...
GenerateSummary();
CToken theToken("viewsource");
nsCParserNode theNode(&theToken,0);
mSink->CloseContainer(theNode);
@ -577,6 +619,17 @@ NS_IMETHODIMP CViewSourceHTML::ConvertEntityToUnicode(const nsString& aEntity, P
return NS_ERROR_NOT_IMPLEMENTED;
}
PRBool CViewSourceHTML::IsBlockElement(PRInt32 aTagID,PRInt32 aParentID) const {
PRBool result=PR_FALSE;
return result;
}
PRBool CViewSourceHTML::IsInlineElement(PRInt32 aTagID,PRInt32 aParentID) const {
PRBool result=PR_FALSE;
return result;
}
/**
* This method gets called to determine whether a given
* tag is itself a container
@ -748,70 +801,6 @@ nsresult CViewSourceHTML::WriteAttributes(PRInt32 attrCount) {
return result;
}
/**
* This method gets called when a tag needs to be sent out
*
* @update gess 3/25/98
* @param
* @return result status
*/
nsresult CViewSourceHTML::WriteTag(nsString &theXMLTagName,CToken* aToken,PRInt32 attrCount,PRBool aNewlineRequired) {
static nsString theString;
nsresult result=NS_OK;
CSharedVSContext& theContext=CSharedVSContext::GetSharedContext();
CToken theTagToken(theXMLTagName);
theContext.mStartNode.Init(&theTagToken,mLineNumber);
STOP_TIMER();
mSink->OpenContainer(theContext.mStartNode); //emit <starttag>...
START_TIMER();
#ifdef rickgdebug
if(aNewlineRequired) {
(*gDumpFile)<<endl;
}
nsCAutoString cstr(theXMLTagName);
(*gDumpFile) << "<" << cstr << ">";
cstr.Assign(aToken->GetStringValueXXX());
if('<'==cstr.First()) {
cstr.Cut(0,2);
cstr.Truncate(cstr.Length()-1);
}
(*gDumpFile) << cstr;
#endif
nsString& theStr=aToken->GetStringValueXXX();
theStr.StripChar(kCR);
theContext.mITextToken.SetIndirectString(theStr); //now emit the tag name...
STOP_TIMER();
mSink->AddLeaf(theContext.mITextNode);
START_TIMER();
if(attrCount){
result=WriteAttributes(attrCount);
}
STOP_TIMER();
theContext.mEndNode.Init(&theTagToken,mLineNumber);
mSink->CloseContainer(theContext.mEndNode); //emit </starttag>...
START_TIMER();
#ifdef rickgdebug
cstr.Assign(theXMLTagName);
(*gDumpFile) << "</" << cstr << ">";
#endif
return result;
}
/**
* This method gets called when a tag needs to be sent out
*
@ -830,9 +819,8 @@ nsresult CViewSourceHTML::WriteTag(nsString &theXMLTagName,nsString & aText,PRIn
theContext.mStartNode.Init(&theTagToken,mLineNumber);
STOP_TIMER();
mSink->OpenContainer(theContext.mStartNode); //emit <starttag>...
START_TIMER();
mSink->OpenContainer(theContext.mStartNode); //emit <starttag>...
#ifdef rickgdebug
@ -849,29 +837,103 @@ nsresult CViewSourceHTML::WriteTag(nsString &theXMLTagName,nsString & aText,PRIn
theContext.mITextToken.SetIndirectString(aText); //now emit the tag name...
STOP_TIMER();
mSink->AddLeaf(theContext.mITextNode);
START_TIMER();
if(attrCount){
result=WriteAttributes(attrCount);
}
theContext.mEndNode.Init(&theTagToken,mLineNumber);
STOP_TIMER();
mSink->CloseContainer(theContext.mEndNode); //emit </starttag>...
START_TIMER();
#ifdef rickgdebug
cstr.Assign(theXMLTagName);
(*gDumpFile) << "</" << cstr << ">";
#endif
START_TIMER();
return result;
}
/**
* This method gets called when a tag needs to be sent out
*
* @update gess 6June2000 -- factored to use WriteTag(txt,txt...);
* @param
* @return result status
*/
nsresult CViewSourceHTML::WriteTag(nsString &theXMLTagName,CToken* aToken,PRInt32 attrCount,PRBool aNewlineRequired) {
nsString& theStr=aToken->GetStringValueXXX();
theStr.StripChar(kCR);
nsresult result=WriteTag(theXMLTagName,theStr,attrCount,aNewlineRequired);
return result;
}
/**
* This method gets called when a tag needs to be sent out but is known to be misplaced (error)
*
* @update gess 6June2000 --
* @param
* @return result status
*/
nsresult CViewSourceHTML::WriteTagWithError(nsString &theXMLTagName,CToken* aToken,PRInt32 attrCount,PRBool aNewlineRequired) {
STOP_TIMER();
CSharedVSContext& theContext=CSharedVSContext::GetSharedContext();
nsresult result=NS_OK;
if(ePlainText!=mDocType) {
//first write the error tag itself...
theContext.mErrorNode.Init(&theContext.mErrorToken,mLineNumber);
result=mSink->OpenContainer(theContext.mErrorNode); //emit <error>...
}
//now write the tag from the source file...
result=WriteTag(theXMLTagName,aToken,attrCount,aNewlineRequired);
if(ePlainText!=mDocType) {
//now close the error tag...
STOP_TIMER();
theContext.mErrorNode.Init(&theContext.mErrorToken,mLineNumber);
mSink->CloseContainer(theContext.mErrorNode);
START_TIMER();
}
return result;
}
void CViewSourceHTML::AddContainmentError(eHTMLTags aChildTag,eHTMLTags aParentTag,PRInt32 aLineNumber) {
#ifdef ENABLE_ERROR_OUTPUT
mErrorCount++;
if(mErrorCount<=gErrorThreshold) {
char theChildMsg[100];
if(eHTMLTag_text==aChildTag)
strcpy(theChildMsg,"text");
else sprintf(theChildMsg,"<%s>",nsHTMLTags::GetCStringValue(aChildTag));
char theMsg[256];
sprintf(theMsg,"\n -- Line (%i) error: %s is not a legal child of <%s>",
aLineNumber,theChildMsg,nsHTMLTags::GetCStringValue(aParentTag));
mErrors.AppendWithConversion(theMsg);
}
else if(gErrorThreshold+1==mErrorCount){
mErrors.AppendWithConversion("\n -- Too many errors -- terminating output.");
}
#endif
}
/**
*
@ -890,25 +952,53 @@ NS_IMETHODIMP CViewSourceHTML::HandleToken(CToken* aToken,nsIParser* aParser) {
CSharedVSContext& theContext=CSharedVSContext::GetSharedContext();
theContext.mTokenNode.Init(theToken,mLineNumber);
eHTMLTags theParent=(mTags.Length()) ? (eHTMLTags)mTags.Last() : eHTMLTag_unknown;
eHTMLTags theChild=(eHTMLTags)aToken->GetTypeID();
switch(theType) {
case eToken_start:
{
mTagCount++;
result=WriteTag(mStartTag,aToken,aToken->GetAttributeCount(),PR_TRUE);
if((ePlainText!=mDocType) && mParser && (NS_OK==result)) {
CObserverService* theService=mParser->GetObserverService();
if(theService) {
CParserContext* pc=mParser->PeekContext();
void* theDocID=(pc)? pc->mKey:0;
eHTMLTags theTag=(eHTMLTags)theToken->GetTypeID();
result=theService->Notify(theTag,theContext.mTokenNode,theDocID, NS_ConvertToString(kViewSourceCommand), mParser);
#ifdef ENABLE_ERROR_OUTPUT
PRBool theChildIsValid=PR_TRUE;
if(mValidator) {
theChildIsValid=mValidator->CanContain(theParent,theChild);
if(theChildIsValid) {
if(mValidator->IsContainer(theChild))
mTags.Append(PRUnichar(theChild));
}
}
if(theChildIsValid)
result=WriteTag(mStartTag,aToken,aToken->GetAttributeCount(),PR_TRUE);
else {
AddContainmentError(theChild,theParent,mLineNumber);
result=WriteTagWithError(mStartTag,aToken,aToken->GetAttributeCount(),PR_TRUE);
}
#else
result=WriteTag(mStartTag,aToken,aToken->GetAttributeCount(),PR_TRUE);
#endif
if((ePlainText!=mDocType) && mParser && (NS_OK==result)) {
CObserverService* theService=mParser->GetObserverService();
if(theService) {
CParserContext* pc=mParser->PeekContext();
void* theDocID=(pc)? pc->mKey:0;
eHTMLTags theTag=(eHTMLTags)theToken->GetTypeID();
result=theService->Notify(theTag,theContext.mTokenNode,theDocID, NS_ConvertToString(kViewSourceCommand), mParser);
}
}
theContext.mTokenNode.Init(0,0,gTokenRecycler); //now recycle.
}
theContext.mTokenNode.Init(0,0,gTokenRecycler); //now recycle.
break;
case eToken_end:
if(theParent==theChild) {
mTags.Truncate(mTags.Length()-1);
}
result=WriteTag(mEndTag,aToken,0,PR_TRUE);
break;
@ -921,7 +1011,7 @@ NS_IMETHODIMP CViewSourceHTML::HandleToken(CToken* aToken,nsIParser* aParser) {
}
break;
case eToken_comment:
case eToken_comment:
result=WriteTag(mCommentTag,aToken,0,PR_TRUE);
break;
@ -932,12 +1022,25 @@ NS_IMETHODIMP CViewSourceHTML::HandleToken(CToken* aToken,nsIParser* aParser) {
break;
case eToken_newline:
mLineNumber++;
mLineNumber++; //now fall through...
case eToken_whitespace:
case eToken_text:
result=WriteTag(mText,aToken,0,PR_FALSE);
break;
case eToken_text:
#ifdef ENABLE_ERROR_OUTPUT
if((0==mValidator) || mValidator->CanContain(theParent,eHTMLTag_text))
result=WriteTag(mText,aToken,aToken->GetAttributeCount(),PR_TRUE);
else {
AddContainmentError(eHTMLTag_text,theParent,mLineNumber);
result=WriteTagWithError(mText,aToken,aToken->GetAttributeCount(),PR_FALSE);
}
#else
result=WriteTag(mText,aToken,aToken->GetAttributeCount(),PR_TRUE);
#endif
break;
case eToken_entity:
{
nsAutoString theStr;

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

@ -51,7 +51,6 @@ class nsParser;
class nsITokenizer;
class nsCParserNode;
class CViewSourceHTML: public nsIDTD {
public:
@ -224,6 +223,9 @@ class CViewSourceHTML: public nsIDTD {
NS_IMETHOD ConvertEntityToUnicode(const nsString& aEntity, PRInt32* aUnicode) const;
virtual PRBool IsBlockElement(PRInt32 aTagID,PRInt32 aParentID) const;
virtual PRBool IsInlineElement(PRInt32 aTagID,PRInt32 aParentID) const;
/**
* This method gets called to determine whether a given
* tag is itself a container
@ -241,7 +243,11 @@ class CViewSourceHTML: public nsIDTD {
private:
nsresult WriteTag(nsString &anXMLName,CToken* aTag,PRInt32 attrCount,PRBool aNewlineRequired);
nsresult WriteTag(nsString &anXMLName,nsString &aText,PRInt32 attrCount,PRBool aNewlineRequired);
nsresult WriteTagWithError(nsString &theXMLTagName,CToken* aToken,PRInt32 attrCount,PRBool aNewlineRequired);
void AddContainmentError(eHTMLTags aChild,eHTMLTags aParent,PRInt32 aLineNumber);
nsresult WriteAttributes(PRInt32 attrCount);
nsresult GenerateSummary();
protected:
@ -260,10 +266,18 @@ protected:
nsAutoString mKey;
nsAutoString mValue;
nsAutoString mPopupTag;
nsAutoString mSummaryTag;
nsDTDMode mDTDMode;
eParserCommands mParserCommand; //tells us to viewcontent/viewsource/viewerrors...
eParserDocType mDocType;
nsAutoString mMimeType;
PRInt32 mErrorCount;
PRInt32 mTagCount;
nsIDTD *mValidator;
nsString mTags;
nsString mErrors;
};
extern NS_HTMLPARS nsresult NS_NewViewSourceHTML(nsIDTD** aInstancePtrResult);

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

@ -472,6 +472,7 @@ NS_IMETHODIMP CWellFormedDTD::ConvertEntityToUnicode(const nsString& aEntity, PR
return NS_ERROR_NOT_IMPLEMENTED;
}
/**
* This method gets called to determine whether a given
* tag is itself a container

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

@ -225,6 +225,9 @@ class CWellFormedDTD : public nsIDTD {
NS_IMETHOD ConvertEntityToUnicode(const nsString& aEntity, PRInt32* aUnicode) const;
virtual PRBool IsBlockElement(PRInt32 aTagID,PRInt32 aParentID) const {return PR_FALSE;}
virtual PRBool IsInlineElement(PRInt32 aTagID,PRInt32 aParentID) const {return PR_FALSE;}
protected:
/*
NS_IMETHODIMP ConsumeTag(PRUnichar aChar,nsScanner& aScanner,CToken*& aToken);

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

@ -931,11 +931,22 @@ NS_IMETHODIMP nsXIFDTD::ConvertEntityToUnicode(const nsString& aEntity, PRInt32*
}
PRBool nsXIFDTD::IsInlineElement(PRInt32 aTagID,PRInt32 aParentID) const {
PRBool result=PR_FALSE;
return result;
}
PRBool nsXIFDTD::IsBlockElement(PRInt32 aTagID,PRInt32 aParentID) const {
PRBool result=PR_FALSE;
return result;
}
/**
* This method gets called to determine whether a given
* tag is itself a container
*
* @update gpk 06/18/98
* @update rickg 06June2000
* @param aTag -- tag to test for containership
* @return PR_TRUE if given tag can contain other tags
*/

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

@ -262,6 +262,9 @@ class nsXIFDTD : public nsIDTD {
NS_IMETHOD ConvertEntityToUnicode(const nsString& aEntity, PRInt32* aUnicode) const;
virtual PRBool IsBlockElement(PRInt32 aTagID,PRInt32 aParentID) const;
virtual PRBool IsInlineElement(PRInt32 aTagID,PRInt32 aParentID) const;
/**
* Set this to TRUE if you want the DTD to verify its
* context stack.

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

@ -327,7 +327,7 @@ PRBool CNavDTD::Verify(nsString& aURLRef,nsIParser* aParser){
* @update gess 02/24/00
* @param
* @return TRUE if this DTD can satisfy the request; FALSE otherwise.
*/
*/
eAutoDetectResult CNavDTD::CanParse(CParserContext& aParserContext,nsString& aBuffer, PRInt32 aVersion) {
eAutoDetectResult result=eUnknownDetect;
@ -338,14 +338,22 @@ eAutoDetectResult CNavDTD::CanParse(CParserContext& aParserContext,nsString& aBu
else if(aParserContext.mMimeType.EqualsWithConversion(kRTFTextContentType)){
result=ePrimaryDetect;
}
}
}
else {
if(PR_TRUE==aParserContext.mMimeType.EqualsWithConversion(kHTMLTextContentType)) {
result=(eDTDMode_strict==aParserContext.mDTDMode) ? eValidDetect : ePrimaryDetect;
switch(aParserContext.mDTDMode) {
case eDTDMode_strict:
case eDTDMode_transitional:
result=eValidDetect;
break;
default:
result=ePrimaryDetect;
break;
}
}
else if(PR_TRUE==aParserContext.mMimeType.EqualsWithConversion(kPlainTextContentType)) {
result=ePrimaryDetect;
}
}
else {
//otherwise, look into the buffer to see if you recognize anything...
PRBool theBufHasXML=PR_FALSE;
@ -354,12 +362,20 @@ eAutoDetectResult CNavDTD::CanParse(CParserContext& aParserContext,nsString& aBu
if(0==aParserContext.mMimeType.Length()) {
aParserContext.SetMimeType(NS_ConvertToString(kHTMLTextContentType));
if(!theBufHasXML) {
result=(eDTDMode_strict==aParserContext.mDTDMode) ? eValidDetect : ePrimaryDetect;
switch(aParserContext.mDTDMode) {
case eDTDMode_strict:
case eDTDMode_transitional:
result=eValidDetect;
break;
default:
result=ePrimaryDetect;
break;
}
}
else result=eValidDetect;
}
}
}
}
}
return result;
}
@ -816,6 +832,12 @@ nsresult CNavDTD::HandleToken(CToken* aToken,nsIParser* aParser){
nsresult CNavDTD::DidHandleStartTag(nsCParserNode& aNode,eHTMLTags aChildTag){
nsresult result=NS_OK;
#if 0
// XXX --- Ignore this: it's just rickg debug testing...
nsAutoString theStr;
aNode.GetSource(theStr);
#endif
switch(aChildTag){
case eHTMLTag_pre:
@ -2097,7 +2119,22 @@ nsresult CNavDTD::HandleDocTypeDeclToken(CToken* aToken){
STOP_TIMER();
MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::HandleDocTypeDeclToken(), this=%p\n", this));
result = (mSink)? mSink->AddDocTypeDecl(*theNode,mDTDMode):NS_OK;
/*************************************************************
While the parser is happy to deal with various modes, the
rest of layout prefers only 2: strict vs. quirks. So we'll
constrain the modes when reporting to layout.
*************************************************************/
nsDTDMode theMode=mDTDMode;
switch(mDTDMode) {
case eDTDMode_transitional:
case eDTDMode_strict:
theMode=eDTDMode_strict;
break;
default:
theMode=eDTDMode_quirks;
}
result = (mSink)? mSink->AddDocTypeDecl(*theNode,theMode):NS_OK;
mNodeRecycler->RecycleNode(theNode,mTokenRecycler);
@ -2270,6 +2307,47 @@ NS_IMETHODIMP CNavDTD::ConvertEntityToUnicode(const nsString& aEntity, PRInt32*
return NS_OK;
}
/**
* This method is called to determine whether or not
* the given childtag is a block element.
*
* @update gess 6June2000
* @param aChildID -- tag id of child
* @param aParentID -- tag id of parent (or eHTMLTag_unknown)
* @return PR_TRUE if this tag is a block tag
*/
PRBool CNavDTD::IsBlockElement(PRInt32 aTagID,PRInt32 aParentID) const {
PRBool result=PR_FALSE;
eHTMLTags theTag=(eHTMLTags)aTagID;
if((theTag>eHTMLTag_unknown) && (theTag<eHTMLTag_userdefined)) {
result=gHTMLElements[theTag].IsBlockEntity();
}
return result;
}
/**
* This method is called to determine whether or not
* the given childtag is an inline element.
*
* @update gess 6June2000
* @param aChildID -- tag id of child
* @param aParentID -- tag id of parent (or eHTMLTag_unknown)
* @return PR_TRUE if this tag is an inline tag
*/
PRBool CNavDTD::IsInlineElement(PRInt32 aTagID,PRInt32 aParentID) const {
PRBool result=PR_FALSE;
eHTMLTags theTag=(eHTMLTags)aTagID;
if((theTag>eHTMLTag_unknown) && (theTag<eHTMLTag_userdefined)) {
result=nsHTMLElement::IsInlineEntity(theTag);
}
return result;
}
/**
* This method is called to determine whether or not
* the necessary intermediate tags should be propagated
@ -3064,6 +3142,9 @@ CNavDTD::OpenContainer(const nsIParserNode *aNode,eHTMLTags aTag,PRBool aClosedB
}
break;
case eHTMLTag_counter: //drop it on the floor.
break;
case eHTMLTag_style:
case eHTMLTag_title:
break;
@ -3336,34 +3417,6 @@ nsresult CNavDTD::CloseContainersTo(PRInt32 anIndex,eHTMLTags aTarget, PRBool aC
mNodeRecycler->RecycleNode(theNode,mTokenRecycler);
}
if(eDTDMode_quirks==mDTDMode) {
#if 0
//This code takes any nodes in style stack for at this level and reopens
//then where they were originally.
if(!aClosedByStartTag) {
nsEntryStack* theStack=mBodyContext->GetStylesAt(anIndex-1);
if(theStack){
PRUint32 scount=theStack->mCount;
PRUint32 sindex=0;
for(sindex=0;sindex<scount;sindex++){
nsIParserNode* theNode=theStack->NodeAt(sindex);
if(theNode) {
((nsCParserNode*)theNode)->mUseCount--;
result=OpenContainer(theNode,(eHTMLTags)theNode->GetNodeType(),PR_FALSE);
}
}
theStack->mCount=0;
} //if
} //if
#endif
}//if
} //if
return result;
}

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

@ -389,6 +389,9 @@ CLASS_EXPORT_HTMLPARS CNavDTD : public nsIDTD {
NS_IMETHOD ConvertEntityToUnicode(const nsString& aEntity, PRInt32* aUnicode) const;
virtual PRBool IsBlockElement(PRInt32 aTagID,PRInt32 aParentID) const;
virtual PRBool IsInlineElement(PRInt32 aTagID,PRInt32 aParentID) const;
/**
* The following set of methods are used to partially construct
* the content model (via the sink) according to the type of token.

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

@ -10,22 +10,22 @@
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Contributor(s): rickg@netscape.com
*/
//#define ENABLE_CRC
//#define RICKG_DEBUG
//#define ENABLE_CRC
//#define RICKG_DEBUG
#include "nsDebug.h"
#include "nsIDTDDebug.h"
#include "nsIDTDDebug.h"
#include "COtherDTD.h"
#include "nsHTMLTokens.h"
#include "nsCRT.h"
@ -56,8 +56,6 @@ static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static NS_DEFINE_IID(kIDTDIID, NS_IDTD_IID);
static NS_DEFINE_IID(kClassIID, NS_IOTHERHTML_DTD_IID);
static const char* kNullToken = "Error: Null token given";
static const char* kInvalidTagStackPos = "Error: invalid tag stack position";
static char* kVerificationDir = "c:/temp";
@ -153,8 +151,12 @@ COtherDTD::COtherDTD() : nsIDTD(), mSharedNodes(0) {
mTokenRecycler=0;
mParserCommand=eViewNormal;
#if 0 //set this to 1 if you want strictDTD to be based on the environment setting.
char* theEnvString = PR_GetEnv("ENABLE_STRICT");
mEnableStrict=PRBool(theEnvString!=0);
else
mEnableStrict=PR_TRUE;
#endif
if(!gElementTable) {
gElementTable = new CElementTable();
@ -391,7 +393,7 @@ PRBool COtherDTD::Verify(nsString& aURLRef,nsIParser* aParser){
* NOTE: Parsing always assumes that the end result will involve
* storing the result in the main content model.
* @update gess6/24/98
* @param
* @param
* @return TRUE if this DTD can satisfy the request; FALSE otherwise.
*/
eAutoDetectResult COtherDTD::CanParse(CParserContext& aParserContext,nsString& aBuffer, PRInt32 aVersion) {
@ -407,12 +409,20 @@ eAutoDetectResult COtherDTD::CanParse(CParserContext& aParserContext,nsString& a
}
}
else {
if(PR_TRUE==aParserContext.mMimeType.EqualsWithConversion(kHTMLTextContentType)) {
result=(eDTDMode_strict==aParserContext.mDTDMode) ? ePrimaryDetect : eValidDetect;
}
else if(PR_TRUE==aParserContext.mMimeType.EqualsWithConversion(kPlainTextContentType)) {
if(PR_TRUE==aParserContext.mMimeType.EqualsWithConversion(kPlainTextContentType)) {
result=eValidDetect;
}
else if(PR_TRUE==aParserContext.mMimeType.EqualsWithConversion(kHTMLTextContentType)) {
switch(aParserContext.mDTDMode) {
case eDTDMode_strict:
case eDTDMode_transitional:
result=ePrimaryDetect;
break;
default:
result=eValidDetect;
break;
}
}
else {
//otherwise, look into the buffer to see if you recognize anything...
PRBool theBufHasXML=PR_FALSE;
@ -421,14 +431,21 @@ eAutoDetectResult COtherDTD::CanParse(CParserContext& aParserContext,nsString& a
if(0==aParserContext.mMimeType.Length()) {
aParserContext.SetMimeType(NS_ConvertToString(kHTMLTextContentType));
if(!theBufHasXML) {
result=(eDTDMode_strict==aParserContext.mDTDMode) ? ePrimaryDetect : eValidDetect;
switch(aParserContext.mDTDMode) {
case eDTDMode_strict:
case eDTDMode_transitional:
result=ePrimaryDetect;
break;
default:
result=eValidDetect;
break;
}
}
else result=eValidDetect;
}
}
}
}
return result;
}
return result;
}
@ -462,6 +479,7 @@ nsresult COtherDTD::WillBuildModel( const CParserContext& aParserContext,nsICon
mTokenRecycler=0;
mDocType=aParserContext.mDocType;
mBodyContext->mTransitional=PRBool(aParserContext.mDTDMode==eDTDMode_transitional);
if(aSink && (!mSink)) {
result=aSink->QueryInterface(kIHTMLContentSinkIID, (void **)&mSink);
}
@ -609,12 +627,9 @@ nsresult COtherDTD::HandleToken(CToken* aToken,nsIParser* aParser){
if(aToken) {
CHTMLToken* theToken= (CHTMLToken*)(aToken);
eHTMLTokenTypes theType=eHTMLTokenTypes(theToken->GetTokenType());
// eHTMLTags theTag=(eHTMLTags)theToken->GetTypeID();
// PRBool execSkipContent=PR_FALSE;
theToken->mUseCount=0; //assume every token coming into this system needs recycling.
mParser=(nsParser*)aParser;
switch(theType) {
@ -625,6 +640,9 @@ nsresult COtherDTD::HandleToken(CToken* aToken,nsIParser* aParser){
case eToken_doctypeDecl:
result=HandleStartToken(theToken); break;
case eToken_entity:
result=HandleEntityToken(theToken); break;
case eToken_end:
result=HandleEndToken(theToken); break;
@ -676,6 +694,35 @@ nsresult COtherDTD::DidHandleStartTag(nsCParserNode& aNode,eHTMLTags aChildTag){
}
break;
case eHTMLTag_meta:
{
//we should only enable user-defined entities in debug builds...
PRInt32 theCount=aNode.GetAttributeCount();
const nsString* theNamePtr=0;
const nsString* theValuePtr=0;
if(theCount) {
PRInt32 theIndex=0;
for(theIndex=0;theIndex<theCount;theIndex++){
const nsString& theKey=aNode.GetKeyAt(theIndex);
if(theKey.EqualsWithConversion("ENTITY",PR_TRUE)) {
const nsString& theName=aNode.GetValueAt(theIndex);
theNamePtr=&theName;
}
else if(theKey.EqualsWithConversion("VALUE",PR_TRUE)) {
//store the named enity with the context...
const nsString& theValue=aNode.GetValueAt(theIndex);
theValuePtr=&theValue;
}
}
}
if(theNamePtr && theValuePtr) {
mBodyContext->RegisterEntity(*theNamePtr,*theValuePtr);
}
}
break;
default:
break;
}//switch
@ -755,9 +802,7 @@ nsresult COtherDTD::WillHandleStartTag(CToken* aToken,eHTMLTags aTag,nsCParserNo
* @param aNode -- CParserNode representing this start token
* @return PR_TRUE if all went well; PR_FALSE if error occured
*/
nsresult COtherDTD::HandleStartToken(CToken* aToken) {
NS_PRECONDITION(0!=aToken,kNullToken);
nsresult COtherDTD::HandleStartToken(CToken* aToken) {
#ifdef RICKG_DEBUG
WriteTokenToLog(aToken);
#endif
@ -781,15 +826,15 @@ nsresult COtherDTD::HandleStartToken(CToken* aToken) {
PRBool theTagWasHandled=PR_FALSE;
switch(theChildTag) {
case eHTMLTag_html:
if(!HasOpenContainer(theChildTag)) {
if(!mBodyContext->HasOpenContainer(theChildTag)){
mSink->OpenHTML(*theNode);
mBodyContext->Push(theNode,0);
}
theTagWasHandled=PR_TRUE;
break;
default:
CElement* theElement=gElementTable->mElements[theParent];
if(theElement) {
@ -798,7 +843,7 @@ nsresult COtherDTD::HandleStartToken(CToken* aToken) {
}
break;
}//switch
if(theTagWasHandled) {
DidHandleStartTag(*theNode,theChildTag);
}
@ -823,9 +868,7 @@ nsresult COtherDTD::HandleStartToken(CToken* aToken) {
* @param aToken -- next (start) token to be handled
* @return PR_TRUE if all went well; PR_FALSE if error occured
*/
nsresult COtherDTD::HandleEndToken(CToken* aToken) {
NS_PRECONDITION(0!=aToken,kNullToken);
nsresult COtherDTD::HandleEndToken(CToken* aToken) {
nsresult result=NS_OK;
eHTMLTags theChildTag=(eHTMLTags)aToken->GetTypeID();
@ -840,7 +883,7 @@ nsresult COtherDTD::HandleEndToken(CToken* aToken) {
break;
case eHTMLTag_script:
mHasOpenScript=PR_FALSE;
mHasOpenScript=PR_FALSE;
default:
PRInt32 theCount=mBodyContext->GetCount();
@ -899,6 +942,38 @@ nsresult COtherDTD::CollectAttributes(nsCParserNode& aNode,eHTMLTags aTag,PRInt3
return result;
}
/**
* This method gets called when an entity token has been
* encountered in the parse process.
*
* @update gess 3/25/98
* @param aToken -- next (start) token to be handled
* @return PR_TRUE if all went well; PR_FALSE if error occured
*/
nsresult COtherDTD::HandleEntityToken(CToken* aToken) {
nsresult result=NS_OK;
nsString& theStr=aToken->GetStringValueXXX();
PRUnichar theChar=theStr.CharAt(0);
if((kHashsign!=theChar) && (-1==nsHTMLEntities::EntityToUnicode(theStr))){
//before we just toss this away as a bogus entity, let's check...
CNamedEntity *theEntity=mBodyContext->GetEntity(theStr);
CToken *theToken=0;
if(theEntity) {
theToken=new CTextToken(theEntity->mValue);
}
else {
//if you're here we have a bogus entity.
//convert it into a text token.
nsAutoString temp; temp.AssignWithConversion("&");
temp.Append(theStr);
theToken=new CTextToken(temp);
}
result=HandleStartToken(theToken);
}
return result;
}
/***********************************************************************************
The preceeding tables determine the set of elements each tag can contain...
@ -914,9 +989,14 @@ nsresult COtherDTD::CollectAttributes(nsCParserNode& aNode,eHTMLTags aTag,PRInt3
* @return PR_TRUE if parent can contain child
*/
PRBool COtherDTD::CanContain(PRInt32 aParent,PRInt32 aChild) const {
PRBool result=PR_FALSE;
//result=gHTMLElements[aParent].CanContain((eHTMLTags)aChild);
return result;
CElement *theParent=gElementTable->mElements[eHTMLTags(aParent)];
if(theParent) {
CElement *theChild=gElementTable->mElements[eHTMLTags(aChild)];
if(aChild) {
return theParent->CanContain(theChild,mBodyContext);
}
}
return PR_FALSE;
}
/**
@ -938,10 +1018,47 @@ NS_IMETHODIMP COtherDTD::ConvertEntityToUnicode(const nsString& aEntity, PRInt32
return NS_OK;
}
/**
* This method is called to determine whether or not
* the given childtag is a block element.
*
* @update gess 6June2000
* @param aChildID -- tag id of child
* @param aParentID -- tag id of parent (or eHTMLTag_unknown)
* @return PR_TRUE if this tag is a block tag
*/
PRBool COtherDTD::IsBlockElement(PRInt32 aChildID,PRInt32 aParentID) const {
PRBool result=PR_FALSE;
if(gElementTable) {
CElement *theElement=gElementTable->GetElement((eHTMLTags)aChildID);
result = (theElement) ? theElement->IsBlockElement((eHTMLTags)aParentID) : PR_FALSE;
}
return result;
}
/**
* This method is called to determine whether or not
* the given childtag is an inline element.
*
* @update gess 6June2000
* @param aChildID -- tag id of child
* @param aParentID -- tag id of parent (or eHTMLTag_unknown)
* @return PR_TRUE if this tag is an inline element
*/
PRBool COtherDTD::IsInlineElement(PRInt32 aChildID,PRInt32 aParentID) const {
PRBool result=PR_FALSE;
if(gElementTable) {
CElement *theElement=gElementTable->GetElement((eHTMLTags)aChildID);
result = (theElement) ? theElement->IsInlineElement((eHTMLTags)aParentID) : PR_FALSE;
}
return result;
}
/**
* This method gets called to determine whether a given
* tag is itself a container
* tag is itself a container
*
* @update gess 4/8/98
* @param aTag -- tag to test as a container
@ -951,155 +1068,6 @@ PRBool COtherDTD::IsContainer(PRInt32 aTag) const {
return gElementTable->mElements[eHTMLTags(aTag)]->IsContainer();
}
/**
* This method allows the caller to determine if a given container
* is currently open
*
* @update gess 11/9/98
* @param
* @return
*/
PRBool COtherDTD::HasOpenContainer(eHTMLTags aContainer) const {
PRBool result=PR_FALSE;
switch(aContainer) {
case eHTMLTag_form:
result=mHasOpenForm; break;
case eHTMLTag_map:
result=mHasOpenMap; break;
default:
result=mBodyContext->HasOpenContainer(aContainer);
break;
}
return result;
}
/**
* This method allows the caller to determine if a any member
* in a set of tags is currently open
*
* @update gess 11/9/98
* @param
* @return
*/
PRBool COtherDTD::HasOpenContainer(const eHTMLTags aTagSet[],PRInt32 aCount) const {
int theIndex;
int theTopIndex=mBodyContext->GetCount()-1;
for(theIndex=theTopIndex;theIndex>0;theIndex--){
if(FindTagInSet((*mBodyContext)[theIndex],aTagSet,aCount))
return PR_TRUE;
}
return PR_FALSE;
}
/**
* This method does two things: 1st, help construct
* our own internal model of the content-stack; and
* 2nd, pass this message on to the sink.
* @update gess4/6/98
* @param aNode -- next node to be removed from our model
* @param aTag -- id of tag to be closed
* @param aClosedByStartTag -- ONLY TRUE if the container is being closed by opening of another container.
* @return TRUE if ok, FALSE if error
*/
nsresult
COtherDTD::CloseContainer(const nsIParserNode *aNode,eHTMLTags aTarget,PRBool aClosedByStartTag){
nsresult result=NS_OK;
eHTMLTags nodeType=(eHTMLTags)aNode->GetNodeType();
#ifdef ENABLE_CRC
#define K_CLOSEOP 200
CRCStruct theStruct(nodeType,K_CLOSEOP);
mComputedCRC32=AccumulateCRC(mComputedCRC32,(char*)&theStruct,sizeof(theStruct));
#endif
switch(nodeType) {
case eHTMLTag_html:
// result=CloseHTML(aNode); break;
case eHTMLTag_map:
// result=CloseMap(aNode);
break;
case eHTMLTag_form:
// result=CloseForm(aNode);
break;
case eHTMLTag_frameset:
// result=CloseFrameset(aNode);
break;
case eHTMLTag_title:
default:
STOP_TIMER();
MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: COtherDTD::CloseContainer(), this=%p\n", this));
result=(mSink) ? mSink->CloseContainer(*aNode) : NS_OK;
MOZ_TIMER_DEBUGLOG(("Start: Parse Time: COtherDTD::CloseContainer(), this=%p\n", this));
START_TIMER();
break;
}
return result;
}
/**
* This method does two things: 1st, help construct
* our own internal model of the content-stack; and
* 2nd, pass this message on to the sink.
* @update gess4/6/98
* @param anIndex
* @param aTag
* @param aClosedByStartTag -- if TRUE, then we're closing something because a start tag caused it
* @return TRUE if ok, FALSE if error
*/
nsresult COtherDTD::CloseContainersTo(PRInt32 anIndex,eHTMLTags aTarget, PRBool aClosedByStartTag){
NS_PRECONDITION(mBodyContext->GetCount() > 0, kInvalidTagStackPos);
nsresult result=NS_OK;
if((anIndex<mBodyContext->GetCount()) && (anIndex>=0)) {
while(mBodyContext->GetCount()>anIndex) {
// eHTMLTags theTag=mBodyContext->Last();
nsEntryStack *theChildStyleStack=0;
nsCParserNode *theNode=(nsCParserNode*)mBodyContext->Pop(theChildStyleStack);
if(theNode) {
result=CloseContainer(theNode,aTarget,aClosedByStartTag);
}//if anode
RecycleNode(theNode);
}
} //if
return result;
}
/**
* This method does two things: 1st, help construct
* our own internal model of the content-stack; and
* 2nd, pass this message on to the sink.
* @update gess4/6/98
* @param aTag --
* @param aClosedByStartTag -- ONLY TRUE if the container is being closed by opening of another container.
* @return TRUE if ok, FALSE if error
*/
nsresult COtherDTD::CloseContainersTo(eHTMLTags aTarget,PRBool aClosedByStartTag){
NS_PRECONDITION(mBodyContext->GetCount() > 0, kInvalidTagStackPos);
nsresult result=NS_OK;
return result;
}
/**
* Retrieve the preferred tokenizer for use by this DTD.

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

@ -269,23 +269,6 @@ CLASS_EXPORT_HTMLPARS COtherDTD : public nsIDTD {
*/
virtual PRBool IsContainer(PRInt32 aTag) const;
/**
* Ask parser if a given container is open ANYWHERE on stack
* @update gess5/11/98
* @param id of container you want to test for
* @return TRUE if the given container type is open -- otherwise FALSE
*/
virtual PRBool HasOpenContainer(eHTMLTags aContainer) const;
/**
* Ask parser if a given container is open ANYWHERE on stack
* @update gess5/11/98
* @param id of container you want to test for
* @return TRUE if the given container type is open -- otherwise FALSE
*/
virtual PRBool HasOpenContainer(const eHTMLTags aTagSet[],PRInt32 aCount) const;
/**
* Use this id you want to stop the building content model
* --------------[ Sets DTD to STOP mode ]----------------
@ -308,6 +291,9 @@ CLASS_EXPORT_HTMLPARS COtherDTD : public nsIDTD {
NS_IMETHOD ConvertEntityToUnicode(const nsString& aEntity, PRInt32* aUnicode) const;
virtual PRBool IsBlockElement(PRInt32 aTagID,PRInt32 aParentID) const;
virtual PRBool IsInlineElement(PRInt32 aTagID,PRInt32 aParentID) const;
/**
* The following set of methods are used to partially construct
* the content model (via the sink) according to the type of token.
@ -317,24 +303,13 @@ CLASS_EXPORT_HTMLPARS COtherDTD : public nsIDTD {
*/
nsresult HandleStartToken(CToken* aToken);
nsresult HandleEndToken(CToken* aToken);
nsresult HandleDocTypeDeclToken(CToken* aToken);
nsresult HandleEntityToken(CToken* aToken);
//*************************************************
//these cover methods mimic the sink, and are used
//by the parser to manage its context-stack.
//*************************************************
/**
* The special purpose methods automatically close
* one or more open containers.
* @update gess5/11/98
* @return error code - 0 if all went well.
*/
nsresult CloseContainer(const nsIParserNode *aNode,eHTMLTags aTarget,PRBool aClosedByStartTag);
nsresult CloseContainersTo(eHTMLTags aTag,PRBool aClosedByStartTag);
nsresult CloseContainersTo(PRInt32 anIndex,eHTMLTags aTag,PRBool aClosedByStartTag);
static void ReleaseTable(void);
protected:

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

@ -17,7 +17,7 @@
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Contributor(s): rickg@netscape.com
*/
/************************************************************************
@ -29,12 +29,10 @@
*
*
************************************************************************/
#ifndef _COTHERELEMENTS_
#define _COTHERELEMENTS_
#undef TRANSITIONAL
/************************************************************************
This union is a bitfield which describes the group membership
************************************************************************/
@ -75,7 +73,7 @@ union CGroupMembers {
inline PRBool ContainsGroup(CGroupMembers& aGroupSet,CGroupMembers& aGroup) {
PRBool result=PR_FALSE;
if(aGroup.mAllBits) {
result=PRBool(aGroupSet.mAllBits & aGroup.mAllBits);
result=(aGroupSet.mAllBits & aGroup.mAllBits) ? PR_TRUE : PR_FALSE;
}
return result;
}
@ -104,7 +102,7 @@ public:
struct CFlags {
PRUint32 mOmitEndTag:1;
PRUint32 mIsContainer:1;
PRUint32 mPropagateDepth:4;
PRUint32 mIsSinkContainer:1;
PRUint32 mDeprecated:1;
PRUint32 mOmitWS:1;
};
@ -139,6 +137,7 @@ public:
static void Initialize(CElement& anElement,eHTMLTags aTag){
anElement.mProperties.mIsContainer=0;
anElement.mProperties.mIsSinkContainer=0;
anElement.mTag=aTag;
anElement.mGroup.mAllBits=0;;
anElement.mContainsGroups.mAllBits=0;
@ -146,6 +145,7 @@ public:
static void InitializeLeaf(CElement& anElement,eHTMLTags aTag,CGroupMembers& aGroup,CGroupMembers& aContainsGroups) {
anElement.mProperties.mIsContainer=PR_FALSE;
anElement.mProperties.mIsSinkContainer=PR_FALSE;
anElement.mTag=aTag;
anElement.mGroup.mAllBits=aGroup.mAllBits;
anElement.mContainsGroups.mAllBits=aContainsGroups.mAllBits;
@ -153,6 +153,7 @@ public:
static void Initialize(CElement& anElement,eHTMLTags aTag,CGroupMembers& aGroup,CGroupMembers& aContainsGroups) {
anElement.mProperties.mIsContainer=PR_TRUE;
anElement.mProperties.mIsSinkContainer=PR_TRUE;
anElement.mTag=aTag;
anElement.mGroup.mAllBits=aGroup.mAllBits;
anElement.mContainsGroups.mAllBits=aContainsGroups.mAllBits;
@ -176,7 +177,19 @@ public:
virtual PRBool CanBeClosedByStartTag(CElement* anElement,nsDTDContext* aContext);
virtual PRBool CanBeClosedByEndTag(CElement* anElement,nsDTDContext* aContext);
virtual PRBool IsContainer(void) {return mProperties.mIsContainer;}
//this tells us whether this tag is a block tag within the given parent
virtual PRBool IsBlockElement(eHTMLTags aParentID);
//this tells us whether this tag is an inline tag within the given parent
//NOTE: aParentID is currently ignored, but shouldn't be.
virtual PRBool IsInlineElement(eHTMLTags aParentID);
//this tells us whether the tag is a container as defined by HTML
//NOTE: aParentID is currently ignored, but shouldn't be.
virtual PRBool IsContainer(void) {return mProperties.mIsContainer; }
//this tells us whether the tag should be opened as a container in the sink (script doesn't, for example).
virtual PRBool IsSinkContainer(void) { return mProperties.mIsSinkContainer; }
virtual eHTMLTags GetSkipTarget(void) {return eHTMLTag_unknown;}
@ -919,6 +932,7 @@ public:
CCounterElement(eHTMLTags aTag=eHTMLTag_counter) : CInlineElement(aTag) {
CInlineElement::Initialize(*this,aTag);
mProperties.mIsSinkContainer=PR_FALSE;
}
/**********************************************************
@ -935,23 +949,21 @@ public:
/**********************************************************
this gets called after each tag is opened in the given context
**********************************************************/
virtual nsresult OpenContainerInContext(nsIParserNode *aNode,eHTMLTags aTag,nsDTDContext *aContext,nsIHTMLContentSink *aSink) {
OpenContext(aNode,aTag,aContext,aSink);
virtual nsresult OpenContext(nsIParserNode *aNode,eHTMLTags aTag,nsDTDContext *aContext,nsIHTMLContentSink *aSink) {
CElement::OpenContext(aNode,aTag,aContext,aSink);
nsresult result=OpenContainer(aNode,aTag,aContext,aSink);
if(NS_SUCCEEDED(result)) {
PRInt32 theCount=aContext->GetCount();
eHTMLTags theGrandParentTag=aContext->TagAt(theCount-2);
nsresult result=NS_OK;
PRInt32 theCount=aContext->GetCount();
eHTMLTags theGrandParentTag=aContext->TagAt(theCount-2);
nsCParserNode *theNode=(nsCParserNode*)aNode;
nsAutoString theNumber;
PRInt32 theCounter=aContext->IncrementCounter(theGrandParentTag,*theNode,theNumber);
nsCParserNode *theNode=(nsCParserNode*)aNode;
nsAutoString theNumber;
PRInt32 theCounter=aContext->IncrementCounter(theGrandParentTag,*theNode,theNumber);
CTextToken theToken(theNumber);
PRInt32 theLineNumber=0;
nsCParserNode theNewNode(&theToken,theLineNumber);
result=aSink->AddLeaf(theNewNode);
}
CTextToken theToken(theNumber);
PRInt32 theLineNumber=0;
nsCParserNode theNewNode(&theToken,theLineNumber);
result=aSink->AddLeaf(theNewNode);
return result;
}
@ -1269,11 +1281,13 @@ public:
static void Initialize(CElement& anElement,eHTMLTags aTag){
CTextContainer::Initialize(anElement,aTag);
anElement.mProperties.mIsSinkContainer=PR_FALSE;
}
CScriptElement() : CTextContainer(eHTMLTag_script) {
mGroup.mBits.mHeadMisc=1;
mGroup.mBits.mBlock=1;
mProperties.mIsSinkContainer=PR_FALSE;
}
/**********************************************************
@ -1791,19 +1805,22 @@ public:
CBodyElement(eHTMLTags aTag=eHTMLTag_body) : CElement(aTag) {
CGroupMembers theGroups=CBlockElement::GetBlockGroupMembers();
#ifdef TRANSITIONAL
theGroups.mBits.mComment=1;
theGroups.mBits.mSpecial=1;
theGroups.mBits.mPhrase=1;
theGroups.mBits.mFontStyle=1;
theGroups.mBits.mFormControl=1;
theGroups.mBits.mLeaf=1;
#endif
CElement::Initialize(*this,aTag,CBodyElement::GetGroup(),theGroups);
mIncludeKids=gBodyKids;
mExcludeKids=gBodyExcludeKids;
}
virtual PRBool CanContain(CElement* anElement,nsDTDContext* aContext) {
PRBool result=CElement::CanContain(anElement,aContext);
if((!result) && (aContext->mTransitional)) {
//let's try so additions that are specific to the body tag,
//and only work in transitional mode...
CGroupMembers& theFlowGroup=CFlowElement::GetContainedGroups();
result=ContainsGroup(theFlowGroup,anElement->mGroup);
}
return result;
}
//this gets called after each tag is opened in the given context
virtual nsresult OpenContainer(nsIParserNode *aNode,eHTMLTags aTag,nsDTDContext *aContext,nsIHTMLContentSink *aSink) {
@ -1823,26 +1840,15 @@ public:
eHTMLTags aTag,
nsDTDContext* aContext,
nsIHTMLContentSink* aSink) {
nsresult result=NS_OK;
switch(aTag) {
case eHTMLTag_script:
result=OpenContext(aNode,aTag,aContext,aSink);
break;
default:
//for now, let's drop other elements onto the floor.
result=CElement::HandleStartToken(aNode,aTag,aContext,aSink);
if(NS_SUCCEEDED(result)) {
nsCParserNode *theNode=(nsCParserNode*)aNode;
CStartToken *theToken=(CStartToken*)theNode->mToken;
if(theToken->IsEmpty() && (aTag==aContext->Last())){
result=CElement::HandleEndToken(aNode,aTag,aContext,aSink);
}
}
break;
}//switch
//for now, let's drop other elements onto the floor.
nsresult result=CElement::HandleStartToken(aNode,aTag,aContext,aSink);
if(NS_SUCCEEDED(result)) {
nsCParserNode *theNode=(nsCParserNode*)aNode;
CStartToken *theToken=(CStartToken*)theNode->mToken;
if(theToken->IsEmpty() && (aTag==aContext->Last())){
result=CElement::HandleEndToken(aNode,aTag,aContext,aSink);
}
}
return result;
}
@ -1902,15 +1908,31 @@ public:
{
memset(mElements,0,sizeof(mElements));
InitializeElements();
//DebugDumpBlockElements();
//DebugDumpInlineElements();
//DebugDumpContainment("all elements");
}
//call this to get a ptr to an element prototype...
CElement* GetElement(eHTMLTags aTagID) {
if(aTagID>eHTMLTag_unknown) {
if(aTagID<eHTMLTag_userdefined) {
return mElements[aTagID];
}
}
return 0;
}
void InitializeElements();
void DebugDumpGroups(CElement* aParent);
void DebugDumpContainment(const char* aTitle);
void DebugDumpContainment(CElement* aParent);
void DebugDumpInlineElements(const char* aTitle);
void DebugDumpBlockElements(const char* aTitle);
CElement* mElements[150]; //add one here for special handling of a given element
CElement mDfltElements[150];
@ -1953,6 +1975,7 @@ static eHTMLTags kBlockQuoteKids[]={eHTMLTag_script,eHTMLTag_unknown};
static eHTMLTags kFramesetKids[]={eHTMLTag_noframes,eHTMLTag_unknown};
static eHTMLTags kObjectKids[]={eHTMLTag_param,eHTMLTag_unknown};
static eHTMLTags kTBodyKids[]={eHTMLTag_tr,eHTMLTag_unknown};
static eHTMLTags kUnknownKids[]={eHTMLTag_html,eHTMLTag_unknown};
inline CElement* CElement::GetElement(eHTMLTags aTag) {
@ -2004,6 +2027,8 @@ void CElementTable::InitializeElements() {
CElement::Initialize( mDfltElements[eHTMLTag_caption], eHTMLTag_caption, CTableElement::GetGroup(), CSpecialElement::GetContainedGroups());
mDfltElements[eHTMLTag_tr].mContainsGroups.mBits.mSelf=0;
CElement::Initialize( mDfltElements[eHTMLTag_center], eHTMLTag_center, CBlockElement::GetGroup(), CFlowElement::GetContainedGroups());
CPhraseElement::Initialize( mDfltElements[eHTMLTag_cite], eHTMLTag_cite);
@ -2169,17 +2194,22 @@ void CElementTable::InitializeElements() {
mDfltElements[eHTMLTag_tbody].mIncludeKids=kTBodyKids;
CElement::Initialize( mDfltElements[eHTMLTag_td], eHTMLTag_td, CElement::GetEmptyGroup(), CFlowElement::GetContainedGroups());
mDfltElements[eHTMLTag_td].mContainsGroups.mBits.mSelf=0;
CElement::Initialize( mDfltElements[eHTMLTag_textarea], eHTMLTag_textarea);
CElement::Initialize( mDfltElements[eHTMLTag_tfoot], eHTMLTag_tfoot, CTableElement::GetGroup(), CLeafElement::GetContainedGroups());
mDfltElements[eHTMLTag_tfoot].mIncludeKids=kTBodyKids;
mDfltElements[eHTMLTag_tfoot].mContainsGroups.mBits.mSelf=0;
CTableRowElement::Initialize( mDfltElements[eHTMLTag_th], eHTMLTag_th);
mDfltElements[eHTMLTag_th].mContainsGroups.mBits.mSelf=0;
CElement::Initialize( mDfltElements[eHTMLTag_thead], eHTMLTag_thead, CTableElement::GetGroup(), CLeafElement::GetContainedGroups());
mDfltElements[eHTMLTag_thead].mIncludeKids=kTBodyKids;
CTableRowElement::Initialize( mDfltElements[eHTMLTag_tr], eHTMLTag_tr);
mDfltElements[eHTMLTag_tr].mContainsGroups.mBits.mSelf=0;
CElement::Initialize( mDfltElements[eHTMLTag_title], eHTMLTag_title);
@ -2199,6 +2229,7 @@ void CElementTable::InitializeElements() {
CLeafElement::Initialize( mDfltElements[eHTMLTag_newline], eHTMLTag_newline);
CLeafElement::Initialize( mDfltElements[eHTMLTag_whitespace],eHTMLTag_whitespace);
CLeafElement::Initialize( mDfltElements[eHTMLTag_unknown], eHTMLTag_unknown);
mDfltElements[eHTMLTag_unknown].mIncludeKids=kUnknownKids;
/************************************************************
@ -2325,6 +2356,42 @@ void CElementTable::DebugDumpContainment(CElement* anElement){
}
}
void CElementTable::DebugDumpInlineElements(const char* aTitle) {
PRInt32 theTagID=eHTMLTag_unknown;
PRBool result=PR_FALSE;
printf("Inline Elements -- %s: \n",aTitle);
while(theTagID<=eHTMLTag_userdefined) {
CElement *theTag=GetElement((eHTMLTags)theTagID);
if(theTag) {
result=theTag->IsInlineElement(eHTMLTag_unknown);
if(result) {
const char* theName=nsHTMLTags::GetCStringValue(theTag->mTag);
printf(" %s\n",theName);
}
}
theTagID++;
}
}
void CElementTable::DebugDumpBlockElements(const char* aTitle) {
PRInt32 theTagID=eHTMLTag_unknown;
PRBool result=PR_FALSE;
printf("Block Elements -- %s: \n");
while(theTagID<=eHTMLTag_userdefined) {
CElement *theTag=GetElement((eHTMLTags)theTagID);
if(theTag) {
result=theTag->IsBlockElement(eHTMLTag_unknown);
if(result) {
const char* theName=nsHTMLTags::GetCStringValue(theTag->mTag);
printf(" %s\n",theName);
}
}
theTagID++;
}
}
void CElementTable::DebugDumpContainment(const char* aTitle){
#if 0
DebugDumpContainment(mElements[eHTMLTag_head]);
@ -2423,6 +2490,37 @@ PRBool CElement::CanContain(CElement* anElement,nsDTDContext* aContext) {
}
else result=mContainsGroups.mBits.mSelf;
}
/***************************************************
This is a (cheesy) exception table, that allows
us to override containment for transitional
documents. A better implementation would be to
create unique classes for each of the tags in
this table, and to override CanContain() there.
***************************************************/
if((!result) && (aContext->mTransitional)) {
switch(anElement->mTag) {
case eHTMLTag_address:
if(eHTMLTag_p==anElement->mTag)
result=PR_TRUE;
break;
case eHTMLTag_blockquote:
case eHTMLTag_form:
case eHTMLTag_iframe:
result=ContainsGroup(CFlowElement::GetContainedGroups(),anElement->mGroup);
break;
case eHTMLTag_button:
if((eHTMLTag_iframe==anElement->mTag) || (eHTMLTag_isindex==anElement->mTag))
result=PR_TRUE;
break;
default:
break;
}
}
}
return result;
}
@ -2452,12 +2550,18 @@ nsresult CElement::HandleStartToken( nsIParserNode* aNode,
}
else
#endif
{
if(theElement) {
if(CanContain(theElement,aContext)) {
if(theElement->IsContainer()) {
result=theElement->OpenContainerInContext(aNode,aTag,aContext,aSink);
if(theElement->IsSinkContainer()) {
result=theElement->OpenContainerInContext(aNode,aTag,aContext,aSink);
}
else {
result=theElement->OpenContext(aNode,aTag,aContext,aSink);
}
}
else {
result=aSink->AddLeaf(*aNode);
@ -2467,7 +2571,7 @@ nsresult CElement::HandleStartToken( nsIParserNode* aNode,
//Ok, so we have a start token that is misplaced. Before handing this off
//to a default container (parent), let's check the autoclose condition.
if(ListContainsTag(mAutoClose,theElement->mTag)) {
if(ListContainsTag(mAutoClose,theElement->mTag) || (aTag==mTag)) {
if(HasOptionalEndTag(theElement)) {
//aha! We have a case where this tag is autoclosed by anElement.
//Let's close this container, then try to open theElement.
@ -2498,7 +2602,7 @@ nsresult CElement::HandleStartToken( nsIParserNode* aNode,
if(mTag!=aTag) {
PRInt32 theLastPos=aContext->LastOf(aTag); //see if it's already open...
if(-1<theLastPos) {
if(-1!=theLastPos) {
PRInt32 theCount=aContext->GetCount();
result=HandleEndToken(aNode,aTag,aContext,aSink);
theElementCanOpen=PRBool(aContext->GetCount()<theCount);
@ -2530,7 +2634,14 @@ nsresult CElement::HandleEndToken(nsIParserNode* aNode,eHTMLTags aTag,nsDTDConte
nsresult result=NS_OK;
if(aContext->Last()==aTag) {
return CloseContainerInContext(aNode,aTag,aContext,aSink);
CElement* theElement=gElementTable->mElements[aTag];
if(theElement) {
if(theElement->IsSinkContainer()) {
CloseContainerInContext(aNode,aTag,aContext,aSink);
}
else CloseContext(aNode,aTag,aContext,aSink);
return result;
}
}
PRInt32 theCount=aContext->GetCount();
@ -2548,39 +2659,6 @@ nsresult CElement::HandleEndToken(nsIParserNode* aNode,eHTMLTags aTag,nsDTDConte
}
return result;
}
/* This junk is intentionally commented out...
PRInt32 theLastOptionalTag=-1;
PRBool done=PR_FALSE;
theIndex=0;
if(!done) {
for(theIndex=theCount-1;theIndex>=0;theIndex--) {
eHTMLTags theTag=aContext->TagAt(theIndex);
CElement* theElement=gElementTable->mElements[theTag];
if(HasOptionalEndTag(theElement)){
theLastOptionalTag=theIndex;
}
else break;
}
if(-1<theLastOptionalTag) {
PRInt32 theLastInstance=aContext->LastOf(aTag);
if(-1<theLastInstance) {
if(theLastOptionalTag-1==theLastInstance) {
for(theIndex=theCount-1;theIndex>=theLastInstance;theIndex--){
CloseContainerInContext(aNode,aTag,aContext,aSink);
}
}
}
//there's nothing to do...
}
//there's nothing to do...
}
*/
return result;
}
@ -2610,5 +2688,21 @@ inline CElement* CElement::GetDefaultContainerFor(CElement* anElement) {
}
//this tells us whether this tag is a block tag within the given parent
//NOTE: aParentID is currently ignored, but shouldn't be.
PRBool CElement::IsBlockElement(eHTMLTags aParentID) {
CGroupMembers& theBlockGroup=CBlockElement::GetBlockGroupMembers();
PRBool result=ContainsGroup(theBlockGroup,mGroup);
return result;
}
//this tells us whether this tag is an inline tag within the given parent
//NOTE: aParentID is currently ignored, but shouldn't be.
PRBool CElement::IsInlineElement(eHTMLTags aParentID) {
CGroupMembers& theInlineGroup=CInlineElement::GetContainedGroups();
PRBool result=ContainsGroup(theInlineGroup,mGroup);
return result;
}
#endif

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

@ -63,6 +63,7 @@ CParserContext::CParserContext(nsScanner* aScanner,
mCopyUnused=aCopyUnused;
mParserCommand=aCommand;
mChannel=0;
mValidator=0;
}
/**

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

@ -76,6 +76,7 @@ public:
nsScanner* mScanner;
nsIDTD* mDTD;
nsIDTD* mValidator;
char* mTransferBuffer;
nsIStreamObserver* mListener;

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

@ -974,11 +974,6 @@ nsresult CRTFContent::Consume(PRUnichar aChar,nsScanner& aScanner,PRInt32 aMode)
***************************************************************/
/************************************************************************
And now for the main class -- nsRTFTokenizer...
************************************************************************/
/**
* This method gets called as part of our COM-like interfaces.
* Its purpose is to create an interface to parser object
@ -1013,6 +1008,7 @@ nsresult nsRTFTokenizer::QueryInterface(const nsIID& aIID, void** aInstancePtr)
}
nsRTFTokenizer::nsRTFTokenizer() : mTokenDeque(0) {
NS_INIT_REFCNT();
}
/**

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

@ -327,6 +327,9 @@ class CRtfDTD : public nsIDTD {
NS_IMETHOD ConvertEntityToUnicode(const nsString& aEntity, PRInt32* aUnicode) const;
virtual PRBool IsBlockElement(PRInt32 aTagID,PRInt32 aParentID) const {return PR_FALSE;}
virtual PRBool IsInlineElement(PRInt32 aTagID,PRInt32 aParentID) const {return PR_FALSE;}
protected:

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

@ -16,13 +16,13 @@
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
*
* Contributor(s):
* Pierre Phaneuf <pp@ludusdesign.com>
*/
#include "nsDTDUtils.h"
*/
#include "nsDTDUtils.h"
#include "CNavDTD.h"
#include "nsIParserNode.h"
#include "nsParserNode.h"
@ -371,8 +371,9 @@ nsDTDContext::nsDTDContext() : mStack(), mEntities(0){
mTableStates=0;
mHadBody=PR_FALSE;
mHadFrameset=PR_TRUE;
mHadDocTypeDecl=PR_FALSE;
mTransitional=PR_FALSE;
ResetCounters();
mHadDocTypeDecl=PR_FALSE;
#ifdef NS_DEBUG
memset(mXTags,0,sizeof(mXTags));
@ -471,7 +472,7 @@ CNamedEntity* nsDTDContext::RegisterEntity(const nsString& aName,const nsString
class CAbacus {
public:
enum eNumFormat {eUnknown,eAlpha,eDecimal,eRoman,eSpoken,eHex,eBinary,eFootnote,eUserSeries};
enum eNumFormat {eUnknown,eAlpha,eDecimal,eRoman,eSpelled,eHex,eBinary,eFootnote,eUserSeries};
CAbacus(PRInt32 aDefaultValue=0,eNumFormat aFormat=eDecimal) {
mUserSeries=0;
@ -504,7 +505,7 @@ public:
case eHex: HexString(aValue,aString); break;
case eBinary: BinaryString(aValue,aString); break;
case eAlpha: AlphaString(aValue,aString); break;
case eSpoken: SpokenString(aValue,aString); break;
case eSpelled: SpelledString(aValue,aString); break;
case eRoman: RomanString(aValue,aString); break;
case eFootnote: FootnoteString(aValue,aString); break;
case eUserSeries: SeriesString(aValue,aString,aCharSet,anOffset,aBase);
@ -536,7 +537,7 @@ public:
}
}
static void SpokenString(PRInt32 aValue,nsString& aString) {
static void SpelledString(PRInt32 aValue,nsString& aString) {
static char ones[][12]= {"zero","one ","two ","three ","four ","five ","six ","seven ","eight ","nine ","ten "};
static char teens[][12]= {"ten ","eleven ","twelve ","thirteen ","fourteen ","fifteen ","sixteen ","seventeen ","eighteen ","nineteen "};
@ -696,7 +697,7 @@ void nsDTDContext::ResetCounters(void) {
name="group"
value="nnn"
noincr="?"
format="alpha|dec|footnote|hex|roman|spoken"
format="alpha|dec|footnote|hex|roman|spelled|talk"
returns the newly incremented value for the (determined) group.
**********************************************************/
@ -737,7 +738,7 @@ PRInt32 nsDTDContext::IncrementCounter(eHTMLTags aTag,nsCParserNode& aNode,nsStr
case 'D': case 'd': theNumFormat=CAbacus::eDecimal; break;
case 'H': case 'h': theNumFormat=CAbacus::eHex; break;
case 'R': case 'r': theNumFormat=CAbacus::eRoman; break;
case 'S': case 's': theNumFormat=CAbacus::eSpoken; break;
case 'S': case 's': theNumFormat=CAbacus::eSpelled; break;
default:
theNumFormat=CAbacus::eDecimal;
break;

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

@ -253,6 +253,7 @@ public:
PRInt32 mContextTopIndex;
PRBool mHadBody;
PRBool mHadFrameset;
PRBool mTransitional;
PRBool mHadDocTypeDecl;
static CNodeRecycler* mNodeRecycler;
@ -383,20 +384,54 @@ inline PRBool FindTagInSet(PRInt32 aTag,const eHTMLTags *aTagSet,PRInt32 aCount)
/**
* Called from various DTD's to determine the type of data in the buffer...
* @update gess11/20/98
* @param
* @return
* @update gess 06Jun2000
* @param aBuffer: contains a string with first block of html from source document
* @param aHasXMLFragment: tells us whether we detect XML in the buffer (based on PI)
* @return TRUE if we find HTML
*/
inline PRBool BufferContainsHTML(nsString& aBuffer,PRBool& aHasXMLFragment){
PRBool result=PR_FALSE;
nsString temp;
aBuffer.Left(temp,200);
temp.ToLowerCase();
aHasXMLFragment=PRBool(-1<temp.Find("<?xml"));
if((-1<temp.Find("<html ") || (-1<temp.Find("!doctype html public")))) {
result=PR_TRUE;
aHasXMLFragment=PRBool(-1!=aBuffer.Find("<?XML",PR_TRUE,100));
PRInt32 theDocTypePos=aBuffer.Find("DOCTYPE",PR_TRUE,0,200);
if(-1!=theDocTypePos) {
PRInt32 theHTMLPos=aBuffer.Find("HTML",PR_TRUE,theDocTypePos+8,200);
if(-1==theHTMLPos) {
theHTMLPos=aBuffer.Find("ISO/IEC 15445",PR_TRUE,theDocTypePos+8,200);
if(-1==theHTMLPos) {
theHTMLPos=aBuffer.Find("HYPERTEXT MARKUP",PR_TRUE,theDocTypePos+8,200);
}
}
result=PRBool(-1!=theHTMLPos);
}
else {
//worst case scenario: let's look for a few HTML tags...
PRInt32 theCount=0;
PRInt32 theLTPos=0;
PRInt32 theStartPos=0;
nsAutoString theTagName;
PRInt32 theTagCount=0;
for(theCount=0;theCount<5;theCount++) {
theLTPos=aBuffer.Find("<",PR_TRUE,theStartPos,200);
if(-1!=theLTPos) {
//we found what may be a start tag...
PRInt32 theTagEnd=aBuffer.FindCharInSet(" >\"",theLTPos);
aBuffer.Mid(theTagName,theLTPos+1,theTagEnd-theLTPos-1);
nsHTMLTag theTag=nsHTMLTags::LookupTag(theTagName);
if(eHTMLTag_userdefined!=theTag) {
theTagCount++;
}
//now let's see if it's a tag or not...
theStartPos=theTagEnd+1;
}
else break;
}
result=PRBool(2<=theTagCount); //claim HTML if we find at least 2 real html tags...
}
return result;
}

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

@ -229,6 +229,9 @@ class nsExpatDTD : public nsIDTD {
NS_IMETHOD ConvertEntityToUnicode(const nsString& aEntity, PRInt32* aUnicode) const;
virtual PRBool IsBlockElement(PRInt32 aTagID,PRInt32 aParentID) const {return PR_FALSE;}
virtual PRBool IsInlineElement(PRInt32 aTagID,PRInt32 aParentID) const {return PR_FALSE;}
/**
* Retrieve a ptr to the global token recycler...
* @update gess8/4/98

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

@ -124,7 +124,7 @@ NS_IMPL_RELEASE(nsHTMLTokenizer)
nsITokenizer(), mTokenDeque(0), mParseMode(aParseMode)
{
NS_INIT_REFCNT();
mDoXMLEmptyTags=(eDTDMode_strict==aParseMode);
mDoXMLEmptyTags=((eDTDMode_strict==aParseMode) || (eDTDMode_transitional==aParseMode));
mDocType=aDocType;
mRecordTrailingContent=PR_FALSE;
mParserCommand=aCommand;

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

@ -615,7 +615,7 @@ nsresult CTextToken::ConsumeUntil(PRUnichar aChar,PRBool aIgnoreComments,nsScann
}
//theTermStrPos=theBuffer.Find(aTerminalString,PR_TRUE,theCurrOffset);
if(theTermStrPos>kNotFound) {
if(aMode!=eDTDMode_strict && !theLastIteration) {
if((aMode!=eDTDMode_strict) && (aMode!=eDTDMode_transitional) && !theLastIteration) {
if(!aIgnoreComments) {
theCurrOffset=theBuffer.Find("<!--",PR_TRUE,theCurrOffset,5);
if(theStartCommentPos==kNotFound && theCurrOffset>kNotFound) {
@ -944,6 +944,7 @@ nsresult ConsumeComment(PRUnichar aChar, nsScanner& aScanner,nsString& aString)
if(NS_OK==result) {
//Read up to the closing '>', unless you already did! (such as <!>).
if(kGreaterThan!=aChar) {
aString.AppendWithConversion("<!- ");
result=aScanner.ReadUntil(aString,kGreaterThan,PR_TRUE);
}
}
@ -960,19 +961,18 @@ nsresult ConsumeComment(PRUnichar aChar, nsScanner& aScanner,nsString& aString)
* @return error result
*/
nsresult CCommentToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aMode) {
nsresult result=(aMode==eDTDMode_strict) ? ConsumeStrictComment(aChar,aScanner,mTextValue) : ConsumeComment(aChar,aScanner,mTextValue);
nsresult result=PR_TRUE;
switch(aMode) {
case eDTDMode_strict:
ConsumeStrictComment(aChar,aScanner,mTextValue);
break;
case eDTDMode_transitional:
default:
ConsumeComment(aChar,aScanner,mTextValue);
break;
} //switch
#if 0
if(NS_OK==result) {
//ok then, all is well so strip off the delimiters...
nsAutoString theLeft("");
mTextValue.Left(theLeft,2);
if(theLeft=="<!")
mTextValue.Cut(0,2);
if('>'==mTextValue.Last())
mTextValue.Truncate(mTextValue.Length()-1);
}
#endif
return result;
}
@ -1220,29 +1220,28 @@ void CAttributeToken::DebugDumpToken(nsOutputStream& out) {
/*
*
*
* @update gess 3/25/98
* @update rickg 6June2000
* @param anOutputString will recieve the result
* @return nada
*/
void CAttributeToken::GetSource(nsString& anOutputString){
anOutputString=mTextKey;
anOutputString.AppendWithConversion("=");
anOutputString+=mTextValue;
anOutputString.AppendWithConversion(";");
anOutputString.Truncate();
AppendSource(anOutputString);
}
/*
*
*
* @update harishd 03/23/00
* @update rickg 6June2000
* @param result appended to the output string.
* @return nada
*/
void CAttributeToken::AppendSource(nsString& anOutputString){
anOutputString+=mTextKey;
anOutputString.AppendWithConversion("=");
if(mTextValue.Length() || mHasEqualWithoutValue)
anOutputString.AppendWithConversion("=");
anOutputString+=mTextValue;
anOutputString.AppendWithConversion(";");
// anOutputString.AppendWithConversion(";");
}
/*

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

@ -52,8 +52,8 @@ enum eAutoDetectResult {
enum nsDTDMode {
eDTDMode_unknown=0,
eDTDMode_quirks, //pre 5.0 versions
eDTDMode_noquirks, //raptor versions...)
eDTDMode_quirks, //pre 4.0 versions
eDTDMode_transitional,
eDTDMode_strict,
eDTDMode_autodetect
};
@ -214,6 +214,10 @@ class nsIDTD : public nsISupports {
NS_IMETHOD IntTagToStringTag(PRInt32 aIntTag, nsString& aTag) const =0;
NS_IMETHOD ConvertEntityToUnicode(const nsString& aEntity, PRInt32* aUnicode) const =0;
virtual PRBool IsBlockElement(PRInt32 aTagID,PRInt32 aParentID) const=0;
virtual PRBool IsInlineElement(PRInt32 aTagID,PRInt32 aParentID) const=0;
};

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

@ -149,6 +149,12 @@ class nsIParserNode : public nsISupports {
virtual PRBool GetGenericState(void) const =0;
virtual void SetGenericState(PRBool aState) =0;
/** Retrieve a string containing the tag and its attributes in "source" form
* @update rickg 06June2000
* @return void
*/
virtual void GetSource(nsString& aString)=0;
};
#endif

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

@ -23,6 +23,7 @@
#define DEBUG_XMLENCODING
#define XMLENCODING_PEEKBYTES 64
//#define TEST_DOCTYPES
#include "nsParser.h"
#include "nsIContentSink.h"
@ -103,11 +104,13 @@ public:
nsIDTD* theDTD;
#if 1
NS_NewNavHTMLDTD(&theDTD); //do this as a default HTML DTD...
mDTDDeque.Push(theDTD);
#endif
NS_NewOtherHTMLDTD(&theDTD); //do this as the default DTD for strict documents...
mDTDDeque.Push(theDTD);
NS_NewOtherHTMLDTD(&mOtherDTD); //do this as the default DTD for strict documents...
mDTDDeque.Push(mOtherDTD);
mHasViewSourceDTD=PR_FALSE;
mHasRTFDTD=mHasXMLDTD=PR_FALSE;
@ -135,6 +138,7 @@ public:
PRBool mHasViewSourceDTD; //this allows us to defer construction of this object.
PRBool mHasXMLDTD; //also defer XML dtd construction
PRBool mHasRTFDTD; //also defer RTF dtd construction
nsIDTD *mOtherDTD; //it's ok to leak this; the deque contains a copy too.
};
static CSharedParserObjects* gSharedParserObjects=0;
@ -515,7 +519,7 @@ void DetermineParseMode(nsString& aBuffer,nsDTDMode& aParseMode,eParserDocType&
aParseMode = eDTDMode_unknown;
PRInt32 theIndex=aBuffer.Find("DOCTYPE",PR_TRUE,0,10);
PRInt32 theIndex=aBuffer.Find("DOCTYPE",PR_TRUE,0,100);
if(kNotFound<theIndex) {
//good, we found "DOCTYPE" -- now go find it's end delimiter '>'
@ -527,102 +531,99 @@ void DetermineParseMode(nsString& aBuffer,nsDTDMode& aParseMode,eParserDocType&
//note that if we don't find '>', then we just scan the first 512 bytes.
if(0<=theSubIndex) {
if(kNotFound!=theSubIndex) {
//if you're here then we found the //DTD identifier type...
PRInt32 theStartPos=theSubIndex+5;
PRInt32 theCount=theEnd-theStartPos;
if(kNotFound<theSubIndex) {
theSubIndex=aBuffer.Find("XHTML",PR_TRUE,theStartPos,theCount);
if(0<=theSubIndex) {
aDocType=eXHTMLText;
aParseMode=eDTDMode_strict;
return;
}
else {
theSubIndex=aBuffer.Find("ISO/IEC 15445:",PR_TRUE,theIndex+8,theEnd-(theIndex+8));
if(0<=theSubIndex) {
aDocType=eHTML4Text;
aParseMode=eDTDMode_strict;
theMajorVersion=4;
theSubIndex+=15;
return;
}
else {
theSubIndex=aBuffer.Find("HTML",PR_TRUE,theStartPos,theCount);
if(0<=theSubIndex) {
aDocType=eHTML4Text;
aParseMode=eDTDMode_strict;
theMajorVersion=3;
}
else {
theSubIndex=aBuffer.Find("HYPERTEXT MARKUP",PR_TRUE,theStartPos,theCount);
if(0<=theSubIndex) {
aDocType=eHTML3Text;
aParseMode=eDTDMode_quirks;
theSubIndex+=20;
}
}
}
}
}
theStartPos=theSubIndex+5;
theCount=theEnd-theStartPos;
nsAutoString theNum;
//get the next substring from the buffer, which should be a number.
//now see what the version number is...
theStartPos=aBuffer.FindCharInSet("123456789",theStartPos);
if(0<=theStartPos) {
PRInt32 theTerminal=aBuffer.FindCharInSet(" />",theStartPos+1);
if(theTerminal) {
aBuffer.Mid(theNum,theStartPos,theTerminal-theStartPos);
}
else aBuffer.Mid(theNum,theStartPos,3);
theMajorVersion=theNum.ToInteger(&theErr);
}
//now see what the
theStartPos+=theNum.Length();
theCount=theEnd-theStartPos;
if((aBuffer.Find("TRANSITIONAL",PR_TRUE,theStartPos,theCount)>kNotFound)||
(aBuffer.Find("LOOSE",PR_TRUE,theStartPos,theCount)>kNotFound) ||
(aBuffer.Find("FRAMESET",PR_TRUE,theStartPos,theCount)>kNotFound) ||
(aBuffer.Find("LATIN1", PR_TRUE,theStartPos,theCount) >kNotFound) ||
(aBuffer.Find("SYMBOLS",PR_TRUE,theStartPos,theCount) >kNotFound) ||
(aBuffer.Find("SPECIAL",PR_TRUE,theStartPos,theCount) >kNotFound)) {
aParseMode=eDTDMode_quirks;
}
//one last thing: look for a URI that specifies the strict.dtd
theStartPos+=6;
theCount=theEnd-theStartPos;
theSubIndex=aBuffer.Find("STRICT.DTD",PR_TRUE,theStartPos,theCount);
if(0<theSubIndex) {
//Since we found it, regardless of what's in the descr-text, kick into strict mode.
if(kNotFound!=aBuffer.Find("ISO/IEC 15445:1999",PR_TRUE,theIndex,theEnd-theIndex)) {
//per spec, this DTD is always strict...
aParseMode=eDTDMode_strict;
aDocType=eHTML4Text;
theMajorVersion=4;
return;
}
if (kNotFound!=aBuffer.Find("XHTML",PR_TRUE,theStartPos,theCount)) {
aDocType=eXHTMLText;
aParseMode=eDTDMode_strict;
return;
}
if (0==theErr){
switch(theMajorVersion) {
case 0: case 1: case 2: case 3:
if(aDocType!=eXHTMLText){
aParseMode=eDTDMode_quirks; //be as backward compatible as possible
aDocType=eHTML3Text;
if(kNotFound<theSubIndex) {
PRInt32 theHTMLTagPos=aBuffer.Find("HTML",PR_TRUE,theStartPos,theCount);
if(kNotFound==theHTMLTagPos) {
theHTMLTagPos=aBuffer.Find("HYPERTEXT MARKUP",PR_TRUE,theStartPos,theCount);
}
if(kNotFound!=theHTMLTagPos) {
//get the next substring from the buffer, which should be a number.
//now see what the version number is...
PRInt32 theVersionPos=aBuffer.FindCharInSet("1234567890",theHTMLTagPos);
if((0<=theVersionPos) && (theVersionPos<theEnd)) {
nsAutoString theNum;
PRInt32 theTerminal=aBuffer.FindCharInSet(" />",theVersionPos+1);
if(theTerminal) {
aBuffer.Mid(theNum,theVersionPos,theTerminal-theVersionPos);
}
break;
default:
//XXX hack -- someday, the next line of code will be criticized
//for it's lack of vision...
if(theMajorVersion>20) {
else aBuffer.Mid(theNum,theVersionPos,3);
theMajorVersion=theNum.ToInteger(&theErr);
if(theMajorVersion>10) {
theMajorVersion=3; //assume that's an error for now.
}
}
//now let's see if we have descriptive text (providing strictness id)...
theStartPos=theVersionPos+2;
theCount=theEnd-theStartPos;
if((aBuffer.Find("TRANSITIONAL",PR_TRUE,theVersionPos+2,theCount)>kNotFound)||
(aBuffer.Find("LOOSE",PR_TRUE,theStartPos,theCount)>kNotFound) ||
(aBuffer.Find("FRAMESET",PR_TRUE,theStartPos,theCount)>kNotFound) ||
(aBuffer.Find("LATIN1", PR_TRUE,theStartPos,theCount) >kNotFound) ||
(aBuffer.Find("SYMBOLS",PR_TRUE,theStartPos,theCount) >kNotFound) ||
(aBuffer.Find("SPECIAL",PR_TRUE,theStartPos,theCount) >kNotFound)) {
//for now TRANSITIONAL 4.0 documents are handled in the compatibility DTD.
//Soon, they'll be handled in the strictDTD in transitional mode.
aParseMode=eDTDMode_transitional;
}
else {
//since we didn't find descriptive text, let's check out the URI...
//to see whether that specifies the strict.dtd...
theStartPos+=6;
theCount=theEnd-theStartPos;
theSubIndex=aBuffer.Find("STRICT.DTD",PR_TRUE,theStartPos,theCount);
if(0<theSubIndex) {
//Since we found it, regardless of what's in the descr-text, kick into strict mode.
aParseMode=eDTDMode_strict;
aDocType=eHTML4Text;
}
break;
} //switch
}
switch(theMajorVersion) {
case 1:
case 2:
case 3:
aParseMode=eDTDMode_quirks;
aDocType=eHTML4Text;
break;
default:
if(eDTDMode_unknown==aParseMode) {
aParseMode=eDTDMode_strict;
}
break;
}
}
}
} //if
@ -651,6 +652,10 @@ void DetermineParseMode(nsString& aBuffer,nsDTDMode& aParseMode,eParserDocType&
aDocType=ePlainText;
aParseMode=eDTDMode_quirks;
}
else if(aMimeType.EqualsWithConversion(kRTFTextContentType)) {
aDocType=ePlainText;
aParseMode=eDTDMode_quirks;
}
if(theModeStr) {
if(0==nsCRT::strcasecmp(theModeStr,"strict"))
@ -680,7 +685,7 @@ PRBool FindSuitableDTD( CParserContext& aParserContext,nsString& aBuffer) {
return PR_TRUE;
CSharedParserObjects& gSharedObjects=GetSharedObjects();
aParserContext.mValidator=gSharedObjects.mOtherDTD;
aParserContext.mAutoDetectStatus=eUnknownDetect;
PRInt32 theDTDIndex=0;
@ -800,7 +805,7 @@ nsresult nsParser::CreateCompatibleDTD(nsIDTD** aDTD,
switch(theDocType) {
case eHTML4Text:
if(theDTDMode==eDTDMode_strict) {
if((theDTDMode==eDTDMode_strict) || (theDTDMode==eDTDMode_transitional)) {
theDTDClassID=&kCOtherDTDCID;
break;
}
@ -821,7 +826,7 @@ nsresult nsParser::CreateCompatibleDTD(nsIDTD** aDTD,
NS_ASSERTION(aDTDMode!=eDTDMode_unknown,"DTD selection might require a parsemode");
if(aMimeType->EqualsWithConversion(kHTMLTextContentType)) {
if(aDTDMode==eDTDMode_strict) {
if((aDTDMode==eDTDMode_strict) || (aDTDMode==eDTDMode_transitional)) {
theDTDClassID=&kCOtherDTDCID;
}
else {
@ -856,37 +861,60 @@ nsresult nsParser::CreateCompatibleDTD(nsIDTD** aDTD,
}
#ifdef TEST_DOCTYPES
static const char* doctypes[] = {
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">",
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">",
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Frameset//EN\" \"http://www.w3.org/TR/html4/frameset.dtd\">",
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\">",
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" >",
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Frameset//EN\">",
//here are a few HTML doctypes we'll treat as strict...
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\">",
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">",
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">",
"<!DOCTYPE HTML PUBLIC PublicID SystemID>",
"<!DOCTYPE HTML SYSTEM SystemID>",
"<!DOCTYPE \"-//W3C//DTD HTML 4.0//EN\">",
"<!DOCTYPE \"-//W3C//DTD HTML 4.01//EN\">",
"<!DOCTYPE \"-//W3C//DTD HTML 4.0 STRICT//EN\">",
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\">",
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">",
"<!DOCTYPE \"ISO/IEC 15445:1999//DTD HyperText Markup Language//EN\">",
"<!DOCTYPE \"ISO/IEC 15445:1999//DTD HTML//EN\">",
"<!DOCTYPE \"-//SoftQuad Software//DTD HoTMetaL PRO 6.::19990601::extensions to HTML 4.//EN\">",
"<!DOCTYPE \"-//W3C//DTD HTML 5.0//EN\">",
"<!DOCTYPE \"-//W3C//DTD HTML 6.01 Transitional//EN\">",
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 6.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">",
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">",
"<!DOCTYPE \"-//W3C//DTD HTML 4.0 STRICT//EN\">",
"<!DOCTYPE \"-//W3C//DTD HTML 4.01//EN\">",
"<!DOCTYPE \"-//W3C//DTD HTML 4.0//EN\">",
"<!DOCTYPE \"ISO/IEC 15445:1999//DTD HyperText Markup Language//EN\">",
"<!DOCTYPE \"ISO/IEC 15445:1999//DTD HTML//EN\">",
"<!DOCTYPE \"-//SoftQuad Software//DTD HoTMetaL PRO 6.::19990601::extensions to HTML 4.//EN\">",
//here are the XHTML doctypes we'll treat as strict...
"<!DOCTYPE \"-//W3C//DTD XHTML 1.0 Strict//EN\">",
"<!DOCTYPE \"-//W3C//DTD XHTML 1.0 Transitional//EN\">",
"<!DOCTYPE \"-//W3C//DTD XHTML 1.0 Frameset//EN\">",
//these we treat as standard (no quirks)...
//these we treat as compatible (no quirks if possible)...
"<!DOCTYPE \"-//W3C//DTD HTML Experimental 19960712//EN\">",
"<!DOCTYPE \"-//W3C//DTD HTML 4.01 Transitional//EN\">",
"<!DOCTYPE \"-//W3C//DTD HTML 4.1 Frameset//EN\">",
"<!DOCTYPE \"-//W3C//DTD HTML 4.0 Transitional//EN\">",
"<!DOCTYPE \"-//W3C//DTD HTML 4.0 Frameset//EN\">",
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">",
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Frameset//EN\">",
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Frameset//EN\" \"http://www.w3.org/TR/html4/frameset.dtd\">",
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">",
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Frameset//EN\">",
//these we treat as quirks... (along with any other we encounter)...
//these we treat as compatible with quirks... (along with any other we encounter)...
"<!DOCTYPE \"-//W3O//DTD W3 HTML 3.0//EN//\">",
"<!DOCTYPE \"-//IETF//DTD HTML//EN//3.\">",
"<!DOCTYPE \"-//W3C//DTD W3 HTML 3.0//EN//\">",
@ -902,6 +930,7 @@ static const char* doctypes[] = {
"<!DOCTYPE \"-//W3C//DTD W3 HTML Strict 3//EN//\">",
"<!DOCTYPE \"-//IETF//DTD HTML Strict Level 3//EN\">",
"<!DOCTYPE \"-//IETF//DTD HTML Strict Level 3//EN//3.0\">",
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">",
"<!DOCTYPE \"HTML\">",
"<!DOCTYPE \"-//IETF//DTD HTML//EN\">",
@ -970,20 +999,20 @@ nsresult nsParser::WillBuildModel(nsString& aFilename){
nsresult result=NS_OK;
#if TEST_DOCTYPES
#ifdef TEST_DOCTYPES
static PRBool tested=PR_FALSE;
const char** theDocType=doctypes;
if(!tested) {
tested=PR_TRUE;
eParseMode theParseMode=eDTDMode_unknown;
eParserDocType theDocumentType=ePlainText;
nsDTDMode theMode=eDTDMode_unknown;
eParserDocType theDocumentType=ePlainText;
while(*theDocType) {
nsAutoString theType;
theType.AssignWithConversion(*theDocType);
DetermineParseMode(theType,theParseMode,theDocumentType,mParserContext->mMimeType);
DetermineParseMode(theType,theMode,theDocumentType,mParserContext->mMimeType);
theDocType++;
}
}

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

@ -352,4 +352,31 @@ CToken* nsCParserNode::PopAttributeToken() {
return result;
}
/** Retrieve a string containing the tag and its attributes in "source" form
* @update rickg 06June2000
* @return void
*/
void nsCParserNode::GetSource(nsString& aString) {
aString.Truncate();
eHTMLTags theTag=(eHTMLTags)mToken->GetTypeID();
aString.AppendWithConversion("<");
const char* theTagName=nsHTMLTags::GetCStringValue(theTag);
if(theTagName) {
aString.AppendWithConversion(theTagName);
}
if(mAttributes) {
nsAutoString theAttrStr;
int index=0;
for(index=0;index<mAttributes->GetSize();index++) {
CAttributeToken *theToken=(CAttributeToken*)mAttributes->ObjectAt(index);
if(theToken) {
theToken->AppendSource(theAttrStr);
aString.AppendWithConversion(" "); //this will get removed...
}
}
aString.Append(theAttrStr);
}
aString.AppendWithConversion(">");
}

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

@ -174,6 +174,12 @@ class nsCParserNode : public nsIParserNode {
*/
virtual CToken* PopAttributeToken();
/** Retrieve a string containing the tag and its attributes in "source" form
* @update rickg 06June2000
* @return void
*/
virtual void GetSource(nsString& aString);
/**
* This pair of methods allows us to set a generic bit (for arbitrary use)
* on each node stored in the context.

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

@ -240,6 +240,9 @@ class CValidDTD : public nsIDTD {
NS_IMETHOD ConvertEntityToUnicode(const nsString& aEntity, PRInt32* aUnicode) const;
virtual PRBool IsBlockElement(PRInt32 aTagID,PRInt32 aParentID) const {return PR_FALSE;}
virtual PRBool IsInlineElement(PRInt32 aTagID,PRInt32 aParentID) const {return PR_FALSE;}
protected:

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

@ -28,6 +28,9 @@
*/
#define ENABLE_ERROR_OUTPUT //debug only for now...
#ifdef RAPTOR_PERF_METRICS
# define START_TIMER() \
if(mParser) mParser->mParseTime.Start(PR_FALSE); \
@ -54,7 +57,7 @@
#include "nsIContentSink.h"
#include "nsIHTMLContentSink.h"
#include "nsHTMLTokenizer.h"
#include "COtherDTD.h"
#include "prenv.h" //this is here for debug reasons...
#include "prtypes.h" //this is here for debug reasons...
@ -73,6 +76,7 @@ Stopwatch vsTimer;
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static NS_DEFINE_IID(kIDTDIID, NS_IDTD_IID);
static NS_DEFINE_IID(kClassIID, NS_VIEWSOURCE_HTML_IID);
static int gErrorThreshold = 10;
static CTokenRecycler* gTokenRecycler=0;
@ -171,9 +175,11 @@ public:
mEndNode(),
mStartNode(),
mTokenNode(),
mErrorNode(),
mITextToken(),
mITextNode(&mITextToken),
mTextToken(),
mErrorToken("error"),
mTextNode(&mTextToken){
}
@ -188,9 +194,11 @@ public:
nsCParserNode mEndNode;
nsCParserNode mStartNode;
nsCParserNode mTokenNode;
nsCParserNode mErrorNode;
CIndirectTextToken mITextToken;
nsCParserNode mITextNode;
CTextToken mTextToken;
CToken mErrorToken;
nsCParserNode mTextNode;
};
@ -202,8 +210,7 @@ public:
* @param
* @return
*/
CViewSourceHTML::CViewSourceHTML()
{
CViewSourceHTML::CViewSourceHTML() : mTags(), mErrors() {
NS_INIT_REFCNT();
mStartTag.AssignWithConversion("start");
@ -216,12 +223,15 @@ CViewSourceHTML::CViewSourceHTML()
mText.AssignWithConversion("txt");
mKey.AssignWithConversion("key");
mValue.AssignWithConversion("val");
mSummaryTag.AssignWithConversion("summary");
mPopupTag.AssignWithConversion("popup");
mParser=0;
mSink=0;
mLineNumber=0;
mTokenizer=0;
mDocType=eHTML3Text;
mValidator=0;
#ifdef rickgdebug
gDumpFile = new fstream("c:/temp/viewsource.xml",ios::trunc);
@ -317,10 +327,16 @@ nsresult CViewSourceHTML::WillBuildModel( const CParserContext& aParserContext,
if((!aParserContext.mPrevContext) && (mSink)) {
mTags.Truncate();
mErrors.AssignWithConversion(" HTML 4.0 Strict-DTD validation (enabled); [Should use Transitional?].\n");
mValidator=aParserContext.mValidator;
mDocType=aParserContext.mDocType;
mMimeType=aParserContext.mMimeType;
mDTDMode=aParserContext.mDTDMode;
mParserCommand=aParserContext.mParserCommand;
mErrorCount=0;
mTagCount=0;
static const char* theHeader="<?xml version=\"1.0\"?>";
CToken ssToken(theHeader);
@ -394,6 +410,29 @@ NS_IMETHODIMP CViewSourceHTML::BuildModel(nsIParser* aParser,nsITokenizer* aToke
return result;
}
/**
* Call this to display an error summary regarding the page.
*
* @update rickg 6June2000
* @return nsresult
*/
nsresult CViewSourceHTML::GenerateSummary() {
nsresult result=NS_OK;
if(mErrorCount && mTagCount) {
mErrors.AppendWithConversion("\n\n ");
mErrors.AppendInt(mErrorCount);
mErrors.AppendWithConversion(" error(s) detected -- see highlighted portions.\n");
result=WriteTag(mSummaryTag,mErrors,0,PR_FALSE);
}
return result;
}
/**
*
* @update gess5/18/98
@ -424,6 +463,9 @@ NS_IMETHODIMP CViewSourceHTML::DidBuildModel(nsresult anErrorCode,PRBool aNotify
if(ePlainText!=mDocType) {
//now let's automatically close the root container...
GenerateSummary();
CToken theToken("viewsource");
nsCParserNode theNode(&theToken,0);
mSink->CloseContainer(theNode);
@ -577,6 +619,17 @@ NS_IMETHODIMP CViewSourceHTML::ConvertEntityToUnicode(const nsString& aEntity, P
return NS_ERROR_NOT_IMPLEMENTED;
}
PRBool CViewSourceHTML::IsBlockElement(PRInt32 aTagID,PRInt32 aParentID) const {
PRBool result=PR_FALSE;
return result;
}
PRBool CViewSourceHTML::IsInlineElement(PRInt32 aTagID,PRInt32 aParentID) const {
PRBool result=PR_FALSE;
return result;
}
/**
* This method gets called to determine whether a given
* tag is itself a container
@ -748,70 +801,6 @@ nsresult CViewSourceHTML::WriteAttributes(PRInt32 attrCount) {
return result;
}
/**
* This method gets called when a tag needs to be sent out
*
* @update gess 3/25/98
* @param
* @return result status
*/
nsresult CViewSourceHTML::WriteTag(nsString &theXMLTagName,CToken* aToken,PRInt32 attrCount,PRBool aNewlineRequired) {
static nsString theString;
nsresult result=NS_OK;
CSharedVSContext& theContext=CSharedVSContext::GetSharedContext();
CToken theTagToken(theXMLTagName);
theContext.mStartNode.Init(&theTagToken,mLineNumber);
STOP_TIMER();
mSink->OpenContainer(theContext.mStartNode); //emit <starttag>...
START_TIMER();
#ifdef rickgdebug
if(aNewlineRequired) {
(*gDumpFile)<<endl;
}
nsCAutoString cstr(theXMLTagName);
(*gDumpFile) << "<" << cstr << ">";
cstr.Assign(aToken->GetStringValueXXX());
if('<'==cstr.First()) {
cstr.Cut(0,2);
cstr.Truncate(cstr.Length()-1);
}
(*gDumpFile) << cstr;
#endif
nsString& theStr=aToken->GetStringValueXXX();
theStr.StripChar(kCR);
theContext.mITextToken.SetIndirectString(theStr); //now emit the tag name...
STOP_TIMER();
mSink->AddLeaf(theContext.mITextNode);
START_TIMER();
if(attrCount){
result=WriteAttributes(attrCount);
}
STOP_TIMER();
theContext.mEndNode.Init(&theTagToken,mLineNumber);
mSink->CloseContainer(theContext.mEndNode); //emit </starttag>...
START_TIMER();
#ifdef rickgdebug
cstr.Assign(theXMLTagName);
(*gDumpFile) << "</" << cstr << ">";
#endif
return result;
}
/**
* This method gets called when a tag needs to be sent out
*
@ -830,9 +819,8 @@ nsresult CViewSourceHTML::WriteTag(nsString &theXMLTagName,nsString & aText,PRIn
theContext.mStartNode.Init(&theTagToken,mLineNumber);
STOP_TIMER();
mSink->OpenContainer(theContext.mStartNode); //emit <starttag>...
START_TIMER();
mSink->OpenContainer(theContext.mStartNode); //emit <starttag>...
#ifdef rickgdebug
@ -849,29 +837,103 @@ nsresult CViewSourceHTML::WriteTag(nsString &theXMLTagName,nsString & aText,PRIn
theContext.mITextToken.SetIndirectString(aText); //now emit the tag name...
STOP_TIMER();
mSink->AddLeaf(theContext.mITextNode);
START_TIMER();
if(attrCount){
result=WriteAttributes(attrCount);
}
theContext.mEndNode.Init(&theTagToken,mLineNumber);
STOP_TIMER();
mSink->CloseContainer(theContext.mEndNode); //emit </starttag>...
START_TIMER();
#ifdef rickgdebug
cstr.Assign(theXMLTagName);
(*gDumpFile) << "</" << cstr << ">";
#endif
START_TIMER();
return result;
}
/**
* This method gets called when a tag needs to be sent out
*
* @update gess 6June2000 -- factored to use WriteTag(txt,txt...);
* @param
* @return result status
*/
nsresult CViewSourceHTML::WriteTag(nsString &theXMLTagName,CToken* aToken,PRInt32 attrCount,PRBool aNewlineRequired) {
nsString& theStr=aToken->GetStringValueXXX();
theStr.StripChar(kCR);
nsresult result=WriteTag(theXMLTagName,theStr,attrCount,aNewlineRequired);
return result;
}
/**
* This method gets called when a tag needs to be sent out but is known to be misplaced (error)
*
* @update gess 6June2000 --
* @param
* @return result status
*/
nsresult CViewSourceHTML::WriteTagWithError(nsString &theXMLTagName,CToken* aToken,PRInt32 attrCount,PRBool aNewlineRequired) {
STOP_TIMER();
CSharedVSContext& theContext=CSharedVSContext::GetSharedContext();
nsresult result=NS_OK;
if(ePlainText!=mDocType) {
//first write the error tag itself...
theContext.mErrorNode.Init(&theContext.mErrorToken,mLineNumber);
result=mSink->OpenContainer(theContext.mErrorNode); //emit <error>...
}
//now write the tag from the source file...
result=WriteTag(theXMLTagName,aToken,attrCount,aNewlineRequired);
if(ePlainText!=mDocType) {
//now close the error tag...
STOP_TIMER();
theContext.mErrorNode.Init(&theContext.mErrorToken,mLineNumber);
mSink->CloseContainer(theContext.mErrorNode);
START_TIMER();
}
return result;
}
void CViewSourceHTML::AddContainmentError(eHTMLTags aChildTag,eHTMLTags aParentTag,PRInt32 aLineNumber) {
#ifdef ENABLE_ERROR_OUTPUT
mErrorCount++;
if(mErrorCount<=gErrorThreshold) {
char theChildMsg[100];
if(eHTMLTag_text==aChildTag)
strcpy(theChildMsg,"text");
else sprintf(theChildMsg,"<%s>",nsHTMLTags::GetCStringValue(aChildTag));
char theMsg[256];
sprintf(theMsg,"\n -- Line (%i) error: %s is not a legal child of <%s>",
aLineNumber,theChildMsg,nsHTMLTags::GetCStringValue(aParentTag));
mErrors.AppendWithConversion(theMsg);
}
else if(gErrorThreshold+1==mErrorCount){
mErrors.AppendWithConversion("\n -- Too many errors -- terminating output.");
}
#endif
}
/**
*
@ -890,25 +952,53 @@ NS_IMETHODIMP CViewSourceHTML::HandleToken(CToken* aToken,nsIParser* aParser) {
CSharedVSContext& theContext=CSharedVSContext::GetSharedContext();
theContext.mTokenNode.Init(theToken,mLineNumber);
eHTMLTags theParent=(mTags.Length()) ? (eHTMLTags)mTags.Last() : eHTMLTag_unknown;
eHTMLTags theChild=(eHTMLTags)aToken->GetTypeID();
switch(theType) {
case eToken_start:
{
mTagCount++;
result=WriteTag(mStartTag,aToken,aToken->GetAttributeCount(),PR_TRUE);
if((ePlainText!=mDocType) && mParser && (NS_OK==result)) {
CObserverService* theService=mParser->GetObserverService();
if(theService) {
CParserContext* pc=mParser->PeekContext();
void* theDocID=(pc)? pc->mKey:0;
eHTMLTags theTag=(eHTMLTags)theToken->GetTypeID();
result=theService->Notify(theTag,theContext.mTokenNode,theDocID, NS_ConvertToString(kViewSourceCommand), mParser);
#ifdef ENABLE_ERROR_OUTPUT
PRBool theChildIsValid=PR_TRUE;
if(mValidator) {
theChildIsValid=mValidator->CanContain(theParent,theChild);
if(theChildIsValid) {
if(mValidator->IsContainer(theChild))
mTags.Append(PRUnichar(theChild));
}
}
if(theChildIsValid)
result=WriteTag(mStartTag,aToken,aToken->GetAttributeCount(),PR_TRUE);
else {
AddContainmentError(theChild,theParent,mLineNumber);
result=WriteTagWithError(mStartTag,aToken,aToken->GetAttributeCount(),PR_TRUE);
}
#else
result=WriteTag(mStartTag,aToken,aToken->GetAttributeCount(),PR_TRUE);
#endif
if((ePlainText!=mDocType) && mParser && (NS_OK==result)) {
CObserverService* theService=mParser->GetObserverService();
if(theService) {
CParserContext* pc=mParser->PeekContext();
void* theDocID=(pc)? pc->mKey:0;
eHTMLTags theTag=(eHTMLTags)theToken->GetTypeID();
result=theService->Notify(theTag,theContext.mTokenNode,theDocID, NS_ConvertToString(kViewSourceCommand), mParser);
}
}
theContext.mTokenNode.Init(0,0,gTokenRecycler); //now recycle.
}
theContext.mTokenNode.Init(0,0,gTokenRecycler); //now recycle.
break;
case eToken_end:
if(theParent==theChild) {
mTags.Truncate(mTags.Length()-1);
}
result=WriteTag(mEndTag,aToken,0,PR_TRUE);
break;
@ -921,7 +1011,7 @@ NS_IMETHODIMP CViewSourceHTML::HandleToken(CToken* aToken,nsIParser* aParser) {
}
break;
case eToken_comment:
case eToken_comment:
result=WriteTag(mCommentTag,aToken,0,PR_TRUE);
break;
@ -932,12 +1022,25 @@ NS_IMETHODIMP CViewSourceHTML::HandleToken(CToken* aToken,nsIParser* aParser) {
break;
case eToken_newline:
mLineNumber++;
mLineNumber++; //now fall through...
case eToken_whitespace:
case eToken_text:
result=WriteTag(mText,aToken,0,PR_FALSE);
break;
case eToken_text:
#ifdef ENABLE_ERROR_OUTPUT
if((0==mValidator) || mValidator->CanContain(theParent,eHTMLTag_text))
result=WriteTag(mText,aToken,aToken->GetAttributeCount(),PR_TRUE);
else {
AddContainmentError(eHTMLTag_text,theParent,mLineNumber);
result=WriteTagWithError(mText,aToken,aToken->GetAttributeCount(),PR_FALSE);
}
#else
result=WriteTag(mText,aToken,aToken->GetAttributeCount(),PR_TRUE);
#endif
break;
case eToken_entity:
{
nsAutoString theStr;

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

@ -51,7 +51,6 @@ class nsParser;
class nsITokenizer;
class nsCParserNode;
class CViewSourceHTML: public nsIDTD {
public:
@ -224,6 +223,9 @@ class CViewSourceHTML: public nsIDTD {
NS_IMETHOD ConvertEntityToUnicode(const nsString& aEntity, PRInt32* aUnicode) const;
virtual PRBool IsBlockElement(PRInt32 aTagID,PRInt32 aParentID) const;
virtual PRBool IsInlineElement(PRInt32 aTagID,PRInt32 aParentID) const;
/**
* This method gets called to determine whether a given
* tag is itself a container
@ -241,7 +243,11 @@ class CViewSourceHTML: public nsIDTD {
private:
nsresult WriteTag(nsString &anXMLName,CToken* aTag,PRInt32 attrCount,PRBool aNewlineRequired);
nsresult WriteTag(nsString &anXMLName,nsString &aText,PRInt32 attrCount,PRBool aNewlineRequired);
nsresult WriteTagWithError(nsString &theXMLTagName,CToken* aToken,PRInt32 attrCount,PRBool aNewlineRequired);
void AddContainmentError(eHTMLTags aChild,eHTMLTags aParent,PRInt32 aLineNumber);
nsresult WriteAttributes(PRInt32 attrCount);
nsresult GenerateSummary();
protected:
@ -260,10 +266,18 @@ protected:
nsAutoString mKey;
nsAutoString mValue;
nsAutoString mPopupTag;
nsAutoString mSummaryTag;
nsDTDMode mDTDMode;
eParserCommands mParserCommand; //tells us to viewcontent/viewsource/viewerrors...
eParserDocType mDocType;
nsAutoString mMimeType;
PRInt32 mErrorCount;
PRInt32 mTagCount;
nsIDTD *mValidator;
nsString mTags;
nsString mErrors;
};
extern NS_HTMLPARS nsresult NS_NewViewSourceHTML(nsIDTD** aInstancePtrResult);

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

@ -472,6 +472,7 @@ NS_IMETHODIMP CWellFormedDTD::ConvertEntityToUnicode(const nsString& aEntity, PR
return NS_ERROR_NOT_IMPLEMENTED;
}
/**
* This method gets called to determine whether a given
* tag is itself a container

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

@ -225,6 +225,9 @@ class CWellFormedDTD : public nsIDTD {
NS_IMETHOD ConvertEntityToUnicode(const nsString& aEntity, PRInt32* aUnicode) const;
virtual PRBool IsBlockElement(PRInt32 aTagID,PRInt32 aParentID) const {return PR_FALSE;}
virtual PRBool IsInlineElement(PRInt32 aTagID,PRInt32 aParentID) const {return PR_FALSE;}
protected:
/*
NS_IMETHODIMP ConsumeTag(PRUnichar aChar,nsScanner& aScanner,CToken*& aToken);

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

@ -931,11 +931,22 @@ NS_IMETHODIMP nsXIFDTD::ConvertEntityToUnicode(const nsString& aEntity, PRInt32*
}
PRBool nsXIFDTD::IsInlineElement(PRInt32 aTagID,PRInt32 aParentID) const {
PRBool result=PR_FALSE;
return result;
}
PRBool nsXIFDTD::IsBlockElement(PRInt32 aTagID,PRInt32 aParentID) const {
PRBool result=PR_FALSE;
return result;
}
/**
* This method gets called to determine whether a given
* tag is itself a container
*
* @update gpk 06/18/98
* @update rickg 06June2000
* @param aTag -- tag to test for containership
* @return PR_TRUE if given tag can contain other tags
*/

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

@ -262,6 +262,9 @@ class nsXIFDTD : public nsIDTD {
NS_IMETHOD ConvertEntityToUnicode(const nsString& aEntity, PRInt32* aUnicode) const;
virtual PRBool IsBlockElement(PRInt32 aTagID,PRInt32 aParentID) const;
virtual PRBool IsInlineElement(PRInt32 aTagID,PRInt32 aParentID) const;
/**
* Set this to TRUE if you want the DTD to verify its
* context stack.