1/* GTK - The GIMP Toolkit
2 * Copyright (C) 2011 Red Hat, Inc.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "config.h"
19
20#include "gtkcsssection.h"
21
22#include "gtkcssparserprivate.h"
23
24struct _GtkCssSection
25{
26 int ref_count;
27 GtkCssSection *parent;
28 GFile *file;
29 GtkCssLocation start_location;
30 GtkCssLocation end_location; /* end location if parser is %NULL */
31};
32
33G_DEFINE_BOXED_TYPE (GtkCssSection, gtk_css_section, gtk_css_section_ref, gtk_css_section_unref)
34
35/**
36 * gtk_css_section_new: (constructor)
37 * @file: (nullable) (transfer none): The file this section refers to
38 * @start: The start location
39 * @end: The end location
40 *
41 * Creates a new `GtkCssSection` referring to the section
42 * in the given `file` from the `start` location to the
43 * `end` location.
44 *
45 * Returns: (transfer full): a new `GtkCssSection`
46 **/
47GtkCssSection *
48gtk_css_section_new (GFile *file,
49 const GtkCssLocation *start,
50 const GtkCssLocation *end)
51{
52 GtkCssSection *result;
53
54 g_return_val_if_fail (file == NULL || G_IS_FILE (file), NULL);
55 g_return_val_if_fail (start != NULL, NULL);
56 g_return_val_if_fail (end != NULL, NULL);
57
58 result = g_slice_new0 (GtkCssSection);
59
60 result->ref_count = 1;
61 if (file)
62 result->file = g_object_ref (file);
63 result->start_location = *start;
64 result->end_location = *end;
65
66 return result;
67}
68
69/**
70 * gtk_css_section_ref:
71 * @section: a `GtkCssSection`
72 *
73 * Increments the reference count on `section`.
74 *
75 * Returns: (transfer full): the CSS section itself.
76 **/
77GtkCssSection *
78gtk_css_section_ref (GtkCssSection *section)
79{
80 g_return_val_if_fail (section != NULL, NULL);
81
82 section->ref_count += 1;
83
84 return section;
85}
86
87/**
88 * gtk_css_section_unref:
89 * @section: (transfer full): a `GtkCssSection`
90 *
91 * Decrements the reference count on `section`, freeing the
92 * structure if the reference count reaches 0.
93 **/
94void
95gtk_css_section_unref (GtkCssSection *section)
96{
97 g_return_if_fail (section != NULL);
98
99 section->ref_count -= 1;
100 if (section->ref_count > 0)
101 return;
102
103 if (section->parent)
104 gtk_css_section_unref (section: section->parent);
105 if (section->file)
106 g_object_unref (object: section->file);
107
108 g_slice_free (GtkCssSection, section);
109}
110
111/**
112 * gtk_css_section_get_parent:
113 * @section: the section
114 *
115 * Gets the parent section for the given `section`.
116 *
117 * The parent section is the section that contains this `section`. A special
118 * case are sections of type `GTK_CSS_SECTION_DOCUMEN`T. Their parent will
119 * either be `NULL` if they are the original CSS document that was loaded by
120 * [method@Gtk.CssProvider.load_from_file] or a section of type
121 * `GTK_CSS_SECTION_IMPORT` if it was loaded with an `@import` rule from
122 * a different file.
123 *
124 * Returns: (nullable) (transfer none): the parent section
125 **/
126GtkCssSection *
127gtk_css_section_get_parent (const GtkCssSection *section)
128{
129 g_return_val_if_fail (section != NULL, NULL);
130
131 return section->parent;
132}
133
134/**
135 * gtk_css_section_get_file:
136 * @section: the section
137 *
138 * Gets the file that @section was parsed from.
139 *
140 * If no such file exists, for example because the CSS was loaded via
141 * [method@Gtk.CssProvider.load_from_data], then `NULL` is returned.
142 *
143 * Returns: (transfer none) (nullable): the `GFile` from which the `section`
144 * was parsed
145 **/
146GFile *
147gtk_css_section_get_file (const GtkCssSection *section)
148{
149 g_return_val_if_fail (section != NULL, NULL);
150
151 return section->file;
152}
153
154/**
155 * gtk_css_section_get_start_location:
156 * @section: the section
157 *
158 * Returns the location in the CSS document where this section starts.
159 *
160 * Returns: (transfer none) (not nullable): The start location of
161 * this section
162 */
163const GtkCssLocation *
164gtk_css_section_get_start_location (const GtkCssSection *section)
165{
166 g_return_val_if_fail (section != NULL, NULL);
167
168 return &section->start_location;
169}
170
171/**
172 * gtk_css_section_get_end_location:
173 * @section: the section
174 *
175 * Returns the location in the CSS document where this section ends.
176 *
177 * Returns: (transfer none) (not nullable): The end location of
178 * this section
179 */
180const GtkCssLocation *
181gtk_css_section_get_end_location (const GtkCssSection *section)
182{
183 g_return_val_if_fail (section != NULL, NULL);
184
185 return &section->end_location;
186}
187
188/**
189 * gtk_css_section_print:
190 * @section: a section
191 * @string: a `GString` to print to
192 *
193 * Prints the `section` into `string` in a human-readable form.
194 *
195 * This is a form like `gtk.css:32:1-23` to denote line 32, characters
196 * 1 to 23 in the file `gtk.css`.
197 **/
198void
199gtk_css_section_print (const GtkCssSection *section,
200 GString *string)
201{
202 if (section->file)
203 {
204 GFileInfo *info;
205
206 info = g_file_query_info (file: section->file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, flags: 0, NULL, NULL);
207
208 if (info)
209 {
210 g_string_append (string, val: g_file_info_get_display_name (info));
211 g_object_unref (object: info);
212 }
213 else
214 {
215 g_string_append (string, val: "<broken file>");
216 }
217 }
218 else
219 {
220 g_string_append (string, val: "<data>");
221 }
222
223 g_string_append_printf (string, format: ":%zu:%zu",
224 section->start_location.lines + 1,
225 section->start_location.line_chars + 1);
226 if (section->start_location.lines != section->end_location.lines ||
227 section->start_location.line_chars != section->end_location.line_chars)
228 {
229 g_string_append (string, val: "-");
230 if (section->start_location.lines != section->end_location.lines)
231 g_string_append_printf (string, format: "%zu:", section->end_location.lines + 1);
232 g_string_append_printf (string, format: "%zu", section->end_location.line_chars + 1);
233 }
234}
235
236/**
237 * gtk_css_section_to_string:
238 * @section: a `GtkCssSection`
239 *
240 * Prints the section into a human-readable text form using
241 * [method@Gtk.CssSection.print].
242 *
243 * Returns: (transfer full): A new string.
244 **/
245char *
246gtk_css_section_to_string (const GtkCssSection *section)
247{
248 GString *string;
249
250 g_return_val_if_fail (section != NULL, NULL);
251
252 string = g_string_new (NULL);
253 gtk_css_section_print (section, string);
254
255 return g_string_free (string, FALSE);
256}
257

source code of gtk/gtk/css/gtkcsssection.c