summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ccss-doc/ccss-sections.txt3
-rw-r--r--ccss-doc/tmpl/ccss-unused.sgml8
-rw-r--r--ccss-doc/tmpl/node.sgml1
-rw-r--r--ccss-doc/tmpl/stylesheet.sgml26
-rw-r--r--ccss/ccss-block-priv.h4
-rw-r--r--ccss/ccss-block.c18
-rw-r--r--ccss/ccss-grammar-parse.c77
-rw-r--r--ccss/ccss-grammar-priv.h3
-rw-r--r--ccss/ccss-grammar.c29
-rw-r--r--ccss/ccss-node-priv.h3
-rw-r--r--ccss/ccss-node.c9
-rw-r--r--ccss/ccss-node.h6
-rw-r--r--ccss/ccss-selector-group.c80
-rw-r--r--ccss/ccss-selector-group.h4
-rw-r--r--ccss/ccss-selector.c89
-rw-r--r--ccss/ccss-selector.h32
-rw-r--r--ccss/ccss-stylesheet-priv.h2
-rw-r--r--ccss/ccss-stylesheet.c136
-rw-r--r--ccss/ccss-stylesheet.h17
-rw-r--r--ccss/ccss.sym3
-rw-r--r--configure.in4
-rw-r--r--examples/Makefile.am3
-rw-r--r--examples/example-10.c60
-rw-r--r--examples/example-2.c3
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;
}