diff options
author | Denis Washington <denisw@online.de> | 2011-08-30 08:38:03 +0200 |
---|---|---|
committer | Denis Washington <denisw@online.de> | 2011-08-30 08:38:03 +0200 |
commit | cea54613538ffaa0a2cf2326de1822f740de1361 (patch) | |
tree | c18de79055af8c6466ab882ac1f257c93c316311 /gtk/gtkcssprovider.c | |
parent | c2107aebe708d44e04a34f9549c110a82cce5153 (diff) | |
parent | 143f943905fc75cb5888011b641e447ee5c75037 (diff) | |
download | gtk+-gtkbuilder-gbinding-transform.tar.gz |
Merge branch 'gtkbuilder-gbinding' into gtkbuilder-gbinding-transformgtkbuilder-gbinding-transform
Diffstat (limited to 'gtk/gtkcssprovider.c')
-rw-r--r-- | gtk/gtkcssprovider.c | 457 |
1 files changed, 285 insertions, 172 deletions
diff --git a/gtk/gtkcssprovider.c b/gtk/gtkcssprovider.c index 984618541e..dd73322ec5 100644 --- a/gtk/gtkcssprovider.c +++ b/gtk/gtkcssprovider.c @@ -28,6 +28,7 @@ #include "gtkcssproviderprivate.h" #include "gtkcssparserprivate.h" +#include "gtkcsssectionprivate.h" #include "gtkcssselectorprivate.h" #include "gtksymboliccolor.h" #include "gtkstyleprovider.h" @@ -964,12 +965,11 @@ struct _GtkCssScanner { GtkCssProvider *provider; GtkCssParser *parser; + GtkCssSection *section; GtkCssScanner *parent; GFile *file; GFile *base; GSList *state; - GSList *cur_selectors; - GHashTable *cur_properties; }; struct _GtkCssProviderPrivate @@ -1022,7 +1022,6 @@ gtk_css_provider_load_internal (GtkCssProvider *css_provider, GtkCssScanner *scanner, GFile *file, const char *data, - gsize length, GError **error); GQuark @@ -1037,10 +1036,8 @@ G_DEFINE_TYPE_EXTENDED (GtkCssProvider, gtk_css_provider, G_TYPE_OBJECT, 0, static void gtk_css_provider_parsing_error (GtkCssProvider *provider, - const gchar *path, - guint line, - guint position, - const GError * error) + GtkCssSection *section, + const GError *error) { /* Only emit a warning when we have no error handlers. This is our * default handlers. And in this case erroneous CSS files are a bug @@ -1053,7 +1050,34 @@ gtk_css_provider_parsing_error (GtkCssProvider *provider, 0, TRUE)) { - g_warning ("Theme parsing error: %s:%u:%u: %s", path ? path : "<unknown>", line, position, error->message); + GFileInfo *info; + GFile *file; + const char *path; + + file = gtk_css_section_get_file (section); + if (file) + { + GFileInfo *info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, 0, NULL, NULL); + + if (info) + path = g_file_info_get_display_name (info); + else + path = "<broken file>"; + } + else + { + info = NULL; + path = "<data>"; + } + + g_warning ("Theme parsing error: %s:%u:%u: %s", + path, + gtk_css_section_get_end_line (section) + 1, + gtk_css_section_get_end_position (section), + error->message); + + if (info) + g_object_unref (info); } } @@ -1065,11 +1089,7 @@ gtk_css_provider_class_init (GtkCssProviderClass *klass) /** * GtkCssProvider::parsing-error: * @provider: the provider that had a parsing error - * @path: path to the parsed file or %NULL if the file cannot be - * identified or the data was not loaded from a file - * @line: line in the file or data or 0 if unknown - * @position: offset into the current line or 0 if unknown or the - * whole line is affected + * @section: section the error happened in * @error: The parsing error * * Signals that a parsing error occured. the @path, @line and @position @@ -1090,9 +1110,8 @@ gtk_css_provider_class_init (GtkCssProviderClass *klass) G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GtkCssProviderClass, parsing_error), NULL, NULL, - _gtk_marshal_VOID__STRING_UINT_UINT_BOXED, - G_TYPE_NONE, 4, - G_TYPE_STRING, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_ERROR); + _gtk_marshal_VOID__BOXED_BOXED, + G_TYPE_NONE, 2, GTK_TYPE_CSS_SECTION, G_TYPE_ERROR); object_class->finalize = gtk_css_provider_finalize; @@ -1102,27 +1121,6 @@ gtk_css_provider_class_init (GtkCssProviderClass *klass) } static void -gtk_css_provider_take_error_full (GtkCssProvider *provider, - GFile *file, - guint line, - guint position, - GError *error) -{ - char *filename; - - if (file) - filename = g_file_get_path (file); - else - filename = NULL; - - g_signal_emit (provider, css_provider_signals[PARSING_ERROR], 0, - filename, line, position, error); - - g_free (filename); - g_error_free (error); -} - -static void gtk_css_ruleset_init_copy (GtkCssRuleset *new, const GtkCssRuleset *ruleset, GtkCssSelector *selector) @@ -1149,19 +1147,39 @@ gtk_css_ruleset_clear (GtkCssRuleset *ruleset) memset (ruleset, 0, sizeof (GtkCssRuleset)); } +typedef struct _PropertyValue PropertyValue; +struct _PropertyValue { + GtkCssSection *section; + GValue value; +}; + +static PropertyValue * +property_value_new (GtkCssSection *section) +{ + PropertyValue *value; + + value = g_slice_new0 (PropertyValue); + + value->section = gtk_css_section_ref (section); + + return value; +} + static void -property_value_free (GValue *value) +property_value_free (PropertyValue *value) { - if (G_IS_VALUE (value)) - g_value_unset (value); + if (G_IS_VALUE (&value->value)) + g_value_unset (&value->value); + + gtk_css_section_unref (value->section); - g_slice_free (GValue, value); + g_slice_free (PropertyValue, value); } static void gtk_css_ruleset_add_style (GtkCssRuleset *ruleset, char *name, - GValue *value) + PropertyValue *value) { if (ruleset->widget_style == NULL) ruleset->widget_style = g_hash_table_new_full (g_str_hash, @@ -1175,7 +1193,7 @@ gtk_css_ruleset_add_style (GtkCssRuleset *ruleset, static void gtk_css_ruleset_add (GtkCssRuleset *ruleset, const GtkStyleProperty *prop, - GValue *value) + PropertyValue *value) { if (ruleset->style == NULL) ruleset->style = g_hash_table_new_full (g_direct_hash, @@ -1188,16 +1206,17 @@ gtk_css_ruleset_add (GtkCssRuleset *ruleset, GParameter *parameters; guint i, n_parameters; - parameters = _gtk_style_property_unpack (prop, value, &n_parameters); + parameters = _gtk_style_property_unpack (prop, &value->value, &n_parameters); for (i = 0; i < n_parameters; i++) { const GtkStyleProperty *child; - GValue *value; + PropertyValue *val; child = _gtk_style_property_lookup (parameters[i].name); - value = g_slice_dup (GValue, ¶meters[i].value); - gtk_css_ruleset_add (ruleset, child, value); + val = property_value_new (value->section); + memcpy (&val->value, ¶meters[i].value, sizeof (GValue)); + gtk_css_ruleset_add (ruleset, child, val); } g_free (parameters); property_value_free (value); @@ -1217,68 +1236,54 @@ gtk_css_ruleset_matches (GtkCssRuleset *ruleset, } static void -gtk_css_scanner_reset (GtkCssScanner *scanner) -{ - g_slist_free (scanner->state); - scanner->state = NULL; - - g_slist_free_full (scanner->cur_selectors, (GDestroyNotify) _gtk_css_selector_free); - scanner->cur_selectors = NULL; - - if (scanner->cur_properties) - g_hash_table_unref (scanner->cur_properties); - - scanner ->cur_properties = g_hash_table_new_full (g_str_hash, - g_str_equal, - (GDestroyNotify) g_free, - (GDestroyNotify) property_value_free); -} - -static void gtk_css_scanner_destroy (GtkCssScanner *scanner) { - gtk_css_scanner_reset (scanner); - g_object_unref (scanner->provider); if (scanner->file) g_object_unref (scanner->file); g_object_unref (scanner->base); - g_hash_table_destroy (scanner->cur_properties); _gtk_css_parser_free (scanner->parser); g_slice_free (GtkCssScanner, scanner); } static void +gtk_css_provider_emit_error (GtkCssProvider *provider, + GtkCssScanner *scanner, + const GError *error) +{ + g_signal_emit (provider, css_provider_signals[PARSING_ERROR], 0, + scanner->section, error); +} + +static void gtk_css_scanner_parser_error (GtkCssParser *parser, const GError *error, gpointer user_data) { GtkCssScanner *scanner = user_data; - gtk_css_provider_take_error_full (scanner->provider, - scanner->file, - _gtk_css_parser_get_line (scanner->parser), - _gtk_css_parser_get_position (scanner->parser), - g_error_copy (error)); + gtk_css_provider_emit_error (scanner->provider, + scanner, + error); } static GtkCssScanner * gtk_css_scanner_new (GtkCssProvider *provider, GtkCssScanner *parent, + GtkCssSection *section, GFile *file, - const gchar *data, - gsize length) + const gchar *text) { GtkCssScanner *scanner; - g_assert (data[length] == 0); - scanner = g_slice_new0 (GtkCssScanner); g_object_ref (provider); scanner->provider = provider; scanner->parent = parent; + if (section) + scanner->section = gtk_css_section_ref (section); if (file) { @@ -1292,12 +1297,7 @@ gtk_css_scanner_new (GtkCssProvider *provider, g_free (dir); } - scanner->cur_properties = g_hash_table_new_full (g_str_hash, - g_str_equal, - (GDestroyNotify) g_free, - (GDestroyNotify) property_value_free); - - scanner->parser = _gtk_css_parser_new (data, + scanner->parser = _gtk_css_parser_new (text, gtk_css_scanner_parser_error, scanner); @@ -1326,6 +1326,40 @@ gtk_css_scanner_would_recurse (GtkCssScanner *scanner, } static void +gtk_css_scanner_push_section (GtkCssScanner *scanner, + GtkCssSectionType section_type) +{ + GtkCssSection *section; + + section = _gtk_css_section_new (scanner->section, + section_type, + scanner->parser, + scanner->file); + + if (scanner->section) + gtk_css_section_unref (scanner->section); + scanner->section = section; +} + +static void +gtk_css_scanner_pop_section (GtkCssScanner *scanner, + GtkCssSectionType check_type) +{ + GtkCssSection *parent; + + g_assert (gtk_css_section_get_section_type (scanner->section) == check_type); + + parent = gtk_css_section_get_parent (scanner->section); + if (parent) + gtk_css_section_ref (parent); + + _gtk_css_section_end (scanner->section); + gtk_css_section_unref (scanner->section); + + scanner->section = parent; +} + +static void gtk_css_provider_init (GtkCssProvider *css_provider) { GtkCssProviderPrivate *priv; @@ -1386,7 +1420,7 @@ gtk_css_provider_get_style (GtkStyleProvider *provider, { GtkCssRuleset *ruleset; GHashTableIter iter; - gpointer key, value; + gpointer key, val; ruleset = &g_array_index (priv->rulesets, GtkCssRuleset, i); @@ -1401,9 +1435,10 @@ gtk_css_provider_get_style (GtkStyleProvider *provider, g_hash_table_iter_init (&iter, ruleset->style); - while (g_hash_table_iter_next (&iter, &key, &value)) + while (g_hash_table_iter_next (&iter, &key, &val)) { GtkStyleProperty *prop = key; + PropertyValue *value = val; if (l != length && !_gtk_style_property_is_inherit (prop)) continue; @@ -1411,7 +1446,7 @@ gtk_css_provider_get_style (GtkStyleProvider *provider, _gtk_style_properties_set_property_by_property (props, prop, _gtk_css_selector_get_state_flags (ruleset->selector), - value); + &value->value); } } } @@ -1419,20 +1454,6 @@ gtk_css_provider_get_style (GtkStyleProvider *provider, return props; } -static void -gtk_css_provider_parser_error (GtkCssParser *parser, - const GError *error, - gpointer user_data) -{ - GtkCssProvider *provider = user_data; - - gtk_css_provider_take_error_full (provider, - NULL, - _gtk_css_parser_get_line (parser), - _gtk_css_parser_get_position (parser), - g_error_copy (error)); -} - static gboolean gtk_css_provider_get_style_property (GtkStyleProvider *provider, GtkWidgetPath *path, @@ -1442,7 +1463,7 @@ gtk_css_provider_get_style_property (GtkStyleProvider *provider, { GtkCssProvider *css_provider = GTK_CSS_PROVIDER (provider); GtkCssProviderPrivate *priv = css_provider->priv; - const GValue *val; + PropertyValue *val; gboolean found = FALSE; gchar *prop_name; gint i; @@ -1473,18 +1494,20 @@ gtk_css_provider_get_style_property (GtkStyleProvider *provider, ((selector_state & state) != 0 && (selector_state & ~(state)) == 0))) { - GtkCssParser *parser; + GtkCssScanner *scanner; - parser = _gtk_css_parser_new (g_value_get_string (val), - gtk_css_provider_parser_error, - provider); + scanner = gtk_css_scanner_new (css_provider, + NULL, + val->section, + gtk_css_section_get_file (val->section), + g_value_get_string (&val->value)); found = _gtk_style_property_parse_value (NULL, value, - parser, + scanner->parser, NULL); - _gtk_css_parser_free (parser); + gtk_css_scanner_destroy (scanner); if (found) break; @@ -1542,11 +1565,11 @@ gtk_css_provider_take_error (GtkCssProvider *provider, GtkCssScanner *scanner, GError *error) { - gtk_css_provider_take_error_full (provider, - scanner->file, - _gtk_css_parser_get_line (scanner->parser), - _gtk_css_parser_get_position (scanner->parser), - error); + gtk_css_provider_emit_error (scanner->provider, + scanner, + error); + + g_error_free (error); } static void @@ -1664,20 +1687,30 @@ gtk_css_provider_propagate_error (GtkCssProvider *provider, g_prefix_error (propagate_to, "%s:%u:%u: ", path ? path : "<unknown>", line, position); } -static void +static gboolean parse_import (GtkCssScanner *scanner) { GFile *file; char *uri; + gtk_css_scanner_push_section (scanner, GTK_CSS_SECTION_IMPORT); + + if (!_gtk_css_parser_try (scanner->parser, "@import", TRUE)) + { + gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_IMPORT); + return FALSE; + } + if (_gtk_css_parser_is_string (scanner->parser)) uri = _gtk_css_parser_read_string (scanner->parser); else uri = _gtk_css_parser_read_uri (scanner->parser); + if (uri == NULL) { _gtk_css_parser_resync (scanner->parser, TRUE, 0); - return; + gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_IMPORT); + return TRUE; } file = g_file_resolve_relative_path (gtk_css_scanner_get_base_url (scanner), uri); @@ -1699,27 +1732,36 @@ parse_import (GtkCssScanner *scanner) gtk_css_provider_load_internal (scanner->provider, scanner, file, - NULL, 0, + NULL, NULL); } if (!_gtk_css_parser_try (scanner->parser, ";", TRUE)) { - g_object_unref (file); gtk_css_provider_invalid_token (scanner->provider, scanner, "semicolon"); _gtk_css_parser_resync (scanner->parser, TRUE, 0); - return; } g_object_unref (file); + + gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_IMPORT); + return TRUE; } -static void +static gboolean parse_color_definition (GtkCssScanner *scanner) { GtkSymbolicColor *symbolic; char *name; + gtk_css_scanner_push_section (scanner, GTK_CSS_SECTION_COLOR_DEFINITION); + + if (!_gtk_css_parser_try (scanner->parser, "@define-color", TRUE)) + { + gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_COLOR_DEFINITION); + return FALSE; + } + name = _gtk_css_parser_try_name (scanner->parser, TRUE); if (name == NULL) { @@ -1729,7 +1771,8 @@ parse_color_definition (GtkCssScanner *scanner) GTK_CSS_PROVIDER_ERROR_SYNTAX, "Not a valid color name"); _gtk_css_parser_resync (scanner->parser, TRUE, 0); - return; + gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_COLOR_DEFINITION); + return TRUE; } symbolic = _gtk_css_parser_read_symbolic_color (scanner->parser); @@ -1737,7 +1780,8 @@ parse_color_definition (GtkCssScanner *scanner) { g_free (name); _gtk_css_parser_resync (scanner->parser, TRUE, 0); - return; + gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_COLOR_DEFINITION); + return TRUE; } if (!_gtk_css_parser_try (scanner->parser, ";", TRUE)) @@ -1750,18 +1794,31 @@ parse_color_definition (GtkCssScanner *scanner) GTK_CSS_PROVIDER_ERROR_SYNTAX, "Missing semicolon at end of color definition"); _gtk_css_parser_resync (scanner->parser, TRUE, 0); - return; + + gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_COLOR_DEFINITION); + return TRUE; } g_hash_table_insert (scanner->provider->priv->symbolic_colors, name, symbolic); + + gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_COLOR_DEFINITION); + return TRUE; } -static void +static gboolean parse_binding_set (GtkCssScanner *scanner) { GtkBindingSet *binding_set; char *name; + gtk_css_scanner_push_section (scanner, GTK_CSS_SECTION_BINDING_SET); + + if (!_gtk_css_parser_try (scanner->parser, "@binding-set", TRUE)) + { + gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_BINDING_SET); + return FALSE; + } + name = _gtk_css_parser_try_ident (scanner->parser, TRUE); if (name == NULL) { @@ -1850,17 +1907,22 @@ skip_semicolon: "Nonstandard semicolon at end of binding set"); _gtk_css_parser_try (scanner->parser, ";", TRUE); } + + gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_BINDING_SET); + + return TRUE; } static void parse_at_keyword (GtkCssScanner *scanner) { - if (_gtk_css_parser_try (scanner->parser, "@import", TRUE)) - parse_import (scanner); - else if (_gtk_css_parser_try (scanner->parser, "@define-color", TRUE)) - parse_color_definition (scanner); - else if (_gtk_css_parser_try (scanner->parser, "@binding-set", TRUE)) - parse_binding_set (scanner); + if (parse_import (scanner)) + return; + if (parse_color_definition (scanner)) + return; + if (parse_binding_set (scanner)) + return; + else { gtk_css_provider_error_literal (scanner->provider, @@ -2152,6 +2214,8 @@ parse_selector_list (GtkCssScanner *scanner) { GSList *selectors = NULL; + gtk_css_scanner_push_section (scanner, GTK_CSS_SECTION_SELECTOR); + do { GtkCssSelector *select = parse_selector (scanner); @@ -2159,6 +2223,7 @@ parse_selector_list (GtkCssScanner *scanner) { g_slist_free_full (selectors, (GDestroyNotify) _gtk_css_selector_free); _gtk_css_parser_resync (scanner->parser, FALSE, 0); + gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_SELECTOR); return NULL; } @@ -2166,6 +2231,8 @@ parse_selector_list (GtkCssScanner *scanner) } while (_gtk_css_parser_try (scanner->parser, ",", TRUE)); + gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_SELECTOR); + return selectors; } @@ -2176,6 +2243,8 @@ parse_declaration (GtkCssScanner *scanner, const GtkStyleProperty *property; char *name; + gtk_css_scanner_push_section (scanner, GTK_CSS_SECTION_DECLARATION); + name = _gtk_css_parser_try_ident (scanner->parser, TRUE); if (name == NULL) goto check_for_semicolon; @@ -2191,6 +2260,7 @@ parse_declaration (GtkCssScanner *scanner, name); _gtk_css_parser_resync (scanner->parser, TRUE, '}'); g_free (name); + gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_DECLARATION); return; } @@ -2199,20 +2269,23 @@ parse_declaration (GtkCssScanner *scanner, gtk_css_provider_invalid_token (scanner->provider, scanner, "':'"); _gtk_css_parser_resync (scanner->parser, TRUE, '}'); g_free (name); + gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_DECLARATION); return; } if (property) { - GValue *val; + PropertyValue *val; g_free (name); - val = g_slice_new0 (GValue); - g_value_init (val, property->pspec->value_type); + gtk_css_scanner_push_section (scanner, GTK_CSS_SECTION_VALUE); + + val = property_value_new (scanner->section); + g_value_init (&val->value, property->pspec->value_type); if (_gtk_style_property_parse_value (property, - val, + &val->value, scanner->parser, gtk_css_scanner_get_base_url (scanner))) { @@ -2230,44 +2303,55 @@ parse_declaration (GtkCssScanner *scanner, GTK_CSS_PROVIDER_ERROR_SYNTAX, "Junk at end of value"); _gtk_css_parser_resync (scanner->parser, TRUE, '}'); - g_value_unset (val); - g_slice_free (GValue, val); + property_value_free (val); + gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_VALUE); + gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_DECLARATION); return; } } else { - g_value_unset (val); - g_slice_free (GValue, val); + property_value_free (val); _gtk_css_parser_resync (scanner->parser, TRUE, '}'); + gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_VALUE); + gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_DECLARATION); return; } + gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_VALUE); } else if (name[0] == '-') { char *value_str; + gtk_css_scanner_push_section (scanner, GTK_CSS_SECTION_VALUE); + value_str = _gtk_css_parser_read_value (scanner->parser); if (value_str) { - GValue *val; + PropertyValue *val; - val = g_slice_new0 (GValue); - g_value_init (val, G_TYPE_STRING); - g_value_take_string (val, value_str); + val = property_value_new (scanner->section); + g_value_init (&val->value, G_TYPE_STRING); + g_value_take_string (&val->value, value_str); gtk_css_ruleset_add_style (ruleset, name, val); } else { _gtk_css_parser_resync (scanner->parser, TRUE, '}'); + gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_VALUE); + gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_DECLARATION); return; } + + gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_VALUE); } else g_free (name); check_for_semicolon: + gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_DECLARATION); + if (!_gtk_css_parser_try (scanner->parser, ";", TRUE)) { if (!_gtk_css_parser_begins_with (scanner->parser, '}') && @@ -2300,9 +2384,14 @@ parse_ruleset (GtkCssScanner *scanner) GSList *selectors; GtkCssRuleset ruleset = { 0, }; + gtk_css_scanner_push_section (scanner, GTK_CSS_SECTION_RULESET); + selectors = parse_selector_list (scanner); if (selectors == NULL) - return; + { + gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_RULESET); + return; + } if (!_gtk_css_parser_try (scanner->parser, "{", TRUE)) { @@ -2313,6 +2402,7 @@ parse_ruleset (GtkCssScanner *scanner) "expected '{' after selectors"); _gtk_css_parser_resync (scanner->parser, FALSE, 0); g_slist_free_full (selectors, (GDestroyNotify) _gtk_css_selector_free); + gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_RULESET); return; } @@ -2330,12 +2420,13 @@ parse_ruleset (GtkCssScanner *scanner) _gtk_css_parser_resync (scanner->parser, FALSE, 0); g_slist_free_full (selectors, (GDestroyNotify) _gtk_css_selector_free); gtk_css_ruleset_clear (&ruleset); - return; + gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_RULESET); } } css_provider_commit (scanner->provider, selectors, &ruleset); gtk_css_ruleset_clear (&ruleset); + gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_RULESET); } static void @@ -2350,6 +2441,8 @@ parse_statement (GtkCssScanner *scanner) static void parse_stylesheet (GtkCssScanner *scanner) { + gtk_css_scanner_push_section (scanner, GTK_CSS_SECTION_DOCUMENT); + _gtk_css_parser_skip_whitespace (scanner->parser); while (!_gtk_css_parser_is_eof (scanner->parser)) @@ -2360,6 +2453,8 @@ parse_stylesheet (GtkCssScanner *scanner) parse_statement (scanner); } + + gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_DOCUMENT); } static int @@ -2396,8 +2491,7 @@ static gboolean gtk_css_provider_load_internal (GtkCssProvider *css_provider, GtkCssScanner *parent, GFile *file, - const char *data, - gsize length, + const char *text, GError **error) { GtkCssScanner *scanner; @@ -2412,41 +2506,43 @@ gtk_css_provider_load_internal (GtkCssProvider *css_provider, else error_handler = 0; /* silence gcc */ - if (data == NULL) + if (text == NULL) { GError *load_error = NULL; if (g_file_load_contents (file, NULL, - &free_data, &length, + &free_data, NULL, NULL, &load_error)) { - data = free_data; + text = free_data; } else { + GtkCssSection *section; + if (parent) - { - gtk_css_provider_error (css_provider, - parent, - GTK_CSS_PROVIDER_ERROR, - GTK_CSS_PROVIDER_ERROR_IMPORT, - "Failed to import: %s", - load_error->message); - g_error_free (load_error); - } + section = gtk_css_section_ref (parent->section); else - { - gtk_css_provider_take_error_full (css_provider, - file, - 0, 0, - load_error); - } + section = _gtk_css_section_new_for_file (GTK_CSS_SECTION_DOCUMENT, file); + + gtk_css_provider_error (css_provider, + parent, + GTK_CSS_PROVIDER_ERROR, + GTK_CSS_PROVIDER_ERROR_IMPORT, + "Failed to import: %s", + load_error->message); + + gtk_css_section_unref (section); } } - if (data) + if (text) { - scanner = gtk_css_scanner_new (css_provider, parent, file, data, length); + scanner = gtk_css_scanner_new (css_provider, + parent, + parent ? parent->section : NULL, + file, + text); parse_stylesheet (scanner); @@ -2477,7 +2573,9 @@ gtk_css_provider_load_internal (GtkCssProvider *css_provider, * gtk_css_provider_load_from_data: * @css_provider: a #GtkCssProvider * @data: (array length=length) (element-type guint8): CSS data loaded in memory - * @length: the length of @data in bytes, or -1 for NUL terminated strings + * @length: the length of @data in bytes, or -1 for NUL terminated strings. If + * @length is not -1, the code will assume it is not NUL terminated and will + * potentially do a copy. * @error: (out) (allow-none): return location for a #GError, or %NULL * * Loads @data into @css_provider, making it clear any previously loaded @@ -2491,15 +2589,30 @@ gtk_css_provider_load_from_data (GtkCssProvider *css_provider, gssize length, GError **error) { + char *free_data; + gboolean ret; + g_return_val_if_fail (GTK_IS_CSS_PROVIDER (css_provider), FALSE); g_return_val_if_fail (data != NULL, FALSE); if (length < 0) - length = strlen (data); + { + length = strlen (data); + free_data = NULL; + } + else + { + free_data = g_strndup (data, length); + data = free_data; + } gtk_css_provider_reset (css_provider); - return gtk_css_provider_load_internal (css_provider, NULL, NULL, data, length, error); + ret = gtk_css_provider_load_internal (css_provider, NULL, NULL, data, error); + + g_free (free_data); + + return ret; } /** @@ -2523,7 +2636,7 @@ gtk_css_provider_load_from_file (GtkCssProvider *css_provider, gtk_css_provider_reset (css_provider); - return gtk_css_provider_load_internal (css_provider, NULL, file, NULL, 0, error); + return gtk_css_provider_load_internal (css_provider, NULL, file, NULL, error); } /** @@ -3083,12 +3196,12 @@ gtk_css_ruleset_print (const GtkCssRuleset *ruleset, for (walk = keys; walk; walk = walk->next) { GtkStyleProperty *prop = walk->data; - const GValue *value = g_hash_table_lookup (ruleset->style, prop); + const PropertyValue *value = g_hash_table_lookup (ruleset->style, prop); g_string_append (str, " "); g_string_append (str, prop->pspec->name); g_string_append (str, ": "); - _gtk_style_property_print_value (prop, value, str); + _gtk_style_property_print_value (prop, &value->value, str); g_string_append (str, ";\n"); } @@ -3104,12 +3217,12 @@ gtk_css_ruleset_print (const GtkCssRuleset *ruleset, for (walk = keys; walk; walk = walk->next) { const char *name = walk->data; - const GValue *value = g_hash_table_lookup (ruleset->widget_style, (gpointer) name); + const PropertyValue *value = g_hash_table_lookup (ruleset->widget_style, (gpointer) name); g_string_append (str, " "); g_string_append (str, name); g_string_append (str, ": "); - g_string_append (str, g_value_get_string (value)); + g_string_append (str, g_value_get_string (&value->value)); g_string_append (str, ";\n"); } |