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 | |
24 | struct _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 | |
33 | G_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 | **/ |
47 | GtkCssSection * |
48 | gtk_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 | **/ |
77 | GtkCssSection * |
78 | gtk_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 | **/ |
94 | void |
95 | gtk_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 | **/ |
126 | GtkCssSection * |
127 | gtk_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 | **/ |
146 | GFile * |
147 | gtk_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 | */ |
163 | const GtkCssLocation * |
164 | gtk_css_section_get_start_location (const GtkCssSection *section) |
165 | { |
166 | g_return_val_if_fail (section != NULL, NULL); |
167 | |
168 | return §ion->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 | */ |
180 | const GtkCssLocation * |
181 | gtk_css_section_get_end_location (const GtkCssSection *section) |
182 | { |
183 | g_return_val_if_fail (section != NULL, NULL); |
184 | |
185 | return §ion->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 | **/ |
198 | void |
199 | gtk_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 | **/ |
245 | char * |
246 | gtk_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 | |