Back to index

lightning-sunbird  0.9+nobinonly
Defines | Enumerations | Functions
CNavDTD.cpp File Reference
#include "nsDebug.h"
#include "nsIAtom.h"
#include "CNavDTD.h"
#include "nsHTMLTokens.h"
#include "nsCRT.h"
#include "nsParser.h"
#include "nsIParser.h"
#include "nsIHTMLContentSink.h"
#include "nsScanner.h"
#include "prenv.h"
#include "prtypes.h"
#include "prio.h"
#include "plstr.h"
#include "nsDTDUtils.h"
#include "nsHTMLTokenizer.h"
#include "nsTime.h"
#include "nsParserNode.h"
#include "nsHTMLEntities.h"
#include "nsLinebreakConverter.h"
#include "nsIFormProcessor.h"
#include "nsVoidArray.h"
#include "nsReadableUtils.h"
#include "nsUnicharUtils.h"
#include "prmem.h"
#include "nsIServiceManager.h"
#include "nsElementTable.h"

Go to the source code of this file.

Defines

#define ENABLE_RESIDUALSTYLE
#define FONTSTYLE_IGNORE_DEPTH   (MAX_REFLOW_DEPTH*80/100)
#define PHRASE_IGNORE_DEPTH   (MAX_REFLOW_DEPTH*90/100)
#define STOP_TIMER()
#define START_TIMER()
#define NS_DTD_FLAG_NONE   0x00000000
#define NS_DTD_FLAG_HAS_OPEN_HEAD   0x00000001
#define NS_DTD_FLAG_HAS_OPEN_BODY   0x00000002
#define NS_DTD_FLAG_HAS_OPEN_FORM   0x00000004
#define NS_DTD_FLAG_HAS_OPEN_SCRIPT   0x00000008
#define NS_DTD_FLAG_HAD_BODY   0x00000010
#define NS_DTD_FLAG_HAD_FRAMESET   0x00000020
#define NS_DTD_FLAG_ENABLE_RESIDUAL_STYLE   0x00000040
#define NS_DTD_FLAG_ALTERNATE_CONTENT   0x00000080
#define NS_DTD_FLAG_MISPLACED_CONTENT   0x00000100
#define NS_DTD_FLAG_IN_MISPLACED_CONTENT   0x00000200
#define NS_DTD_FLAG_STOP_PARSING   0x00000400

Enumerations

enum  eProcessRule { eNormalOp, eLetInlineContainBlock }

Functions

static NS_DEFINE_IID (kISupportsIID, NS_ISUPPORTS_IID)
static NS_DEFINE_IID (kIDTDIID, NS_IDTD_IID)
static NS_DEFINE_IID (kClassIID, NS_INAVHTML_DTD_IID)
static NS_DEFINE_CID (kFormProcessorCID, NS_FORMPROCESSOR_CID)
static PRBool DoesRequireBody (CToken *aToken, nsITokenizer *aTokenizer)
 --- Backwards compatibility --- Use this method to determine if the tag in question needs a BODY.
static PRBool HasOpenTagOfType (PRInt32 aType, const nsDTDContext &aContext)
 Returns whether or not there is a tag of type aType open on aContext.
static void InPlaceConvertLineEndings (nsAString &aString)
static PRBool CanBeContained (eHTMLTags aChildTag, nsDTDContext &aContext)
 This method is called to determine whether or not the child tag is happy being OPENED in the context of the current tag stack.
static void PushMisplacedAttributes (nsIParserNode &aNode, nsDeque &aDeque, PRInt32 &aCount)
static PRBool HasCloseablePeerAboveRoot (const TagList &aRootTagList, nsDTDContext &aContext, eHTMLTags aTag, PRBool anEndTag)
 Call this to see if you have a closeable peer on the stack that is ABOVE one of its root tags.
static eHTMLTags FindAutoCloseTargetForEndTag (eHTMLTags aCurrentTag, nsDTDContext &aContext, nsDTDMode aMode)
 This method is called to determine whether or not an END tag can be autoclosed.
