summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Mark Bell <jmb@netsurf-browser.org>2009-01-25 22:48:11 +0000
committerJohn Mark Bell <jmb@netsurf-browser.org>2009-01-25 22:48:11 +0000
commite89a3e9fdb2cf06c0873d89ee75b31c77574abec (patch)
tree249709552cc7a606a09531aad3cefb3b04bfb209
parent457dcbca24f7c3b558d7590a686d8715bd591cf7 (diff)
downloadlibcss-e89a3e9fdb2cf06c0873d89ee75b31c77574abec.tar.gz
libcss-e89a3e9fdb2cf06c0873d89ee75b31c77574abec.tar.bz2
Implement css_stylesheet_{add,remove}_rule, thus (de)populating the selector hash.
svn path=/trunk/libcss/; revision=6273
-rw-r--r--src/stylesheet.c198
1 files changed, 191 insertions, 7 deletions
diff --git a/src/stylesheet.c b/src/stylesheet.c
index 78f51a8..dfe949d 100644
--- a/src/stylesheet.c
+++ b/src/stylesheet.c
@@ -13,6 +13,9 @@
#include "utils/parserutilserror.h"
#include "utils/utils.h"
+static css_error _add_selectors(css_stylesheet *sheet, css_rule *rule);
+static css_error _remove_selectors(css_stylesheet *sheet, css_rule *rule);
+
/**
* Create a stylesheet
*
@@ -327,7 +330,7 @@ css_error css_stylesheet_set_disabled(css_stylesheet *sheet, bool disabled)
}
/******************************************************************************
- * Private API below here *
+ * Library-private API below here *
******************************************************************************/
/**
@@ -883,9 +886,16 @@ css_error css_stylesheet_rule_set_import(css_stylesheet *sheet,
*/
css_error css_stylesheet_add_rule(css_stylesheet *sheet, css_rule *rule)
{
+ css_error error;
+
if (sheet == NULL || rule == NULL)
return CSS_BADPARM;
+ /* Add any selectors to the hash */
+ error = _add_selectors(sheet, rule);
+ if (error != CSS_OK)
+ return error;
+
/* Fill in rule's index and parent fields */
rule->index = sheet->rule_count;
rule->ptype = CSS_RULE_PARENT_STYLESHEET;
@@ -904,8 +914,7 @@ css_error css_stylesheet_add_rule(css_stylesheet *sheet, css_rule *rule)
sheet->last_rule = rule;
}
- /** \todo If there are selectors in the rule, add them to the hash
- * (this needs to recurse over child rules, too) */
+ /** \todo needs to trigger some event announcing styles have changed */
return CSS_OK;
}
@@ -919,16 +928,191 @@ css_error css_stylesheet_add_rule(css_stylesheet *sheet, css_rule *rule)
*/
css_error css_stylesheet_remove_rule(css_stylesheet *sheet, css_rule *rule)
{
- UNUSED(sheet);
- UNUSED(rule);
+ css_error error;
+
+ if (sheet == NULL || rule == NULL)
+ return CSS_BADPARM;
+
+ error = _remove_selectors(sheet, rule);
+ if (error != CSS_OK)
+ return error;
+
+ if (rule->next == NULL)
+ sheet->last_rule = rule->prev;
+ else
+ rule->next->prev = rule->prev;
+
+ if (rule->prev == NULL)
+ sheet->rule_list = rule->next;
+ else
+ rule->prev->next = rule->next;
+
+ /* Invalidate linkage fields */
+ rule->parent = NULL;
+ rule->prev = NULL;
+ rule->next = NULL;
- /** \todo If there are selectors (recurse over child rules, too),
- * then they must be removed from the hash */
/**\ todo renumber subsequent rules? may not be necessary, as there's
* only an expectation that rules which occur later in the stylesheet
* have a higher index than those that appear earlier. There's no
* guarantee that the number space is continuous. */
+ /** \todo needs to trigger some event announcing styles have changed */
+
+ return CSS_OK;
+}
+
+/******************************************************************************
+ * Private API below here *
+ ******************************************************************************/
+
+/**
+ * Add selectors in a rule to the hash
+ *
+ * \param sheet Stylesheet containing hash
+ * \param rule Rule to consider
+ * \return CSS_OK on success, appropriate error otherwise
+ */
+css_error _add_selectors(css_stylesheet *sheet, css_rule *rule)
+{
+ css_error error;
+
+ if (sheet == NULL || rule == NULL)
+ return CSS_BADPARM;
+
+ /* Rule must not be in sheet */
+ if (rule->parent != NULL)
+ return CSS_INVALID;
+
+ switch (rule->type) {
+ case CSS_RULE_SELECTOR:
+ {
+ css_rule_selector *s = (css_rule_selector *) rule;
+ int32_t i;
+
+ for (i = 0; i < rule->items; i++) {
+ css_selector *sel = s->selectors[i];
+
+ error = css_selector_hash_insert(sheet->selectors, sel);
+ if (error != CSS_OK) {
+ /* Failed, revert our changes */
+ for (i--; i >= 0; i--) {
+ sel = s->selectors[i];
+
+ /* Ignore errors */
+ css_selector_hash_remove(
+ sheet->selectors, sel);
+ }
+
+ return error;
+ }
+ }
+ }
+ break;
+ case CSS_RULE_MEDIA:
+ {
+ css_rule_media *m = (css_rule_media *) rule;
+ css_rule *r;
+
+ for (r = m->first_child; r != NULL; r = r->next) {
+ error = _add_selectors(sheet, r);
+ if (error != CSS_OK) {
+ /* Failed, revert out changes */
+ for (r = r->prev; r != NULL; r = r->prev) {
+ _remove_selectors(sheet, r);
+ }
+
+ return error;
+ }
+ }
+ }
+ break;
+ case CSS_RULE_PAGE:
+ {
+ css_rule_page *p = (css_rule_page *) rule;
+ int32_t i;
+
+ for (i = 0; i < rule->items; i++) {
+ css_selector *sel = p->selectors[i];
+
+ error = css_selector_hash_insert(sheet->selectors, sel);
+ if (error != CSS_OK) {
+ /* Failed, revert our changes */
+ for (i--; i >= 0; i--) {
+ sel = p->selectors[i];
+
+ /* Ignore errors */
+ css_selector_hash_remove(
+ sheet->selectors, sel);
+ }
+
+ return error;
+ }
+ }
+ }
+ break;
+ }
+
+ return CSS_OK;
+}
+
+/**
+ * Remove selectors in a rule from the hash
+ *
+ * \param sheet Stylesheet containing hash
+ * \param rule Rule to consider
+ * \return CSS_OK on success, appropriate error otherwise
+ */
+css_error _remove_selectors(css_stylesheet *sheet, css_rule *rule)
+{
+ css_error error;
+
+ if (sheet == NULL || rule == NULL)
+ return CSS_BADPARM;
+
+ switch (rule->type) {
+ case CSS_RULE_SELECTOR:
+ {
+ css_rule_selector *s = (css_rule_selector *) rule;
+ int32_t i;
+
+ for (i = 0; i < rule->items; i++) {
+ css_selector *sel = s->selectors[i];
+
+ error = css_selector_hash_remove(sheet->selectors, sel);
+ if (error != CSS_OK)
+ return error;
+ }
+ }
+ break;
+ case CSS_RULE_MEDIA:
+ {
+ css_rule_media *m = (css_rule_media *) rule;
+ css_rule *r;
+
+ for (r = m->first_child; r != NULL; r = r->next) {
+ error = _remove_selectors(sheet, r);
+ if (error != CSS_OK)
+ return error;
+ }
+ }
+ break;
+ case CSS_RULE_PAGE:
+ {
+ css_rule_page *p = (css_rule_page *) rule;
+ int32_t i;
+
+ for (i = 0; i < rule->items; i++) {
+ css_selector *sel = p->selectors[i];
+
+ error = css_selector_hash_remove(sheet->selectors, sel);
+ if (error != CSS_OK)
+ return error;
+ }
+ }
+ break;
+ }
+
return CSS_OK;
}