summaryrefslogtreecommitdiff
path: root/gtk/gtkcssprovider.c
diff options
context:
space:
mode:
Diffstat (limited to 'gtk/gtkcssprovider.c')
-rw-r--r--gtk/gtkcssprovider.c457
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, &parameters[i].value);
- gtk_css_ruleset_add (ruleset, child, value);
+ val = property_value_new (value->section);
+ memcpy (&val->value, &parameters[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");
}