static void StripWSFollowingTag (eHTMLTags aChildTag, nsITokenizer *aTokenizer, nsTokenAllocator *aTokenAllocator, PRInt32 &aNewlineCount)

Define Documentation

Definition at line 41 of file CNavDTD.cpp.

Definition at line 77 of file CNavDTD.cpp.

Definition at line 120 of file CNavDTD.cpp.

Definition at line 119 of file CNavDTD.cpp.

#define NS_DTD_FLAG_HAD_BODY   0x00000010

Definition at line 117 of file CNavDTD.cpp.

#define NS_DTD_FLAG_HAD_FRAMESET   0x00000020

Definition at line 118 of file CNavDTD.cpp.

Definition at line 114 of file CNavDTD.cpp.

Definition at line 115 of file CNavDTD.cpp.

Definition at line 113 of file CNavDTD.cpp.

Definition at line 116 of file CNavDTD.cpp.

Definition at line 122 of file CNavDTD.cpp.

Definition at line 121 of file CNavDTD.cpp.

#define NS_DTD_FLAG_NONE   0x00000000

Definition at line 112 of file CNavDTD.cpp.

#define NS_DTD_FLAG_STOP_PARSING   0x00000400

Definition at line 123 of file CNavDTD.cpp.

Definition at line 78 of file CNavDTD.cpp.

Definition at line 104 of file CNavDTD.cpp.

Definition at line 103 of file CNavDTD.cpp.


Enumeration Type Documentation

Enumerator:
eNormalOp 
eLetInlineContainBlock 

Definition at line 1137 of file CNavDTD.cpp.


Function Documentation

static PRBool CanBeContained ( eHTMLTags  aChildTag,
nsDTDContext aContext 
) [static]

This method is called to determine whether or not the child tag is happy being OPENED in the context of the current tag stack.

This is only called if the current parent thinks it wants to contain the given childtag.

Parameters:
aChildTag-- tag enum of child to be opened
aTagStack-- ref to current tag stack in DTD.
Returns:
PR_TRUE if child agrees to be opened here.

Definition at line 1075 of file CNavDTD.cpp.

                                                                  {

  /* #    Interesting test cases:       Result:
   * 1.   <UL><LI>..<B>..<LI>           inner <LI> closes outer <LI>
   * 2.   <CENTER><DL><DT><A><CENTER>   allow nested <CENTER>
   * 3.   <TABLE><TR><TD><TABLE>...     allow nested <TABLE>
   * 4.   <FRAMESET> ... <FRAMESET>
   */

  //Note: This method is going away. First we need to get the elementtable to do closures right, and
  //      therefore we must get residual style handling to work.

  //the changes to this method were added to fix bug 54651...

  PRBool  result=PR_TRUE;
  PRInt32 theCount=aContext.GetCount();

  if(0<theCount){
    const TagList* theRootTags=gHTMLElements[aChildTag].GetRootTags();
    const TagList* theSpecialParents=gHTMLElements[aChildTag].GetSpecialParents();
    if(theRootTags) {
      PRInt32 theRootIndex=LastOf(aContext,*theRootTags);
      PRInt32 theSPIndex=(theSpecialParents) ? LastOf(aContext,*theSpecialParents) : kNotFound;  
      PRInt32 theChildIndex=nsHTMLElement::GetIndexOfChildOrSynonym(aContext,aChildTag);
      PRInt32 theTargetIndex=(theRootIndex>theSPIndex) ? theRootIndex : theSPIndex;

      if((theTargetIndex==theCount-1) ||
        ((theTargetIndex==theChildIndex) && gHTMLElements[aChildTag].CanContainSelf())) {
        result=PR_TRUE;
      }
      else {
        
        result=PR_FALSE;

        static eHTMLTags gTableElements[]={eHTMLTag_td,eHTMLTag_th};

        PRInt32 theIndex=theCount-1;
        while(theChildIndex<theIndex) {
          eHTMLTags theParentTag=aContext.TagAt(theIndex--);
          if (gHTMLElements[theParentTag].IsMemberOf(kBlockEntity)  || 
              gHTMLElements[theParentTag].IsMemberOf(kHeading)      || 
              gHTMLElements[theParentTag].IsMemberOf(kPreformatted) || 
              gHTMLElements[theParentTag].IsMemberOf(kFormControl)  ||  //fixes bug 44479
              gHTMLElements[theParentTag].IsMemberOf(kList)) {
            if(!HasOptionalEndTag(theParentTag)) {
              result=PR_TRUE;
              break;
            }
          }
          else if(FindTagInSet(theParentTag,gTableElements,sizeof(gTableElements)/sizeof(eHTMLTag_unknown))){
            result=PR_TRUE;  //added this to catch a case we missed; bug 57173.
            break;
          }
        }
      }
    }
  }

  return result;

}

