static css_error node_is_disabled(void *pw, void *node, bool *is_disabled);
static css_error node_is_checked(void *pw, void *node, bool *is_checked);
static css_error node_is_target(void *pw, void *node, bool *is_target);
+static css_error node_is_lang(void *pw, void *node,
+ lwc_string *lang, bool *is_lang);
/**
*is_target = false;
return CSS_OK;
}
+
+
+/**
+ * Check if the given node is the given language
+ *
+ * This test is corresponds to the CSS :lang() selector and is not
+ * fully implemented yet: it looks only for "lang" attributes on the
+ * given element and its parents, and performs a simple substring
+ * check. This results in a partial implementation of CSS Level 3 for
+ * SVG 2.0. In particular, it ignores all "xml:lang" attributes in
+ * favor of the "lang" attribute that is defined only in SVG 2.0.
+ *
+ * \param pw Pointer to the current SVG parser state; unused
+ * \param node Libdom SVG node to check
+ * \param lang The language to match
+ * \param is_lang Pointer to the boolean return value
+ *
+ * \return CSS_OK on success, or CSS_NOMEM if anything goes wrong
+ */
+static css_error node_is_lang(void *pw, void *node,
+ lwc_string *lang, bool *is_lang)
+{
+ UNUSED(pw);
+ /* SVG2 elements support both "lang" and "xml:lang"
+ * attributes; earlier versions have only the XML
+ * attribute. It would not be too hard to add support for
+ * xml:lang" here. The main difficulty standing in the way of
+ * a full Level 4 implementation is the complexity of the
+ * :lang() selector:
+ *
+ * https://www.w3.org/TR/selectors-4/#the-lang-pseudo
+ *
+ */
+
+ css_error c_err;
+ dom_exception d_err;
+ dom_node *n; /* current node */
+ dom_node *p; /* parent node */
+ bool match; /* retval from node_has_attribute_substring() */
+
+ /* Define the attribute name "lang" that we're looking for.
+ * We only use a css_qname here because that's what the
+ * node_has_attribute_substring() takes; the namespace
+ * portion of it is irrelevant. */
+ css_qname attr;
+ attr.ns = NULL;
+
+ if (lwc_intern_string("lang", 4, &attr.name) != lwc_error_ok) {
+ return CSS_NOMEM;
+ }
+
+ *is_lang = false; /* default to no match */
+ n = (dom_node *)node;
+
+ /* Loop through all parents of the given node looking for a
+ * substring match */
+ while (n != NULL) {
+ c_err = _node_has_attribute_substring(pw, (void *)n, &attr,
+ lang, &match, true);
+ if (c_err != CSS_OK) {
+ lwc_string_destroy(attr.name);
+ return c_err;
+ }
+ if (match) {
+ /* matched this element; we're done */
+ lwc_string_destroy(attr.name);
+ *is_lang = true;
+ return CSS_OK;
+ }
+
+ /* no match on this element, try its parent */
+ d_err = dom_node_get_parent_node(n, &p);
+ if (d_err != DOM_NO_ERR) {
+ lwc_string_destroy(attr.name);
+ return CSS_NOMEM;
+ }
+ n = p;
+ }
+
+ /* If we never find a match we may wind up here */
+ lwc_string_destroy(attr.name);
+ return CSS_OK;
+}