text
/*tag*/ eHTMLTag_span,
/*req-parent excl-parent*/ eHTMLTag_unknown,eHTMLTag_unknown,
/*rootnodes,endrootnodes*/ &gRootTags,&gRootTags,
/*autoclose starttags and endtags*/ 0,0,0,0,
/*parent,incl,exclgroups*/ kSpecial, (kInlineEntity|kSelf|kFlowEntity), kNone,
/*special props, prop-range*/ 0,kDefaultPropRange,
/*special parents,kids*/ 0,0,
},
{
/*tag*/ eHTMLTag_strike,
/*req-parent excl-parent*/ eHTMLTag_unknown,eHTMLTag_unknown,
/*rootnodes,endrootnodes*/ &gRootTags,&gRootTags,
/*autoclose starttags and endtags*/ 0,0,0,0,
/*parent,incl,exclgroups*/ kFontStyle, (kSelf|kInlineEntity), kNone,
/*special props, prop-range*/ 0, kDefaultPropRange,
/*special parents,kids*/ 0,0,
},
{
/*tag*/ eHTMLTag_strong,
/*req-parent excl-parent*/ eHTMLTag_unknown,eHTMLTag_unknown,
/*rootnodes,endrootnodes*/ &gRootTags,&gRootTags,
/*autoclose starttags and endtags*/ 0,0,0,0,
/*parent,incl,exclgroups*/ kPhrase, (kSelf|kInlineEntity), kNone, //changed this to inline per spec; fix bug 44584.
/*special props, prop-range*/ 0, kDefaultPropRange,
/*special parents,kids*/ 0,&gContainsText,
},
{
/*tag*/ eHTMLTag_style,
/*req-parent excl-parent*/ eHTMLTag_unknown,eHTMLTag_unknown,
/*rootnodes,endrootnodes*/ &gRootTags,&gRootTags,
/*autoclose starttags and endtags*/ 0,0,0,0,
/*parent,incl,exclgroups*/ kAllTags - kHeadContent, kCDATA, kNone,
/*special props, prop-range*/ kNoStyleLeaksIn|kPreferHead|kLegalOpen, kNoPropRange,
/*special parents,kids*/ 0,0,
},
{
/*tag*/ eHTMLTag_sub,
/*req-parent excl-parent*/ eHTMLTag_unknown,eHTMLTag_unknown,
/*rootnodes,endrootnodes*/ &gRootTags,&gRootTags,
/*autoclose starttags and endtags*/ 0,0,0,0,
/*parent,incl,exclgroups*/ kSpecial, (kSelf|kInlineEntity), kNone,
/*special props, prop-range*/ 0, kDefaultPropRange,
/*special parents,kids*/ 0,0,
},
{
/*tag*/ eHTMLTag_sup,
/*req-parent excl-parent*/ eHTMLTag_unknown,eHTMLTag_unknown,
/*rootnodes,endrootnodes*/ &gRootTags,&gRootTags,
/*autoclose starttags and endtags*/ 0,0,0,0,
/*parent,incl,exclgroups*/ kSpecial, (kSelf|kInlineEntity), kNone,
/*special props, prop-range*/ 0, kDefaultPropRange,
/*special parents,kids*/ 0,0,
},
{
/*tag*/ eHTMLTag_table,
/*req-parent excl-parent*/ eHTMLTag_unknown,eHTMLTag_unknown,
/*rootnodes,endrootnodes*/ &gTableRootTags,&gTableRootTags,
/*autoclose starttags and endtags*/ 0,&gTableCloseTags,0,0,
/*parent,incl,exclgroups*/ kBlock, kNone, (kSelf|kInlineEntity),
/*special props, prop-range*/ (kBadContentWatch|kNoStyleLeaksIn|kRequiresBody), 2,
/*special parents,kids*/ 0,&gTableKids,
},
{
/*tag*/ eHTMLTag_tbody,
/*requiredAncestor*/ eHTMLTag_table, eHTMLTag_unknown,
/*rootnodes,endrootnodes*/ &gInTable,&gInTable,
/*autoclose starttags and endtags*/ &gTBodyAutoClose,0,0,0,
/*parent,incl,exclgroups*/ kNone, kNone, (kSelf|kInlineEntity),
/*special props, prop-range*/ (kNoPropagate|kBadContentWatch|kNoStyleLeaksIn|kNoStyleLeaksOut), kDefaultPropRange,
/*special parents,kids*/ &gInTable,&gTBodyKids,
},
{
/*tag*/ eHTMLTag_td,
/*requiredAncestor*/ eHTMLTag_table, eHTMLTag_unknown,
/*rootnodes,endrootnodes*/ &gTDRootTags,&gTDRootTags,
/*autoclose starttags and endtags*/ &gTDCloseTags,&gTDCloseTags,0,&gExcludableParents,
/*parent,incl,exclgroups*/ kNone, kFlowEntity, kSelf,
/*special props, prop-range*/ kNoStyleLeaksIn|kNoStyleLeaksOut, kDefaultPropRange,
/*special parents,kids*/ &gTDRootTags,&gBodyKids,
},
{
/*tag*/ eHTMLTag_textarea,
/*req-parent excl-parent*/ eHTMLTag_unknown,eHTMLTag_unknown,
/*rootnodes,endrootnodes*/ &gInForm,&gInForm,
/*autoclose starttags and endtags*/ &gInputAutoClose,0,0,0,
/*parent,incl,exclgroups*/ kFormControl, kPCDATA, kNone,
/*special props, prop-range*/ kRequiresBody|kNoStyleLeaksIn,kDefaultPropRange,
/*special parents,kids*/ &gInForm,&gContainsText,
},
{
/*tag*/ eHTMLTag_tfoot,
/*requiredAncestor*/ eHTMLTag_table, eHTMLTag_unknown,
/*rootnodes,endrootnodes*/ &gInTable,&gInTable,
/*autoclose starttags and endtags*/ &gTBodyAutoClose,0,0,0,
/*parent,incl,exclgroups*/ kNone, kNone, kSelf,
/*special props, prop-range*/ (kNoPropagate|kBadContentWatch|kNoStyleLeaksIn|kNoStyleLeaksOut), kNoPropRange,
/*special parents,kids*/ &gInTable,&gTableElemKids,
},
{
/*tag*/ eHTMLTag_th,
/*requiredAncestor*/ eHTMLTag_table, eHTMLTag_unknown,
/*rootnodes,endrootnodes*/ &gTDRootTags,&gTDRootTags,
/*autoclose starttags and endtags*/ &gTDCloseTags,&gTDCloseTags,0,0,
/*parent,incl,exclgroups*/ kNone, kFlowEntity, kSelf,
/*special props, prop-range*/ (kNoStyleLeaksIn|kNoStyleLeaksOut), kDefaultPropRange,
/*special parents,kids*/ &gTDRootTags,&gBodyKids,
},
{
/*tag*/ eHTMLTag_thead,
/*req-parent excl-parent*/ eHTMLTag_table,eHTMLTag_unknown, //fix bug 54840...
/*rootnodes,endrootnodes*/ &gInTable,&gInTable,
/*autoclose starttags and endtags*/ &gTBodyAutoClose,0,0,0,
/*parent,incl,exclgroups*/ kNone, kNone, kSelf,
/*special props, prop-range*/ (kNoPropagate|kBadContentWatch|kNoStyleLeaksIn|kNoStyleLeaksOut), kNoPropRange,
/*special parents,kids*/ &gInTable,&gTableElemKids,
},
{
/*tag*/ eHTMLTag_template,
/*req-parent excl-parent*/ eHTMLTag_unknown,eHTMLTag_unknown,
/*rootnodes,endrootnodes*/ &gRootTags,&gRootTags,
/*autoclose starttags and endtags*/ 0,0,0,0,
/*parent,incl,exclgroups*/ kNone, kNone, kNone,
/*special props, prop-range*/ 0,kDefaultPropRange,
/*special parents,kids*/ 0,0,
},
{
/*tag*/ eHTMLTag_time,
/*req-parent excl-parent*/ eHTMLTag_unknown,eHTMLTag_unknown,
/*rootnodes,endrootnodes*/ &gRootTags,&gRootTags,
/*autoclose starttags and endtags*/ 0,0,0,0,
/*parent,incl,exclgroups*/ kPhrase, (kSelf|kInlineEntity), kNone,
/*special props, prop-range*/ 0, kDefaultPropRange,
/*special parents,kids*/ 0,0,
},
{
/*tag*/ eHTMLTag_title,
/*req-parent excl-parent*/ eHTMLTag_unknown,eHTMLTag_unknown,
/*rootnodes,endrootnodes*/ &gInHead,&gInHead,
/*autoclose starttags and endtags*/ 0,0,0,0,
/*parent,incl,exclgroups*/ kHeadContent,kPCDATA, kNone,
/*special props, prop-range*/ kNoStyleLeaksIn, kNoPropRange,
/*special parents,kids*/ &gInHead,&gContainsText,
},
{
/*tag*/ eHTMLTag_tr,
/*requiredAncestor*/ eHTMLTag_table, eHTMLTag_unknown,
/*rootnodes,endrootnodes*/ &gTRParents,&gTREndParents,
/*autoclose starttags and endtags*/ &gTRCloseTags,0,0,0,
/*parent,incl,exclgroups*/ kNone, kNone, kInlineEntity,
/*special props, prop-range*/ (kBadContentWatch|kNoStyleLeaksIn|kNoStyleLeaksOut), kNoPropRange,
/*special parents,kids*/ &gTRParents,&gTRKids,
},
{
/*tag*/ eHTMLTag_track,
/*req-parent excl-parent*/ eHTMLTag_unknown,eHTMLTag_unknown,
/*rootnodes,endrootnodes*/ &gTrackParents,&gTrackParents,
/*autoclose starttags and endtags*/ &gPAutoClose, 0, 0,0,
/*parent,incl,exclgroups*/ kSpecial, kNone, kNone,
/*special props, prop-range*/ kNonContainer,kNoPropRange,
/*special parents,kids*/ &gTrackParents,0,
},
{
/*tag*/ eHTMLTag_tt,
/*req-parent excl-parent*/ eHTMLTag_unknown,eHTMLTag_unknown,
/*rootnodes,endrootnodes*/ &gRootTags,&gRootTags,
/*autoclose starttags and endtags*/ 0,0,0,0,
/*parent,incl,exclgroups*/ kFontStyle, (kSelf|kInlineEntity), kNone,
/*special props, prop-range*/ 0, kDefaultPropRange,
/*special parents,kids*/ 0,0,
},
{
/*tag*/ eHTMLTag_u,
/*req-parent excl-parent*/ eHTMLTag_unknown,eHTMLTag_unknown,
/*rootnodes,endrootnodes*/ &gRootTags,&gRootTags,
/*autoclose starttags and endtags*/ 0,0,0,0,
/*parent,incl,exclgroups*/ kFontStyle, (kSelf|kInlineEntity), kNone,
/*special props, prop-range*/ 0, kDefaultPropRange,
/*special parents,kids*/ 0,0,
},
{
/*tag*/ eHTMLTag_ul,
/*req-parent excl-parent*/ eHTMLTag_unknown,eHTMLTag_unknown,
/*rootnodes,endrootnodes*/ &gOLRootTags,&gOLRootTags,
/*autoclose starttags and endtags*/ &gULAutoClose,&gULCloseTags,0,0,
/*parent,incl,exclgroups*/ kList, (kFlowEntity|kSelf), kNone,
/*special props, prop-range*/ 0,kDefaultPropRange,
/*special parents,kids*/ 0,&gULKids,
},
{
/*tag*/ eHTMLTag_var,
/*req-parent excl-parent*/ eHTMLTag_unknown,eHTMLTag_unknown,
/*rootnodes,endrootnodes*/ &gRootTags,&gRootTags,
/*autoclose starttags and endtags*/ 0,0,0,0,
/*parent,incl,exclgroups*/ kPhrase, (kSelf|kInlineEntity), kNone,
/*special props, prop-range*/ 0,kDefaultPropRange,
/*special parents,kids*/ 0,0,
},
{
/*tag*/ eHTMLTag_video,
/*req-parent excl-parent*/ eHTMLTag_unknown,eHTMLTag_unknown,
/*rootnodes,endrootnodes*/ &gRootTags,&gRootTags,
/*autoclose starttags and endtags*/ 0, 0, 0,0,
/*parent,incl,exclgroups*/ kSpecial, (kFlowEntity|kSelf), kNone,
/*special props, prop-range*/ 0,kDefaultPropRange,
/*special parents,kids*/ 0,&gVideoKids,
},
{
/*tag*/ eHTMLTag_wbr,
/*req-parent excl-parent*/ eHTMLTag_unknown,eHTMLTag_unknown,
/*rootnodes,endrootnodes*/ &gRootTags,&gRootTags,
/*autoclose starttags and endtags*/ 0,0,0,0,
/*parent,incl,exclgroups*/ kExtensions, kNone, kNone,
/*special props, prop-range*/ kNonContainer|kRequiresBody,kNoPropRange,
/*special parents,kids*/ 0,0,
},
{
/*tag*/ eHTMLTag_xmp,
/*req-parent excl-parent*/ eHTMLTag_unknown,eHTMLTag_unknown,
/*rootnodes,endrootnodes*/ &gRootTags,&gRootTags,
/*autoclose starttags and endtags*/ 0,0,0,0,
/*parent,incl,exclgroups*/ kInlineEntity|kPreformatted, kCDATA, kNone,
/*special props, prop-range*/ kNone,kDefaultPropRange,
/*special parents,kids*/ 0,0,
},
{
/*tag*/ eHTMLTag_text,
/*req-parent excl-parent*/ eHTMLTag_unknown,eHTMLTag_unknown,
/*rootnodes,endrootnodes*/ &gInBody,&gInBody,
/*autoclose starttags and endtags*/ 0,0,0,0,
/*parent,incl,exclgroups*/ kFlowEntity, kNone, kNone,
/*special props, prop-range*/ kNonContainer|kRequiresBody,kNoPropRange,
/*special parents,kids*/ 0,0,
},
{
// Whitespace must have a parent model of kHeadMisc to ensure that we
// do the right thing for whitespace in the head section of a document.
// (i.e., it must be non-exclusively a child of the head).
/*tag*/ eHTMLTag_whitespace,
/*req-parent excl-parent*/ eHTMLTag_unknown,eHTMLTag_unknown,
/*rootnodes,endrootnodes*/ &gInBody,&gInBody,
/*autoclose starttags and endtags*/ 0,0,0,0,
/*parent,incl,exclgroups*/ kFlowEntity|kHeadMisc, kNone, kNone,
/*special props, prop-range*/ kNonContainer|kLegalOpen,kNoPropRange,
/*special parents,kids*/ 0,0,
},
{
// Newlines must have a parent model of kHeadMisc to ensure that we
// do the right thing for whitespace in the head section of a document.
// (i.e., it must be non-exclusively a child of the head).
/*tag*/ eHTMLTag_newline,
/*req-parent excl-parent*/ eHTMLTag_unknown,eHTMLTag_unknown,
/*rootnodes,endrootnodes*/ &gInBody,&gInBody,
/*autoclose starttags and endtags*/ 0,0,0,0,
/*parent,incl,exclgroups*/ kFlowEntity|kHeadMisc, kNone, kNone,
/*special props, prop-range*/ kNonContainer|kLegalOpen, kNoPropRange,
/*special parents,kids*/ 0,0,
},
{
// Comments must have a parent model of kHeadMisc to ensure that we
// do the right thing for whitespace in the head section of a document
// (i.e., it must be non-exclusively a child of the head).
/*tag*/ eHTMLTag_comment,
/*req-parent excl-parent*/ eHTMLTag_unknown,eHTMLTag_unknown,
/*rootnodes,endrootnodes*/ &gRootTags,&gRootTags,
/*autoclose starttags and endtags*/ 0,0,0,0,
/*parent,incl,exclgroups*/ kFlowEntity|kHeadMisc, kNone, kNone,
/*special props, prop-range*/ kOmitEndTag|kLegalOpen,kNoPropRange,
/*special parents,kids*/ 0,0,
},
{
/*tag*/ eHTMLTag_entity,
/*req-parent excl-parent*/ eHTMLTag_unknown,eHTMLTag_unknown,
/*rootnodes,endrootnodes*/ &gInBody,&gInBody,
/*autoclose starttags and endtags*/ 0,0,0,0,
/*parent,incl,exclgroups*/ kFlowEntity, kNone, kNone,
/*special props, prop-range*/ 0, kNoPropRange,
/*special parents,kids*/ 0,0,
},
{
/*tag*/ eHTMLTag_doctypeDecl,
/*req-parent excl-parent*/ eHTMLTag_unknown,eHTMLTag_unknown,
/*rootnodes,endrootnodes*/ &gRootTags,&gRootTags,
/*autoclose starttags and endtags*/ 0,0,0,0,
/*parent,incl,exclgroups*/ kFlowEntity, kNone, kNone,
/*special props, prop-range*/ kOmitEndTag,kNoPropRange,
/*special parents,kids*/ 0,0,
},
{
/*tag*/ eHTMLTag_markupDecl,
/*req-parent excl-parent*/ eHTMLTag_unknown,eHTMLTag_unknown,
/*rootnodes,endrootnodes*/ &gRootTags,&gRootTags,
/*autoclose starttags and endtags*/ 0,0,0,0,
/*parent,incl,exclgroups*/ kFlowEntity, kNone, kNone,
/*special props, prop-range*/ kOmitEndTag,kNoPropRange,
/*special parents,kids*/ 0,0,
},
{
/*tag*/ eHTMLTag_instruction,
/*req-parent excl-parent*/ eHTMLTag_unknown,eHTMLTag_unknown,
/*rootnodes,endrootnodes*/ 0,0,
/*autoclose starttags and endtags*/ 0,0,0,0,
/*parent,incl,exclgroups*/ kFlowEntity, kNone, kNone,
/*special props, prop-range*/ kOmitEndTag,kNoPropRange,
/*special parents,kids*/ 0,0,
},
{
// Userdefined tags must have a parent model of kHeadMisc to ensure that
// we do the right thing for whitespace in the head section of a document.
// (i.e., it must be non-exclusively a child of the head).
/*tag*/ eHTMLTag_userdefined,
/*req-parent excl-parent*/ eHTMLTag_unknown,eHTMLTag_frameset,
/*rootnodes,endrootnodes*/ &gRootTags,&gRootTags,
/*autoclose starttags and endtags*/ &gBodyAutoClose,0,0,0,
/*parent,incl,exclgroups*/ (kFlowEntity|kHeadMisc), (kInlineEntity|kSelf), kNone, // Treat userdefined as inline element - Ref bug 56245,66772
/*special props, prop-range*/ kPreferBody, kBodyPropRange,
/*special parents,kids*/ &gInNoframes,&gBodyKids,
}
};
#ifdef DEBUG
void CheckElementTable() {
for (eHTMLTags t = eHTMLTag_unknown; t <= eHTMLTag_userdefined; t = eHTMLTags(t + 1)) {
NS_ASSERTION(gHTMLElements[t].mTagID == t, "gHTMLElements entries does match tag list.");
}
}
#endif
/**
* Call this to find the index of a given child, or (if not found)
* the index of its nearest synonym.
*
* @update gess 3/25/98
* @param aTagStack -- list of open tags
* @param aTag -- tag to test for containership
* @return index of kNotFound
*/
int32_t nsHTMLElement::GetIndexOfChildOrSynonym(nsDTDContext& aContext,eHTMLTags aChildTag) {
int32_t theChildIndex=aContext.LastOf(aChildTag);
if(kNotFound==theChildIndex) {
const TagList* theSynTags=gHTMLElements[aChildTag].GetSynonymousTags(); //get the list of tags that THIS tag can close
if(theSynTags) {
theChildIndex=LastOf(aContext,*theSynTags);
}
}
return theChildIndex;
}
/**
*
* @update gess1/21/99
* @param
* @return
*/
bool nsHTMLElement::HasSpecialProperty(int32_t aProperty) const{
bool result=TestBits(mSpecialProperties,aProperty);
return result;
}
/**
*
* @update gess12/13/98
* @param
* @return
*/
bool nsHTMLElement::IsContainer(eHTMLTags aChild) {
bool result=(eHTMLTag_unknown==aChild);
if(!result){
result=!TestBits(gHTMLElements[aChild].mSpecialProperties,kNonContainer);
}
return result;
}
/**
* This tests whether all the bits in the parentbits
* are included in the given set. It may be too
* broad a question for most cases.
*
* @update gess12/13/98
* @param
* @return
*/
bool nsHTMLElement::IsMemberOf(int32_t aSet) const{
return TestBits(aSet,mParentBits);
}
/**
* This tests whether all the bits in the parentbits
* are included in the given set. It may be too
* broad a question for most cases.
*
* @update gess12/13/98
* @param
* @return
*/
bool nsHTMLElement::ContainsSet(int32_t aSet) const{
return TestBits(mParentBits,aSet);
}
/**
* This method determines whether the given tag closes other blocks.
*
* @update gess 12/20/99 -- added H1..H6 to this list.
* @param
* @return
*/
bool nsHTMLElement::IsBlockCloser(eHTMLTags aTag){
bool result=false;
if((aTag>=eHTMLTag_unknown) & (aTag<=eHTMLTag_xmp)){
result=(gHTMLElements[aTag].IsBlock() ||
gHTMLElements[aTag].IsBlockEntity() ||
(kHeading==gHTMLElements[aTag].mParentBits));
if(!result) {
// NOBR is a block closure - Ref. Bug# 24462
// DIR is a block closure - Ref. Bug# 25845
// TD is a block closure - Ref. Bug# 27490
// TR is a block closure - Ref. Bug# 26488
// OBJECT is a block closure - Ref. Bug# 88992
static eHTMLTags gClosers[]={ eHTMLTag_table,eHTMLTag_tbody,
eHTMLTag_td,eHTMLTag_th,
eHTMLTag_tr,eHTMLTag_caption,
eHTMLTag_object,eHTMLTag_applet,
eHTMLTag_ol, eHTMLTag_ul,
eHTMLTag_optgroup,
eHTMLTag_nobr,eHTMLTag_dir};
result=FindTagInSet(aTag,gClosers,sizeof(gClosers)/sizeof(eHTMLTag_body));
}
}
return result;
}
/**
*
* @update gess 01/04/99
* @param
* @return
*/
bool nsHTMLElement::IsInlineEntity(eHTMLTags aTag){
bool result=false;
if((aTag>=eHTMLTag_unknown) & (aTag<=eHTMLTag_xmp)){
result=TestBits(gHTMLElements[aTag].mParentBits,kInlineEntity);
}
return result;
}
/**
*
* @update gess 01/04/99
* @param
* @return
*/
bool nsHTMLElement::IsFlowEntity(eHTMLTags aTag){
bool result=false;
if((aTag>=eHTMLTag_unknown) & (aTag<=eHTMLTag_xmp)){
result=TestBits(gHTMLElements[aTag].mParentBits,kFlowEntity);
}
return result;
}
/**
*
* @update gess 01/04/99
* @param
* @return
*/
bool nsHTMLElement::IsBlockParent(eHTMLTags aTag){
bool result=false;
if((aTag>=eHTMLTag_unknown) & (aTag<=eHTMLTag_xmp)){
result=TestBits(gHTMLElements[aTag].mInclusionBits,kBlockEntity);
}
return result;
}
/**
*
* @update gess 01/04/99
* @param
* @return
*/
bool nsHTMLElement::IsInlineParent(eHTMLTags aTag){
bool result=false;
if((aTag>=eHTMLTag_unknown) & (aTag<=eHTMLTag_xmp)){
result=TestBits(gHTMLElements[aTag].mInclusionBits,kInlineEntity);
}
return result;
}
/**
*
* @update gess 01/04/99
* @param
* @return
*/
bool nsHTMLElement::IsFlowParent(eHTMLTags aTag){
bool result=false;
if((aTag>=eHTMLTag_unknown) & (aTag<=eHTMLTag_xmp)){
result=TestBits(gHTMLElements[aTag].mInclusionBits,kFlowEntity);
}
return result;
}
/**
*
* @update harishd 11/19/99
* @param
* @return
*/
bool nsHTMLElement::IsSpecialParent(eHTMLTags aTag) const{
bool result=false;
if(mSpecialParents) {
if(FindTagInSet(aTag,mSpecialParents->mTags,mSpecialParents->mCount))
result=true;
}
return result;
}
/**
* Tells us whether the given tag opens a section
* @update gess 01/04/99
* @param id of tag
* @return TRUE if opens section
*/
bool nsHTMLElement::IsSectionTag(eHTMLTags aTag){
bool result=false;
switch(aTag){
case eHTMLTag_html:
case eHTMLTag_frameset:
case eHTMLTag_body:
case eHTMLTag_head:
result=true;
break;
default:
result=false;
}
return result;
}
/**
*
* @update gess 01/04/99
* @param
* @return
*/
bool nsHTMLElement::CanContain(eHTMLTags aParent,eHTMLTags aChild,nsDTDMode aMode){
bool result=false;
if((aParent>=eHTMLTag_unknown) && (aParent<=eHTMLTag_userdefined)){
result=gHTMLElements[aParent].CanContain(aChild,aMode);
}
return result;
}
/**
*
* @update gess 01/04/99
* @param
* @return
*/
bool nsHTMLElement::CanExclude(eHTMLTags aChild) const{
bool result=false;
if(gHTMLElements[aChild].HasSpecialProperty(kLegalOpen)) {
// Some tags could be opened anywhere, in the document, as they please.
return false;
}
//Note that special kids takes precedence over exclusions...
if(mSpecialKids) {
if(FindTagInSet(aChild,mSpecialKids->mTags,mSpecialKids->mCount)) {
return false;
}
}
if(mExclusionBits){
if(gHTMLElements[aChild].IsMemberOf(mExclusionBits)) {
result=true;
}
}
return result;
}
/**
*
* @update harishd 03/01/00
* @param
* @return
*/
bool nsHTMLElement::IsExcludableParent(eHTMLTags aParent) const{
bool result=false;
if(!IsTextTag(mTagID)) {
if(mExcludableParents) {
const TagList* theParents=mExcludableParents;
if(FindTagInSet(aParent,theParents->mTags,theParents->mCount))
result=true;
}
if(!result) {
// If you're a block parent make sure that you're not the
// parent of a TABLE element. ex.
// IE & Nav. render this as table with two cells ( which I think is correct ).
// NOTE: If need arise we could use the root node to solve this problem
if(nsHTMLElement::IsBlockParent(aParent)){
switch(mTagID) {
case eHTMLTag_caption:
case eHTMLTag_thead:
case eHTMLTag_tbody:
case eHTMLTag_tfoot:
case eHTMLTag_td:
case eHTMLTag_th:
case eHTMLTag_tr:
result=true;
default:
break;
}
}
}
}
return result;
}
/**
*
* @update gess 01/04/99
* @param
* @return
*/
bool nsHTMLElement::CanOmitEndTag(void) const{
bool result=!IsContainer(mTagID);
if(!result)
result=TestBits(mSpecialProperties,kOmitEndTag);
return result;
}
/**
* Returns whether a given tag can be a direct child of the node of
* an HTML document.
*
* @param aChild The tag in question.
* @param aExclusively [out]Whether or not this tag can *only* appear in the
* head (as opposed to things like which can be
either in the body or the head).
* @return Whether this tag can appear in the head.
*/
bool nsHTMLElement::IsChildOfHead(eHTMLTags aChild,bool& aExclusively) {
aExclusively = true;
// Is this a head-only tag?
if (gHTMLElements[aChild].mParentBits & kHeadContent) {
return true;
}
// If not, check if it can appear in the head.
if (gHTMLElements[aChild].mParentBits & kHeadMisc) {
aExclusively = false;
return true;
}
return false;
}
/**
*
* @update gess12/13/98
* @param
* @return
*/
bool nsHTMLElement::SectionContains(eHTMLTags aChild,bool allowDepthSearch) const {
bool result=false;
const TagList* theRootTags=gHTMLElements[aChild].GetRootTags();
if(theRootTags){
if(!FindTagInSet(mTagID,theRootTags->mTags,theRootTags->mCount)){
eHTMLTags theRootBase=theRootTags->mTags[0];
if((eHTMLTag_unknown!=theRootBase) && (allowDepthSearch))
result=SectionContains(theRootBase,allowDepthSearch);
}
else result=true;
}
return result;
}
/**
* This method should be called to determine if the a tags
* hierarchy needs to be validated.
*
* @update harishd 04/19/00
* @param
* @return
*/
bool nsHTMLElement::ShouldVerifyHierarchy() const {
bool result=false;
// If the tag cannot contain itself then we need to make sure that
// anywhere in the hierarchy we don't nest accidently.
// Ex: . Inner LI has the potential of getting nested
// inside outer LI.If the tag can contain self, Ex: ,
// ( B can contain self )then ask the child ( ) if it requires a containment check.
if(mTagID!=eHTMLTag_userdefined) {
result=HasSpecialProperty(kVerifyHierarchy);
}
return result;
}
/**
*
* @update gess12/13/98
* @param
* @return
*/
bool nsHTMLElement::IsResidualStyleTag(eHTMLTags aChild) {
bool result=false;
switch(aChild) {
case eHTMLTag_a:
case eHTMLTag_b:
case eHTMLTag_bdo:
case eHTMLTag_big:
case eHTMLTag_del:
case eHTMLTag_em:
case eHTMLTag_font:
case eHTMLTag_i:
case eHTMLTag_ins:
case eHTMLTag_q:
case eHTMLTag_s:
case eHTMLTag_small:
case eHTMLTag_strong:
case eHTMLTag_strike:
case eHTMLTag_sub:
case eHTMLTag_sup:
case eHTMLTag_tt:
case eHTMLTag_u:
result=true;
break;
case eHTMLTag_abbr:
case eHTMLTag_acronym:
case eHTMLTag_center:
case eHTMLTag_cite:
case eHTMLTag_code:
case eHTMLTag_dfn:
case eHTMLTag_kbd:
case eHTMLTag_samp:
case eHTMLTag_span:
case eHTMLTag_var:
result=false;
default:
break;
};
return result;
}
/**
*
* @update gess12/13/98
* @param
* @return
*/
bool nsHTMLElement::CanContainType(int32_t aType) const{
int32_t answer=mInclusionBits & aType;
bool result=bool(0!=answer);
return result;
}
/**
*
* @update gess12/13/98
* @param
* @return
*/
bool nsHTMLElement::IsWhitespaceTag(eHTMLTags aChild) {
bool result=false;
switch(aChild) {
case eHTMLTag_newline:
case eHTMLTag_whitespace:
result=true;
break;
default:
break;
}
return result;
}
/**
*
* @update gess12/13/98
* @param
* @return
*/
bool nsHTMLElement::IsTextTag(eHTMLTags aChild) {
bool result=false;
switch(aChild) {
case eHTMLTag_text:
case eHTMLTag_entity:
case eHTMLTag_newline:
case eHTMLTag_whitespace:
result=true;
break;
default:
break;
}
return result;
}
/**
*
* @update gess12/13/98
* @param
* @return
*/
bool nsHTMLElement::CanContainSelf(void) const {
bool result=bool(TestBits(mInclusionBits,kSelf)!=0);
return result;
}
/**
* This method is called to determine (once and for all) whether a start tag
* can close another tag on the stack. This method will return
* false if something prevents aParentTag from closing.
*
* @update gess 12/20/99
* @param aContext is the tag stack we're testing against
* @param aIndex is the index of the tag we want to close
* @param aChildTag is the child we're trying to close
* @return TRUE if we can autoclose the start tag; FALSE otherwise
*/
bool nsHTMLElement::CanAutoCloseTag(nsDTDContext& aContext,int32_t aIndex,
eHTMLTags aChildTag) const{
int32_t thePos;
bool result = true;
eHTMLTags thePrevTag;
for(thePos = aContext.GetCount() - 1; thePos >= aIndex; thePos--) {
thePrevTag = aContext.TagAt(thePos);
if (thePrevTag == eHTMLTag_applet ||
thePrevTag == eHTMLTag_td) {
result = false;
break;
}
}
return result;
}
/**
*
* @update gess 10.17.2000
* @param
* @return
*/
eHTMLTags nsHTMLElement::GetCloseTargetForEndTag(nsDTDContext& aContext,int32_t anIndex,nsDTDMode aMode) const{
eHTMLTags result=eHTMLTag_unknown;
int theCount=aContext.GetCount();
int theIndex=theCount;
if(IsMemberOf(kPhrase)){
while((--theIndex>=anIndex) && (eHTMLTag_unknown==result)){
eHTMLTags theTag = aContext.TagAt(theIndex);
if(theTag != mTagID) {
// Allow phrasals to close userdefined tags. bug 256731
if(eHTMLTag_userdefined == theTag) {
continue; // We can close this.
}
// Fixes a derivative of bug 22842...
if(CanContainType(kBlock)) { // INS/DEL can contain blocks.
if(gHTMLElements[eHTMLTags(theTag)].IsMemberOf(kBlockEntity) ||
gHTMLElements[eHTMLTags(theTag)].IsMemberOf(kFlowEntity)) {
if(HasOptionalEndTag(theTag)) {
continue; // Then I can close it.
}
}
}
// Phrasal elements can close other phrasals, along with fontstyle,
// extensions, and special tags...
if(!gHTMLElements[theTag].IsMemberOf(kSpecial |
kFontStyle |
kPhrase |
kExtensions)) { //fix bug 56665
break; // It's not something I can close
}
}
else {
result=theTag; // Stop because you just found yourself on the stack
break;
}
}
}
else if(IsMemberOf(kSpecial)){
while((--theIndex>=anIndex) && (eHTMLTag_unknown==result)){
eHTMLTags theTag=aContext.TagAt(theIndex);
if(theTag!=mTagID) {
// Special elements can close other specials, along with fontstyle
// extensions, and phrasal tags...
// Added Phrasal to fix bug 26347
if((eHTMLTag_userdefined==theTag) ||
gHTMLElements[theTag].IsSpecialEntity() ||
gHTMLElements[theTag].IsFontStyleEntity()||
gHTMLElements[theTag].IsPhraseEntity() ||
gHTMLElements[theTag].IsMemberOf(kExtensions)) {
continue;
}
else {
// Fixes bug 22842...
if(CanContainType(kBlock)) {
if(gHTMLElements[eHTMLTags(theTag)].IsMemberOf(kBlockEntity) ||
gHTMLElements[eHTMLTags(theTag)].IsMemberOf(kFlowEntity)) {
if(HasOptionalEndTag(theTag)) {
continue; // Then I can close it.
}
}
}
break; // It's not something I can close
}
}
else {
result=theTag; // Stop because you just found yourself on the stack
break;
}
}
}
else if(ContainsSet(kPreformatted) ||
IsMemberOf(kFormControl|kExtensions|kPreformatted)){ //bug54834...
while((--theIndex>=anIndex) && (eHTMLTag_unknown==result)){
eHTMLTags theTag=aContext.TagAt(theIndex);
if(theTag!=mTagID) {
if(!CanContain(theTag,aMode)) {
break; //it's not something I can close
}
}
else {
result=theTag; //stop because you just found yourself on the stack
break;
}
}
}
else if(IsMemberOf(kList)){
while((--theIndex>=anIndex) && (eHTMLTag_unknown==result)){
eHTMLTags theTag=aContext.TagAt(theIndex);
if(theTag!=mTagID) {
if(!CanContain(theTag,aMode)) {
break; //it's not something I can close
}
}
else {
result=theTag; //stop because you just found yourself on the stack
break;
}
}
}
else if(IsResidualStyleTag(mTagID)){
// Before finding a close target, for the current tag, make sure
// that the tag above does not gate.
// Note: we intentionally make 2 passes:
// The first pass tries to exactly match, the 2nd pass matches the group.
const TagList* theRootTags=gHTMLElements[mTagID].GetEndRootTags();
int32_t theIndexCopy=theIndex;
while(--theIndex>=anIndex){
eHTMLTags theTag=aContext.TagAt(theIndex);
if(theTag == mTagID) {
return theTag; // we found our target.
}
else if (!CanContain(theTag,aMode) ||
(theRootTags && FindTagInSet(theTag,theRootTags->mTags,theRootTags->mCount))) {
// If you cannot contain this tag then
// you cannot close it either. It looks like
// the tag trying to close is misplaced.
// In the following Exs. notice the misplaced /font:
// Ex. -- Ref. bug 37618
// Ex. -- Ref. bug 98187
return eHTMLTag_unknown;
}
}
theIndex=theIndexCopy;
while(--theIndex>=anIndex){
eHTMLTags theTag=aContext.TagAt(theIndex);
if(gHTMLElements[theTag].IsMemberOf(mParentBits)) {
return theTag;
}
}
}
else if(gHTMLElements[mTagID].IsTableElement()) {
//This fixes 57378...
//example: which didn't close the
int32_t theLastTable=aContext.LastOf(eHTMLTag_table);
int32_t theLastOfMe=aContext.LastOf(mTagID);
if(theLastTable=anIndex) && (eHTMLTag_unknown==result)){
eHTMLTags theTag = aContext.TagAt(theIndex);
if (theTag == mTagID) {
result = theTag;
break;
}
if (!CanContain(theTag, aMode)) {
break;
}
}
}
else if (mTagID == eHTMLTag_head) {
while (--theIndex >= anIndex) {
eHTMLTags tag = aContext.TagAt(theIndex);
if (tag == eHTMLTag_html) {
// HTML gates head closing, but the head should never be the parent of
// an html tag.
break;
}
if (tag == eHTMLTag_head) {
result = eHTMLTag_head;
break;
}
}
}
return result;
}
/**
* See whether this tag can DIRECTLY contain the given child.
* @update gess12/13/98
* @param
* @return
*/
bool nsHTMLElement::CanContain(eHTMLTags aChild,nsDTDMode aMode) const{
if(IsContainer(mTagID)){
if(gHTMLElements[aChild].HasSpecialProperty(kLegalOpen)) {
// Some tags could be opened anywhere, in the document, as they please.
return true;
}
if(mTagID==aChild) {
return CanContainSelf(); //not many tags can contain themselves...
}
const TagList* theCloseTags=gHTMLElements[aChild].GetAutoCloseStartTags();
if(theCloseTags){
if(FindTagInSet(mTagID,theCloseTags->mTags,theCloseTags->mCount))
return false;
}
if(gHTMLElements[aChild].mExcludableParents) {
const TagList* theParents=gHTMLElements[aChild].mExcludableParents;
if(FindTagInSet(mTagID,theParents->mTags,theParents->mCount))
return false;
}
if(gHTMLElements[aChild].IsExcludableParent(mTagID))
return false;
if(gHTMLElements[aChild].IsBlockCloser(aChild)){
if(nsHTMLElement::IsBlockParent(mTagID)){
return true;
}
}
if(nsHTMLElement::IsInlineEntity(aChild)){
if(nsHTMLElement::IsInlineParent(mTagID)){
return true;
}
}
if(nsHTMLElement::IsFlowEntity(aChild)) {
if(nsHTMLElement::IsFlowParent(mTagID)){
return true;
}
}
if(nsHTMLElement::IsTextTag(aChild)) {
// Allow to contain text.
if(nsHTMLElement::IsInlineParent(mTagID) || CanContainType(kCDATA)){
return true;
}
}
if(CanContainType(gHTMLElements[aChild].mParentBits)) {
return true;
}
if(mSpecialKids) {
if(FindTagInSet(aChild,mSpecialKids->mTags,mSpecialKids->mCount)) {
return true;
}
}
// Allow to contain
only in Quirks mode, bug 43678 and bug 91927
if (aChild == eHTMLTag_table && mTagID == eHTMLTag_p && aMode == eDTDMode_quirks) {
return true;
}
}
return false;
}
#ifdef DEBUG
void nsHTMLElement::DebugDumpContainment(const char* aFilename,const char* aTitle){
}
void nsHTMLElement::DebugDumpMembership(const char* aFilename){
}
void nsHTMLElement::DebugDumpContainType(const char* aFilename){
}
#endif