Here is the call graph for this function:

Here is the caller graph for this function:

static PRBool DoesRequireBody ( CToken aToken,
nsITokenizer aTokenizer 
) [static]

--- Backwards compatibility --- Use this method to determine if the tag in question needs a BODY.


Definition at line 626 of file CNavDTD.cpp.

                                                                {

  PRBool result=PR_FALSE;

  if(aToken) {
    eHTMLTags theTag=(eHTMLTags)aToken->GetTypeID();
    if(gHTMLElements[theTag].HasSpecialProperty(kRequiresBody)) {
      if(theTag==eHTMLTag_input) {
        // IE & Nav4x opens up a body for type=text - Bug 66985
        PRInt32 ac=aToken->GetAttributeCount();
        for(PRInt32 i=0; i<ac; ++i) {
          CAttributeToken* attr=NS_STATIC_CAST(CAttributeToken*,aTokenizer->GetTokenAt(i));
          const nsSubstring& name=attr->GetKey();
          const nsAString& value=attr->GetValue();

          if((name.EqualsLiteral("type") || 
              name.EqualsLiteral("TYPE"))    
             && 
             !(value.EqualsLiteral("hidden") || 
             value.EqualsLiteral("HIDDEN"))) {
            result=PR_TRUE; 
            break;
          }
        }//for
      }
      else {
        result=PR_TRUE;
      }
    }
  }
 
  return result;
}

Here is the call graph for this function:

static eHTMLTags FindAutoCloseTargetForEndTag ( eHTMLTags  aCurrentTag,
nsDTDContext aContext,
nsDTDMode  aMode 
) [static]

This method is called to determine whether or not an END tag can be autoclosed.

This means that based on the current context, the stack should be closed to the nearest matching tag.

Parameters:
aTag-- tag enum of child to be tested
Returns:
PR_TRUE if autoclosure should occur

