Back to index

lightning-sunbird  0.9+nobinonly
Public Member Functions | Public Attributes | Protected Member Functions | Protected Attributes
CNavDTD Class Reference

#include <CNavDTD.h>

Inheritance diagram for CNavDTD:
Inheritance graph
[legend]
Collaboration diagram for CNavDTD:
Collaboration graph
[legend]

List of all members.

Public Member Functions

NS_DECL_ISUPPORTS NS_DECL_NSIDTD CNavDTD ()
 Common constructor for navdtd.
virtual ~CNavDTD ()
 Default destructor.
virtual PRBool CanPropagate (eHTMLTags aParent, eHTMLTags aChild, PRBool aParentContains)
 This method is called to determine whether or not a tag of one type can contain a tag of another type.
virtual PRBool CanOmit (eHTMLTags aParent, eHTMLTags aChild, PRBool &aParentContains)
 This method gets called to determine whether a given child tag can be omitted by the given parent.
virtual PRBool ForwardPropagate (nsString &aSequence, eHTMLTags aParent, eHTMLTags aChild)
 This method tries to design a context map (without actually changing our parser state) from the parent down to the child.
virtual PRBool BackwardPropagate (nsString &aSequence, eHTMLTags aParent, eHTMLTags aChild) const
 This method tries to design a context map (without actually changing our parser state) from the child up to the parent.
nsresult CreateContextStackFor (eHTMLTags aChild)
 Attempt forward and/or backward propagation for the given child within the current context vector stack.
virtual PRBool HasOpenContainer (eHTMLTags aContainer) const
 Ask parser if a given container is open ANYWHERE on stack gess5/11/98.
virtual PRBool HasOpenContainer (const eHTMLTags aTagSet[], PRInt32 aCount) const
 Ask parser if a given container is open ANYWHERE on stack gess5/11/98.
virtual eHTMLTags GetTopNode () const
 Accessor that retrieves the tag type of the topmost item on context vector stack.
virtual PRInt32 LastOf (eHTMLTags aTagSet[], PRInt32 aCount) const
 Finds the topmost occurance of given tag within context vector stack.
nsresult HandleStartToken (CToken *aToken)
 The following set of methods are used to partially construct the content model (via the sink) according to the type of token.
nsresult HandleDefaultStartToken (CToken *aToken, eHTMLTags aChildTag, nsCParserNode *aNode)
 This method gets called when a start token has been encountered in the parse process.
nsresult HandleEndToken (CToken *aToken)
 This method gets called when an end token has been encountered in the parse process.
nsresult HandleEntityToken (CToken *aToken)
 This method gets called when an entity token has been encountered in the parse process.
nsresult HandleCommentToken (CToken *aToken)
 This method gets called when a comment token has been encountered in the parse process.
nsresult HandleAttributeToken (CToken *aToken)
 This method gets called when an attribute token has been encountered in the parse process.
nsresult HandleScriptToken (const nsIParserNode *aNode)
 This method gets called when a script token has been encountered in the parse process.
nsresult HandleProcessingInstructionToken (CToken *aToken)
 This method gets called when an "instruction" token has been encountered in the parse process.
nsresult HandleDocTypeDeclToken (CToken *aToken)
 This method gets called when a DOCTYPE token has been encountered in the parse process.
nsresult BuildNeglectedTarget (eHTMLTags aTarget, eHTMLTokenTypes aType, nsIParser *aParser, nsIContentSink *aSink)
nsresult OpenHTML (const nsCParserNode *aNode)
 The next set of method open given HTML elements of various types.
nsresult OpenHead (const nsIParserNode *aNode)
 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.
nsresult OpenBody (const nsCParserNode *aNode)
 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.
nsresult OpenForm (const nsIParserNode *aNode)
 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.
nsresult OpenMap (const nsCParserNode *aNode)
 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.
nsresult OpenFrameset (const nsCParserNode *aNode)
 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.
nsresult OpenContainer (const nsCParserNode *aNode, eHTMLTags aTag, PRBool aClosedByStartTag, nsEntryStack *aStyleStack=0)
 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.
nsresult CloseHTML ()
 The next set of methods close the given HTML element.
nsresult CloseHead ()
 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.
nsresult CloseBody ()
 This method does two things: 1st, help close our own internal model of the content-stack; and 2nd, pass this message on to the sink.
nsresult CloseForm ()
 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.
nsresult CloseMap ()
 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.
nsresult CloseFrameset ()
 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.
nsresult CloseContainer (const eHTMLTags aTag, eHTMLTags aTarget, PRBool aClosedByStartTag)
 The special purpose methods automatically close one or more open containers.
nsresult CloseContainersTo (eHTMLTags aTag, PRBool aClosedByStartTag)
 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.
nsresult CloseContainersTo (PRInt32 anIndex, eHTMLTags aTag, PRBool aClosedByStartTag)
 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.
nsresult AddLeaf (const nsIParserNode *aNode)
 Causes leaf to be added to sink at current vector pos.
nsresult AddHeadLeaf (nsIParserNode *aNode)
 Call this method ONLY when you want to write a leaf into the head container.
nsresult OpenTransientStyles (eHTMLTags aChildTag, PRBool aCloseInvalid=PR_TRUE)
 This set of methods is used to create and manage the set of transient styles that occur as a result of poorly formed HTML or bugs in the original navigator.
nsresult CloseTransientStyles (eHTMLTags aChildTag)
 It is with great trepidation that I offer this method (privately of course).
nsresult PopStyle (eHTMLTags aTag)
 This method gets called when an explicit style close-tag is encountered.
