зеркало из https://github.com/mozilla/pjs.git
fixed several nsbeta2+ bugs; r=harish, buster; a=pdt
This commit is contained in:
Родитель
c12a990ef8
Коммит
a52435dd9f
|
@ -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.
|
||||
|
|
Загрузка…
Ссылка в новой задаче