summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Otte <otte@redhat.com>2011-06-17 02:02:24 +0200
committerBenjamin Otte <otte@redhat.com>2011-08-26 16:26:27 +0200
commit00d14e35157d7512ec9892bcc5eebdc186ad52e3 (patch)
treef6883587bb7116d7369db6b7c12a99c907a7693e
parentc8fdd5e847181997cf8f366a1d47bff53d0d7976 (diff)
downloadgtk+-00d14e35157d7512ec9892bcc5eebdc186ad52e3.tar.gz
API: css: Add GtkCssSection
This struct keeps track of an area of text in a CSS file and uses it when specifying information. Also, the cssprovider keeps track of sections when parsing a file.
-rw-r--r--docs/reference/gtk/gtk3-sections.txt14
-rw-r--r--gtk/Makefile.am3
-rw-r--r--gtk/gtk.h1
-rw-r--r--gtk/gtk.symbols10
-rw-r--r--gtk/gtkcssprovider.c136
-rw-r--r--gtk/gtkcsssection.c291
-rw-r--r--gtk/gtkcsssection.h82
-rw-r--r--gtk/gtkcsssectionprivate.h38
8 files changed, 558 insertions, 17 deletions
diff --git a/docs/reference/gtk/gtk3-sections.txt b/docs/reference/gtk/gtk3-sections.txt
index 7ec6f1d82c..2cc0722e57 100644
--- a/docs/reference/gtk/gtk3-sections.txt
+++ b/docs/reference/gtk/gtk3-sections.txt
@@ -5739,6 +5739,19 @@ gtk_css_provider_new
gtk_css_provider_to_string
GTK_CSS_PROVIDER_ERROR
GtkCssProviderError
+<SUBSECTION>
+GtkCssSection
+GtkCssSectionType
+gtk_css_section_get_end_line
+gtk_css_section_get_end_position
+gtk_css_section_get_file
+gtk_css_section_get_parent
+gtk_css_section_get_section_type
+gtk_css_section_get_start_line
+gtk_css_section_get_start_position
+gtk_css_section_get_type
+gtk_css_section_ref
+gtk_css_section_unref
<SUBSECTION Standard>
GTK_TYPE_CSS_PROVIDER
GTK_CSS_PROVIDER
@@ -5749,6 +5762,7 @@ GTK_IS_CSS_PROVIDER_CLASS
<SUBSECTION Private>
gtk_css_provider_get_type
gtk_css_provider_error_quark
+gtk_css_section_get_type
</SECTION>
<SECTION>
diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index ec3ff04121..f6d6ee1fa4 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -199,6 +199,7 @@ gtk_public_h_sources = \
gtkcomboboxtext.h \
gtkcontainer.h \
gtkcssprovider.h \
+ gtkcsssection.h \
gtkdebug.h \
gtkdialog.h \
gtkdnd.h \
@@ -394,6 +395,7 @@ gtk_private_h_sources = \
gtkcontainerprivate.h \
gtkcssparserprivate.h \
gtkcssproviderprivate.h \
+ gtkcsssectionprivate.h \
gtkcssselectorprivate.h \
gtkcsstypesprivate.h \
gtkcustompaperunixdialog.h \
@@ -526,6 +528,7 @@ gtk_base_c_sources = \
gtkcontainer.c \
gtkcssparser.c \
gtkcssprovider.c \
+ gtkcsssection.c \
gtkcssselector.c \
gtkcsstypes.c \
gtkdialog.c \
diff --git a/gtk/gtk.h b/gtk/gtk.h
index 7e2526e5b0..a2813e9b0d 100644
--- a/gtk/gtk.h
+++ b/gtk/gtk.h
@@ -82,6 +82,7 @@
#include <gtk/gtkcomboboxtext.h>
#include <gtk/gtkcontainer.h>
#include <gtk/gtkcssprovider.h>
+#include <gtk/gtkcsssection.h>
#include <gtk/gtkdebug.h>
#include <gtk/gtkdialog.h>
#include <gtk/gtkdnd.h>
diff --git a/gtk/gtk.symbols b/gtk/gtk.symbols
index 2c95bdf87f..9a42c01074 100644
--- a/gtk/gtk.symbols
+++ b/gtk/gtk.symbols
@@ -701,6 +701,16 @@ gtk_css_provider_load_from_file
gtk_css_provider_load_from_path
gtk_css_provider_new
gtk_css_provider_to_string
+gtk_css_section_get_end_line
+gtk_css_section_get_end_position
+gtk_css_section_get_file
+gtk_css_section_get_parent
+gtk_css_section_get_section_type
+gtk_css_section_get_start_line
+gtk_css_section_get_start_position
+gtk_css_section_get_type
+gtk_css_section_ref
+gtk_css_section_unref
#ifdef G_OS_UNIX
gtk_custom_paper_unix_dialog_get_type
#endif
diff --git a/gtk/gtkcssprovider.c b/gtk/gtkcssprovider.c
index 984618541e..30c5b79934 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,6 +965,7 @@ struct _GtkCssScanner
{
GtkCssProvider *provider;
GtkCssParser *parser;
+ GSList *sections;
GtkCssScanner *parent;
GFile *file;
GFile *base;
@@ -1237,6 +1239,8 @@ gtk_css_scanner_reset (GtkCssScanner *scanner)
static void
gtk_css_scanner_destroy (GtkCssScanner *scanner)
{
+ g_assert (scanner->sections == NULL);
+
gtk_css_scanner_reset (scanner);
g_object_unref (scanner->provider);
@@ -1326,6 +1330,40 @@ gtk_css_scanner_would_recurse (GtkCssScanner *scanner,
}
static void
+gtk_css_scanner_push_section (GtkCssScanner *scanner,
+ GtkCssSectionType section_type)
+{
+ GtkCssSection *parent, *section;
+
+ if (scanner->sections)
+ parent = scanner->sections->data;
+ else if (scanner->parent)
+ parent = scanner->parent->sections->data;
+ else
+ parent = NULL;
+
+ section = _gtk_css_section_new (parent,
+ section_type,
+ scanner->parser,
+ scanner->file);
+ scanner->sections = g_slist_prepend (scanner->sections, section);
+}
+
+static void
+gtk_css_scanner_pop_section (GtkCssScanner *scanner,
+ GtkCssSectionType check_type)
+{
+ GtkCssSection *section = scanner->sections->data;
+
+ g_assert (check_type == gtk_css_section_get_section_type (section));
+
+ scanner->sections = g_slist_delete_link (scanner->sections, scanner->sections);
+
+ _gtk_css_section_end (section);
+ gtk_css_section_unref (section);
+}
+
+static void
gtk_css_provider_init (GtkCssProvider *css_provider)
{
GtkCssProviderPrivate *priv;
@@ -1664,20 +1702,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);
@@ -1705,21 +1753,30 @@ parse_import (GtkCssScanner *scanner)
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 +1786,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 +1795,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 +1809,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 +1922,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 +2229,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 +2238,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 +2246,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 +2258,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 +2275,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,6 +2284,7 @@ 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;
}
@@ -2232,6 +2318,7 @@ parse_declaration (GtkCssScanner *scanner,
_gtk_css_parser_resync (scanner->parser, TRUE, '}');
g_value_unset (val);
g_slice_free (GValue, val);
+ gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_DECLARATION);
return;
}
}
@@ -2240,6 +2327,7 @@ parse_declaration (GtkCssScanner *scanner,
g_value_unset (val);
g_slice_free (GValue, val);
_gtk_css_parser_resync (scanner->parser, TRUE, '}');
+ gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_DECLARATION);
return;
}
}
@@ -2261,6 +2349,7 @@ parse_declaration (GtkCssScanner *scanner,
else
{
_gtk_css_parser_resync (scanner->parser, TRUE, '}');
+ gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_DECLARATION);
return;
}
}
@@ -2268,6 +2357,8 @@ parse_declaration (GtkCssScanner *scanner,
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 +2391,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 +2409,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 +2427,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 +2448,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 +2460,8 @@ parse_stylesheet (GtkCssScanner *scanner)
parse_statement (scanner);
}
+
+ gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_DOCUMENT);
}
static int
diff --git a/gtk/gtkcsssection.c b/gtk/gtkcsssection.c
new file mode 100644
index 0000000000..4b1d0e513f
--- /dev/null
+++ b/gtk/gtkcsssection.c
@@ -0,0 +1,291 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include "gtkcsssectionprivate.h"
+
+#include "gtkcssparserprivate.h"
+
+/**
+ * GtkCssSection:
+ *
+ * Defines a part of a CSS document. Because sections are nested into
+ * one another, you can use gtk_css_section_get_parent() to get the
+ * containing region.
+ *
+ * Since: 3.2
+ */
+
+struct _GtkCssSection
+{
+ volatile gint ref_count;
+ GtkCssSectionType section_type;
+ GtkCssSection *parent;
+ GFile *file;
+ guint start_line;
+ guint start_position;
+ GtkCssParser *parser; /* parser if section isn't finished parsing yet or %NULL */
+ guint end_line; /* end line if parser is %NULL */
+ guint end_position; /* end position if parser is %NULL */
+};
+
+G_DEFINE_BOXED_TYPE (GtkCssSection, gtk_css_section, gtk_css_section_ref, gtk_css_section_unref)
+
+GtkCssSection *
+_gtk_css_section_new (GtkCssSection *parent,
+ GtkCssSectionType type,
+ GtkCssParser *parser,
+ GFile *file)
+{
+ GtkCssSection *section;
+
+ g_return_val_if_fail (parser != NULL, NULL);
+ g_return_val_if_fail (file == NULL || G_IS_FILE (file), NULL);
+
+ section = g_slice_new0 (GtkCssSection);
+
+ section->ref_count = 1;
+ section->section_type = type;
+ if (parent)
+ section->parent = gtk_css_section_ref (parent);
+ if (file)
+ section->file = g_object_ref (file);
+ section->start_line = _gtk_css_parser_get_line (parser);
+ section->start_position = _gtk_css_parser_get_position (parser);
+ section->parser = parser;
+
+ return section;
+}
+
+void
+_gtk_css_section_end (GtkCssSection *section)
+{
+ g_return_if_fail (section != NULL);
+ g_return_if_fail (section->parser != NULL);
+
+ section->end_line = _gtk_css_parser_get_line (section->parser);
+ section->end_position = _gtk_css_parser_get_position (section->parser);
+ section->parser = NULL;
+}
+
+/**
+ * gtk_css_section_ref:
+ * @section: a #GtkCssSection
+ *
+ * Increments the reference count on @section.
+ *
+ * Returns: @section itself.
+ *
+ * Since: 3.2
+ **/
+GtkCssSection *
+gtk_css_section_ref (GtkCssSection *section)
+{
+ g_return_val_if_fail (section != NULL, NULL);
+
+ g_atomic_int_add (&section->ref_count, 1);
+
+ return section;
+}
+
+/**
+ * gtk_css_section_unref:
+ * @section: a #GtkCssSection
+ *
+ * Decrements the reference count on @section, freeing the
+ * structure if the reference count reaches 0.
+ *
+ * Since: 3.2
+ **/
+void
+gtk_css_section_unref (GtkCssSection *section)
+{
+ g_return_if_fail (section != NULL);
+
+ if (!g_atomic_int_dec_and_test (&section->ref_count))
+ return;
+
+ if (section->parent)
+ gtk_css_section_unref (section->parent);
+ if (section->file)
+ g_object_unref (section->file);
+
+ g_slice_free (GtkCssSection, section);
+}
+
+/**
+ * gtk_css_section_get_section_type:
+ * @section: the section
+ *
+ * Gets the type of information that @section describes.
+ *
+ * Returns: the type of @section
+ *
+ * Since: 3.2
+ **/
+GtkCssSectionType
+gtk_css_section_get_section_type (const GtkCssSection *section)
+{
+ g_return_val_if_fail (section != NULL, GTK_CSS_SECTION_DOCUMENT);
+
+ return section->section_type;
+}
+
+/**
+ * gtk_css_section_get_parent:
+ * @section: the section
+ *
+ * Gets the parent section for the given @section. The parent section is
+ * the section that contains this @section. A special case are sections of
+ * type #GTK_CSS_SECTION_TYPE_DOCUMENT. Their parent will either be %NULL
+ * if they are the original CSS document that was loaded by
+ * gtk_css_provider_load_from_file() or a section of type
+ * #GTK_CSS_SECTION_TYPE_IMPORT if it was loaded with an import rule from
+ * a different file.
+ *
+ * Returns: the parent section or %NULL if none
+ *
+ * Since: 3.2
+ **/
+GtkCssSection *
+gtk_css_section_get_parent (const GtkCssSection *section)
+{
+ g_return_val_if_fail (section != NULL, NULL);
+
+ return section->parent;
+}
+
+/**
+ * gtk_css_section_get_file:
+ * @section: the section
+ *
+ * Gets the file that @section was parsed from. If no such file exists,
+ * for example because the CSS was loaded via
+ * @gtk_css_provider_load_from_data(), then %NULL is returned.
+ *
+ * Returns: the #GFile that @section was parsed from or %NULL if
+ * @section was parsed from other data.
+ *
+ * Since: 3.2
+ **/
+GFile *
+gtk_css_section_get_file (const GtkCssSection *section)
+{
+ g_return_val_if_fail (section != NULL, NULL);
+
+ return section->file;
+}
+
+/**
+ * gtk_css_section_get_start_line:
+ * @section: the section
+ *
+ * Returns the line in the CSS document where this section starts.
+ * The line number is 0-indexed, so the first line of the document
+ * will return 0.
+ *
+ * Returns: the line number
+ *
+ * Since: 3.2
+ **/
+guint
+gtk_css_section_get_start_line (const GtkCssSection *section)
+{
+ g_return_val_if_fail (section != NULL, 0);
+
+ return section->start_line;
+}
+
+/**
+ * gtk_css_section_get_start_position:
+ * @section: the section
+ *
+ * Returns the offset in bytes from the start of the current line
+ * returned via gtk_css_section_get_start_line().
+ *
+ * Returns: the offset in bytes from the start of the line.
+ *
+ * Since: 3.2
+ **/
+guint
+gtk_css_section_get_start_position (const GtkCssSection *section)
+{
+ g_return_val_if_fail (section != NULL, 0);
+
+ return section->start_position;
+}
+
+/**
+ * gtk_css_section_get_end_line:
+ * @section: the section
+ *
+ * Returns the line in the CSS document where this section end.
+ * The line number is 0-indexed, so the first line of the document
+ * will return 0.
+ * This value may change in future invocations of this function if
+ * @section is not yet parsed completely. This will for example
+ * happen in the GtkCssProvider::parsing-error signal.
+ * The end position and line may be identical to the start
+ * position and line for sections which failed to parse anything
+ * successfully.
+ *
+ * Returns: the line number
+ *
+ * Since: 3.2
+ **/
+guint
+gtk_css_section_get_end_line (const GtkCssSection *section)
+{
+ g_return_val_if_fail (section != NULL, 0);
+
+ if (section->parser)
+ return _gtk_css_parser_get_line (section->parser);
+ else
+ return section->end_line;
+}
+
+/**
+ * gtk_css_section_get_start_position:
+ * @section: the section
+ *
+ * Returns the offset in bytes from the start of the current line
+ * returned via gtk_css_section_get_end_line().
+ * This value may change in future invocations of this function if
+ * @section is not yet parsed completely. This will for example
+ * happen in the GtkCssProvider::parsing-error signal.
+ * The end position and line may be identical to the start
+ * position and line for sections which failed to parse anything
+ * successfully.
+ *
+ * Returns: the offset in bytes from the start of the line.
+ *
+ * Since: 3.2
+ **/
+guint
+gtk_css_section_get_end_position (const GtkCssSection *section)
+{
+ g_return_val_if_fail (section != NULL, 0);
+
+ if (section->parser)
+ return _gtk_css_parser_get_position (section->parser);
+ else
+ return section->end_position;
+}
+
diff --git a/gtk/gtkcsssection.h b/gtk/gtkcsssection.h
new file mode 100644
index 0000000000..761ebd1102
--- /dev/null
+++ b/gtk/gtkcsssection.h
@@ -0,0 +1,82 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GTK_CSS_SECTION_H__
+#define __GTK_CSS_SECTION_H__
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_CSS_SECTION (gtk_css_section_get_type ())
+
+/**
+ * GtkCssSection:
+ * @GTK_CSS_SECTION_DOCUMENT: The section describes a complete document.
+ * This section time is the only one where gtk_css_section_get_parent()
+ * might return %NULL.
+ * @GTK_CSS_SECTION_IMPORT: The section defines an import rule.
+ * @GTK_CSS_SECTION_COLOR_DEFINITION: The section defines a color. This
+ * is a GTK extension to CSS.
+ * @GTK_CSS_SECTION_BINDING_SET: The section defines a binding set. This
+ * is a GTK extension to CSS.
+ * @GTK_CSS_SECTION_RULESET: The section defines a CSS ruleset.
+ * @GTK_CSS_SECTION_SELECTOR: The section defines a CSS selector.
+ * @GTK_CSS_SECTION_DECLARATION: The section defines the declaration of
+ * a CSS variable.
+ *
+ * The different types of sections indicate parts of a CSS document as
+ * parsed by GTK's CSS parser. They are oriented towards the CSS grammar
+ * <ulink url="http://www.w3.org/TR/CSS21/grammar.html">CSS grammer</ulink>,
+ * but may contain extensions.
+ *
+ * More types might be added in the future as the parser incorporates
+ * more features.
+ *
+ * Since: 3.2
+ */
+typedef enum
+{
+ GTK_CSS_SECTION_DOCUMENT,
+ GTK_CSS_SECTION_IMPORT,
+ GTK_CSS_SECTION_COLOR_DEFINITION,
+ GTK_CSS_SECTION_BINDING_SET,
+ GTK_CSS_SECTION_RULESET,
+ GTK_CSS_SECTION_SELECTOR,
+ GTK_CSS_SECTION_DECLARATION,
+} GtkCssSectionType;
+
+typedef struct _GtkCssSection GtkCssSection;
+
+GType gtk_css_section_get_type (void) G_GNUC_CONST;
+
+GtkCssSection * gtk_css_section_ref (GtkCssSection *section);
+void gtk_css_section_unref (GtkCssSection *section);
+
+GtkCssSectionType gtk_css_section_get_section_type (const GtkCssSection *section);
+GtkCssSection * gtk_css_section_get_parent (const GtkCssSection *section);
+GFile * gtk_css_section_get_file (const GtkCssSection *section);
+guint gtk_css_section_get_start_line (const GtkCssSection *section);
+guint gtk_css_section_get_start_position (const GtkCssSection *section);
+guint gtk_css_section_get_end_line (const GtkCssSection *section);
+guint gtk_css_section_get_end_position (const GtkCssSection *section);
+
+G_END_DECLS
+
+#endif /* __GTK_CSS_SECTION_H__ */
diff --git a/gtk/gtkcsssectionprivate.h b/gtk/gtkcsssectionprivate.h
new file mode 100644
index 0000000000..776fd5d9c5
--- /dev/null
+++ b/gtk/gtkcsssectionprivate.h
@@ -0,0 +1,38 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GTK_CSS_SECTION_PRIVATE_H__
+#define __GTK_CSS_SECTION_PRIVATE_H__
+
+#include "gtkcsssection.h"
+
+#include "gtkcssparserprivate.h"
+
+G_BEGIN_DECLS
+
+GtkCssSection * _gtk_css_section_new (GtkCssSection *parent,
+ GtkCssSectionType type,
+ GtkCssParser *parser,
+ GFile *file);
+
+void _gtk_css_section_end (GtkCssSection *section);
+
+G_END_DECLS
+
+#endif /* __GTK_CSS_SECTION_PRIVATE_H__ */