result = PRBool(localTrue == ValueIncludes(value, attr->mValue, isCaseSensitive));
result = localTrue == ValueIncludes(value, attr->mValue, isCaseSensitive);
static PRBool SelectorMatches(RuleProcessorData &data,                              nsCSSSelector* aSelector,                              PRInt32 aStateMask, // states NOT to test                              PRInt8 aNegationIndex) {  // if we are dealing with negations, reverse the values of PR_TRUE and PR_FALSE  PRBool  localFalse = PRBool(0 < aNegationIndex);  PRBool  localTrue = PRBool(0 == aNegationIndex);  PRBool  result = localTrue;  // Do not perform the test if aNegationIndex==1  // because it then contains only negated IDs, classes, attributes and pseudo-  // classes  if (1 != aNegationIndex) {    if (kNameSpaceID_Unknown != aSelector->mNameSpace) {      if (data.mNameSpaceID != aSelector->mNameSpace) {        result = localFalse;      }    }    if (localTrue == result) {      if ((nsnull != aSelector->mTag) && (aSelector->mTag != data.mContentTag)) {        result = localFalse;      }    }    // optimization : bail out early if we can    if (!result) {      return PR_FALSE;    }  }  result = PR_TRUE;  if (nsnull != aSelector->mPseudoClassList) {  // test for pseudo class match    // first-child, root, lang, active, focus, hover, link, visited...    // XXX disabled, enabled, selected, selection    nsAtomList* pseudoClass = aSelector->mPseudoClassList;    while (result && (nsnull != pseudoClass)) {      if ((nsCSSAtoms::firstChildPseudo == pseudoClass->mAtom) ||          (nsCSSAtoms::firstNodePseudo == pseudoClass->mAtom) ) {        nsIContent* firstChild = nsnull;        nsIContent* parent = data.mParentContent;        if (parent) {          PRInt32 index = -1;          do {            parent->ChildAt(++index, firstChild);            if (firstChild) { // stop at first non-comment and non-whitespace node (and non-text node for firstChild)              if (IsSignificantChild(firstChild, (nsCSSAtoms::firstNodePseudo == pseudoClass->mAtom))) {                break;              }              NS_RELEASE(firstChild);            }            else {              break;            }          } while (1 == 1);        }        result = PRBool(localTrue == (data.mContent == firstChild));        NS_IF_RELEASE(firstChild);      }      else if ((nsCSSAtoms::lastChildPseudo == pseudoClass->mAtom) ||               (nsCSSAtoms::lastNodePseudo == pseudoClass->mAtom)) {        nsIContent* lastChild = nsnull;        nsIContent* parent = data.mParentContent;        if (parent) {          PRInt32 index;          parent->ChildCount(index);          do {            parent->ChildAt(--index, lastChild);            if (lastChild) { // stop at first non-comment and non-whitespace node (and non-text node for lastChild)              if (IsSignificantChild(lastChild, (nsCSSAtoms::lastNodePseudo == pseudoClass->mAtom))) {                break;              }              NS_RELEASE(lastChild);            }            else {              break;            }          } while (1 == 1);        }        result = PRBool(localTrue == (data.mContent == lastChild));        NS_IF_RELEASE(lastChild);      }      else if (nsCSSAtoms::emptyPseudo == pseudoClass->mAtom) {        nsIContent* child = nsnull;        nsIContent* element = data.mContent;        PRInt32 index = -1;        do {          element->ChildAt(++index, child);          if (child) { // stop at first non-comment and non-whitespace node            if (IsSignificantChild(child, PR_TRUE)) {              break;            }            NS_RELEASE(child);          }          else {            break;          }        } while (1 == 1);        result = PRBool(localTrue == (child == nsnull));        NS_IF_RELEASE(child);      }      else if (nsCSSAtoms::rootPseudo == pseudoClass->mAtom) {        if (data.mParentContent) {          result = localFalse;        }        else {          result = localTrue;        }      }      else if (nsCSSAtoms::xblBoundElementPseudo == pseudoClass->mAtom) {        result = (data.mScopedRoot && data.mScopedRoot == data.mContent)                   ? localTrue : localFalse;      }      else if (nsCSSAtoms::langPseudo == pseudoClass->mAtom) {        // XXX not yet implemented        result = PR_FALSE;      }      else if (IsEventPseudo(pseudoClass->mAtom)) {        // check if the element is event-sensitive        if (data.mCompatMode == eCompatibility_NavQuirks &&            // global selector:            !aSelector->mTag && !aSelector->mClassList &&            !aSelector->mIDList && !aSelector->mAttrList &&            // :hover or :active            (nsCSSAtoms::activePseudo == pseudoClass->mAtom ||             nsCSSAtoms::hoverPseudo == pseudoClass->mAtom) &&            // important for |IsQuirkEventSensitive|:            data.mIsHTMLContent && !data.mIsHTMLLink &&            !IsQuirkEventSensitive(data.mContentTag)) {          // In quirks mode, only make certain elements sensitive to          // selectors ":hover" and ":active".          // XXX Once we make ":active" work correctly (bug 65917) this          // quirk should apply only to ":hover" (if to anything at all).          result = localFalse;        } else {          if (nsCSSAtoms::activePseudo == pseudoClass->mAtom) {            result = (aStateMask & NS_EVENT_STATE_ACTIVE) ||                     (localTrue == (0 != (data.mEventState & NS_EVENT_STATE_ACTIVE)));          }          else if (nsCSSAtoms::focusPseudo == pseudoClass->mAtom) {            result = (aStateMask & NS_EVENT_STATE_FOCUS) ||                     (localTrue == (0 != (data.mEventState & NS_EVENT_STATE_FOCUS)));          }          else if (nsCSSAtoms::hoverPseudo == pseudoClass->mAtom) {            result = (aStateMask & NS_EVENT_STATE_HOVER) ||                     (localTrue == (0 != (data.mEventState & NS_EVENT_STATE_HOVER)));          }          else if (nsCSSAtoms::dragOverPseudo == pseudoClass->mAtom) {            result = (aStateMask & NS_EVENT_STATE_DRAGOVER) ||                     (localTrue == (0 != (data.mEventState & NS_EVENT_STATE_DRAGOVER)));          }        }       }      else if (IsLinkPseudo(pseudoClass->mAtom)) {        if (data.mIsHTMLLink || data.mIsSimpleXLink) {          if (result) {            if (nsCSSAtoms::anyLinkPseudo == pseudoClass->mAtom) {              result = localTrue;            }            else if (nsCSSAtoms::linkPseudo == pseudoClass->mAtom) {              result = PRBool(localTrue == (eLinkState_Unvisited == data.mLinkState));            }            else if (nsCSSAtoms::visitedPseudo == pseudoClass->mAtom) {              result = PRBool(localTrue == (eLinkState_Visited == data.mLinkState));            }          }        }        else {          result = localFalse;  // not a link        }      }      else if (nsCSSAtoms::checkedPseudo == pseudoClass->mAtom) {        // This pseudoclass matches the selected state on the following elements:        //  <option>        //  <input type=checkbox>        //  <input type=radio>        if (!(aStateMask & NS_EVENT_STATE_CHECKED))          result = data.mIsChecked ? localTrue : localFalse;      }      else {        result = localFalse;  // unknown pseudo class      }      pseudoClass = pseudoClass->mNext;    }  }  // namespace/tag match  if (result && aSelector->mAttrList) { // test for attribute match    // if no attributes on the content, no match    if(!data.mHasAttributes) {      result = localFalse;    } else {      result = localTrue;      nsAttrSelector* attr = aSelector->mAttrList;      do {        if (!data.mContent->HasAttr(attr->mNameSpace, attr->mAttr)) {          result = localFalse;        }        else if (attr->mFunction != NS_ATTR_FUNC_SET) {          nsAutoString value;#ifdef DEBUG          nsresult attrState =#endif              data.mContent->GetAttr(attr->mNameSpace, attr->mAttr, value);          NS_ASSERTION(NS_SUCCEEDED(attrState) &&                       NS_CONTENT_ATTR_NOT_THERE != attrState,                       "HasAttr lied or GetAttr failed");          PRBool isCaseSensitive = attr->mCaseSensitive;          switch (attr->mFunction) {            case NS_ATTR_FUNC_EQUALS:               if (isCaseSensitive) {                result = PRBool(localTrue == value.Equals(attr->mValue));              }              else {                result = PRBool(localTrue == value.Equals(attr->mValue, nsCaseInsensitiveStringComparator()));              }              break;            case NS_ATTR_FUNC_INCLUDES:               result = PRBool(localTrue == ValueIncludes(value, attr->mValue, isCaseSensitive));              break;            case NS_ATTR_FUNC_DASHMATCH:               {                PRUint32 selLen = attr->mValue.Length();                PRUint32 valLen = value.Length();                if (selLen > valLen) {                  result = localFalse;                } else {                  if (selLen != valLen &&                      value.CharAt(selLen) != PRUnichar('-')) {                    // to match, the value must have a dash after the end of                    // the selector's text (unless the selector and the value                    // have the same text)                    result = localFalse;                    break;                  }                  if (isCaseSensitive)                    result = PRBool(localTrue == Substring(value, 0, selLen).Equals(attr->mValue, nsDefaultStringComparator()));                  else                    result = PRBool(localTrue == Substring(value, 0, selLen).Equals(attr->mValue, nsCaseInsensitiveStringComparator()));                }              }              break;            case NS_ATTR_FUNC_ENDSMATCH:              {                PRUint32 selLen = attr->mValue.Length();                PRUint32 valLen = value.Length();                if (selLen > valLen) {                  result = localFalse;                } else {                  if (isCaseSensitive)                    result = PRBool(localTrue == Substring(value, valLen - selLen, selLen).Equals(attr->mValue, nsDefaultStringComparator()));                  else                    result = PRBool(localTrue == Substring(value, valLen - selLen, selLen).Equals(attr->mValue, nsCaseInsensitiveStringComparator()));                }              }              break;            case NS_ATTR_FUNC_BEGINSMATCH:              {                PRUint32 selLen = attr->mValue.Length();                PRUint32 valLen = value.Length();                if (selLen > valLen) {                  result = localFalse;                } else {                  if (isCaseSensitive)                    result = PRBool(localTrue == Substring(value, 0, selLen).Equals(attr->mValue, nsDefaultStringComparator()));                  else                    result = PRBool(localTrue == Substring(value, 0, selLen).Equals(attr->mValue, nsCaseInsensitiveStringComparator()));                }              }              break;            case NS_ATTR_FUNC_CONTAINSMATCH:              result = PRBool(localTrue == (FindInReadable(attr->mValue, value, nsCaseInsensitiveStringComparator())));              break;          }        }        attr = attr->mNext;      } while (result && (nsnull != attr));    }  }  if (result &&      ((nsnull != aSelector->mIDList) || (nsnull != aSelector->mClassList))) {  // test for ID & class match    result = localFalse;    if (data.mStyledContent) {      // case sensitivity: bug 93371      PRBool isCaseSensitive = data.mCompatMode != eCompatibility_NavQuirks;      nsAtomList* IDList = aSelector->mIDList;      if (nsnull == IDList) {        result = PR_TRUE;      }      else if (nsnull != data.mContentID) {        result = PR_TRUE;        if (isCaseSensitive) {          do {            if (localTrue == (IDList->mAtom != data.mContentID)) {              result = PR_FALSE;              break;            }            IDList = IDList->mNext;          } while (IDList);        } else {          const PRUnichar* id1Str;          data.mContentID->GetUnicode(&id1Str);          nsDependentString id1(id1Str);          do {            const PRUnichar* id2Str;            IDList->mAtom->GetUnicode(&id2Str);            nsDependentString id2(id2Str);            if (localTrue !=                id1.Equals(id2, nsCaseInsensitiveStringComparator())) {              result = PR_FALSE;              break;            }            IDList = IDList->mNext;          } while (IDList);        }      }            if (result) {        nsAtomList* classList = aSelector->mClassList;        while (nsnull != classList) {          if (localTrue == (NS_COMFALSE == data.mStyledContent->HasClass(classList->mAtom, isCaseSensitive))) {            result = PR_FALSE;            break;          }          classList = classList->mNext;        }      }    }  }    // apply SelectorMatches to the negated selectors in the chain  if (result && (nsnull != aSelector->mNegations)) {    result = SelectorMatches(data, aSelector->mNegations, aStateMask,                             aNegationIndex+1);  }  return result;}