/* 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, see . */ #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) { GtkCssSection *section; g_return_val_if_fail (parser != NULL, NULL); section = g_slice_new0 (GtkCssSection); section->ref_count = 1; section->section_type = type; if (parent) section->parent = gtk_css_section_ref (parent); section->file = _gtk_css_parser_get_file (parser); if (section->file) g_object_ref (section->file); section->start_line = _gtk_css_parser_get_line (parser); section->start_position = _gtk_css_parser_get_position (parser); section->parser = parser; return section; } GtkCssSection * _gtk_css_section_new_for_file (GtkCssSectionType type, GFile *file) { GtkCssSection *section; g_return_val_if_fail (G_IS_FILE (file), NULL); section = g_slice_new0 (GtkCssSection); section->ref_count = 1; section->section_type = type; section->file = g_object_ref (file); 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 (§ion->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 (§ion->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_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_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: (transfer none): 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_end_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; } void _gtk_css_section_print (const GtkCssSection *section, GString *string) { if (section->file) { GFileInfo *info; info = g_file_query_info (section->file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, 0, NULL, NULL); if (info) { g_string_append (string, g_file_info_get_display_name (info)); g_object_unref (info); } else { g_string_append (string, ""); } } else { g_string_append (string, ""); } g_string_append_printf (string, ":%u:%u", gtk_css_section_get_end_line (section) + 1, gtk_css_section_get_end_position (section)); } char * _gtk_css_section_to_string (const GtkCssSection *section) { GString *string; g_return_val_if_fail (section != NULL, NULL); string = g_string_new (NULL); _gtk_css_section_print (section, string); return g_string_free (string, FALSE); }