diff options
-rw-r--r-- | ccss-doc/ccss-sections.txt | 3 | ||||
-rw-r--r-- | ccss-doc/tmpl/ccss-unused.sgml | 8 | ||||
-rw-r--r-- | ccss-doc/tmpl/node.sgml | 1 | ||||
-rw-r--r-- | ccss-doc/tmpl/stylesheet.sgml | 26 | ||||
-rw-r--r-- | ccss/ccss-block-priv.h | 4 | ||||
-rw-r--r-- | ccss/ccss-block.c | 18 | ||||
-rw-r--r-- | ccss/ccss-grammar-parse.c | 77 | ||||
-rw-r--r-- | ccss/ccss-grammar-priv.h | 3 | ||||
-rw-r--r-- | ccss/ccss-grammar.c | 29 | ||||
-rw-r--r-- | ccss/ccss-node-priv.h | 3 | ||||
-rw-r--r-- | ccss/ccss-node.c | 9 | ||||
-rw-r--r-- | ccss/ccss-node.h | 6 | ||||
-rw-r--r-- | ccss/ccss-selector-group.c | 80 | ||||
-rw-r--r-- | ccss/ccss-selector-group.h | 4 | ||||
-rw-r--r-- | ccss/ccss-selector.c | 89 | ||||
-rw-r--r-- | ccss/ccss-selector.h | 32 | ||||
-rw-r--r-- | ccss/ccss-stylesheet-priv.h | 2 | ||||
-rw-r--r-- | ccss/ccss-stylesheet.c | 136 | ||||
-rw-r--r-- | ccss/ccss-stylesheet.h | 17 | ||||
-rw-r--r-- | ccss/ccss.sym | 3 | ||||
-rw-r--r-- | configure.in | 4 | ||||
-rw-r--r-- | examples/Makefile.am | 3 | ||||
-rw-r--r-- | examples/example-10.c | 60 | ||||
-rw-r--r-- | examples/example-2.c | 3 |
24 files changed, 500 insertions, 120 deletions
diff --git a/ccss-doc/ccss-sections.txt b/ccss-doc/ccss-sections.txt index 2ed1f1f..c3c0a05 100644 --- a/ccss-doc/ccss-sections.txt +++ b/ccss-doc/ccss-sections.txt @@ -68,11 +68,12 @@ ccss_stylesheet_precedence_t ccss_stylesheet_destroy ccss_stylesheet_reference ccss_stylesheet_get_reference_count +ccss_stylesheet_add_from_buffer ccss_stylesheet_add_from_file ccss_stylesheet_foreach -ccss_stylesheet_invalidate_node ccss_stylesheet_query_type ccss_stylesheet_query +ccss_stylesheet_unload ccss_stylesheet_dump </SECTION> diff --git a/ccss-doc/tmpl/ccss-unused.sgml b/ccss-doc/tmpl/ccss-unused.sgml index 34891ab..a93cf66 100644 --- a/ccss-doc/tmpl/ccss-unused.sgml +++ b/ccss-doc/tmpl/ccss-unused.sgml @@ -330,6 +330,14 @@ ccss_selector_group_t @self: +<!-- ##### FUNCTION ccss_stylesheet_invalidate_node ##### --> +<para> + +</para> + +@self: +@instance: + <!-- ##### FUNCTION ccss_stylesheet_iter_init ##### --> <para> diff --git a/ccss-doc/tmpl/node.sgml b/ccss-doc/tmpl/node.sgml index 75fb027..8111d22 100644 --- a/ccss-doc/tmpl/node.sgml +++ b/ccss-doc/tmpl/node.sgml @@ -256,6 +256,7 @@ ccss_node_t </para> @self: +@descriptor: @Returns: diff --git a/ccss-doc/tmpl/stylesheet.sgml b/ccss-doc/tmpl/stylesheet.sgml index e1bb61f..ad21618 100644 --- a/ccss-doc/tmpl/stylesheet.sgml +++ b/ccss-doc/tmpl/stylesheet.sgml @@ -68,35 +68,39 @@ ccss_stylesheet_t @Returns: -<!-- ##### FUNCTION ccss_stylesheet_add_from_file ##### --> +<!-- ##### FUNCTION ccss_stylesheet_add_from_buffer ##### --> <para> </para> @self: -@css_file: +@buffer: +@size: @precedence: @user_data: @Returns: -<!-- ##### FUNCTION ccss_stylesheet_foreach ##### --> +<!-- ##### FUNCTION ccss_stylesheet_add_from_file ##### --> <para> </para> @self: -@func: +@css_file: +@precedence: @user_data: +@Returns: -<!-- ##### FUNCTION ccss_stylesheet_invalidate_node ##### --> +<!-- ##### FUNCTION ccss_stylesheet_foreach ##### --> <para> </para> @self: -@instance: +@func: +@user_data: <!-- ##### FUNCTION ccss_stylesheet_query_type ##### --> @@ -119,6 +123,16 @@ ccss_stylesheet_t @Returns: +<!-- ##### FUNCTION ccss_stylesheet_unload ##### --> +<para> + +</para> + +@self: +@descriptor: +@Returns: + + <!-- ##### FUNCTION ccss_stylesheet_dump ##### --> <para> diff --git a/ccss/ccss-block-priv.h b/ccss/ccss-block-priv.h index db87467..a389b04 100644 --- a/ccss/ccss-block-priv.h +++ b/ccss/ccss-block-priv.h @@ -35,11 +35,13 @@ CCSS_BEGIN_DECLS **/ struct ccss_block_ { /*< private >*/ - GHashTable *properties; + unsigned int reference_count; + GHashTable *properties; }; ccss_block_t * ccss_block_create (void); void ccss_block_destroy (ccss_block_t *self); +ccss_block_t * ccss_block_reference (ccss_block_t *self); void ccss_block_dump (ccss_block_t const *self); diff --git a/ccss/ccss-block.c b/ccss/ccss-block.c index 5347892..2be2244 100644 --- a/ccss/ccss-block.c +++ b/ccss/ccss-block.c @@ -29,6 +29,7 @@ ccss_block_create (void) ccss_block_t *self; self = g_new0 (ccss_block_t, 1); + self->reference_count = 1; self->properties = g_hash_table_new_full ((GHashFunc) g_direct_hash, (GEqualFunc) g_direct_equal, NULL, @@ -42,10 +43,23 @@ ccss_block_destroy (ccss_block_t *self) { g_return_if_fail (self && self->properties); - g_hash_table_destroy (self->properties), self->properties = NULL; - g_free (self); + self->reference_count--; + + if (self->reference_count == 0) { + g_hash_table_destroy (self->properties), self->properties = NULL; + g_free (self); + } } +ccss_block_t * +ccss_block_reference (ccss_block_t *self) +{ + g_return_val_if_fail (self, NULL); + + self->reference_count++; + + return self; +} /** * ccss_block_add_property: diff --git a/ccss/ccss-grammar-parse.c b/ccss/ccss-grammar-parse.c index 937d5c1..6c44e7d 100644 --- a/ccss/ccss-grammar-parse.c +++ b/ccss/ccss-grammar-parse.c @@ -38,6 +38,7 @@ typedef struct { typedef struct { ccss_grammar_t const *grammar; ccss_stylesheet_precedence_t precedence; + unsigned int stylesheet_descriptor; void *user_data; GHashTable *blocks; GHashTable *groups; @@ -94,6 +95,7 @@ calculate_importance (ccss_stylesheet_precedence_t precedence, static ccss_selector_t * walk_additional_selector (CRAdditionalSel *cr_add_sel, ccss_stylesheet_precedence_t precedence, + unsigned int stylesheet_descriptor, bool is_important) { ccss_selector_t *selector; @@ -111,21 +113,35 @@ walk_additional_selector (CRAdditionalSel *cr_add_sel, switch (cr_add_sel->type) { case CLASS_ADD_SELECTOR: name = cr_string_peek_raw_str (cr_add_sel->content.class_name); - selector = ccss_class_selector_create (name, precedence, importance); + selector = ccss_class_selector_create (name, + precedence, + stylesheet_descriptor, + importance); break; case PSEUDO_CLASS_ADD_SELECTOR: name = cr_string_peek_raw_str (cr_add_sel->content.pseudo->name); - selector = ccss_pseudo_class_selector_create (name, precedence, importance); + selector = ccss_pseudo_class_selector_create (name, + precedence, + stylesheet_descriptor, + importance); break; case ID_ADD_SELECTOR: name = cr_string_peek_raw_str (cr_add_sel->content.id_name); - selector = ccss_id_selector_create (name, precedence, importance); + selector = ccss_id_selector_create (name, + precedence, + stylesheet_descriptor, + importance); break; case ATTRIBUTE_ADD_SELECTOR: name = cr_string_peek_raw_str (cr_add_sel->content.attr_sel->name); value = cr_string_peek_raw_str (cr_add_sel->content.attr_sel->value); match = map_attribute_selector_match (cr_add_sel->content.attr_sel->match_way); - selector = ccss_attribute_selector_create (name, value, match, precedence, importance); + selector = ccss_attribute_selector_create (name, + value, + match, + precedence, + stylesheet_descriptor, + importance); break; case NO_ADD_SELECTOR: default: @@ -135,7 +151,10 @@ walk_additional_selector (CRAdditionalSel *cr_add_sel, if (cr_add_sel->next) { ccss_selector_t *refinement; - refinement = walk_additional_selector (cr_add_sel->next, precedence, is_important); + refinement = walk_additional_selector (cr_add_sel->next, + precedence, + stylesheet_descriptor, + is_important); ccss_selector_refine (selector, refinement); } @@ -145,6 +164,7 @@ walk_additional_selector (CRAdditionalSel *cr_add_sel, static ccss_selector_t * walk_simple_selector_r (CRSimpleSel *cr_simple_sel, ccss_stylesheet_precedence_t precedence, + unsigned int stylesheet_descriptor, bool is_important) { ccss_selector_t *selector; @@ -155,9 +175,14 @@ walk_simple_selector_r (CRSimpleSel *cr_simple_sel, selector = NULL; importance = calculate_importance (precedence, is_important); if (UNIVERSAL_SELECTOR & cr_simple_sel->type_mask) { - selector = ccss_universal_selector_create (precedence, importance); + selector = ccss_universal_selector_create (precedence, + stylesheet_descriptor, + importance); } else if (TYPE_SELECTOR & cr_simple_sel->type_mask) { - selector = ccss_type_selector_create (cr_string_peek_raw_str (cr_simple_sel->name), precedence, importance); + selector = ccss_type_selector_create (cr_string_peek_raw_str (cr_simple_sel->name), + precedence, + stylesheet_descriptor, + importance); } else { char const *sel; sel = cr_simple_sel->name ? cr_string_peek_raw_str (cr_simple_sel->name) : NULL; @@ -169,13 +194,19 @@ walk_simple_selector_r (CRSimpleSel *cr_simple_sel, if (cr_simple_sel->add_sel) { ccss_selector_t *refinement; - refinement = walk_additional_selector (cr_simple_sel->add_sel, precedence, is_important); + refinement = walk_additional_selector (cr_simple_sel->add_sel, + precedence, + stylesheet_descriptor, + is_important); ccss_selector_refine (selector, refinement); } if (cr_simple_sel->next) { ccss_selector_t *descendant; - descendant = walk_simple_selector_r (cr_simple_sel->next, precedence, is_important); + descendant = walk_simple_selector_r (cr_simple_sel->next, + precedence, + stylesheet_descriptor, + is_important); if (COMB_WS == cr_simple_sel->next->combinator) { selector = ccss_selector_append_descendant (selector, descendant); @@ -195,6 +226,7 @@ walk_selector (CRSelector *cr_sel, ccss_block_t *block, GHashTable *groups, ccss_stylesheet_precedence_t precedence, + unsigned int stylesheet_descriptor, bool is_important, instance_info_t const *instance_info) { @@ -209,7 +241,9 @@ walk_selector (CRSelector *cr_sel, importance = calculate_importance (precedence, is_important); selector = ccss_instance_selector_create (instance_info->instance, - precedence, importance); + precedence, + stylesheet_descriptor, + importance); ccss_selector_set_block (selector, block); ccss_selector_group_add_selector (instance_info->result_group, selector); @@ -219,7 +253,10 @@ walk_selector (CRSelector *cr_sel, /* Handle `full' CSS statements. */ iter = cr_sel; do { - selector = walk_simple_selector_r (iter->simple_sel, precedence, is_important); + selector = walk_simple_selector_r (iter->simple_sel, + precedence, + stylesheet_descriptor, + is_important); if (selector) { ccss_selector_set_block (selector, block); @@ -354,18 +391,18 @@ end_selector_cb (CRDocHandler *handler, g_assert (info); if (info->block) { - walk_selector (cr_sel, info->block, info->groups, - info->precedence, false, - info->instance); + walk_selector (cr_sel, info->block, info->groups, + info->precedence, info->stylesheet_descriptor, + false, info->instance); info->block = NULL; } /* Properties marked `important' form a block of their own, * so they can be sorted into the cascade at the appropriate position. */ if (info->important_block) { - walk_selector (cr_sel, info->important_block, info->groups, - info->precedence, true, - info->instance); + walk_selector (cr_sel, info->important_block, info->groups, + info->precedence, info->stylesheet_descriptor, + true, info->instance); info->important_block = NULL; } } @@ -374,6 +411,7 @@ enum CRStatus ccss_grammar_parse_file (ccss_grammar_t const *self, char const *css_file, ccss_stylesheet_precedence_t precedence, + unsigned int stylesheet_descriptor, void *user_data, GHashTable *groups, GHashTable *blocks) @@ -391,6 +429,7 @@ ccss_grammar_parse_file (ccss_grammar_t const *self, handler->app_data = (gpointer) &info; info.grammar = self; info.precedence = precedence; + info.stylesheet_descriptor = stylesheet_descriptor; info.user_data = user_data; info.blocks = blocks; info.groups = groups; @@ -424,6 +463,7 @@ ccss_grammar_parse_buffer (ccss_grammar_t const *self, char const *buffer, size_t size, ccss_stylesheet_precedence_t precedence, + unsigned int stylesheet_descriptor, void *user_data, GHashTable *groups, GHashTable *blocks) @@ -442,6 +482,7 @@ ccss_grammar_parse_buffer (ccss_grammar_t const *self, handler->app_data = (gpointer) &info; info.grammar = self; info.precedence = precedence; + info.stylesheet_descriptor = stylesheet_descriptor; info.user_data = user_data; info.blocks = blocks; info.groups = groups; @@ -469,6 +510,7 @@ enum CRStatus ccss_grammar_parse_inline (ccss_grammar_t const *self, char const *buffer, ccss_stylesheet_precedence_t precedence, + unsigned int stylesheet_descriptor, ptrdiff_t instance, void *user_data, ccss_selector_group_t *result_group, @@ -494,6 +536,7 @@ ccss_grammar_parse_inline (ccss_grammar_t const *self, handler->app_data = (gpointer) &info; info.grammar = self; info.precedence = precedence; + info.stylesheet_descriptor = stylesheet_descriptor; info.blocks = blocks; info.user_data = user_data; info.groups = NULL; diff --git a/ccss/ccss-grammar-priv.h b/ccss/ccss-grammar-priv.h index c67e059..05ef177 100644 --- a/ccss/ccss-grammar-priv.h +++ b/ccss/ccss-grammar-priv.h @@ -50,6 +50,7 @@ enum CRStatus ccss_grammar_parse_file (ccss_grammar_t const *self, char const *css_file, ccss_stylesheet_precedence_t precedence, + unsigned int stylesheet_descriptor, void *user_data, GHashTable *groups, GHashTable *blocks); @@ -59,6 +60,7 @@ ccss_grammar_parse_buffer (ccss_grammar_t const *self, char const *buffer, size_t buffer_size, ccss_stylesheet_precedence_t precedence, + unsigned int stylesheet_descriptor, void *user_data, GHashTable *groups, GHashTable *blocks); @@ -67,6 +69,7 @@ enum CRStatus ccss_grammar_parse_inline (ccss_grammar_t const *self, char const *buffer, ccss_stylesheet_precedence_t precedence, + unsigned int stylesheet_descriptor, ptrdiff_t instance, void *user_data, ccss_selector_group_t *result_group, diff --git a/ccss/ccss-grammar.c b/ccss/ccss-grammar.c index 1ffde28..4a319c4 100644 --- a/ccss/ccss-grammar.c +++ b/ccss/ccss-grammar.c @@ -266,16 +266,25 @@ ccss_grammar_create_stylesheet_from_buffer (ccss_grammar_t *self, ccss_stylesheet_t *stylesheet; enum CRStatus ret; + g_return_val_if_fail (self, NULL); + g_return_val_if_fail (buffer, NULL); + g_return_val_if_fail (size, NULL); + stylesheet = ccss_stylesheet_create (); stylesheet->grammar = ccss_grammar_reference (self); + stylesheet->current_descriptor++; - ret = ccss_grammar_parse_buffer (self, buffer, size, - CCSS_STYLESHEET_AUTHOR, user_data, - stylesheet->groups, stylesheet->blocks); + ret = ccss_grammar_parse_buffer (self, buffer, size, + CCSS_STYLESHEET_AUTHOR, + stylesheet->current_descriptor, + user_data, + stylesheet->groups, stylesheet->blocks); if (CR_OK == ret) { ccss_stylesheet_fix_dangling_selectors (stylesheet); return stylesheet; + } else { + /* TODO clean up using stylesheet->current_descriptor */ } return NULL; @@ -299,16 +308,24 @@ ccss_grammar_create_stylesheet_from_file (ccss_grammar_t *self, ccss_stylesheet_t *stylesheet; enum CRStatus ret; + g_return_val_if_fail (self, NULL); + g_return_val_if_fail (css_file, NULL); + stylesheet = ccss_stylesheet_create (); stylesheet->grammar = ccss_grammar_reference (self); + stylesheet->current_descriptor++; - ret = ccss_grammar_parse_file (self, css_file, CCSS_STYLESHEET_AUTHOR, - user_data, stylesheet->groups, - stylesheet->blocks); + ret = ccss_grammar_parse_file (self, css_file, + CCSS_STYLESHEET_AUTHOR, + stylesheet->current_descriptor, + user_data, + stylesheet->groups, stylesheet->blocks); if (CR_OK == ret) { ccss_stylesheet_fix_dangling_selectors (stylesheet); return stylesheet; + } else { + /* TODO clean up using stylesheet->current_descriptor */ } return NULL; diff --git a/ccss/ccss-node-priv.h b/ccss/ccss-node-priv.h index 73e1e92..791fb88 100644 --- a/ccss/ccss-node-priv.h +++ b/ccss/ccss-node-priv.h @@ -59,7 +59,8 @@ ccss_node_get_attribute (ccss_node_t const *self, char const *name); char const * -ccss_node_get_style (ccss_node_t *self); +ccss_node_get_style (ccss_node_t *self, + unsigned int descriptor); bool ccss_node_get_viewport (ccss_node_t const *self, diff --git a/ccss/ccss-node.c b/ccss/ccss-node.c index 39d7a1d..306b2a5 100644 --- a/ccss/ccss-node.c +++ b/ccss/ccss-node.c @@ -81,7 +81,8 @@ get_attribute (ccss_node_t const *self, } static char const * -get_style (ccss_node_t const *self) +get_style (ccss_node_t const *self, + unsigned int descriptor) { return NULL; } @@ -275,14 +276,16 @@ ccss_node_get_attribute (ccss_node_t const *self, } char const * -ccss_node_get_style (ccss_node_t *self) +ccss_node_get_style (ccss_node_t *self, + unsigned int descriptor) { g_return_val_if_fail (self, NULL); g_return_val_if_fail (self->node_class, NULL); g_return_val_if_fail (self->node_class->get_style, NULL); if (NULL == self->inline_style) - self->inline_style = self->node_class->get_style (self); + self->inline_style = self->node_class->get_style (self, + descriptor); return self->inline_style; } diff --git a/ccss/ccss-node.h b/ccss/ccss-node.h index c534c2a..409d273 100644 --- a/ccss/ccss-node.h +++ b/ccss/ccss-node.h @@ -134,12 +134,16 @@ typedef char * (*ccss_node_get_attribute_f) (ccss_node_t const *self, /** * ccss_node_get_style_f: * @self: a #ccss_node_t. + * @descriptor: handle to unload this style from the stylesheet later on. * * Hook function to query a #ccss_node_t's inline CSS style. * + * See: ccss_stylesheet_unload(). + * * Returns: the node's CSS properties or %NULL. **/ -typedef const char * (*ccss_node_get_style_f) (ccss_node_t const *self); +typedef const char * (*ccss_node_get_style_f) (ccss_node_t const *self, + unsigned int descriptor); /** * ccss_node_get_viewport_f: diff --git a/ccss/ccss-selector-group.c b/ccss/ccss-selector-group.c index b09cb91..ecdc391 100644 --- a/ccss/ccss-selector-group.c +++ b/ccss/ccss-selector-group.c @@ -98,6 +98,86 @@ ccss_selector_group_destroy (ccss_selector_group_t *self) g_free (self); } +typedef struct { + unsigned int descriptor; + GSList *empty_sets; + bool ret; +} traverse_unload_info_t; + +static bool +traverse_unload (size_t specificity, + ccss_selector_set_t *set, + traverse_unload_info_t *info) +{ + ccss_selector_t *selector; + GSList *iter; + + g_assert (info); + + iter = set->selectors; + while (iter) { + selector = (ccss_selector_t *) iter->data; + if (ccss_selector_get_descriptor (selector) == info->descriptor) { + ccss_selector_destroy (selector); + if (iter == set->selectors) { + /* Removing the last element? */ + iter = g_slist_delete_link (iter, iter); + if (NULL == iter) { + /* Yes, remember to remove the node. */ + info->empty_sets = g_slist_prepend (info->empty_sets, + GSIZE_TO_POINTER (specificity)); + set->selectors = NULL; + } else { + /* No, but new head. */ + set->selectors = iter; + } + } else { + iter = g_slist_delete_link (iter, iter); + } + info->ret = true; + } else { + iter = iter->next; + } + } + + return false; +} + +/** + * ccss_selector_group_unload: + * @self: a #ccss_selector_group_t. + * @descriptor descriptor of a part that was loaded. + * + * Unload a CSS file, buffer or inline style that was loaded into the selector group. + * + * Returns: %TRUE if anything had been unloaded. + */ +bool +ccss_selector_group_unload (ccss_selector_group_t *self, + unsigned int descriptor) +{ + GSList *iter; + traverse_unload_info_t info; + + g_return_val_if_fail (self, false); + g_return_val_if_fail (descriptor, false); + + info.descriptor = descriptor; + info.empty_sets = NULL; + info.ret = false; + + g_tree_foreach (self->sets, (GTraverseFunc) traverse_unload, &info); + + /* Prune empty sets. */ + iter = info.empty_sets; + while (iter) { + g_tree_remove (self->sets, iter->data); + iter = g_slist_delete_link (iter, iter); + } + + return info.ret; +} + /* * Takes ownership of the selector. */ diff --git a/ccss/ccss-selector-group.h b/ccss/ccss-selector-group.h index def0f72..c2c5e77 100644 --- a/ccss/ccss-selector-group.h +++ b/ccss/ccss-selector-group.h @@ -40,6 +40,10 @@ void ccss_selector_group_destroy (ccss_selector_group_t *self); bool +ccss_selector_group_unload (ccss_selector_group_t *self, + unsigned int descriptor); + +bool ccss_selector_group_apply_type (ccss_selector_group_t const *self, char const *type, ccss_style_t *style); diff --git a/ccss/ccss-selector.c b/ccss/ccss-selector.c index 829c944..17ab68e 100644 --- a/ccss/ccss-selector.c +++ b/ccss/ccss-selector.c @@ -53,6 +53,7 @@ typedef enum { */ struct ccss_selector_ { ccss_selector_modality_t modality; + unsigned int stylesheet_descriptor; unsigned int importance : 2; unsigned int precedence : 5; unsigned int a : 5; @@ -63,7 +64,7 @@ struct ccss_selector_ { struct ccss_selector_ *refinement; struct ccss_selector_ *container; struct ccss_selector_ *antecessor; - ccss_block_t const *block; + ccss_block_t *block; }; static void @@ -73,6 +74,7 @@ selector_sync (ccss_selector_t const *self, g_assert (self && to); to->modality = self->modality; + to->stylesheet_descriptor = self->stylesheet_descriptor; to->importance = self->importance; to->precedence = self->precedence; to->a = self->a; @@ -83,7 +85,7 @@ selector_sync (ccss_selector_t const *self, to->refinement = NULL; to->container = NULL; to->antecessor = NULL; - to->block = self->block; + to->block = ccss_block_reference (self->block); } /* @@ -92,13 +94,15 @@ selector_sync (ccss_selector_t const *self, typedef ccss_selector_t ccss_universal_selector_t; ccss_selector_t * -ccss_universal_selector_create (unsigned int precedence, - ccss_selector_importance_t importance) +ccss_universal_selector_create (unsigned int precedence, + unsigned int stylesheet_descriptor, + ccss_selector_importance_t importance) { ccss_universal_selector_t *self; self = g_new0 (ccss_universal_selector_t, 1); self->modality = CCSS_SELECTOR_MODALITY_UNIVERSAL; + self->stylesheet_descriptor = stylesheet_descriptor; self->importance = importance; self->precedence = precedence; @@ -141,8 +145,9 @@ typedef struct { ccss_selector_t * ccss_type_selector_create (char const *type_name, - unsigned int precedence, - ccss_selector_importance_t importance) + unsigned int precedence, + unsigned int stylesheet_descriptor, + ccss_selector_importance_t importance) { ccss_type_selector_t *self; @@ -150,6 +155,7 @@ ccss_type_selector_create (char const *type_name, self = g_new0 (ccss_type_selector_t, 1); self->parent.modality = CCSS_SELECTOR_MODALITY_TYPE; + self->parent.stylesheet_descriptor = stylesheet_descriptor; self->parent.importance = importance; self->parent.precedence = precedence; self->parent.d = 1; @@ -192,16 +198,19 @@ type_selector_serialize (ccss_type_selector_t const *self, */ ccss_selector_t * ccss_base_type_selector_create (char const *type_name, - unsigned int precedence, - ccss_selector_importance_t importance, - unsigned int specificity_e) + unsigned int precedence, + unsigned int stylesheet_descriptor, + ccss_selector_importance_t importance, + unsigned int specificity_e) { ccss_selector_t *self; - self = ccss_type_selector_create (type_name, precedence, importance); + self = ccss_type_selector_create (type_name, + precedence, + stylesheet_descriptor, + importance); self->modality = CCSS_SELECTOR_MODALITY_BASE_TYPE; - self->importance = importance; - self->precedence = precedence; + self->a = 0; self->b = 0; self->c = 0; @@ -221,8 +230,9 @@ typedef struct { ccss_selector_t * ccss_class_selector_create (char const *class_name, - unsigned int precedence, - ccss_selector_importance_t importance) + unsigned int precedence, + unsigned int stylesheet_descriptor, + ccss_selector_importance_t importance) { ccss_class_selector_t *self; @@ -230,6 +240,7 @@ ccss_class_selector_create (char const *class_name, self = g_new0 (ccss_class_selector_t, 1); self->parent.modality = CCSS_SELECTOR_MODALITY_CLASS; + self->parent.stylesheet_descriptor = stylesheet_descriptor; self->parent.importance = importance; self->parent.precedence = precedence; self->parent.c = 1; @@ -276,8 +287,9 @@ typedef struct { ccss_selector_t * ccss_id_selector_create (char const *id, - unsigned int precedence, - ccss_selector_importance_t importance) + unsigned int precedence, + unsigned int stylesheet_descriptor, + ccss_selector_importance_t importance) { ccss_id_selector_t *self; @@ -285,6 +297,7 @@ ccss_id_selector_create (char const *id, self = g_new0 (ccss_id_selector_t, 1); self->parent.modality = CCSS_SELECTOR_MODALITY_ID; + self->parent.stylesheet_descriptor = stylesheet_descriptor; self->parent.importance = importance; self->parent.precedence = precedence; self->parent.b = 1; @@ -332,11 +345,12 @@ typedef struct { } ccss_attribute_selector_t; ccss_selector_t * -ccss_attribute_selector_create (char const *name, - char const *value, - ccss_attribute_selector_match_t match, - unsigned int precedence, - ccss_selector_importance_t importance) +ccss_attribute_selector_create (char const *name, + char const *value, + ccss_attribute_selector_match_t match, + unsigned int precedence, + unsigned int stylesheet_descriptor, + ccss_selector_importance_t importance) { ccss_attribute_selector_t *self; @@ -344,6 +358,7 @@ ccss_attribute_selector_create (char const *name, self = g_new0 (ccss_attribute_selector_t, 1); self->parent.modality = CCSS_SELECTOR_MODALITY_ATTRIBUTE; + self->parent.stylesheet_descriptor = stylesheet_descriptor; self->parent.importance = importance; self->parent.precedence = precedence; self->parent.c = 1; @@ -404,8 +419,9 @@ typedef struct { ccss_selector_t * ccss_pseudo_class_selector_create (char const *pseudo_class, - unsigned int precedence, - ccss_selector_importance_t importance) + unsigned int precedence, + unsigned int stylesheet_descriptor, + ccss_selector_importance_t importance) { ccss_pseudo_class_selector_t *self; @@ -413,6 +429,7 @@ ccss_pseudo_class_selector_create (char const *pseudo_class, self = g_new0 (ccss_pseudo_class_selector_t, 1); self->parent.modality = CCSS_SELECTOR_MODALITY_PSEUDO_CLASS; + self->parent.stylesheet_descriptor = stylesheet_descriptor; self->parent.importance = importance; self->parent.precedence = precedence; self->parent.d = 1; @@ -459,8 +476,9 @@ typedef struct { ccss_selector_t * ccss_instance_selector_create (ptrdiff_t instance, - unsigned int precedence, - ccss_selector_importance_t importance) + unsigned int precedence, + unsigned int stylesheet_descriptor, + ccss_selector_importance_t importance) { ccss_instance_selector_t *self; @@ -468,6 +486,7 @@ ccss_instance_selector_create (ptrdiff_t instance, self = g_new0 (ccss_instance_selector_t, 1); self->parent.modality = CCSS_SELECTOR_MODALITY_INSTANCE; + self->parent.stylesheet_descriptor = stylesheet_descriptor; self->parent.importance = importance; self->parent.precedence = precedence; self->parent.a = 1; @@ -612,6 +631,11 @@ ccss_selector_destroy (ccss_selector_t *self) ccss_selector_destroy (self->antecessor), self->antecessor = NULL; } + /* Only the innermost type selector references the block. */ + if (self->block) { + ccss_block_destroy (self->block); + } + switch (self->modality) { case CCSS_SELECTOR_MODALITY_UNIVERSAL: universal_selector_destroy ((ccss_universal_selector_t *) self); @@ -778,12 +802,12 @@ ccss_selector_get_block (ccss_selector_t const *self) } void -ccss_selector_set_block (ccss_selector_t *self, - ccss_block_t const *block) +ccss_selector_set_block (ccss_selector_t *self, + ccss_block_t *block) { - g_assert (self); + g_assert (self && self->block == NULL); - self->block = block; + self->block = ccss_block_reference (block); } ccss_selector_importance_t @@ -833,6 +857,12 @@ ccss_selector_get_key (ccss_selector_t const *self) return NULL; } +unsigned int +ccss_selector_get_descriptor (ccss_selector_t const *self) +{ + return self->stylesheet_descriptor; +} + uint32_t ccss_selector_get_specificity (ccss_selector_t const *self) { @@ -1125,6 +1155,7 @@ ccss_selector_dump (ccss_selector_t const *self) selector = g_string_new (NULL); ccss_selector_serialize_selector (self, selector); g_string_append (selector, " /* "); + g_string_append_printf (selector, "'%d' ", self->stylesheet_descriptor); ccss_selector_serialize_specificity (self, selector); g_string_append (selector, " */\n"); printf ("%s", selector->str); diff --git a/ccss/ccss-selector.h b/ccss/ccss-selector.h index 3338e6d..d1420ff 100644 --- a/ccss/ccss-selector.h +++ b/ccss/ccss-selector.h @@ -53,59 +53,69 @@ typedef enum { ccss_selector_t * ccss_universal_selector_create (unsigned int precedence, + unsigned int stylesheet_descriptor, ccss_selector_importance_t importance); ccss_selector_t * ccss_type_selector_create (char const *type_name, unsigned int precedence, + unsigned int stylesheet_descriptor, ccss_selector_importance_t importance); ccss_selector_t * ccss_base_type_selector_create (char const *type_name, unsigned int precedence, + unsigned int stylesheet_descriptor, ccss_selector_importance_t importance, unsigned int specificity_e); ccss_selector_t * ccss_class_selector_create (char const *class_name, unsigned int precedence, + unsigned int stylesheet_descriptor, ccss_selector_importance_t importance); ccss_selector_t * ccss_id_selector_create (char const *id, unsigned int precedence, + unsigned int stylesheet_descriptor, ccss_selector_importance_t importance); ccss_selector_t * ccss_attribute_selector_create (char const *name, char const *value, ccss_attribute_selector_match_t match, unsigned int precedence, + unsigned int stylesheet_descriptor, ccss_selector_importance_t importance); ccss_selector_t * ccss_pseudo_class_selector_create (char const *pseudo_class, - unsigned int precedence, - ccss_selector_importance_t importance); + unsigned int precedence, + unsigned int stylesheet_descriptor, + ccss_selector_importance_t importance); ccss_selector_t * ccss_instance_selector_create (ptrdiff_t instance, unsigned int precedence, + unsigned int stylesheet_descriptor, ccss_selector_importance_t importance); +void ccss_selector_destroy (ccss_selector_t *self); + ccss_selector_t * ccss_selector_copy (ccss_selector_t const *original); ccss_selector_t * ccss_selector_copy_as_base (ccss_selector_t const *original, - int specificity_e); - -void ccss_selector_destroy (ccss_selector_t *self); + int specificity_e); -void ccss_selector_refine (ccss_selector_t *self, ccss_selector_t *selector); -ccss_selector_t * ccss_selector_append_child (ccss_selector_t *self, ccss_selector_t *selector); -ccss_selector_t * ccss_selector_append_descendant (ccss_selector_t *self, ccss_selector_t *selector); +void ccss_selector_refine (ccss_selector_t *self, ccss_selector_t *selector); +ccss_selector_t * ccss_selector_append_child (ccss_selector_t *self, ccss_selector_t *selector); +ccss_selector_t * ccss_selector_append_descendant (ccss_selector_t *self, ccss_selector_t *selector); bool ccss_selector_is_type (ccss_selector_t const *self); bool ccss_selector_is_class (ccss_selector_t const *self); -bool ccss_selector_is_id (ccss_selector_t const *self); +bool ccss_selector_is_id (ccss_selector_t const *self); -ccss_block_t const * ccss_selector_get_block (ccss_selector_t const *self); -void ccss_selector_set_block (ccss_selector_t *self, ccss_block_t const *block); +ccss_block_t const * ccss_selector_get_block (ccss_selector_t const *self); +void ccss_selector_set_block (ccss_selector_t *self, + ccss_block_t *block); char const * ccss_selector_get_key (ccss_selector_t const *self); ccss_selector_importance_t ccss_selector_get_importance (ccss_selector_t const *self); /*ccss_stylesheet_precedence_t ccss_selector_get_precedence (ccss_selector_t const *self);*/ +unsigned int ccss_selector_get_descriptor (ccss_selector_t const *self); uint32_t ccss_selector_get_specificity (ccss_selector_t const *self); void ccss_selector_get_specificity_values (ccss_selector_t const *self, unsigned int *a, diff --git a/ccss/ccss-stylesheet-priv.h b/ccss/ccss-stylesheet-priv.h index 4cc6c1e..8efab44 100644 --- a/ccss/ccss-stylesheet-priv.h +++ b/ccss/ccss-stylesheet-priv.h @@ -34,6 +34,7 @@ CCSS_BEGIN_DECLS * @grammar: The grammar for this stylesheet. * @blocks: List owning all blocks parsed from the stylesheet. * @groups: Associates type names with all applying selectors. + * @current_descriptor: descriptor of the recently loaded CSS file or buffer. * * Represents a parsed instance of a stylesheet. **/ @@ -43,6 +44,7 @@ struct ccss_stylesheet_ { ccss_grammar_t *grammar; GHashTable *blocks; GHashTable *groups; + unsigned int current_descriptor; }; ccss_stylesheet_t * diff --git a/ccss/ccss-stylesheet.c b/ccss/ccss-stylesheet.c index 3253e01..c22e2b9 100644 --- a/ccss/ccss-stylesheet.c +++ b/ccss/ccss-stylesheet.c @@ -37,9 +37,14 @@ ccss_stylesheet_create (void) self = g_new0 (ccss_stylesheet_t, 1); self->reference_count = 1; - self->blocks = g_hash_table_new_full (g_direct_hash, g_direct_equal, - NULL, (GDestroyNotify) ccss_block_destroy); - self->groups = g_hash_table_new (g_str_hash, g_str_equal); + self->blocks = g_hash_table_new_full (g_direct_hash, + g_direct_equal, + NULL, + (GDestroyNotify) ccss_block_destroy); + self->groups = g_hash_table_new_full (g_str_hash, + g_str_equal, + NULL, + (GDestroyNotify) ccss_selector_group_destroy); return self; } @@ -90,16 +95,17 @@ ccss_stylesheet_fix_dangling_selectors (ccss_stylesheet_t *self) /** * ccss_stylesheet_add_from_file: - * @self: #ccss_stylesheet_t instance or %NULL. + * @self: a #ccss_stylesheet_t. * @css_file: file to parse. * @precedence: see #ccss_stylesheet_precedence_t. * @user_data: user-data passed to property- and function-handlers. * * Load a CSS file with a given precedence. * - * Returns: a #ccss_stylesheet_t representation of the CSS file. + * Returns: a stylesheet descriptor that can be used to unload the CSS file + * contents from the stylesheet instance. **/ -ccss_stylesheet_t * +unsigned int ccss_stylesheet_add_from_file (ccss_stylesheet_t *self, char const *css_file, ccss_stylesheet_precedence_t precedence, @@ -107,16 +113,88 @@ ccss_stylesheet_add_from_file (ccss_stylesheet_t *self, { enum CRStatus ret; - g_return_val_if_fail (self && css_file, NULL); + g_return_val_if_fail (self, 0); + g_return_val_if_fail (css_file, 0); + self->current_descriptor++; ret = ccss_grammar_parse_file (self->grammar, css_file, precedence, + self->current_descriptor, user_data, self->groups, self->blocks); if (CR_OK == ret) { ccss_stylesheet_fix_dangling_selectors (self); - return self; + return self->current_descriptor; + } else { + /* TODO clean up using self->current_descriptor */ + return 0; } +} - return NULL; +/** + * ccss_stylesheet_add_from_buffer: + * @self: a #ccss_stylesheet_t. + * @buffer: buffer to parse. + * @size: size of the buffer. + * @precedence: see #ccss_stylesheet_precedence_t. + * @user_data: user-data passed to property- and function-handlers. + * + * Load a CSS file with a given precedence. + * + * Returns: a stylesheet descriptor that can be used to unload the CSS file + * contents from the stylesheet instance. + **/ +unsigned int +ccss_stylesheet_add_from_buffer (ccss_stylesheet_t *self, + char const *buffer, + size_t size, + ccss_stylesheet_precedence_t precedence, + void *user_data) +{ + enum CRStatus ret; + + g_return_val_if_fail (self, 0); + g_return_val_if_fail (buffer, 0); + g_return_val_if_fail (size, 0); + + self->current_descriptor++; + ret = ccss_grammar_parse_buffer (self->grammar, buffer, size, precedence, + self->current_descriptor, + user_data, + self->groups, self->blocks); + if (CR_OK == ret) { + ccss_stylesheet_fix_dangling_selectors (self); + return self->current_descriptor; + } else { + /* TODO clean up using self->current_descriptor */ + return 0; + } +} + +/** + * ccss_stylesheet_unload: + * @self: a #ccss_stylesheet_t. + * @descriptor descriptor of a part that was loaded. + * + * Unload a CSS file, buffer or inline style that was loaded into the stylesheet. + * + * Returns: %TRUE if anything had been unloaded. + */ +bool +ccss_stylesheet_unload (ccss_stylesheet_t *self, + unsigned int descriptor) +{ + ccss_selector_group_t *group; + GHashTableIter iter; + bool ret; + + g_return_val_if_fail (self, false); + + ret = false; + g_hash_table_iter_init (&iter, self->groups); + while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &group)) { + ret |= ccss_selector_group_unload (group, descriptor); + } + + return ret; } /** @@ -278,13 +356,14 @@ query_type_r (ccss_stylesheet_t const *self, * Do not recurse containers. */ static bool -query_node (ccss_stylesheet_t const *self, - ccss_node_t *node, - ccss_style_t *style) +query_node (ccss_stylesheet_t *self, + ccss_node_t *node, + ccss_style_t *style) { ccss_selector_group_t const *universal_group; ccss_selector_group_t *result_group; char const *inline_css; + unsigned int prospective_descriptor; enum CRStatus status; bool ret; @@ -304,7 +383,8 @@ query_node (ccss_stylesheet_t const *self, ret |= query_type_r (self, node, node, false, result_group); /* Handle inline styling. */ - inline_css = ccss_node_get_style (node); + prospective_descriptor = self->current_descriptor + 1; + inline_css = ccss_node_get_style (node, prospective_descriptor); if (inline_css) { ptrdiff_t instance; instance = ccss_node_get_instance (node); @@ -316,10 +396,16 @@ query_node (ccss_stylesheet_t const *self, status = ccss_grammar_parse_inline (self->grammar, inline_css, CCSS_STYLESHEET_AUTHOR, + prospective_descriptor, instance, NULL, result_group, self->blocks); ret |= (status == CR_OK); + if (CR_OK == ret) { + self->current_descriptor = prospective_descriptor; + } else { + /* TODO clean up using prospective_descriptor. */ + } } } @@ -415,10 +501,10 @@ inherit_container_style (ccss_style_t const *container_style, * successful or if no inheritance is required. **/ static bool -query_container_r (ccss_stylesheet_t const *self, - ccss_node_t *node, - GHashTable *inherit, - ccss_style_t *style) +query_container_r (ccss_stylesheet_t *self, + ccss_node_t *node, + GHashTable *inherit, + ccss_style_t *style) { ccss_node_t *container; ccss_style_t *container_style; @@ -524,22 +610,6 @@ ccss_stylesheet_query (ccss_stylesheet_t *self, } /** - * ccss_stylesheet_invalidate_node: - * @self: a #ccss_stylesheet_t. - * @instance: an instance identifyer, as returned by #ccss_node_get_instance_f. - * - * Frees parsed inline CSS asocciated to a document node. - **/ -void -ccss_stylesheet_invalidate_node (ccss_stylesheet_t const *self, - ptrdiff_t instance) -{ - g_assert (self && self->blocks); - - g_hash_table_remove (self->blocks, (gconstpointer) instance); -} - -/** * ccss_stylesheet_foreach: * @self: a #ccss_stylesheet_t. * @func: a #ccss_stylesheet_iterator_f. diff --git a/ccss/ccss-stylesheet.h b/ccss/ccss-stylesheet.h index 8a6ccde..3f81893 100644 --- a/ccss/ccss-stylesheet.h +++ b/ccss/ccss-stylesheet.h @@ -58,12 +58,23 @@ ccss_stylesheet_get_reference_count (ccss_stylesheet_t const *self); struct ccss_grammar_ * ccss_stylesheet_get_grammar (ccss_stylesheet_t const *self); -ccss_stylesheet_t * +unsigned int ccss_stylesheet_add_from_file (ccss_stylesheet_t *self, char const *css_file, ccss_stylesheet_precedence_t precedence, void *user_data); +unsigned int +ccss_stylesheet_add_from_buffer (ccss_stylesheet_t *self, + char const *buffer, + size_t size, + ccss_stylesheet_precedence_t precedence, + void *user_data); + +bool +ccss_stylesheet_unload (ccss_stylesheet_t *self, + unsigned int descriptor); + ccss_style_t * ccss_stylesheet_query_type (ccss_stylesheet_t *self, char const *type_name); @@ -72,10 +83,6 @@ ccss_style_t * ccss_stylesheet_query (ccss_stylesheet_t *self, ccss_node_t *node); -void -ccss_stylesheet_invalidate_node (ccss_stylesheet_t const *self, - ptrdiff_t instance); - /** * ccss_stylesheet_iterator_f: * @self: a #ccss_stylesheet_t. diff --git a/ccss/ccss.sym b/ccss/ccss.sym index 511f6b8..6f031db 100644 --- a/ccss/ccss.sym +++ b/ccss/ccss.sym @@ -31,12 +31,13 @@ ccss_style_get_string ccss_style_set_property ccss_style_hash ccss_style_interpret_property +ccss_stylesheet_add_from_buffer ccss_stylesheet_add_from_file ccss_stylesheet_destroy ccss_stylesheet_dump ccss_stylesheet_foreach ccss_stylesheet_get_reference_count -ccss_stylesheet_invalidate_node ccss_stylesheet_query ccss_stylesheet_query_type ccss_stylesheet_reference +ccss_stylesheet_unload diff --git a/configure.in b/configure.in index e32ba86..15fe81f 100644 --- a/configure.in +++ b/configure.in @@ -7,8 +7,8 @@ AC_PREREQ(2.54) m4_define([ccss_version_major], [0]) -m4_define([ccss_version_minor], [4]) -m4_define([ccss_version_micro], [1]) +m4_define([ccss_version_minor], [5]) +m4_define([ccss_version_micro], [0]) m4_define([ccss_version_extra], []) m4_define([ccss_version], [ccss_version_major.ccss_version_minor.ccss_version_micro[]ccss_version_extra]) diff --git a/examples/Makefile.am b/examples/Makefile.am index 30f4029..d351e09 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -25,6 +25,7 @@ noinst_PROGRAMS = \ example-7 \ example-8 \ example-9 \ + example-10 \ $(NULL) noinst_LTLIBRARIES = libexample-8-noinst.la @@ -65,6 +66,8 @@ libexample_8_la_SOURCES = example-8.c example_9_SOURCES = example-9.c +example_10_SOURCES = example-10.c + EXTRA_DIST = \ example-3.png \ example-5.svg \ diff --git a/examples/example-10.c b/examples/example-10.c new file mode 100644 index 0000000..b0c249e --- /dev/null +++ b/examples/example-10.c @@ -0,0 +1,60 @@ +/* vim: set ts=8 sw=8 noexpandtab: */ + +#include <stdio.h> +#include <stdlib.h> +#include <ccss/ccss.h> +#include "config.h" + +static char const _css_1[] = " \ + a { \ + bar: 1; \ + } \ +"; + +static char const _css_2[] = " \ + a { \ + baz: 2; \ + } \ + b { \ + frob: 3; \ + } \ +"; + +int +main (int argc, + char **argv) +{ + ccss_grammar_t *grammar; + ccss_stylesheet_t *stylesheet; + unsigned int descriptor; + + grammar = ccss_grammar_create_css (); + stylesheet = ccss_grammar_create_stylesheet (grammar); + ccss_grammar_destroy (grammar); + + g_debug ("Empty stylesheet"); + ccss_stylesheet_dump (stylesheet); + + descriptor = ccss_stylesheet_add_from_buffer (stylesheet, + _css_1, sizeof (_css_1), + CCSS_STYLESHEET_AUTHOR, + NULL); + g_debug ("With buffer 1 ('%d')", descriptor); + ccss_stylesheet_dump (stylesheet); + + descriptor = ccss_stylesheet_add_from_buffer (stylesheet, + _css_2, sizeof (_css_2), + CCSS_STYLESHEET_AUTHOR, + NULL); + g_debug ("With buffer 2 ('%d')", descriptor); + ccss_stylesheet_dump (stylesheet); + + ccss_stylesheet_unload (stylesheet, descriptor); + g_debug ("Back to just buffer 1"); + ccss_stylesheet_dump (stylesheet); + + ccss_stylesheet_destroy (stylesheet); + + return EXIT_SUCCESS; +} + diff --git a/examples/example-2.c b/examples/example-2.c index 716ce60..088a1cc 100644 --- a/examples/example-2.c +++ b/examples/example-2.c @@ -26,7 +26,8 @@ get_instance (node_t const *self) } static char const * -get_style (node_t const *self) +get_style (node_t const *self, + unsigned int descriptor) { return self->inline_css; } |