Definition at line 1727 of file CNavDTD.cpp.

                                                                                                     {
  int theTopIndex=aContext.GetCount();
  eHTMLTags thePrevTag=aContext.Last();
 
  if(nsHTMLElement::IsContainer(aCurrentTag)){
    PRInt32 theChildIndex=nsHTMLElement::GetIndexOfChildOrSynonym(aContext,aCurrentTag);
    
    if(kNotFound<theChildIndex) {
      if(thePrevTag==aContext[theChildIndex]){
        return aContext[theChildIndex];
      } 
    
      if(nsHTMLElement::IsBlockCloser(aCurrentTag)) {

          /*here's what to do: 
              Our here is sitting at aChildIndex. There are other tags above it
              on the stack. We have to try to close them out, but we may encounter
              one that can block us. The way to tell is by comparing each tag on
              the stack against our closeTag and rootTag list. 

              For each tag above our hero on the stack, ask 3 questions:
                1. Is it in the closeTag list? If so, the we can skip over it
                2. Is it in the rootTag list? If so, then we're gated by it
                3. Otherwise its non-specified and we simply presume we can close it.
          */
 
        const TagList* theCloseTags=gHTMLElements[aCurrentTag].GetAutoCloseEndTags();
        const TagList* theRootTags=gHTMLElements[aCurrentTag].GetEndRootTags();
      
        if(theCloseTags){  
            //at a min., this code is needed for H1..H6
        
          while(theChildIndex<--theTopIndex) {
            eHTMLTags theNextTag=aContext[theTopIndex];
            if(PR_FALSE==FindTagInSet(theNextTag,theCloseTags->mTags,theCloseTags->mCount)) {
              if(PR_TRUE==FindTagInSet(theNextTag,theRootTags->mTags,theRootTags->mCount)) {
                return eHTMLTag_unknown; //we encountered a tag in root list so fail (because we're gated).
              }
              //otherwise presume it's something we can simply ignore and continue search...
            }
            //otherwise its in the close list so skip to next tag...
          } 
          eHTMLTags theTarget=aContext.TagAt(theChildIndex);
          if(aCurrentTag!=theTarget) {
            aCurrentTag=theTarget; //use the synonym.
          }
          return aCurrentTag; //if you make it here, we're ungated and found a target!
        }//if
        else if(theRootTags) {
          //since we didn't find any close tags, see if there is an instance of aCurrentTag
          //above the stack from the roottag.
          if(HasCloseablePeerAboveRoot(*theRootTags,aContext,aCurrentTag,PR_TRUE))
            return aCurrentTag;
          else return eHTMLTag_unknown;
        }
      } //if blockcloser
      else{
        //Ok, a much more sensible approach for non-block closers; use the tag group to determine closure:
        //For example: %phrasal closes %phrasal, %fontstyle and %special
        return gHTMLElements[aCurrentTag].GetCloseTargetForEndTag(aContext,theChildIndex,aMode);
      }
    }//if
  } //if
  return eHTMLTag_unknown;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static PRBool HasCloseablePeerAboveRoot ( const TagList aRootTagList,
nsDTDContext aContext,
eHTMLTags  aTag,
PRBool  anEndTag 
) [static]

Call this to see if you have a closeable peer on the stack that is ABOVE one of its root tags.

gess 4/11/99

Parameters:
aRootTagList-- list of root tags for aTag
aTag-- tag to test for containership
Returns:
PR_TRUE if given tag can contain other tags

Definition at line 1698 of file CNavDTD.cpp.

                                                                                                                    {
  PRInt32   theRootIndex=LastOf(aContext,aRootTagList);  
  const TagList*  theCloseTags=(anEndTag) ? gHTMLElements[aTag].GetAutoCloseEndTags() : gHTMLElements[aTag].GetAutoCloseStartTags();
  PRInt32 theChildIndex=-1;

  if(theCloseTags) {
    theChildIndex=LastOf(aContext,*theCloseTags);
  }
  else {
    if((anEndTag) || (!gHTMLElements[aTag].CanContainSelf()))
      theChildIndex=aContext.LastOf(aTag);
  }
    // I changed this to theRootIndex<=theChildIndex so to handle this case:
    //  <SELECT><OPTGROUP>...</OPTGROUP>
    //
  return PRBool(theRootIndex<=theChildIndex);  
}

Here is the call graph for this function:

Here is the caller graph for this function:

static PRBool HasOpenTagOfType ( PRInt32  aType,
const nsDTDContext aContext 
) [static]

Returns whether or not there is a tag of type aType open on aContext.

Definition at line 664 of file CNavDTD.cpp.

                                                                     {
  PRInt32 count = aContext.GetCount();

  while (--count >= 0) {
    if (gHTMLElements[aContext.TagAt(count)].IsMemberOf(aType)) {
      return PR_TRUE;
    }
  }

  return PR_FALSE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void InPlaceConvertLineEndings ( nsAString &  aString) [static]

Definition at line 677 of file CNavDTD.cpp.

{
    // go from '\r\n' or '\r' to '\n'
  nsAString::iterator iter;
  aString.BeginWriting(iter);

  PRUnichar* S = iter.get();
  size_t N = iter.size_forward();

    // this fragment must be the entire string because
    //  (a) no multi-fragment string is writable, so only an illegal cast could give us one, and
    //  (b) else we would have to do more work (watching for |to| to fall off the end)
  NS_ASSERTION(aString.Length() == N, "You cheated... multi-fragment strings are never writable!");

    // we scan/convert in two phases (but only one pass over the string)
    // until we have to skip a character, we only need to touch end-of-line chars
    // after that, we'll have to start moving every character we want to keep

    // use array indexing instead of pointers, because compilers optimize that better


    // this first loop just converts line endings... no characters get moved
  size_t i = 0;
  PRBool just_saw_cr = PR_FALSE;
  for ( ; i < N; ++i )
    {
        // if it's something we need to convert...
      if ( S[i] == '\r' )
        {
          S[i] = '\n';
          just_saw_cr = PR_TRUE;
        }
      else
        {
            // else, if it's something we need to skip...
            //   i.e., a '\n' immediately following a '\r',
            //   then we need to start moving any character we want to keep
            //   and we have a second loop for that, so get out of this one
          if ( S[i] == '\n' && just_saw_cr )
            break;

          just_saw_cr = PR_FALSE;
        }
    }


    // this second loop handles the rest of the buffer, moving characters down
    //  _and_ converting line-endings as it goes
    //  start the loop at |from = i| so that that |just_saw_cr| gets cleared automatically
  size_t to = i;
  for ( size_t from = i; from < N; ++from )
    {
        // if it's something we need to convert...
      if ( S[from] == '\r' )
        {
          S[to++] = '\n';
          just_saw_cr = PR_TRUE;
        }
      else
        {
            // else, if it's something we need to copy...
            //  i.e., NOT a '\n' immediately following a '\r'
          if ( S[from] != '\n' || !just_saw_cr )
            S[to++] = S[from];

          just_saw_cr = PR_FALSE;
        }
    }

    // if we chopped characters out of the string, we need to shorten it logically
  if ( to < N )
    aString.SetLength(to);
}

Here is the caller graph for this function:

static NS_DEFINE_CID ( kFormProcessorCID  ,
NS_FORMPROCESSOR_CID   
) [static]
static NS_DEFINE_IID ( kISupportsIID  ,
NS_ISUPPORTS_IID   
) [static]
static NS_DEFINE_IID ( kIDTDIID  ,
NS_IDTD_IID   
) [static]
static NS_DEFINE_IID ( kClassIID  ,
NS_INAVHTML_DTD_IID   
) [static]
static void PushMisplacedAttributes ( nsIParserNode aNode,
nsDeque &  aDeque,
PRInt32 aCount 
) [static]

Definition at line 1379 of file CNavDTD.cpp.

                                                                                          {
  if(aCount > 0) {
    CToken* theAttrToken=nsnull;
    nsCParserNode* theAttrNode = (nsCParserNode*)&aNode;
    if(theAttrNode) {
      while(aCount){ 
        theAttrToken=theAttrNode->PopAttributeTokenFront();
        if(theAttrToken) {
          theAttrToken->SetNewlineCount(0);
          aDeque.Push(theAttrToken);
        }
        aCount--;
      }//while
    }//if
  }//if
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void StripWSFollowingTag ( eHTMLTags  aChildTag,
nsITokenizer aTokenizer,
nsTokenAllocator aTokenAllocator,
PRInt32 aNewlineCount 
) [static]
Parameters:
@paramgess 10/11/99
Returns:
nada

Definition at line 1800 of file CNavDTD.cpp.

                                                                                                                                       { 
  CToken* theToken= (aTokenizer)? aTokenizer->PeekToken():nsnull; 

  if(aTokenAllocator) { 
    while(theToken) { 
      eHTMLTokenTypes theType=eHTMLTokenTypes(theToken->GetTokenType()); 
      switch(theType) { 
        case eToken_newline: ++aNewlineCount; 
        case eToken_whitespace: 
          theToken=aTokenizer->PopToken();
          IF_FREE(theToken, aTokenAllocator);
          theToken=aTokenizer->PeekToken(); 
          break; 
        default: 
          theToken=0; 
          break; 
      } 
    } 
  } 
}

Here is the call graph for this function:

Here is the caller graph for this function: