Author: jmb
Date: Sun Jan 25 16:48:11 2009
New Revision: 6273

URL: http://source.netsurf-browser.org?rev=6273&view=rev
Log:
Implement css_stylesheet_{add,remove}_rule, thus (de)populating the selector 
hash.

Modified:
    trunk/libcss/src/stylesheet.c

Modified: trunk/libcss/src/stylesheet.c
URL: 
http://source.netsurf-browser.org/trunk/libcss/src/stylesheet.c?rev=6273&r1=6272&r2=6273&view=diff
==============================================================================
--- trunk/libcss/src/stylesheet.c (original)
+++ trunk/libcss/src/stylesheet.c Sun Jan 25 16:48:11 2009
@@ -12,6 +12,9 @@
 #include "parse/language.h"
 #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 @@
 }
 
 /******************************************************************************
- * Private API below here                                                     *
+ * Library-private API below here                                             *
  
******************************************************************************/
 
 /**
@@ -883,8 +886,15 @@
  */
 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;
@@ -904,8 +914,7 @@
                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_remove_rule(css_stylesheet *sheet, css_rule *rule)
 {
-       UNUSED(sheet);
-       UNUSED(rule);
-
-       /** \todo If there are selectors (recurse over child rules, too),
-        * then they must be removed from the hash */
+       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 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. */
 
-       return CSS_OK;
-}
-
+       /** \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;
+}
+


_______________________________________________
netsurf-commits mailing list
[email protected]
http://vlists.pepperfish.net/cgi-bin/mailman/listinfo/netsurf-commits-netsurf-browser.org

Reply via email to