nsresult PushIntoMisplacedStack (CToken *aToken)
 NS_IMETHOD_ (const nsIID &) GetMostDerivedIID(void) const =0
 NS_IMETHOD_ (eAutoDetectResult) CanParse(CParserContext &aParserContext)=0
 This method is called to determine if the given DTD can parse a document in a given source-type.
 NS_IMETHOD_ (PRBool) CanContain(PRInt32 aParent
 This method is called to determine whether or not a tag of one type can contain a tag of another type.
 NS_IMETHOD_ (PRBool) IsContainer(PRInt32 aTag) const =0
 This method gets called to determine whether a given tag is itself a container.
 NS_IMETHOD_ (void) Terminate()=0
 Use this id you want to stop the building content model --------------[ Sets DTD to STOP mode ]---------------- It's recommended to use this method in accordance with the parser's terminate() method.
 NS_IMETHOD_ (PRInt32) GetType()=0
NS_IMETHOD CreateNewInstance (nsIDTD **aInstancePtrResult)=0
 Call this method if you want the DTD to construct a clone of itself.
NS_IMETHOD WillBuildModel (const CParserContext &aParserContext, nsITokenizer *aTokenizer, nsIContentSink *aSink)=0
NS_IMETHOD DidBuildModel (nsresult anErrorCode, PRBool aNotifySink, nsIParser *aParser, nsIContentSink *aSink)=0
 Called by the parser after the parsing process has concluded gess5/18/98.
NS_IMETHOD BuildModel (nsIParser *aParser, nsITokenizer *aTokenizer, nsITokenObserver *anObserver, nsIContentSink *aSink)=0
 Called by the parser after the parsing process has concluded gess5/18/98.
NS_IMETHOD HandleToken (CToken *aToken, nsIParser *aParser)=0
 Called during model building phase of parse process.
NS_IMETHOD WillResumeParse (nsIContentSink *aSink)=0
 If the parse process gets interrupted midway, this method is called by the parser prior to resuming the process.
NS_IMETHOD WillInterruptParse (nsIContentSink *aSink)=0
 If the parse process gets interrupted, this method is called by the parser to notify the DTD that interruption will occur.
NS_IMETHOD CollectSkippedContent (PRInt32 aTag, nsAString &aContent, PRInt32 &aLineNo)=0

Public Attributes

PRInt32 aChild const = 0

Protected Member Functions

nsresult CollectAttributes (nsIParserNode *aNode, eHTMLTags aTag, PRInt32 aCount)
 Retrieve the attributes for this node, and add then into the node.
nsresult CollectSkippedContent (nsIParserNode &aNode, PRInt32 &aCount)
 Causes the next skipped-content token (if any) to be consumed by this node.
nsresult WillHandleStartTag (CToken *aToken, eHTMLTags aChildTag, nsIParserNode &aNode)
 This gets called before we've handled a given start tag.
nsresult DidHandleStartTag (nsIParserNode &aNode, eHTMLTags aChildTag)
 This gets called after we've handled a given start tag.
nsresult HandleOmittedTag (CToken *aToken, eHTMLTags aChildTag, eHTMLTags aParent, nsIParserNode *aNode)
 This method gets called when a start token has been encountered that the parent wants to omit.
nsresult HandleSavedTokens (PRInt32 anIndex)
 This method will be triggered when the end of a table is encountered.
nsresult HandleKeyGen (nsIParserNode *aNode)
 This method gets called when a kegen token is found.
PRBool IsAlternateTag (eHTMLTags aTag)
PRBool IsBlockElement (PRInt32 aTagID, PRInt32 aParentID) const
 This method is called to determine whether or not the given childtag is a block element.
PRBool IsInlineElement (PRInt32 aTagID, PRInt32 aParentID) const
 This method is called to determine whether or not the given childtag is an inline element.

Protected Attributes

nsDeque mMisplacedContent
nsDeque mSkippedContent
nsIHTMLContentSinkmSink
nsTokenAllocatormTokenAllocator
nsDTDContextmBodyContext
nsDTDContextmTempContext
nsParsermParser
nsITokenizermTokenizer
nsString mFilename
nsString mScratch
nsCString mMimeType
nsNodeAllocator mNodeAllocator
nsDTDMode mDTDMode
eParserDocType mDocType
eParserCommands mParserCommand
eHTMLTags mSkipTarget
PRInt32 mLineNumber
PRInt32 mOpenMapCount
PRUint16 mFlags

Detailed Description

Definition at line 135 of file CNavDTD.h.


Constructor & Destructor Documentation

Common constructor for navdtd.

Default constructor.

You probably want to call NS_NewNavHTMLDTD().

gess 7/9/98

gess 4/9/98

Parameters:
@return

Definition at line 168 of file CNavDTD.cpp.

CNavDTD::~CNavDTD ( ) [virtual]

Default destructor.

gess 4/9/98

Parameters:
@return

Definition at line 246 of file CNavDTD.cpp.

                 {
  if(mBodyContext) {
    delete mBodyContext;
    mBodyContext=0;
  }

  if(mTempContext) {
    delete mTempContext;
    mTempContext=0;
  }

  
#ifdef NS_DEBUG
  if(mSink) {
    nsLoggingSink *theLogSink=GetLoggingSink();
    if(mSink==theLogSink) {
      theLogSink->ReleaseProxySink();
    }
  }
#endif

  NS_IF_RELEASE(mSink);
}

Here is the call graph for this function:


Member Function Documentation

Call this method ONLY when you want to write a leaf into the head container.

gess 03/14/99

Parameters:
aNode-- next node to be added to model
Returns:
error code; 0 means OK

Definition at line 3596 of file CNavDTD.cpp.

                                                 {
  nsresult result=NS_OK;

  static eHTMLTags gNoXTags[] = {eHTMLTag_noembed,eHTMLTag_noframes};

  eHTMLTags theTag = (eHTMLTags)aNode->GetNodeType();
  
  // XXX - SCRIPT inside NOTAGS should not get executed unless the pref.
  // says so.  Since we don't have this support yet..lets ignore the
  // SCRIPT inside NOTAGS.  Ref Bug 25880.
  if (eHTMLTag_meta == theTag || eHTMLTag_script == theTag) {
    if (HasOpenContainer(gNoXTags,sizeof(gNoXTags)/sizeof(eHTMLTag_unknown))) {
      return result;
    }
  }
  
  if (mSink) {
    STOP_TIMER();
    MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::AddHeadLeaf(), this=%p\n", this));
    
    result = mSink->AddHeadContent(*aNode);
          
    MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::AddHeadLeaf(), this=%p\n", this));
    START_TIMER();
  }
  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Causes leaf to be added to sink at current vector pos.

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.

gess5/11/98

Parameters:
aNodeis leaf node to be added.
Returns:
error code - 0 if all went well.

gess4/6/98

Parameters:
aNode-- next node to be added to model
Returns:
error code; 0 means OK

Definition at line 3569 of file CNavDTD.cpp.

                                                   {
  nsresult result=NS_OK;
  
  if(mSink){
    eHTMLTags theTag=(eHTMLTags)aNode->GetNodeType();
    OpenTransientStyles(theTag); 

    STOP_TIMER();
    MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::AddLeaf(), this=%p\n", this));
    
    result=mSink->AddLeaf(*aNode);

    MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::AddLeaf(), this=%p\n", this));
    START_TIMER();

  }
  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

PRBool CNavDTD::BackwardPropagate ( nsString aSequence,
eHTMLTags  aParent,
eHTMLTags  aChild 
) const [virtual]

This method tries to design a context map (without actually changing our parser state) from the child up to the parent.

gess4/6/98

Parameters:
aParent-- tag type of parent
aChild-- tag type of child
Returns:
True if closure was achieved -- other false

gess4/6/98

Parameters:
aVectoris the string where we store our output vector in bottom-up order.
aParent-- tag type of parent
aChild-- tag type of child
Returns:
TRUE if propagation closes; false otherwise

Definition at line 2641 of file CNavDTD.cpp.

                                                                                              {

  eHTMLTags theParent=aParent; //just init to get past first condition...

  do {
    const TagList* theRootTags=gHTMLElements[aChild].GetRootTags();
    if(theRootTags) {
      theParent=theRootTags->mTags[0];
      if(CanContain(theParent,aChild)) {
        //we've found a complete sequence, so push the parent...
        aChild=theParent;
        aSequence.Append((PRUnichar)theParent);
      }
    }
    else break;
  } 
  while((theParent!=eHTMLTag_unknown) && (theParent!=aParent));

  return PRBool(aParent==theParent);
}

Here is the call graph for this function:

Here is the caller graph for this function:

NS_IMETHOD nsIDTD::BuildModel ( nsIParser aParser,
nsITokenizer aTokenizer,
nsITokenObserver anObserver,
nsIContentSink aSink 
) [pure virtual, inherited]

Called by the parser after the parsing process has concluded gess5/18/98.

Parameters:
anErrorCode- contains error code resulting from parse process
Returns:

Here is the caller graph for this function:

nsresult CNavDTD::BuildNeglectedTarget ( eHTMLTags  aTarget,
eHTMLTokenTypes  aType,
nsIParser aParser,
nsIContentSink aSink 
)
Parameters:
aTarget- Tag that was neglected in the document.
aType- Specifies the type of the target. Ex. start, end, text, etc.
aParser- Parser to drive this process
aSink- HTML Content sink

Definition at line 504 of file CNavDTD.cpp.

{ 
  NS_ASSERTION(mTokenizer, "tokenizer is null! unable to build target.");
  NS_ASSERTION(mTokenAllocator, "unable to create tokens without an allocator.");
  if (!mTokenizer || !mTokenAllocator)
    return NS_OK;
  CHTMLToken* target = 
      NS_STATIC_CAST(CHTMLToken*, mTokenAllocator->CreateTokenOfType(aType, aTarget));
  mTokenizer->PushTokenFront(target);
  return BuildModel(aParser, mTokenizer, 0, aSink);
}

Here is the call graph for this function:

PRBool CNavDTD::CanOmit ( eHTMLTags  aParent,
eHTMLTags  aChild,
PRBool aParentContains 
) [virtual]

This method gets called to determine whether a given child tag can be omitted by the given parent.

This method gets called to determine whether a given tag can be omitted from opening.

gess 3/25/98

Parameters:
aParent-- parent tag being asked about omitting given child
aChild-- child tag being tested for omittability by parent
aParentContains-- can be 0,1,-1 (false,true, unknown)
Returns:
PR_TRUE if given tag can be omitted

Most cannot.

gess 3/25/98

Parameters:
aParent
aChild
aParentContains
Returns:
PR_TRUE if given tag can contain other tags

Definition at line 2511 of file CNavDTD.cpp.

                                                                                   {

  eHTMLTags theAncestor=gHTMLElements[aChild].mExcludingAncestor;
  if (eHTMLTag_unknown!=theAncestor){
    if (HasOpenContainer(theAncestor)) {
      return PR_TRUE;
    }
  }

  theAncestor=gHTMLElements[aChild].mRequiredAncestor;
  if(eHTMLTag_unknown!=theAncestor){
    if(!HasOpenContainer(theAncestor)) {
      if(!CanPropagate(aParent,aChild,aParentContains)) {
        return PR_TRUE;
      }
    }
    return PR_FALSE;
  }


  if(gHTMLElements[aParent].CanExclude(aChild)){
    return PR_TRUE;
  }

    //Now the obvious test: if the parent can contain the child, don't omit.
  if(-1==aParentContains)
    aParentContains=CanContain(aParent,aChild);

  if(aParentContains || (aChild==aParent)){
    return PR_FALSE;
  }

  if(gHTMLElements[aParent].IsBlockEntity()) {
    if(nsHTMLElement::IsInlineEntity(aChild)) {  //feel free to drop inlines that a block doesn't contain.
      return PR_TRUE;
    }
  }

  if(gHTMLElements[aParent].HasSpecialProperty(kBadContentWatch)) {

    if(-1==aParentContains) {    
      //we need to compute parent containment here, since it wasn't given...
      if(!gHTMLElements[aParent].CanContain(aChild,mDTDMode)){
        return PR_TRUE;
      }
    }
    else if (!aParentContains) {
      if(!gHTMLElements[aChild].HasSpecialProperty(kBadContentWatch)) {
        return PR_TRUE; 
      }
      return PR_FALSE; // Ref. Bug 25658
    }
  }

  if(gHTMLElements[aParent].HasSpecialProperty(kSaveMisplaced)) {
    return PR_TRUE;
  }

  return PR_FALSE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

PRBool CNavDTD::CanPropagate ( eHTMLTags  aParent,
eHTMLTags  aChild,
PRBool  aParentContains 
) [virtual]

This method is called to determine whether or not a tag of one type can contain a tag of another type.

This method is called to determine whether or not the necessary intermediate tags should be propagated between the given parent and given child.

gess 3/25/98

Parameters:
aParent-- int tag of parent container
aChild-- int tag of child container
Returns:
PR_TRUE if parent can contain child

gess 4/8/98

Parameters:
aParent-- tag enum of parent container
aChild-- tag enum of child container
Returns:
PR_TRUE if propagation should occur

Definition at line 2464 of file CNavDTD.cpp.

                                                                                       {
  PRBool    result=PR_FALSE;
  PRBool    theParentContains=(-1==aParentContains) ? CanContain(aParent,aChild) : aParentContains;

  if(aParent==aChild) {
    return result;
  }

  if(nsHTMLElement::IsContainer(aChild)){
    mScratch.Truncate();
    if(!gHTMLElements[aChild].HasSpecialProperty(kNoPropagate)){
      if(nsHTMLElement::IsBlockParent(aParent) || (gHTMLElements[aParent].GetSpecialChildren())) {

        result=ForwardPropagate(mScratch,aParent,aChild);

        if(PR_FALSE==result){

          if(eHTMLTag_unknown!=aParent) {
            if(aParent!=aChild) //dont even bother if we're already inside a similar element...
              result=BackwardPropagate(mScratch,aParent,aChild);
          } //if
          else result=BackwardPropagate(mScratch,eHTMLTag_html,aChild);

        } //elseif

      }//if
    }//if
    if(mScratch.Length()-1>gHTMLElements[aParent].mPropagateRange)
      result=PR_FALSE;
  }//if
  else result=theParentContains;


  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

This method does two things: 1st, help close our own internal model of the content-stack; and 2nd, pass this message on to the sink.

gess4/6/98

Parameters:
aNode-- next node to be removed from our model
Returns:
TRUE if ok, FALSE if error

Definition at line 2997 of file CNavDTD.cpp.

{
  STOP_TIMER();
  MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::CloseBody(), this=%p\n", this));

  nsresult result= (mSink) ? mSink->CloseBody() : NS_OK; 

  MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::CloseBody(), this=%p\n", this));
  START_TIMER();

  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult CNavDTD::CloseContainer ( const eHTMLTags  aTag,
eHTMLTags  aTarget,
PRBool  aClosedByStartTag 
)

The special purpose methods automatically close one or more open containers.

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.

gess5/11/98

Returns:
error code - 0 if all went well.

gess4/6/98

Parameters:
aNode-- next node to be removed from our model
aTag-- id of tag to be closed
aClosedByStartTag-- ONLY TRUE if the container is being closed by opening of another container.
Returns:
TRUE if ok, FALSE if error

Definition at line 3293 of file CNavDTD.cpp.

{
  nsresult   result = NS_OK;

  switch (aTag) {

    case eHTMLTag_html:
      result=CloseHTML(); break;

    case eHTMLTag_style:
      break;

    case eHTMLTag_head:
      result=CloseHead(); 
      break;

    case eHTMLTag_body:
      result=CloseBody(); 
      break;

    case eHTMLTag_map:
      result=CloseMap();
      break;

    case eHTMLTag_form:
      result=CloseForm(); 
      break;

    case eHTMLTag_frameset:
      result=CloseFrameset(); 
      break;
    
    case eHTMLTag_iframe:
    case eHTMLTag_noembed:
    case eHTMLTag_noscript:
    case eHTMLTag_noframes:
      // switch from alternate content state to regular state
      mFlags &= ~NS_DTD_FLAG_ALTERNATE_CONTENT;
      // falling thro' intentionally....
    case eHTMLTag_title:
    default:
      STOP_TIMER();
      MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::CloseContainer(), this=%p\n", this));

      result=(mSink) ? mSink->CloseContainer(aTag) : NS_OK; 

      MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::CloseContainer(), this=%p\n", this));
      START_TIMER();
      break;
  }

  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult CNavDTD::CloseContainersTo ( eHTMLTags  aTag,
PRBool  aClosedByStartTag 
)

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.

gess4/6/98

Parameters:
aTag--
aClosedByStartTag-- ONLY TRUE if the container is being closed by opening of another container.
Returns:
TRUE if ok, FALSE if error

Definition at line 3520 of file CNavDTD.cpp.

                                                                          {
  NS_PRECONDITION(mBodyContext->GetCount() > 0, kInvalidTagStackPos);

  PRInt32 pos=mBodyContext->LastOf(aTag);

  if(kNotFound!=pos) {
    //the tag is indeed open, so close it.
    return CloseContainersTo(pos,aTag,aClosedByStartTag);
  }

  eHTMLTags theTopTag=mBodyContext->Last();

  PRBool theTagIsSynonymous=((nsHTMLElement::IsResidualStyleTag(aTag)) && (nsHTMLElement::IsResidualStyleTag(theTopTag)));
  if(!theTagIsSynonymous){
    theTagIsSynonymous=(gHTMLElements[aTag].IsMemberOf(kHeading) && 
                        gHTMLElements[theTopTag].IsMemberOf(kHeading));  
  }

  if(theTagIsSynonymous) {
    //if you're here, it's because we're trying to close one tag,
    //but a different (synonymous) one is actually open. Because this is NAV4x
    //compatibililty mode, we must close the one that's really open.
    aTag=theTopTag;    
    pos=mBodyContext->LastOf(aTag);
    if(kNotFound!=pos) {
      //the tag is indeed open, so close it.
      return CloseContainersTo(pos,aTag,aClosedByStartTag);
    }
  }
  
  nsresult result=NS_OK;
  const TagList* theRootTags=gHTMLElements[aTag].GetRootTags();
  eHTMLTags theParentTag=(theRootTags) ? theRootTags->mTags[0] : eHTMLTag_unknown;
  pos=mBodyContext->LastOf(theParentTag);
  if(kNotFound!=pos) {
    //the parent container is open, so close it instead
    result=CloseContainersTo(pos+1,aTag,aClosedByStartTag);
  }
  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult CNavDTD::CloseContainersTo ( PRInt32  anIndex,
eHTMLTags  aTarget,
PRBool  aClosedByStartTag 
)

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.

gess4/6/98

Parameters:
anIndex
aTag
aClosedByStartTag-- if TRUE, then we're closing something because a start tag caused it
Returns:
TRUE if ok, FALSE if error

Definition at line 3357 of file CNavDTD.cpp.

{
  NS_PRECONDITION(mBodyContext->GetCount() > 0, kInvalidTagStackPos);
  nsresult result = NS_OK;
  
  if ((anIndex<mBodyContext->GetCount()) && (anIndex>=0)) {

    PRInt32 count = 0;
    while ((count = mBodyContext->GetCount()) > anIndex) {
      nsEntryStack* theChildStyleStack = 0;      
      eHTMLTags theTag = mBodyContext->Last();
      nsCParserNode* theNode = mBodyContext->Pop(theChildStyleStack);
      result = CloseContainer(theTag, aTarget,aClosedByStartTag);  

#ifdef  ENABLE_RESIDUALSTYLE

        PRBool theTagIsStyle=nsHTMLElement::IsResidualStyleTag(theTag);
        // If the current tag cannot leak out then we shouldn't leak out of the target - Fix 40713
        PRBool theStyleDoesntLeakOut = gHTMLElements[theTag].HasSpecialProperty(kNoStyleLeaksOut);
        if(!theStyleDoesntLeakOut) {
          theStyleDoesntLeakOut = gHTMLElements[aTarget].HasSpecialProperty(kNoStyleLeaksOut);
        }
      
        /*************************************************************
          Do not invoke residual style handling when dealing with
          alternate content. This fixes bug 25214.
         *************************************************************/

        if(theTagIsStyle && !(mFlags & NS_DTD_FLAG_ALTERNATE_CONTENT)) {
          NS_ASSERTION(theNode, "residual style node should not be null");
          if (!theNode) {
            if (theChildStyleStack)
              mBodyContext->PushStyles(theChildStyleStack);
            return NS_OK;
          }
          PRBool theTargetTagIsStyle = nsHTMLElement::IsResidualStyleTag(aTarget);
          if(aClosedByStartTag) { 

            /***********************************************************
              Handle closure due to new start tag.          

              The cases we're handing here:
                1. <body><b><DIV>       //<b> gets pushed onto <body>.mStyles.
                2. <body><a>text<a>     //in this case, the target matches, so don't push style
             ***************************************************************************/

            if (theNode->mUseCount == 0){
              if (theTag != aTarget) {
                  //don't push if thechild==theTarget
                if (theChildStyleStack)
                  theChildStyleStack->PushFront(theNode);
                else 
                  mBodyContext->PushStyle(theNode);
              }
            } 
            else if (theTag == aTarget && !gHTMLElements[aTarget].CanContainSelf()) {
              //here's a case we missed:  <a><div>text<a>text</a></div>
              //The <div> pushes the 1st <a> onto the rs-stack, then the 2nd <a>
              //pops the 1st <a> from the rs-stack altogether.
              nsCParserNode* node = mBodyContext->PopStyle(theTag);
              IF_FREE(node, &mNodeAllocator);
            }

            if (theChildStyleStack) {
              mBodyContext->PushStyles(theChildStyleStack);
            }
          }
          else { //Handle closure due to another close tag.      

            /***********************************************************             
              if you're here, then we're dealing with the closure of tags
              caused by a close tag (as opposed to an open tag).
              At a minimum, we should consider pushing residual styles up 
              up the stack or popping and recycling displaced nodes.

              Known cases: 
                1. <body><b><div>text</DIV> 
                      Here the <b> will leak into <div> (see case given above), and 
                      when <div> closes the <b> is dropped since it's already residual.

                2. <body><div><b>text</div>
                      Here the <b> will leak out of the <div> and get pushed onto
                      the RS stack for the <body>, since it originated in the <div>.

                3. <body><span><b>text</span>
                      In this case, the the <b> get's pushed onto the style stack.
                      Later we deal with RS styles stored on the <span>

                4. <body><span><b>text</i>
                      Here we the <b>is closed by a (synonymous) style tag. 
                      In this case, the <b> is simply closed.
             ***************************************************************************/

            if (theChildStyleStack) {
              if (!theStyleDoesntLeakOut) {
                if (theTag != aTarget) {
                  if (theNode->mUseCount == 0) {
                    theChildStyleStack->PushFront(theNode);
                  }
                }
                else if (theNode->mUseCount == 1) {
                  // This fixes bug 30885,29626.
                  // Make sure that the node, which is about to
                  // get released does not stay on the style stack...
                  // Also be sure to remove the correct style off the
                  // style stack. -  Ref. bug 94208.
                  // Ex <FONT><B><I></FONT><FONT></B></I></FONT>
                  // Make sure that </B> removes B off the style stack.
                  mBodyContext->RemoveStyle(theTag);
                }
                mBodyContext->PushStyles(theChildStyleStack);
              }
              else{
                IF_DELETE(theChildStyleStack,&mNodeAllocator);
              }
            }
            else if (theNode->mUseCount == 0) {

              //The old version of this only pushed if the targettag wasn't style.
              //But that misses this case: <font><b>text</font>, where the b should leak
              if (aTarget != theTag) {
                mBodyContext->PushStyle(theNode);
              }
            } 
            else {
              //Ah, at last, the final case. If you're here, then we just popped a 
              //style tag that got onto that tag stack from a stylestack somewhere.
              //Pop it from the stylestack if the target is also a style tag.
              //Make sure to remove the matching style. In the following example
              //<FONT><B><I></FONT><FONT color=red></B></I></FONT> make sure that 
              //</I> does not remove <FONT color=red> off the style stack. - bug 94208
              if (theTargetTagIsStyle && theTag == aTarget) {
                mBodyContext->RemoveStyle(theTag);
              }
            }
          }
        } //if
        else { 
          //the tag is not a style tag...
          if (theChildStyleStack) {
            if (theStyleDoesntLeakOut)
              IF_DELETE(theChildStyleStack,&mNodeAllocator);
            else 
              mBodyContext->PushStyles(theChildStyleStack);
          }
        }
#endif
        IF_FREE(theNode, &mNodeAllocator);
    }

  } //if
  return result;
}

Here is the call graph for this function:

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.

gess4/6/98

Parameters:
aNode-- next node to be removed from our model
Returns:
TRUE if ok, FALSE if error

Definition at line 3045 of file CNavDTD.cpp.

{
  nsresult result = NS_OK;
  if (mFlags & NS_DTD_FLAG_HAS_OPEN_FORM) {
    mFlags &= ~NS_DTD_FLAG_HAS_OPEN_FORM;
    STOP_TIMER();
    MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::CloseForm(), this=%p\n", this));

    result = (mSink) ? mSink->CloseForm() : NS_OK; 

    MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::CloseForm(), this=%p\n", this));
    START_TIMER();
  }
  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

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.

gess4/6/98

Parameters:
aNode-- next node to be removed from our model
Returns:
TRUE if ok, FALSE if error

Definition at line 3143 of file CNavDTD.cpp.

{
  STOP_TIMER();
  MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::CloseFrameset(), this=%p\n", this));

  nsresult result = (mSink) ? mSink->CloseFrameset() : NS_OK; 

  MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::CloseFrameset(), this=%p\n", this));
  START_TIMER();

  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

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.

gess4/6/98

Parameters:
aNode-- next node to be removed from our model
Returns:
TRUE if ok, FALSE if error

Definition at line 2935 of file CNavDTD.cpp.

{
  nsresult result = NS_OK;

  if (mFlags & NS_DTD_FLAG_HAS_OPEN_HEAD) {
    mFlags &= ~NS_DTD_FLAG_HAS_OPEN_HEAD;

    STOP_TIMER();
    MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::CloseHead(), this=%p\n", this));

    result = mSink ? mSink->CloseHead() : NS_OK;

    MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::CloseHead(), this=%p\n", this));
    START_TIMER();
  }

  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

The next set of methods close the given HTML element.

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.

gess5/11/98

Parameters:
HTML(node) to be opened in content sink.
Returns:
error code - 0 if all went well.

gess4/6/98

Parameters:
aNode-- next node to be removed from our model
Returns:
TRUE if ok, FALSE if error

Definition at line 2887 of file CNavDTD.cpp.

                           {

  STOP_TIMER();
  MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::CloseHTML(), this=%p\n", this));

  nsresult result = (mSink) ? mSink->CloseHTML() : NS_OK; 

  MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::CloseHTML(), this=%p\n", this));
  START_TIMER();

  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

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.

gess4/6/98

Parameters:
aNode-- next node to be removed from our model
Returns:
TRUE if ok, FALSE if error

Definition at line 3094 of file CNavDTD.cpp.

{
  nsresult result = NS_OK;
  if (mOpenMapCount) {
    mOpenMapCount--;
    STOP_TIMER();
    MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::CloseMap(), this=%p\n", this));

    result = (mSink) ? mSink->CloseMap() : NS_OK; 

    MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::CloseMap(), this=%p\n", this));
    START_TIMER();
  }
  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

It is with great trepidation that I offer this method (privately of course).

The gets called just prior when a container gets opened. This methods job is to take a look at the (transient) style stack, and close any style containers that are there. Of course, we shouldn't bother to open styles that are incompatible with our parent container. SEE THE TOP OF THIS FILE for more information about how the transient style stack works.

gess6/4/98

Parameters:
tagof the container just opened
Returns:
0 (for now)

Definition at line 2825 of file CNavDTD.cpp.

                                                         {
  return NS_OK;
}
nsresult CNavDTD::CollectAttributes ( nsIParserNode aNode,
eHTMLTags  aTag,
PRInt32  aCount 
) [protected]

Retrieve the attributes for this node, and add then into the node.

gess4/22/98

Parameters:
aNodeis the node you want to collect attributes for
aCountis the # of attributes you're expecting
Returns:
error code (should be 0)

Definition at line 2276 of file CNavDTD.cpp.

{
  int attr=0;

  nsresult result=NS_OK;
  int theAvailTokenCount=mTokenizer->GetCount() + mSkippedContent.GetSize();
  if(aCount<=theAvailTokenCount) {
    CToken* theToken=0;
    eHTMLTags theSkipTarget=gHTMLElements[aTag].mSkipTarget;
    for(attr=0;attr<aCount;++attr){
      if((eHTMLTag_unknown!=theSkipTarget) && mSkippedContent.GetSize())
        theToken=NS_STATIC_CAST(CToken*,mSkippedContent.PopFront());
      else 
        theToken=mTokenizer->PopToken();
      if(theToken)  {
        eHTMLTokenTypes theType=eHTMLTokenTypes(theToken->GetTokenType());
        if(theType!=eToken_attribute) {
          // If you're here then it means that the token does not
          // belong to this node. Put the token back into the tokenizer
          // and let it go thro' the regular path. Bug: 59189.
          mTokenizer->PushTokenFront(theToken);
          break;
        }

        mLineNumber += theToken->GetNewlineCount();

        if(aNode) {
          // If the key is empty, the attribute is unusable, so we should not
          // add it to the node.
          if (!((CAttributeToken*)theToken)->GetKey().IsEmpty()) {
            aNode->AddAttribute(theToken);
          } else {
            IF_FREE(theToken, mTokenAllocator);
          }
        } else {
          IF_FREE(theToken, mTokenAllocator);
        }
      }
    }
  }
  else {
    result=kEOF;
  }
  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

NS_IMETHOD nsIDTD::CollectSkippedContent ( PRInt32  aTag,
nsAString &  aContent,
PRInt32 aLineNo 
) [pure virtual, inherited]

Here is the caller graph for this function:

NS_IMETHODIMP CNavDTD::CollectSkippedContent ( nsIParserNode aNode,
PRInt32 aCount 
) [protected]

Causes the next skipped-content token (if any) to be consumed by this node.

gess 4Sep2000

Parameters:
nodeto consume skipped-content
holdsthe number of skipped content elements encountered
Returns:
Error condition.

Definition at line 2334 of file CNavDTD.cpp.

                                                                                  {

  NS_ASSERTION(aTag >= eHTMLTag_unknown && aTag <= NS_HTML_TAG_MAX, "tag array out of bounds");

  aContent.Truncate();

  NS_ASSERTION(eHTMLTag_unknown != gHTMLElements[aTag].mSkipTarget, "cannot collect content for this tag");
  if (eHTMLTag_unknown == gHTMLElements[aTag].mSkipTarget) {
    // This tag doesn't support skipped content.
    aLineNo = -1;
    return NS_OK;
  }
  
  aLineNo = mLineNumber;
  mScratch.Truncate();
  PRInt32 i = 0;
  PRInt32 tagCount = mSkippedContent.GetSize();
  for (i = 0; i< tagCount; ++i){
    CHTMLToken* theNextToken = (CHTMLToken*)mSkippedContent.PopFront();
    if (theNextToken) {
      theNextToken->AppendSourceTo(aContent);
    }

    IF_FREE(theNextToken, mTokenAllocator);
  }
  
  InPlaceConvertLineEndings(aContent);

  // Note: TITLE content is PCDATA and hence the newlines are already accounted for.
  mLineNumber += (aTag != eHTMLTag_title) ? aContent.CountChar(kNewLine) : 0;
  
  return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Attempt forward and/or backward propagation for the given child within the current context vector stack.

This method gets called to create a valid context stack for the given child.

gess5/11/98

Parameters:
aChild-- type of child to be propagated.
Returns:
TRUE if succeeds, otherwise FALSE

We compare the current stack to the default needs of the child, and push new guys onto the stack until the child can be properly placed.

gess 4/8/98

Parameters:
aChildis the child for whom we need to create a new context vector
Returns:
true if we succeeded, otherwise false

Definition at line 3635 of file CNavDTD.cpp.

                                                       {
  
  mScratch.Truncate();
  
  nsresult  result=(nsresult)kContextMismatch;
  eHTMLTags theTop=mBodyContext->Last();
  PRBool    bResult=ForwardPropagate(mScratch,theTop,aChild);
  
  if(PR_FALSE==bResult){

    if(eHTMLTag_unknown!=theTop) {
      if(theTop!=aChild) //dont even bother if we're already inside a similar element...
        bResult=BackwardPropagate(mScratch,theTop,aChild);      
    } //if
    else bResult=BackwardPropagate(mScratch,eHTMLTag_html,aChild);
  } //elseif

  PRInt32   theLen=mScratch.Length();
  eHTMLTags theTag=(eHTMLTags)mScratch[--theLen];

  if((0==mBodyContext->GetCount()) || (mBodyContext->Last()==theTag))
    result=NS_OK;

  //now, build up the stack according to the tags 
  //you have that aren't in the stack...
  if(PR_TRUE==bResult){
    while(theLen) {
      theTag=(eHTMLTags)mScratch[--theLen];

#ifdef ALLOW_TR_AS_CHILD_OF_TABLE
      if((eHTML3_Quirks==mDocType) && (eHTMLTag_tbody==theTag)) {
        //the prev. condition prevents us from emitting tbody in html3.2 docs; fix bug 30378
        continue;
      }
#endif
      CStartToken *theToken=(CStartToken*)mTokenAllocator->CreateTokenOfType(eToken_start,theTag);
      HandleToken(theToken,mParser);  //these should all wind up on contextstack, so don't recycle.
    }
    result=NS_OK;
  }
  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

NS_IMETHOD nsIDTD::CreateNewInstance ( nsIDTD **  aInstancePtrResult) [pure virtual, inherited]

Call this method if you want the DTD to construct a clone of itself.

gess7/23/98

Parameters:
@return

Here is the caller graph for this function:

NS_IMETHOD nsIDTD::DidBuildModel ( nsresult  anErrorCode,
PRBool  aNotifySink,
nsIParser aParser,
nsIContentSink aSink 
) [pure virtual, inherited]

Called by the parser after the parsing process has concluded gess5/18/98.

Parameters:
anErrorCode- contains error code resulting from parse process
Returns:

Here is the caller graph for this function:

nsresult CNavDTD::DidHandleStartTag ( nsIParserNode aNode,
eHTMLTags  aChildTag 
) [protected]

This gets called after we've handled a given start tag.

It's a generic hook to let us to post processing.

Parameters:
aTokencontains the tag in question
aChildTagis the tag itself.
Returns:
status

Definition at line 1005 of file CNavDTD.cpp.

                                                                           {
  nsresult result=NS_OK;

  switch(aChildTag){

    case eHTMLTag_pre:
    case eHTMLTag_listing:
      {
        CToken* theNextToken=mTokenizer->PeekToken();
        if(theNextToken)  {
          eHTMLTokenTypes theType=eHTMLTokenTypes(theNextToken->GetTokenType());
          if(eToken_newline==theType){
            mLineNumber += theNextToken->GetNewlineCount();
            theNextToken=mTokenizer->PopToken();  //skip 1st newline inside PRE and LISTING
            IF_FREE(theNextToken, mTokenAllocator); // fix for Bug 29379
          }//if
        }//if
      }
      break;
    default:
      break;
  }//switch 

  //handle <empty/> tags by generating a close tag...
  //added this to fix bug 48351, which contains XHTML and uses empty tags.
  nsCParserNode* theNode=NS_STATIC_CAST(nsCParserNode*,&aNode);
  if(nsHTMLElement::IsContainer(aChildTag) && theNode && theNode->mToken) {  //nullptr test fixes bug 56085
    CStartToken *theToken=NS_STATIC_CAST(CStartToken*,theNode->mToken);
    if(theToken->IsEmpty()){

      CToken *theEndToken=mTokenAllocator->CreateTokenOfType(eToken_end,aChildTag); 
      if(theEndToken) {
        result=HandleEndToken(theEndToken);
        IF_FREE(theEndToken, mTokenAllocator);
      }
    }
  }

  return result;
} 

Here is the call graph for this function:

Here is the caller graph for this function:

PRBool CNavDTD::ForwardPropagate ( nsString aSequence,
eHTMLTags  aParent,
eHTMLTags  aChild 
) [virtual]

This method tries to design a context map (without actually changing our parser state) from the parent down to the child.

This method tries to design a context vector (without actually changing our parser state) from the parent down to the child.

gess4/6/98

Parameters:
aParent-- tag type of parent
aChild-- tag type of child
Returns:
True if closure was achieved -- other false

gess4/6/98

Parameters:
aVectoris the string where we store our output vector in bottom-up order.
aParent-- tag type of parent
aChild-- tag type of child
Returns:
TRUE if propagation closes; false otherwise

Definition at line 2598 of file CNavDTD.cpp.

                                                                                        {
  PRBool result=PR_FALSE;

  switch(aParent) {
    case eHTMLTag_table:
      {
        if((eHTMLTag_tr==aChild) || (eHTMLTag_td==aChild)) {
          return BackwardPropagate(aSequence,aParent,aChild);
        }
      }
      //otherwise, intentionally fall through...

    case eHTMLTag_tr:
      {  
        PRBool theCanContainResult=CanContain(eHTMLTag_td,aChild);
        if(PR_TRUE==theCanContainResult) {
          aSequence.Append((PRUnichar)eHTMLTag_td);
          result=BackwardPropagate(aSequence,aParent,eHTMLTag_td);
        }
      }
      break;

    case eHTMLTag_th:
      break;

    default:
      break;
  }//switch
  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

eHTMLTags CNavDTD::GetTopNode ( ) const [virtual]

Accessor that retrieves the tag type of the topmost item on context vector stack.

This method retrieves the HTMLTag type of the topmost container on the stack.

gess5/11/98

Returns:
tag type (may be unknown)

gess 4/2/98

Returns:
tag id of topmost node in contextstack

Definition at line 2713 of file CNavDTD.cpp.

                                    {
  return mBodyContext->Last();
}

Here is the call graph for this function:

This method gets called when an attribute token has been encountered in the parse process.

This is an error, since all attributes should have been accounted for in the prior start or end tokens

gess 3/25/98

Parameters:
aToken-- next (start) token to be handled
Returns:
PR_TRUE if all went well; PR_FALSE if error occured

Definition at line 2163 of file CNavDTD.cpp.

                                                     {
  NS_PRECONDITION(0!=aToken,kNullToken);
  NS_ERROR("attribute encountered -- this shouldn't happen unless the attribute was not part of a start tag!");

  return NS_OK;
}

This method gets called when a comment token has been encountered in the parse process.

After making sure we're somewhere in the body, we handle the comment in the same code that we use for text.

gess 3/25/98

Parameters:
aToken-- next (start) token to be handled
Returns:
PR_TRUE if all went well; PR_FALSE if error occured

Definition at line 2129 of file CNavDTD.cpp.

                                                   {
  NS_PRECONDITION(0!=aToken,kNullToken);
  
  nsresult  result=NS_OK;

  nsCParserNode* theNode=mNodeAllocator.CreateNode(aToken, mTokenAllocator);

  if(theNode) {

    STOP_TIMER();
    MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::HandleCommentToken(), this=%p\n", this));

    result=(mSink) ? mSink->AddComment(*theNode) : NS_OK;  

    IF_FREE(theNode, &mNodeAllocator);

    MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::HandleCommentToken(), this=%p\n", this));
    START_TIMER();
  }

  return result;
}

Here is the call graph for this function:

nsresult CNavDTD::HandleDefaultStartToken ( CToken aToken,
eHTMLTags  aChildTag,
nsCParserNode aNode 
)

This method gets called when a start token has been encountered in the parse process.

If the current container can contain this tag, then add it. Otherwise, you have two choices: 1) create an implicit container for this tag to be stored in 2) close the top container, and add this to whatever container ends up on top.

gess 3/25/98

Parameters:
aToken-- next (start) token to be handled
aNode-- CParserNode representing this start token
Returns:
PR_TRUE if all went well; PR_FALSE if error occured

Definition at line 1153 of file CNavDTD.cpp.

                                                                                                 {
  NS_PRECONDITION(0!=aToken,kNullToken);

  nsresult  result=NS_OK;
  PRBool  theChildIsContainer=nsHTMLElement::IsContainer(aChildTag);

  // client of parser is spefically trying to parse a fragment that 
  // may lack required context.  Suspend containment rules if so.
  if (mParserCommand != eViewFragment)
  {
    PRBool  theChildAgrees=PR_TRUE;
    PRInt32 theIndex=mBodyContext->GetCount();
    PRBool  theParentContains=-1;
    
    do {
   
      eHTMLTags theParentTag=mBodyContext->TagAt(--theIndex);
      theParentContains=CanContain(theParentTag,aChildTag);  //precompute containment, and pass it to CanOmit()...

      if(CanOmit(theParentTag,aChildTag,theParentContains)) {
        result=HandleOmittedTag(aToken,aChildTag,theParentTag,aNode);
        return result;
      }

      eProcessRule theRule=eNormalOp; 

      if (!theParentContains &&
          (IsBlockElement(aChildTag,theParentTag) &&
           IsInlineElement(theParentTag,theParentTag))) { //broaden this to fix <inline><block></block></inline>
        if (eHTMLTag_li != aChildTag) {  //remove test for table to fix 57554
          nsCParserNode* theParentNode = NS_STATIC_CAST(nsCParserNode*, mBodyContext->PeekNode());
          if (theParentNode && theParentNode->mToken->IsWellFormed()) {
            theRule = eLetInlineContainBlock;
          }
        }
      }

      switch(theRule){

        case eNormalOp:        

          theChildAgrees=PR_TRUE;
          if(theParentContains) {

            eHTMLTags theAncestor=gHTMLElements[aChildTag].mRequiredAncestor;
            if(eHTMLTag_unknown!=theAncestor){
              theChildAgrees=HasOpenContainer(theAncestor);
            }
            
            if(theChildAgrees && theChildIsContainer) {
              if(theParentTag!=aChildTag) {             
                // Double check the power structure a
                // Note: The bit is currently set on <A> and <LI>.
                if(gHTMLElements[aChildTag].ShouldVerifyHierarchy()){
                  PRInt32 theChildIndex=nsHTMLElement::GetIndexOfChildOrSynonym(*mBodyContext,aChildTag);
              
                  if((kNotFound<theChildIndex) && (theChildIndex<theIndex)) {
                   
                  /*-------------------------------------------------------------------------------------
                     1  Here's a tricky case from bug 22596:  <h5><li><h5>
                        How do we know that the 2nd <h5> should close the <LI> rather than nest inside the <LI>?
                        (Afterall, the <h5> is a legal child of the <LI>).
              
                        The way you know is that there is no root between the two, so the <h5> binds more
                        tightly to the 1st <h5> than to the <LI>.
                     2.  Also, bug 6148 shows this case: <SPAN><DIV><SPAN>
                        From this case we learned not to execute this logic if the parent is a block.
                    
                     3. Fix for 26583
                        Ex. <A href=foo.html><B>foo<A href-bar.html>bar</A></B></A>  <-- A legal HTML
                        In the above example clicking on "foo" or "bar" should link to
                        foo.html or bar.html respectively. That is, the inner <A> should be informed
                        about the presence of an open <A> above <B>..so that the inner <A> can close out
                        the outer <A>. The following code does it for us.
                     
                     4. Fix for 27865 [ similer to 22596 ]. Ex: <DL><DD><LI>one<DD><LI>two
                   -------------------------------------------------------------------------------------*/
                     
                    theChildAgrees=CanBeContained(aChildTag,*mBodyContext);
                  } //if
                }//if
              } //if
            } //if
          } //if parentcontains

          if(!(theParentContains && theChildAgrees)) {
            if (!CanPropagate(theParentTag,aChildTag,theParentContains)) { 
              if(theChildIsContainer || (!theParentContains)){ 
                if(!theChildAgrees && 
                   !gHTMLElements[aChildTag].CanAutoCloseTag(*mBodyContext,theIndex,aChildTag)) {
                  // Closing the tags above might cause non-compatible results.
                  // Ex. <TABLE><TR><TD><TBODY>Text</TD></TR></TABLE>. 
                  // In the example above <TBODY> is badly misplaced, but 
                  // we should not attempt to close the tags above it, 
                  // The safest thing to do is to discard this tag.
                  return result;
                }
                else if (mBodyContext->mContextTopIndex > 0 && theIndex <= mBodyContext->mContextTopIndex) {
                  // Looks like the parent tag does not want to contain the current tag ( aChildTag ). 
                  // However, we have to force the containment, when handling misplaced content, to avoid data loss.
                  // Ref. bug 138577.
                  theParentContains = PR_TRUE;
                }
                else {
                  CloseContainersTo(theIndex,aChildTag,PR_TRUE);
                }
              }//if
              else break;
            }//if
            else {
              CreateContextStackFor(aChildTag);
              theIndex=mBodyContext->GetCount();
            }
          }//if
          break;

        case eLetInlineContainBlock:
          theParentContains=theChildAgrees=PR_TRUE; //cause us to fall out of loop and open the block.
          break;

        default:
          break;

      }//switch
    } while(!(theParentContains && theChildAgrees));
  }
  
  if(theChildIsContainer){
    result=OpenContainer(aNode,aChildTag,PR_TRUE);
  }
  else {  //we're writing a leaf...
    result=AddLeaf(aNode);
  }

  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

This method gets called when a DOCTYPE token has been encountered in the parse process.

harishd 09/02/99

Parameters:
aToken-- The very first token to be handled
Returns:
PR_TRUE if all went well; PR_FALSE if error occured

Definition at line 2233 of file CNavDTD.cpp.

                                                      {
  NS_PRECONDITION(0!=aToken,kNullToken);

  nsresult result=NS_OK;

  CDoctypeDeclToken* theToken = NS_STATIC_CAST(CDoctypeDeclToken*,aToken);
  nsAutoString docTypeStr(theToken->GetStringValue());
  mLineNumber += docTypeStr.CountChar(kNewLine);
  
  PRInt32 len=docTypeStr.Length();
  PRInt32 pos=docTypeStr.RFindChar(kGreaterThan);
  if(pos>-1) {
    docTypeStr.Cut(pos,len-pos);// First remove '>' from the end.
  }
  docTypeStr.Cut(0,2); // Now remove "<!" from the begining
  theToken->SetStringValue(docTypeStr);

  nsCParserNode* theNode=mNodeAllocator.CreateNode(aToken, mTokenAllocator);
  if(theNode) {

  STOP_TIMER();
  MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::HandleDocTypeDeclToken(), this=%p\n", this));
  
  result = (mSink)? mSink->AddDocTypeDecl(*theNode):NS_OK;
    
  IF_FREE(theNode, &mNodeAllocator);
  
  MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::HandleDocTypeDeclToken(), this=%p\n", this));
  START_TIMER();

  }
  return result;
}

Here is the call graph for this function:

This method gets called when an end token has been encountered in the parse process.

If the end tag matches the start tag on the stack, then simply close it. Otherwise, we have a erroneous state condition. This can be because we have a close tag with no prior open tag (user error) or because we screwed something up in the parse process. I'm not sure yet how to tell the difference.

gess 3/25/98

Parameters:
aToken-- next (start) token to be handled
Returns:
PR_TRUE if all went well; PR_FALSE if error occured

Definition at line 1834 of file CNavDTD.cpp.

                                               {
  NS_PRECONDITION(0!=aToken,kNullToken);

  nsresult    result=NS_OK;
  eHTMLTags   theChildTag=(eHTMLTags)aToken->GetTypeID();

  //Begin by dumping any attributes (bug 143512)
  PRInt16     attrCount=aToken->GetAttributeCount();
  CollectAttributes(nsnull,theChildTag,attrCount);

  switch(theChildTag) {

    case eHTMLTag_script:
      mFlags &= ~NS_DTD_FLAG_HAS_OPEN_SCRIPT;
    case eHTMLTag_style:
    case eHTMLTag_link:
    case eHTMLTag_meta:
    case eHTMLTag_title:
      break;

    case eHTMLTag_head:
      StripWSFollowingTag(theChildTag,mTokenizer, mTokenAllocator, mLineNumber);
      result = CloseContainer(eHTMLTag_head, theChildTag, PR_FALSE);
      break;

    case eHTMLTag_form:
      result = CloseContainer(eHTMLTag_form, theChildTag, PR_FALSE);
      break;

    case eHTMLTag_br:
      {
          //This is special NAV-QUIRKS code that allows users
          //to use </BR>, even though that isn't a legitimate tag.
        if(eDTDMode_quirks==mDTDMode) {
          // Use recycler and pass the token thro' HandleToken() to fix bugs like 32782.
          CHTMLToken* theToken = NS_STATIC_CAST(CHTMLToken*,mTokenAllocator->CreateTokenOfType(eToken_start,theChildTag));
          result=HandleToken(theToken,mParser);
        }
      }
      break;

    case eHTMLTag_body:
    case eHTMLTag_html:
      StripWSFollowingTag(theChildTag,mTokenizer,mTokenAllocator,mLineNumber);
      break;

    default:
     {
        //now check to see if this token should be omitted, or 
        //if it's gated from closing by the presence of another tag.
        if(gHTMLElements[theChildTag].CanOmitEndTag()) {
          PopStyle(theChildTag);
        }
        else {
          eHTMLTags theParentTag=mBodyContext->Last();

          if(kNotFound==nsHTMLElement::GetIndexOfChildOrSynonym(*mBodyContext,theChildTag)) {

            // Ref: bug 30487
            // Make sure that we don't cross boundaries, of certain elements,
            // to close stylistic information.
            // Ex. <font face="helvetica"><table><tr><td></font></td></tr></table> some text...
            // In the above ex. the orphaned FONT tag, inside TD, should cross TD boundaryto 
            // close the FONT tag above TABLE. 
            static eHTMLTags gBarriers[]={eHTMLTag_thead,eHTMLTag_tbody,eHTMLTag_tfoot,eHTMLTag_table};

            if(!FindTagInSet(theParentTag,gBarriers,sizeof(gBarriers)/sizeof(theParentTag))) {
              if(nsHTMLElement::IsResidualStyleTag(theChildTag)) {
                mBodyContext->RemoveStyle(theChildTag); // fix bug 77746
              }
            }

            // If the bit kHandleStrayTag is set then we automatically open up a matching
            // start tag ( compatibility ).  Currently this bit is set on P tag.
            // This also fixes Bug: 22623
            if(gHTMLElements[theChildTag].HasSpecialProperty(kHandleStrayTag) &&
               mDTDMode != eDTDMode_full_standards &&
               mDTDMode != eDTDMode_almost_standards) {
              // Oh boy!! we found a "stray" tag. Nav4.x and IE introduce line break in
              // such cases. So, let's simulate that effect for compatibility.
              // Ex. <html><body>Hello</P>There</body></html>
              PRBool theParentContains=-1; //set to -1 to force canomit to recompute.
              if(!CanOmit(theParentTag,theChildTag,theParentContains)) {
                CHTMLToken* theStartToken = NS_STATIC_CAST(CHTMLToken*,mTokenAllocator->CreateTokenOfType(eToken_start,theChildTag));

                // This check for NS_DTD_FLAG_IN_MISPLACED_CONTENT was added
                // to fix bug 142965.
                if (!(mFlags & NS_DTD_FLAG_IN_MISPLACED_CONTENT)) {
                  // We're not handling misplaced content right now, just push
                  // these new tokens back on the stack and handle them in the
                  // regular flow of HandleToken.
                  IF_HOLD(aToken);
                  mTokenizer->PushTokenFront(aToken); //put this end token back...
                  mTokenizer->PushTokenFront(theStartToken); //put the new token onto the stack...
                }
                else {
                  // Oops, we're in misplaced content. Handle these tokens 
                  // directly instead of trying to push them onto the tokenizer
                  // stack.
                  result = HandleToken(theStartToken, mParser);
                  NS_ENSURE_SUCCESS(result, result);

                  result = HandleToken(aToken, mParser);
                }
              }
            }
            return result;
          }
          if(result==NS_OK) {
            eHTMLTags theTarget=FindAutoCloseTargetForEndTag(theChildTag,*mBodyContext,mDTDMode);
            if(eHTMLTag_unknown!=theTarget) {
              if (nsHTMLElement::IsResidualStyleTag(theChildTag)) {
                result=OpenTransientStyles(theChildTag); 
                if(NS_FAILED(result)) {
                  return result;
                }
              }
              result=CloseContainersTo(theTarget,PR_FALSE);
            }
          }
        }
      }
      break;
  }

  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

This method gets called when an entity token has been encountered in the parse process.

gess 3/25/98

Parameters:
aToken-- next (start) token to be handled
Returns:
PR_TRUE if all went well; PR_FALSE if error occured

Definition at line 2082 of file CNavDTD.cpp.

                                                  {
  NS_PRECONDITION(0!=aToken,kNullToken);

  nsresult  result=NS_OK;

  const nsSubstring& theStr = aToken->GetStringValue();

  if((kHashsign!=theStr.First()) && (-1==nsHTMLEntities::EntityToUnicode(theStr))){
    //if you're here we have a bogus entity.
    //convert it into a text token.
    CToken *theToken=0;

    nsAutoString entityName;
    entityName.AssignLiteral("&");
    entityName.Append(theStr); //should append the entity name; fix bug 51161.
    theToken = mTokenAllocator->CreateTokenOfType(eToken_text,eHTMLTag_text,entityName);

    return HandleToken(theToken,mParser); //theToken should get recycled automagically...
  }

  eHTMLTags theParentTag=mBodyContext->Last();

  nsCParserNode* theNode=mNodeAllocator.CreateNode(aToken, mTokenAllocator);
  if(theNode) {
    PRBool theParentContains=-1; //set to -1 to force CanOmit to recompute...
    if(CanOmit(theParentTag,eHTMLTag_entity,theParentContains)) {
      eHTMLTags theCurrTag=(eHTMLTags)aToken->GetTypeID();
      result=HandleOmittedTag(aToken,theCurrTag,theParentTag,theNode);
    }
    else {
      result=AddLeaf(theNode);
    }
    IF_FREE(theNode, &mNodeAllocator);
  }  
  return result;
}

Here is the call graph for this function:

nsresult CNavDTD::HandleKeyGen ( nsIParserNode aNode) [protected]

This method gets called when a kegen token is found.

harishd 05/02/00

Parameters:
aNode-- CParserNode representing keygen
Returns:
NS_OK if all went well; ERROR if error occured

Definition at line 1476 of file CNavDTD.cpp.

                                                   { 
  nsresult result=NS_OK; 

  if(aNode) { 
  
    nsCOMPtr<nsIFormProcessor> theFormProcessor = 
             do_GetService(kFormProcessorCID, &result);
  
    if(NS_SUCCEEDED(result)) { 
      PRInt32      theAttrCount=aNode->GetAttributeCount(); 
      nsVoidArray  theContent; 
      nsAutoString theAttribute; 
      nsAutoString theFormType; 
      CToken*      theToken=nsnull; 

      theFormType.AssignLiteral("select"); 
  
      result=theFormProcessor->ProvideContent(theFormType,theContent,theAttribute); 

      if(NS_SUCCEEDED(result)) {
        nsString* theTextValue=nsnull; 
        PRInt32   theIndex=nsnull; 
  
        if(mTokenizer && mTokenAllocator) {
          // Populate the tokenizer with the fabricated elements in the reverse order 
          // such that <SELECT> is on the top fo the tokenizer followed by <OPTION>s 
          // and </SELECT> 
          theToken=mTokenAllocator->CreateTokenOfType(eToken_end,eHTMLTag_select); 
          mTokenizer->PushTokenFront(theToken); 
  
          for(theIndex=theContent.Count()-1;theIndex>-1;theIndex--) { 
            theTextValue=(nsString*)theContent[theIndex]; 
            theToken=mTokenAllocator->CreateTokenOfType(eToken_text,eHTMLTag_text,*theTextValue); 
            mTokenizer->PushTokenFront(theToken); 
            theToken=mTokenAllocator->CreateTokenOfType(eToken_start,eHTMLTag_option); 
            mTokenizer->PushTokenFront(theToken); 
          } 
  
          // The attribute ( provided by the form processor ) should be a part of the SELECT.
          // Placing the attribute token on the tokenizer to get picked up by the SELECT.
          theToken=mTokenAllocator->CreateTokenOfType(eToken_attribute,eHTMLTag_unknown,theAttribute);

          ((CAttributeToken*)theToken)->SetKey(NS_LITERAL_STRING("_moz-type")); 
          mTokenizer->PushTokenFront(theToken); 
  
          // Pop out NAME and CHALLENGE attributes ( from the keygen NODE ) 
          // and place it in the tokenizer such that the attribtues get 
          // sucked into SELECT node. 
          for(theIndex=theAttrCount;theIndex>0;theIndex--) { 
            mTokenizer->PushTokenFront(((nsCParserNode*)aNode)->PopAttributeToken()); 
          } 
  
          theToken=mTokenAllocator->CreateTokenOfType(eToken_start,eHTMLTag_select); 
          // Increament the count because of the additional attribute from the form processor.
          theToken->SetAttributeCount(theAttrCount+1); 
          mTokenizer->PushTokenFront(theToken); 
        }//if(mTokenizer && mTokenAllocator)
      }//if(NS_SUCCEEDED(result))
    }// if(NS_SUCCEEDED(result)) 
  } //if(aNode) 
  return result; 
} 

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult CNavDTD::HandleOmittedTag ( CToken aToken,
eHTMLTags  aChildTag,
eHTMLTags  aParent,
nsIParserNode aNode 
) [protected]

This method gets called when a start token has been encountered that the parent wants to omit.

gess 3/25/98

Parameters:
aToken-- next (start) token to be handled
aChildTag-- id of the child in question
aParent-- id of the parent in question
aNode-- CParserNode representing this start token
Returns:
PR_TRUE if all went well; PR_FALSE if error occured

Definition at line 1407 of file CNavDTD.cpp.

                                                                                                            {
  NS_PRECONDITION(mBodyContext != nsnull,"need a context to work with");

  nsresult  result=NS_OK;

  //The trick here is to see if the parent can contain the child, but prefers not to.
  //Only if the parent CANNOT contain the child should we look to see if it's potentially a child
  //of another section. If it is, the cache it for later.
  //  1. Get the root node for the child. See if the ultimate node is the BODY, FRAMESET, HEAD or HTML
  PRInt32   theTagCount = mBodyContext->GetCount();

  if(aToken) {
    PRInt32   attrCount = aToken->GetAttributeCount();
    if((gHTMLElements[aParent].HasSpecialProperty(kBadContentWatch)) &&
       (!nsHTMLElement::IsWhitespaceTag(aChildTag))) {
      eHTMLTags theTag=eHTMLTag_unknown;
    
      // Determine the insertion point
      while(theTagCount > 0) {
        theTag = mBodyContext->TagAt(--theTagCount);
        if(!gHTMLElements[theTag].HasSpecialProperty(kBadContentWatch)) {
          mBodyContext->mContextTopIndex = theTagCount; // This is our insertion point
          break;
        }
      }

      if(mBodyContext->mContextTopIndex>-1) {
                  
        PushIntoMisplacedStack(aToken);  

        IF_HOLD(aToken);  // Hold on to this token for later use.

        // If the token is attributed then save those attributes too.    
        if(attrCount > 0) PushMisplacedAttributes(*aNode,mMisplacedContent,attrCount);

        if(gHTMLElements[aChildTag].mSkipTarget) {
          nsAutoString theString;
          PRInt32 lineNo = 0;
          
          result = CollectSkippedContent(aChildTag, theString, lineNo);
          NS_ENSURE_SUCCESS(result, result);

          PushIntoMisplacedStack(mTokenAllocator->CreateTokenOfType(eToken_text,eHTMLTag_text,theString));
          PushIntoMisplacedStack(mTokenAllocator->CreateTokenOfType(eToken_end,aChildTag));      
        }
              
        mFlags |= NS_DTD_FLAG_MISPLACED_CONTENT; // This state would help us in gathering all the misplaced elements
      }//if
    }//if

    if((aChildTag!=aParent) && (gHTMLElements[aParent].HasSpecialProperty(kSaveMisplaced))) {
      
      IF_HOLD(aToken);  // Hold on to this token for later use. Ref Bug. 53695
      
      PushIntoMisplacedStack(aToken);
      // If the token is attributed then save those attributes too.
       if(attrCount > 0) PushMisplacedAttributes(*aNode,mMisplacedContent,attrCount);
    }
  }
  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

This method gets called when an "instruction" token has been encountered in the parse process.

gess 3/25/98

Parameters:
aToken-- next (start) token to be handled
Returns:
PR_TRUE if all went well; PR_FALSE if error occured

Definition at line 2203 of file CNavDTD.cpp.

                                                                {
  NS_PRECONDITION(0!=aToken,kNullToken);

  nsresult  result=NS_OK;

  nsCParserNode* theNode=mNodeAllocator.CreateNode(aToken, mTokenAllocator);
  if(theNode) {

    STOP_TIMER();
    MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::HandleProcessingInstructionToken(), this=%p\n", this));

    result=(mSink) ? mSink->AddProcessingInstruction(*theNode) : NS_OK; 

    IF_FREE(theNode, &mNodeAllocator);

    MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::HandleProcessingInstructionToken(), this=%p\n", this));
    START_TIMER();

  }
  return result;
}

Here is the call graph for this function:

nsresult CNavDTD::HandleSavedTokens ( PRInt32  anIndex) [protected]

This method will be triggered when the end of a table is encountered.

Its primary purpose is to process all the bad-contents pertaining a particular table. The position of the table is the token bank ID.

harishd 03/24/99

Parameters:
aTag- This ought to be a table tag

Definition at line 1972 of file CNavDTD.cpp.

                                                   {
    NS_PRECONDITION(mBodyContext != nsnull && mBodyContext->GetCount() > 0,"invalid context");

    nsresult  result      = NS_OK;

    if(anIndex>kNotFound) {
      PRInt32  theBadTokenCount   = mMisplacedContent.GetSize();

      if(theBadTokenCount > 0) {
        mFlags |= NS_DTD_FLAG_IN_MISPLACED_CONTENT;

        if(mTempContext==nsnull) mTempContext=new nsDTDContext();

        CToken*   theToken;
        eHTMLTags theTag;
        PRInt32   attrCount;
        PRInt32   theTopIndex = anIndex + 1;
        PRInt32   theTagCount = mBodyContext->GetCount();
               
        if (mSink && mSink->IsFormOnStack()) {
          // Do this to synchronize dtd stack and the sink stack.
          // Note: FORM is never on the dtd stack because its always 
          // considered as a leaf. However, in the sink FORM can either
          // be a container or a leaf. Therefore, we have to check
          // with the sink -- Ref: Bug 20087.
          ++anIndex;
        }

        STOP_TIMER()
        MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::HandleSavedTokensAbove(), this=%p\n", this));     
        // Pause the main context and switch to the new context.
        mSink->BeginContext(anIndex);
        MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::HandleSavedTokensAbove(), this=%p\n", this));
        START_TIMER()
      
        // The body context should contain contents only upto the marked position.  
        mBodyContext->MoveEntries(*mTempContext, theTagCount - theTopIndex);
     
        // Now flush out all the bad contents.
        while(theBadTokenCount-- > 0){
          theToken=(CToken*)mMisplacedContent.PopFront();
          if(theToken) {
            theTag       = (eHTMLTags)theToken->GetTypeID();
            attrCount    = (gHTMLElements[theTag].mSkipTarget)? 0:theToken->GetAttributeCount();
            // Put back attributes, which once got popped out, into the
            // tokenizer.  Make sure we preserve their ordering, however!
            // XXXbz would it be faster to get the tokens out with ObjectAt and
            // put them in the tokenizer and then PopFront them all from
            // mMisplacedContent?
            nsDeque temp(nsnull);
            // Put back attributes, which once got popped out, into the tokenizer
            for(PRInt32 j=0;j<attrCount; ++j){
              CToken* theAttrToken = (CToken*)mMisplacedContent.PopFront();
              if(theAttrToken) {
                temp.Push(theAttrToken);
              }
              theBadTokenCount--;
            }
            mTokenizer->PrependTokens(temp);
            
            if(eToken_end==theToken->GetTokenType()) {
              // Ref: Bug 25202
              // Make sure that the BeginContext() is ended only by the call to
              // EndContext(). Ex: <center><table><a></center>.
              // In the Ex. above </center> should not close <center> above table.
              // Doing so will cause the current context to get closed prematurely. 
              eHTMLTags closed = FindAutoCloseTargetForEndTag(theTag, *mBodyContext,
                                                              mDTDMode);
              PRInt32 theIndex = closed != eHTMLTag_unknown
                                 ? mBodyContext->LastOf(closed)
                                 : kNotFound;
              
              if(theIndex!=kNotFound && theIndex<=mBodyContext->mContextTopIndex) {
                IF_FREE(theToken, mTokenAllocator);
                continue;
              }
            }
            result=HandleToken(theToken,mParser);
          }
        }//while
        if(theTopIndex != mBodyContext->GetCount()) {
           CloseContainersTo(theTopIndex,mBodyContext->TagAt(theTopIndex),PR_TRUE);
        }
     
        // Bad-contents were successfully processed. Now, itz time to get
        // back to the original body context state.
        mTempContext->MoveEntries(*mBodyContext, theTagCount - theTopIndex);

        STOP_TIMER()
        MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::HandleSavedTokensAbove(), this=%p\n", this));     
        // Terminate the new context and switch back to the main context
        mSink->EndContext(anIndex);
        MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::HandleSavedTokensAbove(), this=%p\n", this));
        START_TIMER()

        mFlags &= ~NS_DTD_FLAG_IN_MISPLACED_CONTENT;
      }
    }
    return result;
}

Here is the call graph for this function:

This method gets called when a script token has been encountered in the parse process.

n

gess 3/25/98

Parameters:
aToken-- next (start) token to be handled
Returns:
PR_TRUE if all went well; PR_FALSE if error occured

Definition at line 2178 of file CNavDTD.cpp.

                                                              {
  // PRInt32 attrCount=aNode.GetAttributeCount(PR_TRUE);

  STOP_TIMER();
  MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::HandleScriptToken(), this=%p\n", this));

  nsresult result=AddLeaf(aNode);

  mParser->SetCanInterrupt(PR_FALSE);

  MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::HandleScriptToken(), this=%p\n", this));
  START_TIMER();

  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

The following set of methods are used to partially construct the content model (via the sink) according to the type of token.

This method gets called when a start token has been encountered in the parse process.

gess5/11/98

Parameters:
aTokenis the token (of a given type) to be handled
Returns:
error code representing construction state; usually 0.

If the current container can contain this tag, then add it. Otherwise, you have two choices: 1) create an implicit container for this tag to be stored in 2) close the top container, and add this to whatever container ends up on top.

gess 1/04/99

Parameters:
aToken-- next (start) token to be handled
aNode-- CParserNode representing this start token
Returns:
PR_TRUE if all went well; PR_FALSE if error occured

Definition at line 1567 of file CNavDTD.cpp.

                                                 {
  NS_PRECONDITION(0!=aToken,kNullToken);

  //Begin by gathering up attributes...

  nsCParserNode* theNode=mNodeAllocator.CreateNode(aToken, mTokenAllocator);
  
  eHTMLTags     theChildTag=(eHTMLTags)aToken->GetTypeID();
  PRInt16       attrCount=aToken->GetAttributeCount();
  eHTMLTags     theParent=mBodyContext->Last();
  nsresult      result=(0==attrCount) ? NS_OK : CollectAttributes(theNode,theChildTag,attrCount);

  if(NS_OK==result) {
    result=WillHandleStartTag(aToken,theChildTag,*theNode);
    if(NS_OK==result) {
      PRBool isTokenHandled =PR_FALSE;
      PRBool theHeadIsParent=PR_FALSE;

      if(nsHTMLElement::IsSectionTag(theChildTag)){
        switch(theChildTag){
          case eHTMLTag_html:
            if(mBodyContext->GetCount()>0) {
              result=OpenContainer(theNode,theChildTag,PR_FALSE);
              isTokenHandled=PR_TRUE;
            }
            break;
          case eHTMLTag_body:
            if(mFlags & NS_DTD_FLAG_HAS_OPEN_BODY) {
              result=OpenContainer(theNode,theChildTag,PR_FALSE);
              isTokenHandled=PR_TRUE;
            }
            break;
          case eHTMLTag_head:
            if(mFlags & (NS_DTD_FLAG_HAD_BODY | NS_DTD_FLAG_HAD_FRAMESET)) {
              result=HandleOmittedTag(aToken,theChildTag,theParent,theNode);
              isTokenHandled=PR_TRUE;
            }
            break;
          default:
            break;
        }
      }

      PRBool isExclusive=PR_FALSE;
      theHeadIsParent=nsHTMLElement::IsChildOfHead(theChildTag,isExclusive);
      
      switch(theChildTag) { 
        case eHTMLTag_area:
          if(!mOpenMapCount) isTokenHandled=PR_TRUE;

          STOP_TIMER();
          MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::HandleStartToken(), this=%p\n", this));
          
          if (mOpenMapCount>0 && mSink) {
            result=mSink->AddLeaf(*theNode);
            isTokenHandled=PR_TRUE;
          }
          
          MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::HandleStartToken(), this=%p\n", this));
          START_TIMER();
          break;

        case eHTMLTag_image:
          aToken->SetTypeID(theChildTag=eHTMLTag_img);
          break;

        case eHTMLTag_keygen:
          result=HandleKeyGen(theNode);
          isTokenHandled=PR_TRUE;
          break;

        case eHTMLTag_script:
          // Script isn't really exclusively in the head. However, we treat it
          // as such to make sure that we don't pull scripts outside the head
          // into the body.
          isExclusive = !(mFlags & NS_DTD_FLAG_HAD_BODY);
          mFlags |= NS_DTD_FLAG_HAS_OPEN_SCRIPT;

        default:
            break;
      }//switch

      if(!isTokenHandled) {
        PRBool prefersBody =
          gHTMLElements[theChildTag].HasSpecialProperty(kPreferBody);

        // If this tag prefers to be in the head (when neither the head nor the
        // body have been explicitly opened) then check that we haven't seen the
        // body (true until the <body> tag has really been seen). Otherwise,
        // check if the head has been explicitly opened. See bug 307122.
        theHeadIsParent = theHeadIsParent &&
          (isExclusive ||
           (prefersBody
            ? (mFlags & NS_DTD_FLAG_HAS_OPEN_HEAD)
            : !(mFlags & (NS_DTD_FLAG_HAD_BODY | NS_DTD_FLAG_HAD_FRAMESET))));

        if(theHeadIsParent) {
          // These tokens prefer to be in the head.
          result = AddHeadLeaf(theNode);
        }
        else {
          result = HandleDefaultStartToken(aToken,theChildTag,theNode); 
        }
      }

      //now do any post processing necessary on the tag...
      if(NS_OK==result)
        DidHandleStartTag(*theNode,theChildTag);
    }//if
  } //if

  if(kHierarchyTooDeep==result) {
    //reset this error to ok; all that happens here is that given inline tag
    //gets dropped because the stack is too deep. Don't terminate parsing.
    result=NS_OK;
  }

  IF_FREE(theNode, &mNodeAllocator);
  return result;
}

Here is the call graph for this function:

NS_IMETHOD nsIDTD::HandleToken ( CToken aToken,
nsIParser aParser 
) [pure virtual, inherited]

Called during model building phase of parse process.

Each token created during the parse phase is stored in a deque (in the parser) and are passed to this method so that the DTD can process the token. Ultimately, the DTD will transform given token into calls onto a contentsink. gess 3/25/98

Parameters:
aToken-- token object to be put into content model
Returns:
error code (usually 0)

Here is the caller graph for this function:

PRBool CNavDTD::HasOpenContainer ( eHTMLTags  aContainer) const [virtual]

Ask parser if a given container is open ANYWHERE on stack gess5/11/98.

This method allows the caller to determine if a given container is currently open.

Parameters:
idof container you want to test for
Returns:
TRUE if the given container type is open -- otherwise FALSE

gess 11/9/98

Parameters:
@return

Definition at line 2671 of file CNavDTD.cpp.

                                                           {
  PRBool result=PR_FALSE;

  switch(aContainer) {
    case eHTMLTag_form:
      result= !(~mFlags & NS_DTD_FLAG_HAS_OPEN_FORM); break;
    case eHTMLTag_map: 
      result=mOpenMapCount>0; break; 
    default:
      result=mBodyContext->HasOpenContainer(aContainer);
      break;
  }
  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

PRBool CNavDTD::HasOpenContainer ( const eHTMLTags  aTagSet[],
PRInt32  aCount 
) const [virtual]

Ask parser if a given container is open ANYWHERE on stack gess5/11/98.

This method allows the caller to determine if a any member in a set of tags is currently open.

Parameters:
idof container you want to test for
Returns:
TRUE if the given container type is open -- otherwise FALSE

gess 11/9/98

Parameters:
@return

Definition at line 2694 of file CNavDTD.cpp.

                                                                               {

  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;
}

Here is the call graph for this function:

PRBool CNavDTD::IsAlternateTag ( eHTMLTags  aTag) [protected]

Definition at line 1539 of file CNavDTD.cpp.

                                             {
  switch (aTag) {
    case eHTMLTag_noembed:
      return PR_TRUE;
    case eHTMLTag_noscript:
      return (mFlags & NS_IPARSER_FLAG_SCRIPT_ENABLED) != 0;
    case eHTMLTag_iframe:
    case eHTMLTag_noframes:
      return (mFlags & NS_IPARSER_FLAG_FRAMES_ENABLED) != 0;
    default:
      return PR_FALSE;
  }
}
PRBool CNavDTD::IsBlockElement ( PRInt32  aTagID,
PRInt32  aParentID 
) const [protected]

This method is called to determine whether or not the given childtag is a block element.

gess 6June2000

Parameters:
aChildID-- tag id of child
aParentID-- tag id of parent (or eHTMLTag_unknown)
Returns:
PR_TRUE if this tag is a block tag

Definition at line 2415 of file CNavDTD.cpp.

                                                                     {
  PRBool result=PR_FALSE;
  eHTMLTags theTag=(eHTMLTags)aTagID;

  if((theTag>eHTMLTag_unknown) && (theTag<eHTMLTag_userdefined)) {
    result=((gHTMLElements[theTag].IsMemberOf(kBlock))       || 
            (gHTMLElements[theTag].IsMemberOf(kBlockEntity)) || 
            (gHTMLElements[theTag].IsMemberOf(kHeading))     || 
            (gHTMLElements[theTag].IsMemberOf(kPreformatted))|| 
            (gHTMLElements[theTag].IsMemberOf(kList))); 
  }

  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

PRBool CNavDTD::IsInlineElement ( PRInt32  aTagID,
PRInt32  aParentID 
) const [protected]

This method is called to determine whether or not the given childtag is an inline element.

gess 6June2000

Parameters:
aChildID-- tag id of child
aParentID-- tag id of parent (or eHTMLTag_unknown)
Returns:
PR_TRUE if this tag is an inline tag

Definition at line 2439 of file CNavDTD.cpp.

                                                                      {
  PRBool result=PR_FALSE;
  eHTMLTags theTag=(eHTMLTags)aTagID;

  if((theTag>eHTMLTag_unknown) && (theTag<eHTMLTag_userdefined)) {
    result=((gHTMLElements[theTag].IsMemberOf(kInlineEntity))|| 
            (gHTMLElements[theTag].IsMemberOf(kFontStyle))   || 
            (gHTMLElements[theTag].IsMemberOf(kPhrase))      || 
            (gHTMLElements[theTag].IsMemberOf(kSpecial))     || 
            (gHTMLElements[theTag].IsMemberOf(kFormControl)));
  }

  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

PRInt32 CNavDTD::LastOf ( eHTMLTags  aTagSet[],
PRInt32  aCount 
) const [virtual]

Finds the topmost occurance of given tag within context vector stack.

Determine whether the given tag is open anywhere in our context stack.

gess5/11/98

Parameters:
tagto be found
Returns:
index of topmost tag occurance -- may be -1 (kNotFound). Finds the topmost occurance of given tag within context vector stack. gess5/11/98
Parameters:
tagto be found
Returns:
index of topmost tag occurance -- may be -1 (kNotFound).

gess 4/2/98

Parameters:
eHTMLTagstag to be searched for in stack
Returns:
topmost index of tag on stack

Definition at line 1054 of file CNavDTD.cpp.

                                                                {
  int theIndex=0;
  for(theIndex=mBodyContext->GetCount()-1;theIndex>=0;theIndex--){
    if(FindTagInSet((*mBodyContext)[theIndex],aTagSet,aCount)) { 
      return theIndex;
    } 
  } 
  return kNotFound;
}

Here is the call graph for this function:

nsIDTD::NS_IMETHOD_ ( const nsIID ) const [pure virtual, inherited]
nsIDTD::NS_IMETHOD_ ( eAutoDetectResult  ) [pure virtual, inherited]

This method is called to determine if the given DTD can parse a document in a given source-type.

NOTE: Parsing always assumes that the end result will involve storing the result in the main content model.

Parameters:
aParserContext-- the context for this document (knows the content type, document type, parser command, etc).
Returns:
eUnknownDetect if you don't know how to parse it, eValidDetect if you do, but someone may have a better idea, ePrimaryDetect if you think you know best
nsIDTD::NS_IMETHOD_ ( PRBool  ) [inherited]

This method is called to determine whether or not a tag of one type can contain a tag of another type.

gess 3/25/98

Parameters:
aParent-- int tag of parent container
aChild-- int tag of child container
Returns:
PR_TRUE if parent can contain child
nsIDTD::NS_IMETHOD_ ( PRBool  ) const [pure virtual, inherited]

This method gets called to determine whether a given tag is itself a container.

gess 3/25/98

Parameters:
aTag-- tag to test for containership
Returns:
PR_TRUE if given tag can contain other tags
nsIDTD::NS_IMETHOD_ ( void  ) [pure virtual, inherited]

Use this id you want to stop the building content model --------------[ Sets DTD to STOP mode ]---------------- It's recommended to use this method in accordance with the parser's terminate() method.

harishd 07/22/99

Parameters:
@return
nsIDTD::NS_IMETHOD_ ( PRInt32  ) [pure virtual, inherited]

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.

gess4/6/98

Parameters:
aNode-- next node to be added to model
Returns:
TRUE if ok, FALSE if error

Definition at line 2962 of file CNavDTD.cpp.

{
  NS_PRECONDITION(mBodyContext->GetCount() >= 0, kInvalidTagStackPos);

  nsresult result = NS_OK;
  
  if (!(mFlags & NS_DTD_FLAG_HAD_FRAMESET)) {

    mFlags |= NS_DTD_FLAG_HAD_BODY;

    STOP_TIMER();
    MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::OpenBody(), this=%p\n", this));

    result = (mSink) ? mSink->OpenBody(*aNode) : NS_OK; 

    MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::OpenBody(), this=%p\n", this));
    START_TIMER();

    if (!HasOpenContainer(eHTMLTag_body)) {
      mBodyContext->Push(NS_CONST_CAST(nsCParserNode*, aNode), 0, PR_FALSE);
      mTokenizer->PrependTokens(mMisplacedContent);
    }
  }

  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult CNavDTD::OpenContainer ( const nsCParserNode aNode,
eHTMLTags  aTag,
PRBool  aClosedByStartTag,
nsEntryStack aStyleStack = 0 
)

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.

gess4/6/98

Parameters:
aNode-- next node to be added to model
aClosedByStartTag-- ONLY TRUE if the container is being closed by opening of another container.
Returns:
TRUE if ok, FALSE if error

Definition at line 3166 of file CNavDTD.cpp.

{
  NS_PRECONDITION(mBodyContext->GetCount() >= 0, kInvalidTagStackPos);
  
  nsresult   result = NS_OK; 
  PRBool     done   = PR_TRUE;
  PRBool     rs_tag = nsHTMLElement::IsResidualStyleTag(aTag);
  // We need to open transient styles to encompass the <li> so that the bullets
  // inherit the proper colors.
  PRBool     li_tag = aTag == eHTMLTag_li;

  if (rs_tag || li_tag) {
    /***********************************************************************
     *  Here's an interesting problem:
     *
     *  If there's an <a> on the RS-stack, and you're trying to open 
     *  another <a>, the one on the RS-stack should be discarded.
     *
     *  I'm updating OpenTransientStyles to throw old <a>'s away.
     *
     ***********************************************************************/

    OpenTransientStyles(aTag, !li_tag); 
  }

  switch (aTag) {
    case eHTMLTag_html:
      result=OpenHTML(aNode); break;

    case eHTMLTag_head:
      result=OpenHead(aNode); 
      break;

    case eHTMLTag_body:
      {
        eHTMLTags theParent=mBodyContext->Last();
        if (!gHTMLElements[aTag].IsSpecialParent(theParent)) {
          mFlags |= NS_DTD_FLAG_HAS_OPEN_BODY;
          result = OpenBody(aNode); 
        }
        else {
          done = PR_FALSE;
        }
      }
      break;

    case eHTMLTag_style:
    case eHTMLTag_title:
      break;

    case eHTMLTag_map:
      result = OpenMap(aNode);
      break;

    case eHTMLTag_form:
      result = OpenForm(aNode); 
      break;

    case eHTMLTag_frameset:
      result = OpenFrameset(aNode); 
      break;

    case eHTMLTag_script:
      result = HandleScriptToken(aNode);
      break;
    
    case eHTMLTag_noembed:
      // <noembed> is unconditionally alternate content.
      done = PR_FALSE;
      mFlags |= NS_DTD_FLAG_ALTERNATE_CONTENT;
      break;

    case eHTMLTag_noscript:
      // we want to make sure that OpenContainer gets called below since we're
      // not doing it here
      done=PR_FALSE;
      // If the script is disabled noscript should not be
      // in the content model until the layout can somehow
      // turn noscript's display property to block <-- bug 67899
      if(mFlags & NS_IPARSER_FLAG_SCRIPT_ENABLED) {
        mFlags |= NS_DTD_FLAG_ALTERNATE_CONTENT;
      }
      break;
       
    case eHTMLTag_iframe: // Bug 84491 
    case eHTMLTag_noframes:
      done=PR_FALSE;
      if(mFlags & NS_IPARSER_FLAG_FRAMES_ENABLED) {
        mFlags |= NS_DTD_FLAG_ALTERNATE_CONTENT;
      }
      break;

    default:
      done=PR_FALSE;
      break;
  }

  if (!done) {
    STOP_TIMER();
    MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::OpenContainer(), this=%p\n", this));

    result=(mSink) ? mSink->OpenContainer(*aNode) : NS_OK; 

    MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::OpenContainer(), this=%p\n", this));
    START_TIMER();
    // For residual style tags rs_tag will be true and hence
    // the body context will hold an extra reference to the node.
    mBodyContext->Push(NS_CONST_CAST(nsCParserNode*, aNode), aStyleStack, rs_tag); 
  }

  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

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.

gess4/6/98

Parameters:
aNode-- next node to be added to model
Returns:
TRUE if ok, FALSE if error

Definition at line 3018 of file CNavDTD.cpp.

{
  nsresult result = NS_OK;
  if (!(mFlags & NS_DTD_FLAG_HAS_OPEN_FORM)) { // discard nested forms - bug 72639
    STOP_TIMER();
    MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::OpenForm(), this=%p\n", this));

    result = (mSink) ? mSink->OpenForm(*aNode) : NS_OK; 

    MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::OpenForm(), this=%p\n", this));
    START_TIMER();
    if (NS_OK == result) {
      mFlags |= NS_DTD_FLAG_HAS_OPEN_FORM;
    }
  }

  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

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.

gess4/6/98

Parameters:
aNode-- next node to be added to model
Returns:
TRUE if ok, FALSE if error

Definition at line 3118 of file CNavDTD.cpp.

{
  NS_PRECONDITION(mBodyContext->GetCount() >= 0, kInvalidTagStackPos);

  mFlags |= NS_DTD_FLAG_HAD_FRAMESET;
  STOP_TIMER();
  MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::OpenFrameset(), this=%p\n", this));

  nsresult result =( mSink) ? mSink->OpenFrameset(*aNode) : NS_OK; 

  MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::OpenFrameset(), this=%p\n", this));
  START_TIMER();
  mBodyContext->Push(NS_CONST_CAST(nsCParserNode*, aNode), 0, PR_FALSE);

  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

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.

gess4/6/98

Parameters:
aNode-- next node to be added to model
Returns:
TRUE if ok, FALSE if error

Definition at line 2909 of file CNavDTD.cpp.

{
  nsresult result = NS_OK;

  STOP_TIMER();
  MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::OpenHead(), this=%p\n", this));

  if (!(mFlags & NS_DTD_FLAG_HAS_OPEN_HEAD)) {
    mFlags |= NS_DTD_FLAG_HAS_OPEN_HEAD;
    result = mSink ? mSink->OpenHead(*aNode) : NS_OK;
  }

  MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::OpenHead(), this=%p\n", this));
  START_TIMER();

  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

The next set of method open given HTML elements of various types.

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.

gess5/11/98

Parameters:
nodeto be opened in content sink.
Returns:
error code representing error condition-- usually 0.

gess4/22/98

Parameters:
aNode-- next node to be added to model

Definition at line 2860 of file CNavDTD.cpp.

                                                    {
  NS_PRECONDITION(mBodyContext->GetCount() >= 0, kInvalidTagStackPos);

  STOP_TIMER();
  MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::OpenHTML(), this=%p\n", this));

  nsresult result = (mSink) ? mSink->OpenHTML(*aNode) : NS_OK; 

  MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::OpenHTML(), this=%p\n", this));
  START_TIMER();

  // Don't push more than one HTML tag into the stack...
  if (mBodyContext->GetCount() == 0) 
    mBodyContext->Push(NS_CONST_CAST(nsCParserNode*, aNode), 0, PR_FALSE); 

  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

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.

gess4/6/98

Parameters:
aNode-- next node to be added to model
Returns:
TRUE if ok, FALSE if error

Definition at line 3069 of file CNavDTD.cpp.

{
  STOP_TIMER();
  MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::OpenMap(), this=%p\n", this));

  nsresult result = (mSink) ? mSink->OpenMap(*aNode) : NS_OK; 

  MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::OpenMap(), this=%p\n", this));
  START_TIMER();

  if (NS_OK == result) {
    mBodyContext->Push(NS_CONST_CAST(nsCParserNode*, aNode), 0, PR_FALSE);
    ++mOpenMapCount;
  }
  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult CNavDTD::OpenTransientStyles ( eHTMLTags  aChildTag,
PRBool  aCloseInvalid = PR_TRUE 
)

This set of methods is used to create and manage the set of transient styles that occur as a result of poorly formed HTML or bugs in the original navigator.

It is with great trepidation that I offer this method (privately of course).

gess5/11/98

Parameters:
aTag-- represents the transient style tag to be handled.
Returns:
error code -- usually 0

The gets called whenever a container gets opened. This methods job is to take a look at the (transient) style stack, and open any style containers that are there. Of course, we shouldn't bother to open styles that are incompatible with our parent container.

gess6/4/98

Parameters:
tagof the container just opened
Returns:
0 (for now)

Definition at line 2734 of file CNavDTD.cpp.

                                                                              {
  nsresult result=NS_OK;

  // No need to open transient styles in head context - Fix for 41427
  if((mFlags & NS_DTD_FLAG_ENABLE_RESIDUAL_STYLE) && 
     eHTMLTag_newline!=aChildTag && 
     !(mFlags & NS_DTD_FLAG_HAS_OPEN_HEAD)) {

#ifdef  ENABLE_RESIDUALSTYLE

    if(CanContain(eHTMLTag_font,aChildTag)) {

      PRUint32 theCount=mBodyContext->GetCount();
      PRUint32 theLevel=theCount;

        //this first loop is used to determine how far up the containment
        //hierarchy we go looking for residual styles.
      while ( 1<theLevel) {
        eHTMLTags theParentTag = mBodyContext->TagAt(--theLevel);
        if(gHTMLElements[theParentTag].HasSpecialProperty(kNoStyleLeaksIn)) {
          break;
        }
      }

      mFlags &= ~NS_DTD_FLAG_ENABLE_RESIDUAL_STYLE;
      for(;theLevel<theCount;++theLevel){
        nsEntryStack* theStack=mBodyContext->GetStylesAt(theLevel);
        if(theStack){
          // Don't open transient styles if it makes the stack deep, bug 58917.
          if (theCount + theStack->mCount >= FONTSTYLE_IGNORE_DEPTH) {
            break;
          }

          PRInt32 sindex=0;

          nsTagEntry *theEntry=theStack->mEntries;
          PRBool isHeadingOpen = HasOpenTagOfType(kHeading, *mBodyContext);
          for(sindex=0;sindex<theStack->mCount;++sindex){            
            nsCParserNode* theNode=(nsCParserNode*)theEntry->mNode;
            if(1==theNode->mUseCount) {
              eHTMLTags theNodeTag=(eHTMLTags)theNode->GetNodeType();
              if(gHTMLElements[theNodeTag].CanContain(aChildTag,mDTDMode)) {
                theEntry->mParent = theStack;  //we do this too, because this entry differs from the new one we're pushing...
                if(isHeadingOpen) {
                  // Bug 77352
                  // The style system needs to identify residual style tags
                  // within heading tags so that heading tags' size can take
                  // precedence over the residual style tags' size info.. 
                  // *Note: Make sure that this attribute is transient since it
                  // should not get carried over to cases other than heading.
                  CAttributeToken theAttrToken(NS_LITERAL_STRING("_moz-rs-heading"), EmptyString());
                  theNode->AddAttribute(&theAttrToken);
                  result = OpenContainer(theNode,theNodeTag,PR_FALSE,theStack);
                  theNode->PopAttributeToken();
                }
                else { 
                  result = OpenContainer(theNode,theNodeTag,PR_FALSE,theStack);
                }
              }
              else if (aCloseInvalid) {
                //if the node tag can't contain the child tag, then remove the child tag from the style stack
                nsCParserNode* node=theStack->Remove(sindex,theNodeTag);
                IF_FREE(node, &mNodeAllocator);
                --theEntry; //back up by one
              }
            } //if
            ++theEntry;
          } //for
        } //if
      } //for
      mFlags |= NS_DTD_FLAG_ENABLE_RESIDUAL_STYLE;

    } //if

#endif
  }//if
  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

This method gets called when an explicit style close-tag is encountered.

It results in the style tag id being popped from our internal style stack.

gess6/4/98

Parameters:
@return0 if all went well (which it always does)

Definition at line 2837 of file CNavDTD.cpp.

                                        {
  nsresult result=0;

  if(mFlags & NS_DTD_FLAG_ENABLE_RESIDUAL_STYLE) {
#ifdef  ENABLE_RESIDUALSTYLE
    if(nsHTMLElement::IsResidualStyleTag(aTag)) {
      nsCParserNode* node=mBodyContext->PopStyle(aTag);
      IF_FREE(node, &mNodeAllocator);  
    }
#endif
  } //if
  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 356 of file CNavDTD.h.

    {
      NS_ENSURE_ARG_POINTER(aToken);
      aToken->SetNewlineCount(0); // Note: We have already counted the newlines for these tokens

      mMisplacedContent.Push(aToken);
      return NS_OK;
    }

Here is the call graph for this function:

Here is the caller graph for this function:

NS_IMETHOD nsIDTD::WillBuildModel ( const CParserContext aParserContext,
nsITokenizer aTokenizer,
nsIContentSink aSink 
) [pure virtual, inherited]

Here is the caller graph for this function:

nsresult CNavDTD::WillHandleStartTag ( CToken aToken,
eHTMLTags  aTag,
nsIParserNode aNode 
) [protected]

This gets called before we've handled a given start tag.

It's a generic hook to let us do pre processing.

Parameters:
aTokencontains the tag in question
aTagis the tag itself.
aNodeis the node (tag) with associated attributes.
Returns:
TRUE if tag processing should continue; FALSE if the tag has been handled.

Definition at line 1298 of file CNavDTD.cpp.

{ 
  nsresult result = NS_OK;

  //this little gem creates a special attribute for the editor team to use.
  //The attribute only get's applied to unknown tags, and is used by ender
  //(during editing) to display a special icon for unknown tags.
  if(eHTMLTag_userdefined == aTag) {
    CAttributeToken* theToken= NS_STATIC_CAST(CAttributeToken*,mTokenAllocator->CreateTokenOfType(eToken_attribute,aTag));
    if(theToken) {
      theToken->SetKey(NS_LITERAL_STRING("_moz-userdefined"));
      aNode.AddAttribute(theToken);    
    }
  }

  PRInt32 stackDepth = mBodyContext->GetCount();
  if (stackDepth >= FONTSTYLE_IGNORE_DEPTH &&
      gHTMLElements[aTag].IsMemberOf(kFontStyle)) {
    // Prevent bug 58917 by tossing the new kFontStyle start tag
    return kHierarchyTooDeep;
  }

  if (stackDepth >= PHRASE_IGNORE_DEPTH &&
      gHTMLElements[aTag].IsMemberOf(kPhrase)) {
    // Prevent bug 58917 by tossing the new kPhrase start tag
    return kHierarchyTooDeep;
  }

    /**************************************************************************************
     *
     * Now a little code to deal with bug #49687 (crash when layout stack gets too deep)
     * I've also opened this up to any container (not just inlines): re bug 55095
     * Improved to handle bug 55980 (infinite loop caused when DEPTH is exceeded and
     * </P> is encountered by itself (<P>) is continuously produced.
     *
     **************************************************************************************/
  
  if (stackDepth > MAX_REFLOW_DEPTH) {
    if (nsHTMLElement::IsContainer(aTag) &&
        !gHTMLElements[aTag].HasSpecialProperty(kHandleStrayTag)) {
      // Ref. bug 98261,49678,55095,55980
      // Instead of throwing away the current tag close it's parent
      // such that the stack level does not go beyond the max_reflow_depth.
      // This would allow leaf tags, that follow the current tag, to find
      // the correct node. 
      while (stackDepth != MAX_REFLOW_DEPTH && NS_SUCCEEDED(result)) {
        result = CloseContainersTo(mBodyContext->Last(),PR_FALSE);
        --stackDepth;
      }
    }        
  }

  STOP_TIMER()
  MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::WillHandleStartTag(), this=%p\n", this));

  if (aTag <= NS_HTML_TAG_MAX) {
    result = mSink->NotifyTagObservers(&aNode);
  }

  MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::WillHandleStartTag(), this=%p\n", this));
  START_TIMER()

  if(NS_SUCCEEDED(result)) {
    // This code is here to make sure the head is closed before we deal 
    // with any tags that don't belong in the head. If the tag is not exclusive
    // then we do not have enough information, and we have to trust the logic
    // in HandleToken() to not hand us non-exclusive tokens  
    PRBool isExclusive = PR_FALSE;
    PRBool isChildOfHead = 
      gHTMLElements[eHTMLTag_head].IsChildOfHead(aTag, isExclusive);

    if (NS_SUCCEEDED(result) && ((mFlags & NS_DTD_FLAG_HAS_OPEN_HEAD) &&
                                  isExclusive &&
                                  !isChildOfHead)) {
      result = CloseHead();
    }
  }

  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

NS_IMETHOD nsIDTD::WillInterruptParse ( nsIContentSink aSink) [pure virtual, inherited]

If the parse process gets interrupted, this method is called by the parser to notify the DTD that interruption will occur.

gess5/18/98

Returns:
ignored

Here is the caller graph for this function:

NS_IMETHOD nsIDTD::WillResumeParse ( nsIContentSink aSink) [pure virtual, inherited]

If the parse process gets interrupted midway, this method is called by the parser prior to resuming the process.

gess5/18/98

Returns:
ignored

Here is the caller graph for this function:


Member Data Documentation

PRInt32 aChild nsIDTD::const = 0 [inherited]

Definition at line 178 of file nsIDTD.h.

Definition at line 383 of file CNavDTD.h.

Definition at line 394 of file CNavDTD.h.

Definition at line 393 of file CNavDTD.h.

Definition at line 388 of file CNavDTD.h.

Definition at line 401 of file CNavDTD.h.

Definition at line 398 of file CNavDTD.h.

Definition at line 390 of file CNavDTD.h.

nsDeque CNavDTD::mMisplacedContent [protected]

Definition at line 378 of file CNavDTD.h.

Definition at line 392 of file CNavDTD.h.

Definition at line 399 of file CNavDTD.h.

nsParser* CNavDTD::mParser [protected]

Definition at line 385 of file CNavDTD.h.

Definition at line 395 of file CNavDTD.h.

Definition at line 389 of file CNavDTD.h.

Definition at line 381 of file CNavDTD.h.

nsDeque CNavDTD::mSkippedContent [protected]

Definition at line 379 of file CNavDTD.h.

Definition at line 397 of file CNavDTD.h.

Definition at line 384 of file CNavDTD.h.

Definition at line 382 of file CNavDTD.h.

Definition at line 386 of file CNavDTD.h.


The documentation for this class was generated from the following files: