ReferenceCountable& ReferenceCountable::operator=(const ReferenceCountable& /*copy*/) { ROCKET_ERRORMSG("Attempting to copy a reference counted object. This is not advisable."); return *this; }
// Returns true if this node is applicable to the given element, given its IDs, classes and heritage. bool StyleSheetNode::IsApplicable(const Element* element) const { // This function is called with an element that matches a style node only with the tag name. We have to determine // here whether or not it also matches the required hierarchy. // We must have a parent; if not, something's amok with the style tree. if (parent == NULL) { ROCKET_ERRORMSG("Invalid RCSS hierarchy."); return false; } // If we've hit a child of the root of the style sheet tree, then we're done; no more lineage to resolve. if (parent->type == ROOT) return true; // Determine the tag (and possibly id / class as well) of the next required parent in the RCSS hierarchy. const StyleSheetNode* parent_node = parent; String ancestor_id; StringList ancestor_classes; StringList ancestor_pseudo_classes; std::vector< const StyleSheetNode* > ancestor_structural_pseudo_classes; while (parent_node != NULL && parent_node->type != TAG) { switch (parent_node->type) { case ID: ancestor_id = parent_node->name; break; case CLASS: ancestor_classes.push_back(parent_node->name); break; case PSEUDO_CLASS: ancestor_pseudo_classes.push_back(parent_node->name); break; case STRUCTURAL_PSEUDO_CLASS: ancestor_structural_pseudo_classes.push_back(parent_node); break; default: ROCKET_ERRORMSG("Invalid RCSS hierarchy."); return false; } parent_node = parent_node->parent; } // Check for an invalid RCSS hierarchy. if (parent_node == NULL) { ROCKET_ERRORMSG("Invalid RCSS hierarchy."); return false; } // Now we know the name / class / ID / pseudo-class / structural requirements for the next ancestor requirement of // the element. So we look back through the element's ancestors to find one that matches. for (const Element* ancestor_element = element->GetParentNode(); ancestor_element != NULL; ancestor_element = ancestor_element->GetParentNode()) { // Skip this ancestor if the name of the next style node doesn't match its tag name, and one was specified. if (!parent_node->name.Empty() && parent_node->name != ancestor_element->GetTagName()) continue; // Skip this ancestor if the ID of the next style node doesn't match its ID, and one was specified. if (!ancestor_id.Empty() && ancestor_id != ancestor_element->GetId()) continue; // Skip this ancestor if the class of the next style node don't match its classes. bool resolved_requirements = true; for (size_t i = 0; i < ancestor_classes.size(); ++i) { if (!ancestor_element->IsClassSet(ancestor_classes[i])) { resolved_requirements = false; break; } } if (!resolved_requirements) continue; // Skip this ancestor if the required pseudo-classes of the style node aren't set on it. resolved_requirements = true; for (size_t i = 0; i < ancestor_pseudo_classes.size(); ++i) { if (!ancestor_element->IsPseudoClassSet(ancestor_pseudo_classes[i])) { resolved_requirements = false; break; } } if (!resolved_requirements) continue; // Skip this ancestor if the required structural pseudo-classes of the style node aren't applicable to it. resolved_requirements = true; for (size_t i = 0; i < ancestor_structural_pseudo_classes.size(); ++i) { if (!ancestor_structural_pseudo_classes[i]->selector->IsApplicable(ancestor_element, ancestor_structural_pseudo_classes[i]->a, ancestor_structural_pseudo_classes[i]->b)) { resolved_requirements = false; break; } } if (!resolved_requirements) continue; return parent_node->IsApplicable(ancestor_element); } // We hit the end of the hierarchy before matching the required ancestor, so bail. return false; }