Bug Summary

File:ctk/ctkcssselector.c
Warning:line 1928, column 26
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name ctkcssselector.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/ctk -resource-dir /usr/lib/llvm-16/lib/clang/16 -D HAVE_CONFIG_H -I . -I .. -D G_LOG_DOMAIN="Ctk" -D G_LOG_USE_STRUCTURED=1 -D CTK_VERSION="3.25.5" -D CTK_BINARY_VERSION="3.0.0" -D CTK_COMPILATION -D CTK_PRINT_BACKEND_ENABLE_UNSUPPORTED -D CTK_LIBDIR="/usr/lib" -D CTK_LOCALEDIR="/usr/share/locale" -D CTK_DATADIR="/usr/share" -D CTK_DATA_PREFIX="/usr" -D CTK_SYSCONFDIR="/usr/etc" -D CTK_HOST="x86_64-pc-linux-gnu" -D CTK_PRINT_BACKENDS="file,cups" -D X11_DATA_PREFIX="/usr" -D ISO_CODES_PREFIX="" -I .. -I ../ctk -I .. -I ../cdk -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -D G_ENABLE_DEBUG -D G_ENABLE_CONSISTENCY_CHECKS -D GLIB_MIN_REQUIRED_VERSION=GLIB_VERSION_2_66 -D GLIB_MAX_ALLOWED_VERSION=GLIB_VERSION_2_66 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/atk-1.0 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/pango-1.0 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -D PIC -internal-isystem /usr/lib/llvm-16/lib/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir=/rootdir/ctk -ferror-limit 19 -fvisibility=hidden -fgnuc-version=4.2.1 -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2024-09-19-172241-43638-1 -x c ctkcssselector.c
1/* CTK - The GIMP Toolkit
2 * Copyright (C) 2011 Benjamin Otte <otte@gnome.org>
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 "ctkcssselectorprivate.h"
21
22#include <stdlib.h>
23#include <string.h>
24
25#include "ctkcssprovider.h"
26#include "ctkstylecontextprivate.h"
27
28#if defined(_MSC_VER) && _MSC_VER >= 1500
29# include <intrin.h>
30#endif
31
32typedef struct _CtkCssSelectorClass CtkCssSelectorClass;
33typedef gboolean (* CtkCssSelectorForeachFunc) (const CtkCssSelector *selector,
34 const CtkCssMatcher *matcher,
35 gpointer data);
36
37struct _CtkCssSelectorClass {
38 const char *name;
39
40 void (* print) (const CtkCssSelector *selector,
41 GString *string);
42 /* NULL or an iterator that calls func with each submatcher of @matcher.
43 * Potentially no submatcher exists.
44 * If any @invocation of @func returns %TRUE, the function will immediately
45 * return %TRUE itself. If @func never returns %TRUE (or isn't called at all),
46 * %FALSE will be returned.
47 */
48 gboolean (* foreach_matcher) (const CtkCssSelector *selector,
49 const CtkCssMatcher *matcher,
50 CtkCssSelectorForeachFunc func,
51 gpointer data);
52 gboolean (* match_one) (const CtkCssSelector *selector,
53 const CtkCssMatcher *matcher);
54 CtkCssChange (* get_change) (const CtkCssSelector *selector,
55 CtkCssChange previous_change);
56 void (* add_specificity) (const CtkCssSelector *selector,
57 guint *ids,
58 guint *classes,
59 guint *elements);
60 guint (* hash_one) (const CtkCssSelector *selector);
61 int (* compare_one) (const CtkCssSelector *a,
62 const CtkCssSelector *b);
63
64 guint is_simple :1;
65};
66
67typedef enum {
68 POSITION_FORWARD,
69 POSITION_BACKWARD,
70 POSITION_ONLY,
71 POSITION_SORTED
72} PositionType;
73#define POSITION_TYPE_BITS4 4
74#define POSITION_NUMBER_BITS((sizeof (gpointer) * 8 - 4) / 2) ((sizeof (gpointer) * 8 - POSITION_TYPE_BITS4) / 2)
75
76union _CtkCssSelector
77{
78 const CtkCssSelectorClass *class; /* type of check this selector does */
79 struct {
80 const CtkCssSelectorClass *class;
81 const char *name; /* interned */
82 } id;
83 struct {
84 const CtkCssSelectorClass *class;
85 const char *name; /* interned */
86 CtkRegionFlags flags;
87 } region;
88 struct {
89 const CtkCssSelectorClass *class;
90 GQuark style_class;
91 } style_class;
92 struct {
93 const CtkCssSelectorClass *class;
94 const char *name; /* interned */
95 } name;
96 struct {
97 const CtkCssSelectorClass *class;
98 CtkStateFlags state;
99 } state;
100 struct {
101 const CtkCssSelectorClass *class;
102 PositionType type :POSITION_TYPE_BITS4;
103 gssize a :POSITION_NUMBER_BITS((sizeof (gpointer) * 8 - 4) / 2);
104 gssize b :POSITION_NUMBER_BITS((sizeof (gpointer) * 8 - 4) / 2);
105 } position;
106};
107
108#define CTK_CSS_SELECTOR_TREE_EMPTY_OFFSET((gint32) 0x7fffffff) G_MAXINT32((gint32) 0x7fffffff)
109struct _CtkCssSelectorTree
110{
111 CtkCssSelector selector;
112 gint32 parent_offset;
113 gint32 previous_offset;
114 gint32 sibling_offset;
115 gint32 matches_offset; /* pointers that we return as matches if selector matches */
116};
117
118static gboolean
119ctk_css_selector_equal (const CtkCssSelector *a,
120 const CtkCssSelector *b)
121{
122 return
123 a->class == b->class &&
124 a->class->compare_one (a, b) == 0;
125}
126
127static guint
128ctk_css_selector_hash_one (const CtkCssSelector *selector)
129{
130 return GPOINTER_TO_UINT (selector->class)((guint) (gulong) (selector->class)) ^ selector->class->hash_one (selector);
131}
132
133static gpointer *
134ctk_css_selector_tree_get_matches (const CtkCssSelectorTree *tree)
135{
136 if (tree->matches_offset == CTK_CSS_SELECTOR_TREE_EMPTY_OFFSET((gint32) 0x7fffffff))
137 return NULL((void*)0);
138
139 return (gpointer *) ((guint8 *)tree + tree->matches_offset);
140}
141
142static void
143g_ptr_array_insert_sorted (GPtrArray *array,
144 gpointer data)
145{
146 gint i;
147
148 for (i = 0; i < array->len; i++)
149 {
150 if (data == array->pdata[i])
151 return;
152
153 if (data < array->pdata[i])
154 break;
155 }
156
157 g_ptr_array_insert (array, i, data);
158}
159
160static void
161ctk_css_selector_tree_found_match (const CtkCssSelectorTree *tree,
162 GPtrArray **array)
163{
164 int i;
165 gpointer *matches;
166
167 matches = ctk_css_selector_tree_get_matches (tree);
168 if (matches)
169 {
170 if (!*array)
171 *array = g_ptr_array_sized_new (16);
172
173 for (i = 0; matches[i] != NULL((void*)0); i++)
174 g_ptr_array_insert_sorted (*array, matches[i]);
175 }
176}
177
178static gboolean
179ctk_css_selector_match (const CtkCssSelector *selector,
180 const CtkCssMatcher *matcher)
181{
182 return selector->class->match_one (selector, matcher);
183}
184
185static gboolean
186ctk_css_selector_foreach (const CtkCssSelector *selector,
187 const CtkCssMatcher *matcher,
188 CtkCssSelectorForeachFunc func,
189 gpointer data)
190{
191 return selector->class->foreach_matcher (selector, matcher, func, data);
192}
193
194static int
195ctk_css_selector_compare_one (const CtkCssSelector *a, const CtkCssSelector *b)
196{
197 if (a->class != b->class)
198 return strcmp (a->class->name, b->class->name);
199 else
200 return a->class->compare_one (a, b);
201}
202
203static const CtkCssSelector *
204ctk_css_selector_previous (const CtkCssSelector *selector)
205{
206 selector = selector + 1;
207
208 return selector->class ? selector : NULL((void*)0);
209}
210
211static const CtkCssSelectorTree *
212ctk_css_selector_tree_at_offset (const CtkCssSelectorTree *tree,
213 gint32 offset)
214{
215 if (offset == CTK_CSS_SELECTOR_TREE_EMPTY_OFFSET((gint32) 0x7fffffff))
216 return NULL((void*)0);
217
218 return (CtkCssSelectorTree *) ((guint8 *)tree + offset);
219}
220
221static const CtkCssSelectorTree *
222ctk_css_selector_tree_get_parent (const CtkCssSelectorTree *tree)
223{
224 return ctk_css_selector_tree_at_offset (tree, tree->parent_offset);
225}
226
227static const CtkCssSelectorTree *
228ctk_css_selector_tree_get_previous (const CtkCssSelectorTree *tree)
229{
230 return ctk_css_selector_tree_at_offset (tree, tree->previous_offset);
231}
232
233static const CtkCssSelectorTree *
234ctk_css_selector_tree_get_sibling (const CtkCssSelectorTree *tree)
235{
236 return ctk_css_selector_tree_at_offset (tree, tree->sibling_offset);
237}
238
239/* DEFAULTS */
240
241static void
242ctk_css_selector_default_add_specificity (const CtkCssSelector *selector G_GNUC_UNUSED__attribute__ ((__unused__)),
243 guint *ids G_GNUC_UNUSED__attribute__ ((__unused__)),
244 guint *classes G_GNUC_UNUSED__attribute__ ((__unused__)),
245 guint *elements G_GNUC_UNUSED__attribute__ ((__unused__)))
246{
247 /* no specificity changes */
248}
249
250static gboolean
251ctk_css_selector_default_foreach_matcher (const CtkCssSelector *selector,
252 const CtkCssMatcher *matcher,
253 CtkCssSelectorForeachFunc func,
254 gpointer data)
255{
256 return func (selector, matcher, data);
257}
258
259static gboolean
260ctk_css_selector_default_match_one (const CtkCssSelector *selector G_GNUC_UNUSED__attribute__ ((__unused__)),
261 const CtkCssMatcher *matcher G_GNUC_UNUSED__attribute__ ((__unused__)))
262{
263 return TRUE(!(0));
264}
265
266static guint
267ctk_css_selector_default_hash_one (const CtkCssSelector *selector G_GNUC_UNUSED__attribute__ ((__unused__)))
268{
269 return 0;
270}
271
272static int
273ctk_css_selector_default_compare_one (const CtkCssSelector *a G_GNUC_UNUSED__attribute__ ((__unused__)),
274 const CtkCssSelector *b G_GNUC_UNUSED__attribute__ ((__unused__)))
275{
276 return 0;
277}
278
279/* DESCENDANT */
280
281static void
282ctk_css_selector_descendant_print (const CtkCssSelector *selector G_GNUC_UNUSED__attribute__ ((__unused__)),
283 GString *string)
284{
285 g_string_append_c (string, ' ')g_string_append_c_inline (string, ' ');
286}
287
288static gboolean
289ctk_css_selector_descendant_foreach_matcher (const CtkCssSelector *selector,
290 const CtkCssMatcher *matcher,
291 CtkCssSelectorForeachFunc func,
292 gpointer data)
293{
294 CtkCssMatcher ancestor;
295
296 while (_ctk_css_matcher_get_parent (&ancestor, matcher))
297 {
298 matcher = &ancestor;
299
300 if (func (selector, &ancestor, data))
301 return TRUE(!(0));
302
303 /* any matchers are dangerous here, as we may loop forever, but
304 we can terminate now as all possible matches have already been added */
305 if (_ctk_css_matcher_matches_any (matcher))
306 break;
307 }
308
309 return FALSE(0);
310}
311
312static CtkCssChange
313ctk_css_selector_descendant_get_change (const CtkCssSelector *selector G_GNUC_UNUSED__attribute__ ((__unused__)),
314 CtkCssChange previous_change)
315{
316 return _ctk_css_change_for_child (previous_change);
317}
318
319static const CtkCssSelectorClass CTK_CSS_SELECTOR_DESCENDANT = {
320 "descendant",
321 ctk_css_selector_descendant_print,
322 ctk_css_selector_descendant_foreach_matcher,
323 ctk_css_selector_default_match_one,
324 ctk_css_selector_descendant_get_change,
325 ctk_css_selector_default_add_specificity,
326 ctk_css_selector_default_hash_one,
327 ctk_css_selector_default_compare_one,
328 FALSE(0)
329};
330
331/* CHILD */
332
333static void
334ctk_css_selector_child_print (const CtkCssSelector *selector G_GNUC_UNUSED__attribute__ ((__unused__)),
335 GString *string)
336{
337 g_string_append (string, " > ")(__builtin_constant_p (" > ") ? __extension__ ({ const char
* const __val = (" > "); g_string_append_len_inline (string
, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !
(__val))) : (gssize) -1); }) : g_string_append_len_inline (string
, " > ", (gssize) -1))
;
338}
339
340static gboolean
341ctk_css_selector_child_foreach_matcher (const CtkCssSelector *selector,
342 const CtkCssMatcher *matcher,
343 CtkCssSelectorForeachFunc func,
344 gpointer data)
345{
346 CtkCssMatcher parent;
347
348 if (!_ctk_css_matcher_get_parent (&parent, matcher))
349 return FALSE(0);
350
351 return func (selector, &parent, data);
352}
353
354static CtkCssChange
355ctk_css_selector_child_get_change (const CtkCssSelector *selector G_GNUC_UNUSED__attribute__ ((__unused__)),
356 CtkCssChange previous_change)
357{
358 return _ctk_css_change_for_child (previous_change);
359}
360
361static const CtkCssSelectorClass CTK_CSS_SELECTOR_CHILD = {
362 "child",
363 ctk_css_selector_child_print,
364 ctk_css_selector_child_foreach_matcher,
365 ctk_css_selector_default_match_one,
366 ctk_css_selector_child_get_change,
367 ctk_css_selector_default_add_specificity,
368 ctk_css_selector_default_hash_one,
369 ctk_css_selector_default_compare_one,
370 FALSE(0)
371};
372
373/* SIBLING */
374
375static void
376ctk_css_selector_sibling_print (const CtkCssSelector *selector G_GNUC_UNUSED__attribute__ ((__unused__)),
377 GString *string)
378{
379 g_string_append (string, " ~ ")(__builtin_constant_p (" ~ ") ? __extension__ ({ const char *
const __val = (" ~ "); g_string_append_len_inline (string, __val
, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !(__val
))) : (gssize) -1); }) : g_string_append_len_inline (string, " ~ "
, (gssize) -1))
;
380}
381
382static gboolean
383ctk_css_selector_sibling_foreach_matcher (const CtkCssSelector *selector,
384 const CtkCssMatcher *matcher,
385 CtkCssSelectorForeachFunc func,
386 gpointer data)
387{
388 CtkCssMatcher previous;
389
390 while (_ctk_css_matcher_get_previous (&previous, matcher))
391 {
392 matcher = &previous;
393
394 if (func (selector, matcher, data))
395 return TRUE(!(0));
396
397 /* any matchers are dangerous here, as we may loop forever, but
398 we can terminate now as all possible matches have already been added */
399 if (_ctk_css_matcher_matches_any (matcher))
400 break;
401 }
402
403 return FALSE(0);
404}
405
406static CtkCssChange
407ctk_css_selector_sibling_get_change (const CtkCssSelector *selector G_GNUC_UNUSED__attribute__ ((__unused__)),
408 CtkCssChange previous_change)
409{
410 return _ctk_css_change_for_sibling (previous_change);
411}
412
413static const CtkCssSelectorClass CTK_CSS_SELECTOR_SIBLING = {
414 "sibling",
415 ctk_css_selector_sibling_print,
416 ctk_css_selector_sibling_foreach_matcher,
417 ctk_css_selector_default_match_one,
418 ctk_css_selector_sibling_get_change,
419 ctk_css_selector_default_add_specificity,
420 ctk_css_selector_default_hash_one,
421 ctk_css_selector_default_compare_one,
422 FALSE(0)
423};
424
425/* ADJACENT */
426
427static void
428ctk_css_selector_adjacent_print (const CtkCssSelector *selector G_GNUC_UNUSED__attribute__ ((__unused__)),
429 GString *string)
430{
431 g_string_append (string, " + ")(__builtin_constant_p (" + ") ? __extension__ ({ const char *
const __val = (" + "); g_string_append_len_inline (string, __val
, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !(__val
))) : (gssize) -1); }) : g_string_append_len_inline (string, " + "
, (gssize) -1))
;
432}
433
434static gboolean
435ctk_css_selector_adjacent_foreach_matcher (const CtkCssSelector *selector,
436 const CtkCssMatcher *matcher,
437 CtkCssSelectorForeachFunc func,
438 gpointer data)
439{
440 CtkCssMatcher previous;
441
442 if (!_ctk_css_matcher_get_previous (&previous, matcher))
443 return FALSE(0);
444
445 return func (selector, &previous, data);
446}
447
448static CtkCssChange
449ctk_css_selector_adjacent_get_change (const CtkCssSelector *selector G_GNUC_UNUSED__attribute__ ((__unused__)),
450 CtkCssChange previous_change)
451{
452 return _ctk_css_change_for_sibling (previous_change);
453}
454
455static const CtkCssSelectorClass CTK_CSS_SELECTOR_ADJACENT = {
456 "adjacent",
457 ctk_css_selector_adjacent_print,
458 ctk_css_selector_adjacent_foreach_matcher,
459 ctk_css_selector_default_match_one,
460 ctk_css_selector_adjacent_get_change,
461 ctk_css_selector_default_add_specificity,
462 ctk_css_selector_default_hash_one,
463 ctk_css_selector_default_compare_one,
464 FALSE(0)
465};
466
467/* SIMPLE SELECTOR DEFINE */
468
469#define DEFINE_SIMPLE_SELECTOR(n, \static void ctk_css_selector_n_print (const CtkCssSelector *selector
, GString *string) { print_func (selector, string); } static void
ctk_css_selector_not_n_print (const CtkCssSelector *selector
, GString *string) { (__builtin_constant_p (":not(") ? __extension__
({ const char * const __val = (":not("); g_string_append_len_inline
(string, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val
) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(string, ":not(", (gssize) -1)); print_func (selector, string
); (__builtin_constant_p (")") ? __extension__ ({ const char *
const __val = (")"); g_string_append_len_inline (string, __val
, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !(__val
))) : (gssize) -1); }) : g_string_append_len_inline (string, ")"
, (gssize) -1)); } static gboolean ctk_css_selector_not_n_match_one
(const CtkCssSelector *selector, const CtkCssMatcher *matcher
) { return !match_func (selector, matcher); } static CtkCssChange
ctk_css_selector_n_get_change (const CtkCssSelector *selector
__attribute__ ((__unused__)), CtkCssChange previous_change) {
return previous_change | CTK_CSS_CHANGE_c; } static void ctk_css_selector_n_add_specificity
(const CtkCssSelector *selector __attribute__ ((__unused__))
, guint *ids, guint *classes, guint *elements) { if (increase_id_specificity
) { (*ids)++; } if (increase_class_specificity) { (*classes)++
; } if (increase_element_specificity) { (*elements)++; } } static
const CtkCssSelectorClass CTK_CSS_SELECTOR_c = { "n", ctk_css_selector_n_print
, ctk_css_selector_default_foreach_matcher, match_func, ctk_css_selector_n_get_change
, ctk_css_selector_n_add_specificity, hash_func, comp_func, (
!(0)) };static const CtkCssSelectorClass CTK_CSS_SELECTOR_NOT_c
= { "not_" "n", ctk_css_selector_not_n_print, ctk_css_selector_default_foreach_matcher
, ctk_css_selector_not_n_match_one, ctk_css_selector_n_get_change
, ctk_css_selector_n_add_specificity, hash_func, comp_func, (
!(0)) };
470 c, \static void ctk_css_selector_n_print (const CtkCssSelector *selector
, GString *string) { print_func (selector, string); } static void
ctk_css_selector_not_n_print (const CtkCssSelector *selector
, GString *string) { (__builtin_constant_p (":not(") ? __extension__
({ const char * const __val = (":not("); g_string_append_len_inline
(string, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val
) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(string, ":not(", (gssize) -1)); print_func (selector, string
); (__builtin_constant_p (")") ? __extension__ ({ const char *
const __val = (")"); g_string_append_len_inline (string, __val
, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !(__val
))) : (gssize) -1); }) : g_string_append_len_inline (string, ")"
, (gssize) -1)); } static gboolean ctk_css_selector_not_n_match_one
(const CtkCssSelector *selector, const CtkCssMatcher *matcher
) { return !match_func (selector, matcher); } static CtkCssChange
ctk_css_selector_n_get_change (const CtkCssSelector *selector
__attribute__ ((__unused__)), CtkCssChange previous_change) {
return previous_change | CTK_CSS_CHANGE_c; } static void ctk_css_selector_n_add_specificity
(const CtkCssSelector *selector __attribute__ ((__unused__))
, guint *ids, guint *classes, guint *elements) { if (increase_id_specificity
) { (*ids)++; } if (increase_class_specificity) { (*classes)++
; } if (increase_element_specificity) { (*elements)++; } } static
const CtkCssSelectorClass CTK_CSS_SELECTOR_c = { "n", ctk_css_selector_n_print
, ctk_css_selector_default_foreach_matcher, match_func, ctk_css_selector_n_get_change
, ctk_css_selector_n_add_specificity, hash_func, comp_func, (
!(0)) };static const CtkCssSelectorClass CTK_CSS_SELECTOR_NOT_c
= { "not_" "n", ctk_css_selector_not_n_print, ctk_css_selector_default_foreach_matcher
, ctk_css_selector_not_n_match_one, ctk_css_selector_n_get_change
, ctk_css_selector_n_add_specificity, hash_func, comp_func, (
!(0)) };
471 print_func, \static void ctk_css_selector_n_print (const CtkCssSelector *selector
, GString *string) { print_func (selector, string); } static void
ctk_css_selector_not_n_print (const CtkCssSelector *selector
, GString *string) { (__builtin_constant_p (":not(") ? __extension__
({ const char * const __val = (":not("); g_string_append_len_inline
(string, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val
) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(string, ":not(", (gssize) -1)); print_func (selector, string
); (__builtin_constant_p (")") ? __extension__ ({ const char *
const __val = (")"); g_string_append_len_inline (string, __val
, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !(__val
))) : (gssize) -1); }) : g_string_append_len_inline (string, ")"
, (gssize) -1)); } static gboolean ctk_css_selector_not_n_match_one
(const CtkCssSelector *selector, const CtkCssMatcher *matcher
) { return !match_func (selector, matcher); } static CtkCssChange
ctk_css_selector_n_get_change (const CtkCssSelector *selector
__attribute__ ((__unused__)), CtkCssChange previous_change) {
return previous_change | CTK_CSS_CHANGE_c; } static void ctk_css_selector_n_add_specificity
(const CtkCssSelector *selector __attribute__ ((__unused__))
, guint *ids, guint *classes, guint *elements) { if (increase_id_specificity
) { (*ids)++; } if (increase_class_specificity) { (*classes)++
; } if (increase_element_specificity) { (*elements)++; } } static
const CtkCssSelectorClass CTK_CSS_SELECTOR_c = { "n", ctk_css_selector_n_print
, ctk_css_selector_default_foreach_matcher, match_func, ctk_css_selector_n_get_change
, ctk_css_selector_n_add_specificity, hash_func, comp_func, (
!(0)) };static const CtkCssSelectorClass CTK_CSS_SELECTOR_NOT_c
= { "not_" "n", ctk_css_selector_not_n_print, ctk_css_selector_default_foreach_matcher
, ctk_css_selector_not_n_match_one, ctk_css_selector_n_get_change
, ctk_css_selector_n_add_specificity, hash_func, comp_func, (
!(0)) };
472 match_func, \static void ctk_css_selector_n_print (const CtkCssSelector *selector
, GString *string) { print_func (selector, string); } static void
ctk_css_selector_not_n_print (const CtkCssSelector *selector
, GString *string) { (__builtin_constant_p (":not(") ? __extension__
({ const char * const __val = (":not("); g_string_append_len_inline
(string, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val
) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(string, ":not(", (gssize) -1)); print_func (selector, string
); (__builtin_constant_p (")") ? __extension__ ({ const char *
const __val = (")"); g_string_append_len_inline (string, __val
, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !(__val
))) : (gssize) -1); }) : g_string_append_len_inline (string, ")"
, (gssize) -1)); } static gboolean ctk_css_selector_not_n_match_one
(const CtkCssSelector *selector, const CtkCssMatcher *matcher
) { return !match_func (selector, matcher); } static CtkCssChange
ctk_css_selector_n_get_change (const CtkCssSelector *selector
__attribute__ ((__unused__)), CtkCssChange previous_change) {
return previous_change | CTK_CSS_CHANGE_c; } static void ctk_css_selector_n_add_specificity
(const CtkCssSelector *selector __attribute__ ((__unused__))
, guint *ids, guint *classes, guint *elements) { if (increase_id_specificity
) { (*ids)++; } if (increase_class_specificity) { (*classes)++
; } if (increase_element_specificity) { (*elements)++; } } static
const CtkCssSelectorClass CTK_CSS_SELECTOR_c = { "n", ctk_css_selector_n_print
, ctk_css_selector_default_foreach_matcher, match_func, ctk_css_selector_n_get_change
, ctk_css_selector_n_add_specificity, hash_func, comp_func, (
!(0)) };static const CtkCssSelectorClass CTK_CSS_SELECTOR_NOT_c
= { "not_" "n", ctk_css_selector_not_n_print, ctk_css_selector_default_foreach_matcher
, ctk_css_selector_not_n_match_one, ctk_css_selector_n_get_change
, ctk_css_selector_n_add_specificity, hash_func, comp_func, (
!(0)) };
473 hash_func, \static void ctk_css_selector_n_print (const CtkCssSelector *selector
, GString *string) { print_func (selector, string); } static void
ctk_css_selector_not_n_print (const CtkCssSelector *selector
, GString *string) { (__builtin_constant_p (":not(") ? __extension__
({ const char * const __val = (":not("); g_string_append_len_inline
(string, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val
) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(string, ":not(", (gssize) -1)); print_func (selector, string
); (__builtin_constant_p (")") ? __extension__ ({ const char *
const __val = (")"); g_string_append_len_inline (string, __val
, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !(__val
))) : (gssize) -1); }) : g_string_append_len_inline (string, ")"
, (gssize) -1)); } static gboolean ctk_css_selector_not_n_match_one
(const CtkCssSelector *selector, const CtkCssMatcher *matcher
) { return !match_func (selector, matcher); } static CtkCssChange
ctk_css_selector_n_get_change (const CtkCssSelector *selector
__attribute__ ((__unused__)), CtkCssChange previous_change) {
return previous_change | CTK_CSS_CHANGE_c; } static void ctk_css_selector_n_add_specificity
(const CtkCssSelector *selector __attribute__ ((__unused__))
, guint *ids, guint *classes, guint *elements) { if (increase_id_specificity
) { (*ids)++; } if (increase_class_specificity) { (*classes)++
; } if (increase_element_specificity) { (*elements)++; } } static
const CtkCssSelectorClass CTK_CSS_SELECTOR_c = { "n", ctk_css_selector_n_print
, ctk_css_selector_default_foreach_matcher, match_func, ctk_css_selector_n_get_change
, ctk_css_selector_n_add_specificity, hash_func, comp_func, (
!(0)) };static const CtkCssSelectorClass CTK_CSS_SELECTOR_NOT_c
= { "not_" "n", ctk_css_selector_not_n_print, ctk_css_selector_default_foreach_matcher
, ctk_css_selector_not_n_match_one, ctk_css_selector_n_get_change
, ctk_css_selector_n_add_specificity, hash_func, comp_func, (
!(0)) };
474 comp_func, \static void ctk_css_selector_n_print (const CtkCssSelector *selector
, GString *string) { print_func (selector, string); } static void
ctk_css_selector_not_n_print (const CtkCssSelector *selector
, GString *string) { (__builtin_constant_p (":not(") ? __extension__
({ const char * const __val = (":not("); g_string_append_len_inline
(string, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val
) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(string, ":not(", (gssize) -1)); print_func (selector, string
); (__builtin_constant_p (")") ? __extension__ ({ const char *
const __val = (")"); g_string_append_len_inline (string, __val
, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !(__val
))) : (gssize) -1); }) : g_string_append_len_inline (string, ")"
, (gssize) -1)); } static gboolean ctk_css_selector_not_n_match_one
(const CtkCssSelector *selector, const CtkCssMatcher *matcher
) { return !match_func (selector, matcher); } static CtkCssChange
ctk_css_selector_n_get_change (const CtkCssSelector *selector
__attribute__ ((__unused__)), CtkCssChange previous_change) {
return previous_change | CTK_CSS_CHANGE_c; } static void ctk_css_selector_n_add_specificity
(const CtkCssSelector *selector __attribute__ ((__unused__))
, guint *ids, guint *classes, guint *elements) { if (increase_id_specificity
) { (*ids)++; } if (increase_class_specificity) { (*classes)++
; } if (increase_element_specificity) { (*elements)++; } } static
const CtkCssSelectorClass CTK_CSS_SELECTOR_c = { "n", ctk_css_selector_n_print
, ctk_css_selector_default_foreach_matcher, match_func, ctk_css_selector_n_get_change
, ctk_css_selector_n_add_specificity, hash_func, comp_func, (
!(0)) };static const CtkCssSelectorClass CTK_CSS_SELECTOR_NOT_c
= { "not_" "n", ctk_css_selector_not_n_print, ctk_css_selector_default_foreach_matcher
, ctk_css_selector_not_n_match_one, ctk_css_selector_n_get_change
, ctk_css_selector_n_add_specificity, hash_func, comp_func, (
!(0)) };
475 increase_id_specificity, \static void ctk_css_selector_n_print (const CtkCssSelector *selector
, GString *string) { print_func (selector, string); } static void
ctk_css_selector_not_n_print (const CtkCssSelector *selector
, GString *string) { (__builtin_constant_p (":not(") ? __extension__
({ const char * const __val = (":not("); g_string_append_len_inline
(string, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val
) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(string, ":not(", (gssize) -1)); print_func (selector, string
); (__builtin_constant_p (")") ? __extension__ ({ const char *
const __val = (")"); g_string_append_len_inline (string, __val
, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !(__val
))) : (gssize) -1); }) : g_string_append_len_inline (string, ")"
, (gssize) -1)); } static gboolean ctk_css_selector_not_n_match_one
(const CtkCssSelector *selector, const CtkCssMatcher *matcher
) { return !match_func (selector, matcher); } static CtkCssChange
ctk_css_selector_n_get_change (const CtkCssSelector *selector
__attribute__ ((__unused__)), CtkCssChange previous_change) {
return previous_change | CTK_CSS_CHANGE_c; } static void ctk_css_selector_n_add_specificity
(const CtkCssSelector *selector __attribute__ ((__unused__))
, guint *ids, guint *classes, guint *elements) { if (increase_id_specificity
) { (*ids)++; } if (increase_class_specificity) { (*classes)++
; } if (increase_element_specificity) { (*elements)++; } } static
const CtkCssSelectorClass CTK_CSS_SELECTOR_c = { "n", ctk_css_selector_n_print
, ctk_css_selector_default_foreach_matcher, match_func, ctk_css_selector_n_get_change
, ctk_css_selector_n_add_specificity, hash_func, comp_func, (
!(0)) };static const CtkCssSelectorClass CTK_CSS_SELECTOR_NOT_c
= { "not_" "n", ctk_css_selector_not_n_print, ctk_css_selector_default_foreach_matcher
, ctk_css_selector_not_n_match_one, ctk_css_selector_n_get_change
, ctk_css_selector_n_add_specificity, hash_func, comp_func, (
!(0)) };
476 increase_class_specificity, \static void ctk_css_selector_n_print (const CtkCssSelector *selector
, GString *string) { print_func (selector, string); } static void
ctk_css_selector_not_n_print (const CtkCssSelector *selector
, GString *string) { (__builtin_constant_p (":not(") ? __extension__
({ const char * const __val = (":not("); g_string_append_len_inline
(string, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val
) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(string, ":not(", (gssize) -1)); print_func (selector, string
); (__builtin_constant_p (")") ? __extension__ ({ const char *
const __val = (")"); g_string_append_len_inline (string, __val
, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !(__val
))) : (gssize) -1); }) : g_string_append_len_inline (string, ")"
, (gssize) -1)); } static gboolean ctk_css_selector_not_n_match_one
(const CtkCssSelector *selector, const CtkCssMatcher *matcher
) { return !match_func (selector, matcher); } static CtkCssChange
ctk_css_selector_n_get_change (const CtkCssSelector *selector
__attribute__ ((__unused__)), CtkCssChange previous_change) {
return previous_change | CTK_CSS_CHANGE_c; } static void ctk_css_selector_n_add_specificity
(const CtkCssSelector *selector __attribute__ ((__unused__))
, guint *ids, guint *classes, guint *elements) { if (increase_id_specificity
) { (*ids)++; } if (increase_class_specificity) { (*classes)++
; } if (increase_element_specificity) { (*elements)++; } } static
const CtkCssSelectorClass CTK_CSS_SELECTOR_c = { "n", ctk_css_selector_n_print
, ctk_css_selector_default_foreach_matcher, match_func, ctk_css_selector_n_get_change
, ctk_css_selector_n_add_specificity, hash_func, comp_func, (
!(0)) };static const CtkCssSelectorClass CTK_CSS_SELECTOR_NOT_c
= { "not_" "n", ctk_css_selector_not_n_print, ctk_css_selector_default_foreach_matcher
, ctk_css_selector_not_n_match_one, ctk_css_selector_n_get_change
, ctk_css_selector_n_add_specificity, hash_func, comp_func, (
!(0)) };
477 increase_element_specificity)static void ctk_css_selector_n_print (const CtkCssSelector *selector
, GString *string) { print_func (selector, string); } static void
ctk_css_selector_not_n_print (const CtkCssSelector *selector
, GString *string) { (__builtin_constant_p (":not(") ? __extension__
({ const char * const __val = (":not("); g_string_append_len_inline
(string, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val
) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(string, ":not(", (gssize) -1)); print_func (selector, string
); (__builtin_constant_p (")") ? __extension__ ({ const char *
const __val = (")"); g_string_append_len_inline (string, __val
, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !(__val
))) : (gssize) -1); }) : g_string_append_len_inline (string, ")"
, (gssize) -1)); } static gboolean ctk_css_selector_not_n_match_one
(const CtkCssSelector *selector, const CtkCssMatcher *matcher
) { return !match_func (selector, matcher); } static CtkCssChange
ctk_css_selector_n_get_change (const CtkCssSelector *selector
__attribute__ ((__unused__)), CtkCssChange previous_change) {
return previous_change | CTK_CSS_CHANGE_c; } static void ctk_css_selector_n_add_specificity
(const CtkCssSelector *selector __attribute__ ((__unused__))
, guint *ids, guint *classes, guint *elements) { if (increase_id_specificity
) { (*ids)++; } if (increase_class_specificity) { (*classes)++
; } if (increase_element_specificity) { (*elements)++; } } static
const CtkCssSelectorClass CTK_CSS_SELECTOR_c = { "n", ctk_css_selector_n_print
, ctk_css_selector_default_foreach_matcher, match_func, ctk_css_selector_n_get_change
, ctk_css_selector_n_add_specificity, hash_func, comp_func, (
!(0)) };static const CtkCssSelectorClass CTK_CSS_SELECTOR_NOT_c
= { "not_" "n", ctk_css_selector_not_n_print, ctk_css_selector_default_foreach_matcher
, ctk_css_selector_not_n_match_one, ctk_css_selector_n_get_change
, ctk_css_selector_n_add_specificity, hash_func, comp_func, (
!(0)) };
\
478static void \
479ctk_css_selector_ ## n ## _print (const CtkCssSelector *selector, \
480 GString *string) \
481{ \
482 print_func (selector, string); \
483} \
484\
485static void \
486ctk_css_selector_not_ ## n ## _print (const CtkCssSelector *selector, \
487 GString *string) \
488{ \
489 g_string_append (string, ":not(")(__builtin_constant_p (":not(") ? __extension__ ({ const char
* const __val = (":not("); g_string_append_len_inline (string
, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !
(__val))) : (gssize) -1); }) : g_string_append_len_inline (string
, ":not(", (gssize) -1))
; \
490 print_func (selector, string); \
491 g_string_append (string, ")")(__builtin_constant_p (")") ? __extension__ ({ const char * const
__val = (")"); g_string_append_len_inline (string, __val, (__val
!= ((void*)0)) ? (gssize) strlen (((__val) + !(__val))) : (gssize
) -1); }) : g_string_append_len_inline (string, ")", (gssize)
-1))
; \
492} \
493\
494static gboolean \
495ctk_css_selector_not_ ## n ## _match_one (const CtkCssSelector *selector, \
496 const CtkCssMatcher *matcher) \
497{ \
498 return !match_func (selector, matcher); \
499} \
500\
501static CtkCssChange \
502ctk_css_selector_ ## n ## _get_change (const CtkCssSelector *selector G_GNUC_UNUSED__attribute__ ((__unused__)), CtkCssChange previous_change) \
503{ \
504 return previous_change | CTK_CSS_CHANGE_ ## c; \
505} \
506\
507static void \
508ctk_css_selector_ ## n ## _add_specificity (const CtkCssSelector *selector G_GNUC_UNUSED__attribute__ ((__unused__)), \
509 guint *ids, \
510 guint *classes, \
511 guint *elements) \
512{ \
513 if (increase_id_specificity) \
514 { \
515 (*ids)++; \
516 } \
517 if (increase_class_specificity) \
518 { \
519 (*classes)++; \
520 } \
521 if (increase_element_specificity) \
522 { \
523 (*elements)++; \
524 } \
525} \
526\
527static const CtkCssSelectorClass CTK_CSS_SELECTOR_ ## c = { \
528 G_STRINGIFY(n)"n", \
529 ctk_css_selector_ ## n ## _print, \
530 ctk_css_selector_default_foreach_matcher, \
531 match_func, \
532 ctk_css_selector_ ## n ## _get_change, \
533 ctk_css_selector_ ## n ## _add_specificity, \
534 hash_func, \
535 comp_func, \
536 TRUE(!(0)) \
537};\
538\
539static const CtkCssSelectorClass CTK_CSS_SELECTOR_NOT_ ## c = { \
540 "not_" G_STRINGIFY(n)"n", \
541 ctk_css_selector_not_ ## n ## _print, \
542 ctk_css_selector_default_foreach_matcher, \
543 ctk_css_selector_not_ ## n ## _match_one, \
544 ctk_css_selector_ ## n ## _get_change, \
545 ctk_css_selector_ ## n ## _add_specificity, \
546 hash_func, \
547 comp_func, \
548 TRUE(!(0)) \
549};
550
551/* ANY */
552
553static void
554print_any (const CtkCssSelector *selector G_GNUC_UNUSED__attribute__ ((__unused__)),
555 GString *string)
556{
557 g_string_append_c (string, '*')g_string_append_c_inline (string, '*');
558}
559
560static gboolean
561match_any (const CtkCssSelector *selector G_GNUC_UNUSED__attribute__ ((__unused__)),
562 const CtkCssMatcher *matcher G_GNUC_UNUSED__attribute__ ((__unused__)))
563{
564 return TRUE(!(0));
565}
566
567#undef CTK_CSS_CHANGE_ANY
568#define CTK_CSS_CHANGE_ANY 0
569DEFINE_SIMPLE_SELECTOR(any, ANY, print_any, match_any,static void ctk_css_selector_any_print (const CtkCssSelector *
selector, GString *string) { print_any (selector, string); } static
void ctk_css_selector_not_any_print (const CtkCssSelector *selector
, GString *string) { (__builtin_constant_p (":not(") ? __extension__
({ const char * const __val = (":not("); g_string_append_len_inline
(string, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val
) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(string, ":not(", (gssize) -1)); print_any (selector, string
); (__builtin_constant_p (")") ? __extension__ ({ const char *
const __val = (")"); g_string_append_len_inline (string, __val
, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !(__val
))) : (gssize) -1); }) : g_string_append_len_inline (string, ")"
, (gssize) -1)); } static gboolean ctk_css_selector_not_any_match_one
(const CtkCssSelector *selector, const CtkCssMatcher *matcher
) { return !match_any (selector, matcher); } static CtkCssChange
ctk_css_selector_any_get_change (const CtkCssSelector *selector
__attribute__ ((__unused__)), CtkCssChange previous_change) {
return previous_change | CTK_CSS_CHANGE_ANY; } static void ctk_css_selector_any_add_specificity
(const CtkCssSelector *selector __attribute__ ((__unused__))
, guint *ids, guint *classes, guint *elements) { if ((0)) { (
*ids)++; } if ((0)) { (*classes)++; } if ((0)) { (*elements)++
; } } static const CtkCssSelectorClass CTK_CSS_SELECTOR_ANY =
{ "any", ctk_css_selector_any_print, ctk_css_selector_default_foreach_matcher
, match_any, ctk_css_selector_any_get_change, ctk_css_selector_any_add_specificity
, ctk_css_selector_default_hash_one, ctk_css_selector_default_compare_one
, (!(0)) };static const CtkCssSelectorClass CTK_CSS_SELECTOR_NOT_ANY
= { "not_" "any", ctk_css_selector_not_any_print, ctk_css_selector_default_foreach_matcher
, ctk_css_selector_not_any_match_one, ctk_css_selector_any_get_change
, ctk_css_selector_any_add_specificity, ctk_css_selector_default_hash_one
, ctk_css_selector_default_compare_one, (!(0)) };
570 ctk_css_selector_default_hash_one, ctk_css_selector_default_compare_one,static void ctk_css_selector_any_print (const CtkCssSelector *
selector, GString *string) { print_any (selector, string); } static
void ctk_css_selector_not_any_print (const CtkCssSelector *selector
, GString *string) { (__builtin_constant_p (":not(") ? __extension__
({ const char * const __val = (":not("); g_string_append_len_inline
(string, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val
) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(string, ":not(", (gssize) -1)); print_any (selector, string
); (__builtin_constant_p (")") ? __extension__ ({ const char *
const __val = (")"); g_string_append_len_inline (string, __val
, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !(__val
))) : (gssize) -1); }) : g_string_append_len_inline (string, ")"
, (gssize) -1)); } static gboolean ctk_css_selector_not_any_match_one
(const CtkCssSelector *selector, const CtkCssMatcher *matcher
) { return !match_any (selector, matcher); } static CtkCssChange
ctk_css_selector_any_get_change (const CtkCssSelector *selector
__attribute__ ((__unused__)), CtkCssChange previous_change) {
return previous_change | CTK_CSS_CHANGE_ANY; } static void ctk_css_selector_any_add_specificity
(const CtkCssSelector *selector __attribute__ ((__unused__))
, guint *ids, guint *classes, guint *elements) { if ((0)) { (
*ids)++; } if ((0)) { (*classes)++; } if ((0)) { (*elements)++
; } } static const CtkCssSelectorClass CTK_CSS_SELECTOR_ANY =
{ "any", ctk_css_selector_any_print, ctk_css_selector_default_foreach_matcher
, match_any, ctk_css_selector_any_get_change, ctk_css_selector_any_add_specificity
, ctk_css_selector_default_hash_one, ctk_css_selector_default_compare_one
, (!(0)) };static const CtkCssSelectorClass CTK_CSS_SELECTOR_NOT_ANY
= { "not_" "any", ctk_css_selector_not_any_print, ctk_css_selector_default_foreach_matcher
, ctk_css_selector_not_any_match_one, ctk_css_selector_any_get_change
, ctk_css_selector_any_add_specificity, ctk_css_selector_default_hash_one
, ctk_css_selector_default_compare_one, (!(0)) };
571 FALSE, FALSE, FALSE)static void ctk_css_selector_any_print (const CtkCssSelector *
selector, GString *string) { print_any (selector, string); } static
void ctk_css_selector_not_any_print (const CtkCssSelector *selector
, GString *string) { (__builtin_constant_p (":not(") ? __extension__
({ const char * const __val = (":not("); g_string_append_len_inline
(string, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val
) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(string, ":not(", (gssize) -1)); print_any (selector, string
); (__builtin_constant_p (")") ? __extension__ ({ const char *
const __val = (")"); g_string_append_len_inline (string, __val
, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !(__val
))) : (gssize) -1); }) : g_string_append_len_inline (string, ")"
, (gssize) -1)); } static gboolean ctk_css_selector_not_any_match_one
(const CtkCssSelector *selector, const CtkCssMatcher *matcher
) { return !match_any (selector, matcher); } static CtkCssChange
ctk_css_selector_any_get_change (const CtkCssSelector *selector
__attribute__ ((__unused__)), CtkCssChange previous_change) {
return previous_change | CTK_CSS_CHANGE_ANY; } static void ctk_css_selector_any_add_specificity
(const CtkCssSelector *selector __attribute__ ((__unused__))
, guint *ids, guint *classes, guint *elements) { if ((0)) { (
*ids)++; } if ((0)) { (*classes)++; } if ((0)) { (*elements)++
; } } static const CtkCssSelectorClass CTK_CSS_SELECTOR_ANY =
{ "any", ctk_css_selector_any_print, ctk_css_selector_default_foreach_matcher
, match_any, ctk_css_selector_any_get_change, ctk_css_selector_any_add_specificity
, ctk_css_selector_default_hash_one, ctk_css_selector_default_compare_one
, (!(0)) };static const CtkCssSelectorClass CTK_CSS_SELECTOR_NOT_ANY
= { "not_" "any", ctk_css_selector_not_any_print, ctk_css_selector_default_foreach_matcher
, ctk_css_selector_not_any_match_one, ctk_css_selector_any_get_change
, ctk_css_selector_any_add_specificity, ctk_css_selector_default_hash_one
, ctk_css_selector_default_compare_one, (!(0)) };
572#undef CTK_CSS_CHANGE_ANY
573
574/* NAME */
575
576static void
577print_name (const CtkCssSelector *selector,
578 GString *string)
579{
580 g_string_append (string, selector->name.name)(__builtin_constant_p (selector->name.name) ? __extension__
({ const char * const __val = (selector->name.name); g_string_append_len_inline
(string, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val
) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(string, selector->name.name, (gssize) -1))
;
581}
582
583static gboolean
584match_name (const CtkCssSelector *selector,
585 const CtkCssMatcher *matcher)
586{
587 return _ctk_css_matcher_has_name (matcher, selector->name.name);
588}
589
590static guint
591hash_name (const CtkCssSelector *a)
592{
593 return g_str_hash (a->name.name);
594}
595
596static int
597comp_name (const CtkCssSelector *a,
598 const CtkCssSelector *b)
599{
600 return strcmp (a->name.name,
601 b->name.name);
602}
603
604DEFINE_SIMPLE_SELECTOR(name, NAME, print_name, match_name, hash_name, comp_name, FALSE, FALSE, TRUE)static void ctk_css_selector_name_print (const CtkCssSelector
*selector, GString *string) { print_name (selector, string);
} static void ctk_css_selector_not_name_print (const CtkCssSelector
*selector, GString *string) { (__builtin_constant_p (":not("
) ? __extension__ ({ const char * const __val = (":not("); g_string_append_len_inline
(string, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val
) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(string, ":not(", (gssize) -1)); print_name (selector, string
); (__builtin_constant_p (")") ? __extension__ ({ const char *
const __val = (")"); g_string_append_len_inline (string, __val
, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !(__val
))) : (gssize) -1); }) : g_string_append_len_inline (string, ")"
, (gssize) -1)); } static gboolean ctk_css_selector_not_name_match_one
(const CtkCssSelector *selector, const CtkCssMatcher *matcher
) { return !match_name (selector, matcher); } static CtkCssChange
ctk_css_selector_name_get_change (const CtkCssSelector *selector
__attribute__ ((__unused__)), CtkCssChange previous_change) {
return previous_change | (1ULL << 1); } static void ctk_css_selector_name_add_specificity
(const CtkCssSelector *selector __attribute__ ((__unused__))
, guint *ids, guint *classes, guint *elements) { if ((0)) { (
*ids)++; } if ((0)) { (*classes)++; } if ((!(0))) { (*elements
)++; } } static const CtkCssSelectorClass CTK_CSS_SELECTOR_NAME
= { "name", ctk_css_selector_name_print, ctk_css_selector_default_foreach_matcher
, match_name, ctk_css_selector_name_get_change, ctk_css_selector_name_add_specificity
, hash_name, comp_name, (!(0)) };static const CtkCssSelectorClass
CTK_CSS_SELECTOR_NOT_NAME = { "not_" "name", ctk_css_selector_not_name_print
, ctk_css_selector_default_foreach_matcher, ctk_css_selector_not_name_match_one
, ctk_css_selector_name_get_change, ctk_css_selector_name_add_specificity
, hash_name, comp_name, (!(0)) };
605
606/* CLASS */
607
608static void
609print_class (const CtkCssSelector *selector,
610 GString *string)
611{
612 g_string_append_c (string, '.')g_string_append_c_inline (string, '.');
613 g_string_append (string, g_quark_to_string (selector->style_class.style_class))(__builtin_constant_p (g_quark_to_string (selector->style_class
.style_class)) ? __extension__ ({ const char * const __val = (
g_quark_to_string (selector->style_class.style_class)); g_string_append_len_inline
(string, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val
) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(string, g_quark_to_string (selector->style_class.style_class
), (gssize) -1))
;
614}
615
616static gboolean
617match_class (const CtkCssSelector *selector,
618 const CtkCssMatcher *matcher)
619{
620 return _ctk_css_matcher_has_class (matcher, selector->style_class.style_class);
621}
622
623static guint
624hash_class (const CtkCssSelector *a)
625{
626 return a->style_class.style_class;
627}
628
629static int
630comp_class (const CtkCssSelector *a,
631 const CtkCssSelector *b)
632{
633 if (a->style_class.style_class < b->style_class.style_class)
634 return -1;
635 if (a->style_class.style_class > b->style_class.style_class)
636 return 1;
637 else
638 return 0;
639}
640
641DEFINE_SIMPLE_SELECTOR(class, CLASS, print_class, match_class, hash_class, comp_class, FALSE, TRUE, FALSE)static void ctk_css_selector_class_print (const CtkCssSelector
*selector, GString *string) { print_class (selector, string)
; } static void ctk_css_selector_not_class_print (const CtkCssSelector
*selector, GString *string) { (__builtin_constant_p (":not("
) ? __extension__ ({ const char * const __val = (":not("); g_string_append_len_inline
(string, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val
) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(string, ":not(", (gssize) -1)); print_class (selector, string
); (__builtin_constant_p (")") ? __extension__ ({ const char *
const __val = (")"); g_string_append_len_inline (string, __val
, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !(__val
))) : (gssize) -1); }) : g_string_append_len_inline (string, ")"
, (gssize) -1)); } static gboolean ctk_css_selector_not_class_match_one
(const CtkCssSelector *selector, const CtkCssMatcher *matcher
) { return !match_class (selector, matcher); } static CtkCssChange
ctk_css_selector_class_get_change (const CtkCssSelector *selector
__attribute__ ((__unused__)), CtkCssChange previous_change) {
return previous_change | (1ULL << 0); } static void ctk_css_selector_class_add_specificity
(const CtkCssSelector *selector __attribute__ ((__unused__))
, guint *ids, guint *classes, guint *elements) { if ((0)) { (
*ids)++; } if ((!(0))) { (*classes)++; } if ((0)) { (*elements
)++; } } static const CtkCssSelectorClass CTK_CSS_SELECTOR_CLASS
= { "class", ctk_css_selector_class_print, ctk_css_selector_default_foreach_matcher
, match_class, ctk_css_selector_class_get_change, ctk_css_selector_class_add_specificity
, hash_class, comp_class, (!(0)) };static const CtkCssSelectorClass
CTK_CSS_SELECTOR_NOT_CLASS = { "not_" "class", ctk_css_selector_not_class_print
, ctk_css_selector_default_foreach_matcher, ctk_css_selector_not_class_match_one
, ctk_css_selector_class_get_change, ctk_css_selector_class_add_specificity
, hash_class, comp_class, (!(0)) };
642
643/* ID */
644
645static void
646print_id (const CtkCssSelector *selector,
647 GString *string)
648{
649 g_string_append_c (string, '#')g_string_append_c_inline (string, '#');
650 g_string_append (string, selector->id.name)(__builtin_constant_p (selector->id.name) ? __extension__ (
{ const char * const __val = (selector->id.name); g_string_append_len_inline
(string, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val
) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(string, selector->id.name, (gssize) -1))
;
651}
652
653static gboolean
654match_id (const CtkCssSelector *selector,
655 const CtkCssMatcher *matcher)
656{
657 return _ctk_css_matcher_has_id (matcher, selector->id.name);
658}
659
660static guint
661hash_id (const CtkCssSelector *a)
662{
663 return GPOINTER_TO_UINT (a->id.name)((guint) (gulong) (a->id.name));
664}
665
666static int
667comp_id (const CtkCssSelector *a,
668 const CtkCssSelector *b)
669{
670 if (a->id.name < b->id.name)
671 return -1;
672 else if (a->id.name > b->id.name)
673 return 1;
674 else
675 return 0;
676}
677
678DEFINE_SIMPLE_SELECTOR(id, ID, print_id, match_id, hash_id, comp_id, TRUE, FALSE, FALSE)static void ctk_css_selector_id_print (const CtkCssSelector *
selector, GString *string) { print_id (selector, string); } static
void ctk_css_selector_not_id_print (const CtkCssSelector *selector
, GString *string) { (__builtin_constant_p (":not(") ? __extension__
({ const char * const __val = (":not("); g_string_append_len_inline
(string, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val
) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(string, ":not(", (gssize) -1)); print_id (selector, string)
; (__builtin_constant_p (")") ? __extension__ ({ const char *
const __val = (")"); g_string_append_len_inline (string, __val
, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !(__val
))) : (gssize) -1); }) : g_string_append_len_inline (string, ")"
, (gssize) -1)); } static gboolean ctk_css_selector_not_id_match_one
(const CtkCssSelector *selector, const CtkCssMatcher *matcher
) { return !match_id (selector, matcher); } static CtkCssChange
ctk_css_selector_id_get_change (const CtkCssSelector *selector
__attribute__ ((__unused__)), CtkCssChange previous_change) {
return previous_change | (1ULL << 2); } static void ctk_css_selector_id_add_specificity
(const CtkCssSelector *selector __attribute__ ((__unused__))
, guint *ids, guint *classes, guint *elements) { if ((!(0))) {
(*ids)++; } if ((0)) { (*classes)++; } if ((0)) { (*elements
)++; } } static const CtkCssSelectorClass CTK_CSS_SELECTOR_ID
= { "id", ctk_css_selector_id_print, ctk_css_selector_default_foreach_matcher
, match_id, ctk_css_selector_id_get_change, ctk_css_selector_id_add_specificity
, hash_id, comp_id, (!(0)) };static const CtkCssSelectorClass
CTK_CSS_SELECTOR_NOT_ID = { "not_" "id", ctk_css_selector_not_id_print
, ctk_css_selector_default_foreach_matcher, ctk_css_selector_not_id_match_one
, ctk_css_selector_id_get_change, ctk_css_selector_id_add_specificity
, hash_id, comp_id, (!(0)) };
679
680const gchar *
681ctk_css_pseudoclass_name (CtkStateFlags state)
682{
683 static const char * state_names[] = {
684 "active",
685 "hover",
686 "selected",
687 "disabled",
688 "indeterminate",
689 "focus",
690 "backdrop",
691 "dir(ltr)",
692 "dir(rtl)",
693 "link",
694 "visited",
695 "checked",
696 "drop(active)"
697 };
698 guint i;
699
700 for (i = 0; i < G_N_ELEMENTS (state_names)(sizeof (state_names) / sizeof ((state_names)[0])); i++)
701 {
702 if (state == (1 << i))
703 return state_names[i];
704 }
705
706 return NULL((void*)0);
707}
708
709/* PSEUDOCLASS FOR STATE */
710static void
711print_pseudoclass_state (const CtkCssSelector *selector,
712 GString *string)
713{
714 g_string_append_c (string, ':')g_string_append_c_inline (string, ':');
715 g_string_append (string, ctk_css_pseudoclass_name (selector->state.state))(__builtin_constant_p (ctk_css_pseudoclass_name (selector->
state.state)) ? __extension__ ({ const char * const __val = (
ctk_css_pseudoclass_name (selector->state.state)); g_string_append_len_inline
(string, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val
) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(string, ctk_css_pseudoclass_name (selector->state.state)
, (gssize) -1))
;
716}
717
718static gboolean
719match_pseudoclass_state (const CtkCssSelector *selector,
720 const CtkCssMatcher *matcher)
721{
722 return (_ctk_css_matcher_get_state (matcher) & selector->state.state) == selector->state.state;
723}
724
725static guint
726hash_pseudoclass_state (const CtkCssSelector *selector)
727{
728 return selector->state.state;
729}
730
731
732static int
733comp_pseudoclass_state (const CtkCssSelector *a,
734 const CtkCssSelector *b)
735{
736 return a->state.state - b->state.state;
737}
738
739#define CTK_CSS_CHANGE_PSEUDOCLASS_STATE CTK_CSS_CHANGE_STATE(1ULL << 7)
740DEFINE_SIMPLE_SELECTOR(pseudoclass_state, PSEUDOCLASS_STATE, print_pseudoclass_state,static void ctk_css_selector_pseudoclass_state_print (const CtkCssSelector
*selector, GString *string) { print_pseudoclass_state (selector
, string); } static void ctk_css_selector_not_pseudoclass_state_print
(const CtkCssSelector *selector, GString *string) { (__builtin_constant_p
(":not(") ? __extension__ ({ const char * const __val = (":not("
); g_string_append_len_inline (string, __val, (__val != ((void
*)0)) ? (gssize) strlen (((__val) + !(__val))) : (gssize) -1)
; }) : g_string_append_len_inline (string, ":not(", (gssize) -
1)); print_pseudoclass_state (selector, string); (__builtin_constant_p
(")") ? __extension__ ({ const char * const __val = (")"); g_string_append_len_inline
(string, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val
) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(string, ")", (gssize) -1)); } static gboolean ctk_css_selector_not_pseudoclass_state_match_one
(const CtkCssSelector *selector, const CtkCssMatcher *matcher
) { return !match_pseudoclass_state (selector, matcher); } static
CtkCssChange ctk_css_selector_pseudoclass_state_get_change (
const CtkCssSelector *selector __attribute__ ((__unused__)), CtkCssChange
previous_change) { return previous_change | CTK_CSS_CHANGE_PSEUDOCLASS_STATE
; } static void ctk_css_selector_pseudoclass_state_add_specificity
(const CtkCssSelector *selector __attribute__ ((__unused__))
, guint *ids, guint *classes, guint *elements) { if ((0)) { (
*ids)++; } if ((!(0))) { (*classes)++; } if ((0)) { (*elements
)++; } } static const CtkCssSelectorClass CTK_CSS_SELECTOR_PSEUDOCLASS_STATE
= { "pseudoclass_state", ctk_css_selector_pseudoclass_state_print
, ctk_css_selector_default_foreach_matcher, match_pseudoclass_state
, ctk_css_selector_pseudoclass_state_get_change, ctk_css_selector_pseudoclass_state_add_specificity
, hash_pseudoclass_state, comp_pseudoclass_state, (!(0)) };static
const CtkCssSelectorClass CTK_CSS_SELECTOR_NOT_PSEUDOCLASS_STATE
= { "not_" "pseudoclass_state", ctk_css_selector_not_pseudoclass_state_print
, ctk_css_selector_default_foreach_matcher, ctk_css_selector_not_pseudoclass_state_match_one
, ctk_css_selector_pseudoclass_state_get_change, ctk_css_selector_pseudoclass_state_add_specificity
, hash_pseudoclass_state, comp_pseudoclass_state, (!(0)) };
741 match_pseudoclass_state, hash_pseudoclass_state, comp_pseudoclass_state,static void ctk_css_selector_pseudoclass_state_print (const CtkCssSelector
*selector, GString *string) { print_pseudoclass_state (selector
, string); } static void ctk_css_selector_not_pseudoclass_state_print
(const CtkCssSelector *selector, GString *string) { (__builtin_constant_p
(":not(") ? __extension__ ({ const char * const __val = (":not("
); g_string_append_len_inline (string, __val, (__val != ((void
*)0)) ? (gssize) strlen (((__val) + !(__val))) : (gssize) -1)
; }) : g_string_append_len_inline (string, ":not(", (gssize) -
1)); print_pseudoclass_state (selector, string); (__builtin_constant_p
(")") ? __extension__ ({ const char * const __val = (")"); g_string_append_len_inline
(string, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val
) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(string, ")", (gssize) -1)); } static gboolean ctk_css_selector_not_pseudoclass_state_match_one
(const CtkCssSelector *selector, const CtkCssMatcher *matcher
) { return !match_pseudoclass_state (selector, matcher); } static
CtkCssChange ctk_css_selector_pseudoclass_state_get_change (
const CtkCssSelector *selector __attribute__ ((__unused__)), CtkCssChange
previous_change) { return previous_change | CTK_CSS_CHANGE_PSEUDOCLASS_STATE
; } static void ctk_css_selector_pseudoclass_state_add_specificity
(const CtkCssSelector *selector __attribute__ ((__unused__))
, guint *ids, guint *classes, guint *elements) { if ((0)) { (
*ids)++; } if ((!(0))) { (*classes)++; } if ((0)) { (*elements
)++; } } static const CtkCssSelectorClass CTK_CSS_SELECTOR_PSEUDOCLASS_STATE
= { "pseudoclass_state", ctk_css_selector_pseudoclass_state_print
, ctk_css_selector_default_foreach_matcher, match_pseudoclass_state
, ctk_css_selector_pseudoclass_state_get_change, ctk_css_selector_pseudoclass_state_add_specificity
, hash_pseudoclass_state, comp_pseudoclass_state, (!(0)) };static
const CtkCssSelectorClass CTK_CSS_SELECTOR_NOT_PSEUDOCLASS_STATE
= { "not_" "pseudoclass_state", ctk_css_selector_not_pseudoclass_state_print
, ctk_css_selector_default_foreach_matcher, ctk_css_selector_not_pseudoclass_state_match_one
, ctk_css_selector_pseudoclass_state_get_change, ctk_css_selector_pseudoclass_state_add_specificity
, hash_pseudoclass_state, comp_pseudoclass_state, (!(0)) };
742 FALSE, TRUE, FALSE)static void ctk_css_selector_pseudoclass_state_print (const CtkCssSelector
*selector, GString *string) { print_pseudoclass_state (selector
, string); } static void ctk_css_selector_not_pseudoclass_state_print
(const CtkCssSelector *selector, GString *string) { (__builtin_constant_p
(":not(") ? __extension__ ({ const char * const __val = (":not("
); g_string_append_len_inline (string, __val, (__val != ((void
*)0)) ? (gssize) strlen (((__val) + !(__val))) : (gssize) -1)
; }) : g_string_append_len_inline (string, ":not(", (gssize) -
1)); print_pseudoclass_state (selector, string); (__builtin_constant_p
(")") ? __extension__ ({ const char * const __val = (")"); g_string_append_len_inline
(string, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val
) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(string, ")", (gssize) -1)); } static gboolean ctk_css_selector_not_pseudoclass_state_match_one
(const CtkCssSelector *selector, const CtkCssMatcher *matcher
) { return !match_pseudoclass_state (selector, matcher); } static
CtkCssChange ctk_css_selector_pseudoclass_state_get_change (
const CtkCssSelector *selector __attribute__ ((__unused__)), CtkCssChange
previous_change) { return previous_change | CTK_CSS_CHANGE_PSEUDOCLASS_STATE
; } static void ctk_css_selector_pseudoclass_state_add_specificity
(const CtkCssSelector *selector __attribute__ ((__unused__))
, guint *ids, guint *classes, guint *elements) { if ((0)) { (
*ids)++; } if ((!(0))) { (*classes)++; } if ((0)) { (*elements
)++; } } static const CtkCssSelectorClass CTK_CSS_SELECTOR_PSEUDOCLASS_STATE
= { "pseudoclass_state", ctk_css_selector_pseudoclass_state_print
, ctk_css_selector_default_foreach_matcher, match_pseudoclass_state
, ctk_css_selector_pseudoclass_state_get_change, ctk_css_selector_pseudoclass_state_add_specificity
, hash_pseudoclass_state, comp_pseudoclass_state, (!(0)) };static
const CtkCssSelectorClass CTK_CSS_SELECTOR_NOT_PSEUDOCLASS_STATE
= { "not_" "pseudoclass_state", ctk_css_selector_not_pseudoclass_state_print
, ctk_css_selector_default_foreach_matcher, ctk_css_selector_not_pseudoclass_state_match_one
, ctk_css_selector_pseudoclass_state_get_change, ctk_css_selector_pseudoclass_state_add_specificity
, hash_pseudoclass_state, comp_pseudoclass_state, (!(0)) };
743#undef CTK_CSS_CHANGE_PSEUDOCLASS_STATE
744
745/* PSEUDOCLASS FOR POSITION */
746
747static void
748print_pseudoclass_position (const CtkCssSelector *selector,
749 GString *string)
750{
751 switch (selector->position.type)
752 {
753 case POSITION_FORWARD:
754 if (selector->position.a == 0)
755 {
756 if (selector->position.b == 1)
757 g_string_append (string, ":first-child")(__builtin_constant_p (":first-child") ? __extension__ ({ const
char * const __val = (":first-child"); g_string_append_len_inline
(string, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val
) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(string, ":first-child", (gssize) -1))
;
758 else
759 g_string_append_printf (string, ":nth-child(%d)", selector->position.b);
760 }
761 else if (selector->position.a == 2 && selector->position.b == 0)
762 g_string_append (string, ":nth-child(even)")(__builtin_constant_p (":nth-child(even)") ? __extension__ ({
const char * const __val = (":nth-child(even)"); g_string_append_len_inline
(string, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val
) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(string, ":nth-child(even)", (gssize) -1))
;
763 else if (selector->position.a == 2 && selector->position.b == 1)
764 g_string_append (string, ":nth-child(odd)")(__builtin_constant_p (":nth-child(odd)") ? __extension__ ({ const
char * const __val = (":nth-child(odd)"); g_string_append_len_inline
(string, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val
) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(string, ":nth-child(odd)", (gssize) -1))
;
765 else
766 {
767 g_string_append (string, ":nth-child(")(__builtin_constant_p (":nth-child(") ? __extension__ ({ const
char * const __val = (":nth-child("); g_string_append_len_inline
(string, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val
) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(string, ":nth-child(", (gssize) -1))
;
768 if (selector->position.a == 1)
769 g_string_append (string, "n")(__builtin_constant_p ("n") ? __extension__ ({ const char * const
__val = ("n"); g_string_append_len_inline (string, __val, (__val
!= ((void*)0)) ? (gssize) strlen (((__val) + !(__val))) : (gssize
) -1); }) : g_string_append_len_inline (string, "n", (gssize)
-1))
;
770 else if (selector->position.a == -1)
771 g_string_append (string, "-n")(__builtin_constant_p ("-n") ? __extension__ ({ const char * const
__val = ("-n"); g_string_append_len_inline (string, __val, (
__val != ((void*)0)) ? (gssize) strlen (((__val) + !(__val)))
: (gssize) -1); }) : g_string_append_len_inline (string, "-n"
, (gssize) -1))
;
772 else
773 g_string_append_printf (string, "%dn", selector->position.a);
774 if (selector->position.b > 0)
775 g_string_append_printf (string, "+%d)", selector->position.b);
776 else if (selector->position.b < 0)
777 g_string_append_printf (string, "%d)", selector->position.b);
778 else
779 g_string_append (string, ")")(__builtin_constant_p (")") ? __extension__ ({ const char * const
__val = (")"); g_string_append_len_inline (string, __val, (__val
!= ((void*)0)) ? (gssize) strlen (((__val) + !(__val))) : (gssize
) -1); }) : g_string_append_len_inline (string, ")", (gssize)
-1))
;
780 }
781 break;
782 case POSITION_BACKWARD:
783 if (selector->position.a == 0)
784 {
785 if (selector->position.b == 1)
786 g_string_append (string, ":last-child")(__builtin_constant_p (":last-child") ? __extension__ ({ const
char * const __val = (":last-child"); g_string_append_len_inline
(string, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val
) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(string, ":last-child", (gssize) -1))
;
787 else
788 g_string_append_printf (string, ":nth-last-child(%d)", selector->position.b);
789 }
790 else if (selector->position.a == 2 && selector->position.b == 0)
791 g_string_append (string, ":nth-last-child(even)")(__builtin_constant_p (":nth-last-child(even)") ? __extension__
({ const char * const __val = (":nth-last-child(even)"); g_string_append_len_inline
(string, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val
) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(string, ":nth-last-child(even)", (gssize) -1))
;
792 else if (selector->position.a == 2 && selector->position.b == 1)
793 g_string_append (string, ":nth-last-child(odd)")(__builtin_constant_p (":nth-last-child(odd)") ? __extension__
({ const char * const __val = (":nth-last-child(odd)"); g_string_append_len_inline
(string, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val
) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(string, ":nth-last-child(odd)", (gssize) -1))
;
794 else
795 {
796 g_string_append (string, ":nth-last-child(")(__builtin_constant_p (":nth-last-child(") ? __extension__ ({
const char * const __val = (":nth-last-child("); g_string_append_len_inline
(string, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val
) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(string, ":nth-last-child(", (gssize) -1))
;
797 if (selector->position.a == 1)
798 g_string_append (string, "n")(__builtin_constant_p ("n") ? __extension__ ({ const char * const
__val = ("n"); g_string_append_len_inline (string, __val, (__val
!= ((void*)0)) ? (gssize) strlen (((__val) + !(__val))) : (gssize
) -1); }) : g_string_append_len_inline (string, "n", (gssize)
-1))
;
799 else if (selector->position.a == -1)
800 g_string_append (string, "-n")(__builtin_constant_p ("-n") ? __extension__ ({ const char * const
__val = ("-n"); g_string_append_len_inline (string, __val, (
__val != ((void*)0)) ? (gssize) strlen (((__val) + !(__val)))
: (gssize) -1); }) : g_string_append_len_inline (string, "-n"
, (gssize) -1))
;
801 else
802 g_string_append_printf (string, "%dn", selector->position.a);
803 if (selector->position.b > 0)
804 g_string_append_printf (string, "+%d)", selector->position.b);
805 else if (selector->position.b < 0)
806 g_string_append_printf (string, "%d)", selector->position.b);
807 else
808 g_string_append (string, ")")(__builtin_constant_p (")") ? __extension__ ({ const char * const
__val = (")"); g_string_append_len_inline (string, __val, (__val
!= ((void*)0)) ? (gssize) strlen (((__val) + !(__val))) : (gssize
) -1); }) : g_string_append_len_inline (string, ")", (gssize)
-1))
;
809 }
810 break;
811 case POSITION_ONLY:
812 g_string_append (string, ":only-child")(__builtin_constant_p (":only-child") ? __extension__ ({ const
char * const __val = (":only-child"); g_string_append_len_inline
(string, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val
) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(string, ":only-child", (gssize) -1))
;
813 break;
814 case POSITION_SORTED:
815 g_string_append (string, ":sorted")(__builtin_constant_p (":sorted") ? __extension__ ({ const char
* const __val = (":sorted"); g_string_append_len_inline (string
, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !
(__val))) : (gssize) -1); }) : g_string_append_len_inline (string
, ":sorted", (gssize) -1))
;
816 break;
817 default:
818 g_assert_not_reached ()do { g_assertion_message_expr ("Ctk", "ctkcssselector.c", 818
, ((const char*) (__func__)), ((void*)0)); } while (0)
;
819 break;
820 }
821}
822
823static gboolean
824match_pseudoclass_position (const CtkCssSelector *selector,
825 const CtkCssMatcher *matcher)
826{
827 switch (selector->position.type)
828 {
829 case POSITION_FORWARD:
830 if (!_ctk_css_matcher_has_position (matcher, TRUE(!(0)), selector->position.a, selector->position.b))
831 return FALSE(0);
832 break;
833 case POSITION_BACKWARD:
834 if (!_ctk_css_matcher_has_position (matcher, FALSE(0), selector->position.a, selector->position.b))
835 return FALSE(0);
836 break;
837 case POSITION_ONLY:
838 if (!_ctk_css_matcher_has_position (matcher, TRUE(!(0)), 0, 1) ||
839 !_ctk_css_matcher_has_position (matcher, FALSE(0), 0, 1))
840 return FALSE(0);
841 break;
842 case POSITION_SORTED:
843 return FALSE(0);
844 default:
845 g_assert_not_reached ()do { g_assertion_message_expr ("Ctk", "ctkcssselector.c", 845
, ((const char*) (__func__)), ((void*)0)); } while (0)
;
846 return FALSE(0);
847 }
848
849 return TRUE(!(0));
850}
851
852static guint
853hash_pseudoclass_position (const CtkCssSelector *a)
854{
855 return (guint)(((((gulong)a->position.type) << POSITION_NUMBER_BITS((sizeof (gpointer) * 8 - 4) / 2)) | a->position.a) << POSITION_NUMBER_BITS((sizeof (gpointer) * 8 - 4) / 2)) | a->position.b;
856}
857
858static int
859comp_pseudoclass_position (const CtkCssSelector *a,
860 const CtkCssSelector *b)
861{
862 int diff;
863
864 diff = a->position.type - b->position.type;
865 if (diff)
866 return diff;
867
868 diff = a->position.a - b->position.a;
869 if (diff)
870 return diff;
871
872 return a->position.b - b->position.b;
873}
874
875static CtkCssChange
876change_pseudoclass_position (const CtkCssSelector *selector)
877{
878 switch (selector->position.type)
879 {
880 case POSITION_FORWARD:
881 if (selector->position.a == 0 && selector->position.b == 1)
882 return CTK_CSS_CHANGE_FIRST_CHILD(1ULL << 3);
883 else
884 return CTK_CSS_CHANGE_NTH_CHILD(1ULL << 5);
885 case POSITION_BACKWARD:
886 if (selector->position.a == 0 && selector->position.b == 1)
887 return CTK_CSS_CHANGE_LAST_CHILD(1ULL << 4);
888 else
889 return CTK_CSS_CHANGE_NTH_LAST_CHILD(1ULL << 6);
890 case POSITION_ONLY:
891 return CTK_CSS_CHANGE_FIRST_CHILD(1ULL << 3) | CTK_CSS_CHANGE_LAST_CHILD(1ULL << 4);
892 default:
893 g_assert_not_reached ()do { g_assertion_message_expr ("Ctk", "ctkcssselector.c", 893
, ((const char*) (__func__)), ((void*)0)); } while (0)
;
894 case POSITION_SORTED:
895 return 0;
896 }
897}
898
899#define CTK_CSS_CHANGE_PSEUDOCLASS_POSITION change_pseudoclass_position(selector)
900DEFINE_SIMPLE_SELECTOR(pseudoclass_position, PSEUDOCLASS_POSITION, print_pseudoclass_position,static void ctk_css_selector_pseudoclass_position_print (const
CtkCssSelector *selector, GString *string) { print_pseudoclass_position
(selector, string); } static void ctk_css_selector_not_pseudoclass_position_print
(const CtkCssSelector *selector, GString *string) { (__builtin_constant_p
(":not(") ? __extension__ ({ const char * const __val = (":not("
); g_string_append_len_inline (string, __val, (__val != ((void
*)0)) ? (gssize) strlen (((__val) + !(__val))) : (gssize) -1)
; }) : g_string_append_len_inline (string, ":not(", (gssize) -
1)); print_pseudoclass_position (selector, string); (__builtin_constant_p
(")") ? __extension__ ({ const char * const __val = (")"); g_string_append_len_inline
(string, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val
) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(string, ")", (gssize) -1)); } static gboolean ctk_css_selector_not_pseudoclass_position_match_one
(const CtkCssSelector *selector, const CtkCssMatcher *matcher
) { return !match_pseudoclass_position (selector, matcher); }
static CtkCssChange ctk_css_selector_pseudoclass_position_get_change
(const CtkCssSelector *selector __attribute__ ((__unused__))
, CtkCssChange previous_change) { return previous_change | CTK_CSS_CHANGE_PSEUDOCLASS_POSITION
; } static void ctk_css_selector_pseudoclass_position_add_specificity
(const CtkCssSelector *selector __attribute__ ((__unused__))
, guint *ids, guint *classes, guint *elements) { if ((0)) { (
*ids)++; } if ((!(0))) { (*classes)++; } if ((0)) { (*elements
)++; } } static const CtkCssSelectorClass CTK_CSS_SELECTOR_PSEUDOCLASS_POSITION
= { "pseudoclass_position", ctk_css_selector_pseudoclass_position_print
, ctk_css_selector_default_foreach_matcher, match_pseudoclass_position
, ctk_css_selector_pseudoclass_position_get_change, ctk_css_selector_pseudoclass_position_add_specificity
, hash_pseudoclass_position, comp_pseudoclass_position, (!(0)
) };static const CtkCssSelectorClass CTK_CSS_SELECTOR_NOT_PSEUDOCLASS_POSITION
= { "not_" "pseudoclass_position", ctk_css_selector_not_pseudoclass_position_print
, ctk_css_selector_default_foreach_matcher, ctk_css_selector_not_pseudoclass_position_match_one
, ctk_css_selector_pseudoclass_position_get_change, ctk_css_selector_pseudoclass_position_add_specificity
, hash_pseudoclass_position, comp_pseudoclass_position, (!(0)
) };
901 match_pseudoclass_position, hash_pseudoclass_position, comp_pseudoclass_position,static void ctk_css_selector_pseudoclass_position_print (const
CtkCssSelector *selector, GString *string) { print_pseudoclass_position
(selector, string); } static void ctk_css_selector_not_pseudoclass_position_print
(const CtkCssSelector *selector, GString *string) { (__builtin_constant_p
(":not(") ? __extension__ ({ const char * const __val = (":not("
); g_string_append_len_inline (string, __val, (__val != ((void
*)0)) ? (gssize) strlen (((__val) + !(__val))) : (gssize) -1)
; }) : g_string_append_len_inline (string, ":not(", (gssize) -
1)); print_pseudoclass_position (selector, string); (__builtin_constant_p
(")") ? __extension__ ({ const char * const __val = (")"); g_string_append_len_inline
(string, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val
) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(string, ")", (gssize) -1)); } static gboolean ctk_css_selector_not_pseudoclass_position_match_one
(const CtkCssSelector *selector, const CtkCssMatcher *matcher
) { return !match_pseudoclass_position (selector, matcher); }
static CtkCssChange ctk_css_selector_pseudoclass_position_get_change
(const CtkCssSelector *selector __attribute__ ((__unused__))
, CtkCssChange previous_change) { return previous_change | CTK_CSS_CHANGE_PSEUDOCLASS_POSITION
; } static void ctk_css_selector_pseudoclass_position_add_specificity
(const CtkCssSelector *selector __attribute__ ((__unused__))
, guint *ids, guint *classes, guint *elements) { if ((0)) { (
*ids)++; } if ((!(0))) { (*classes)++; } if ((0)) { (*elements
)++; } } static const CtkCssSelectorClass CTK_CSS_SELECTOR_PSEUDOCLASS_POSITION
= { "pseudoclass_position", ctk_css_selector_pseudoclass_position_print
, ctk_css_selector_default_foreach_matcher, match_pseudoclass_position
, ctk_css_selector_pseudoclass_position_get_change, ctk_css_selector_pseudoclass_position_add_specificity
, hash_pseudoclass_position, comp_pseudoclass_position, (!(0)
) };static const CtkCssSelectorClass CTK_CSS_SELECTOR_NOT_PSEUDOCLASS_POSITION
= { "not_" "pseudoclass_position", ctk_css_selector_not_pseudoclass_position_print
, ctk_css_selector_default_foreach_matcher, ctk_css_selector_not_pseudoclass_position_match_one
, ctk_css_selector_pseudoclass_position_get_change, ctk_css_selector_pseudoclass_position_add_specificity
, hash_pseudoclass_position, comp_pseudoclass_position, (!(0)
) };
902 FALSE, TRUE, FALSE)static void ctk_css_selector_pseudoclass_position_print (const
CtkCssSelector *selector, GString *string) { print_pseudoclass_position
(selector, string); } static void ctk_css_selector_not_pseudoclass_position_print
(const CtkCssSelector *selector, GString *string) { (__builtin_constant_p
(":not(") ? __extension__ ({ const char * const __val = (":not("
); g_string_append_len_inline (string, __val, (__val != ((void
*)0)) ? (gssize) strlen (((__val) + !(__val))) : (gssize) -1)
; }) : g_string_append_len_inline (string, ":not(", (gssize) -
1)); print_pseudoclass_position (selector, string); (__builtin_constant_p
(")") ? __extension__ ({ const char * const __val = (")"); g_string_append_len_inline
(string, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val
) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(string, ")", (gssize) -1)); } static gboolean ctk_css_selector_not_pseudoclass_position_match_one
(const CtkCssSelector *selector, const CtkCssMatcher *matcher
) { return !match_pseudoclass_position (selector, matcher); }
static CtkCssChange ctk_css_selector_pseudoclass_position_get_change
(const CtkCssSelector *selector __attribute__ ((__unused__))
, CtkCssChange previous_change) { return previous_change | CTK_CSS_CHANGE_PSEUDOCLASS_POSITION
; } static void ctk_css_selector_pseudoclass_position_add_specificity
(const CtkCssSelector *selector __attribute__ ((__unused__))
, guint *ids, guint *classes, guint *elements) { if ((0)) { (
*ids)++; } if ((!(0))) { (*classes)++; } if ((0)) { (*elements
)++; } } static const CtkCssSelectorClass CTK_CSS_SELECTOR_PSEUDOCLASS_POSITION
= { "pseudoclass_position", ctk_css_selector_pseudoclass_position_print
, ctk_css_selector_default_foreach_matcher, match_pseudoclass_position
, ctk_css_selector_pseudoclass_position_get_change, ctk_css_selector_pseudoclass_position_add_specificity
, hash_pseudoclass_position, comp_pseudoclass_position, (!(0)
) };static const CtkCssSelectorClass CTK_CSS_SELECTOR_NOT_PSEUDOCLASS_POSITION
= { "not_" "pseudoclass_position", ctk_css_selector_not_pseudoclass_position_print
, ctk_css_selector_default_foreach_matcher, ctk_css_selector_not_pseudoclass_position_match_one
, ctk_css_selector_pseudoclass_position_get_change, ctk_css_selector_pseudoclass_position_add_specificity
, hash_pseudoclass_position, comp_pseudoclass_position, (!(0)
) };
903#undef CTK_CSS_CHANGE_PSEUDOCLASS_POSITION
904/* API */
905
906static guint
907ctk_css_selector_size (const CtkCssSelector *selector)
908{
909 guint size = 0;
910
911 while (selector)
912 {
913 selector = ctk_css_selector_previous (selector);
914 size++;
915 }
916
917 return size;
918}
919
920static CtkCssSelector *
921ctk_css_selector_new (const CtkCssSelectorClass *class,
922 CtkCssSelector *selector)
923{
924 guint size;
925
926 size = ctk_css_selector_size (selector);
927 selector = g_realloc (selector, sizeof (CtkCssSelector) * (size + 1) + sizeof (gpointer));
928 if (size == 0)
929 selector[1].class = NULL((void*)0);
930 else
931 memmove (selector + 1, selector, sizeof (CtkCssSelector) * size + sizeof (gpointer));
932
933 memset (selector, 0, sizeof (CtkCssSelector));
934 selector->class = class;
935
936 return selector;
937}
938
939static CtkCssSelector *
940parse_selector_class (CtkCssParser *parser,
941 CtkCssSelector *selector,
942 gboolean negate)
943{
944 char *name;
945
946 name = _ctk_css_parser_try_name (parser, FALSE(0));
947
948 if (name == NULL((void*)0))
949 {
950 _ctk_css_parser_error (parser, "Expected a valid name for class");
951 if (selector)
952 _ctk_css_selector_free (selector);
953 return NULL((void*)0);
954 }
955
956 selector = ctk_css_selector_new (negate ? &CTK_CSS_SELECTOR_NOT_CLASS
957 : &CTK_CSS_SELECTOR_CLASS,
958 selector);
959 selector->style_class.style_class = g_quark_from_string (name);
960
961 g_free (name);
962
963 return selector;
964}
965
966static CtkCssSelector *
967parse_selector_id (CtkCssParser *parser,
968 CtkCssSelector *selector,
969 gboolean negate)
970{
971 char *name;
972
973 name = _ctk_css_parser_try_name (parser, FALSE(0));
974
975 if (name == NULL((void*)0))
976 {
977 _ctk_css_parser_error (parser, "Expected a valid name for id");
978 if (selector)
979 _ctk_css_selector_free (selector);
980 return NULL((void*)0);
981 }
982
983 selector = ctk_css_selector_new (negate ? &CTK_CSS_SELECTOR_NOT_ID
984 : &CTK_CSS_SELECTOR_ID,
985 selector);
986 selector->id.name = g_intern_string (name);
987
988 g_free (name);
989
990 return selector;
991}
992
993static CtkCssSelector *
994parse_selector_pseudo_class_nth_child (CtkCssParser *parser,
995 CtkCssSelector *selector,
996 PositionType type,
997 gboolean negate)
998{
999 int a, b;
1000
1001 if (!_ctk_css_parser_try (parser, "(", TRUE(!(0))))
1002 {
1003 _ctk_css_parser_error (parser, "Missing opening bracket for pseudo-class");
1004 if (selector)
1005 _ctk_css_selector_free (selector);
1006 return NULL((void*)0);
1007 }
1008
1009 if (_ctk_css_parser_try (parser, "even", TRUE(!(0))))
1010 {
1011 a = 2;
1012 b = 0;
1013 }
1014 else if (_ctk_css_parser_try (parser, "odd", TRUE(!(0))))
1015 {
1016 a = 2;
1017 b = 1;
1018 }
1019 else if (type == POSITION_FORWARD &&
1020 _ctk_css_parser_try (parser, "first", TRUE(!(0))))
1021 {
1022 a = 0;
1023 b = 1;
1024 }
1025 else if (type == POSITION_FORWARD &&
1026 _ctk_css_parser_try (parser, "last", TRUE(!(0))))
1027 {
1028 a = 0;
1029 b = 1;
1030 type = POSITION_BACKWARD;
1031 }
1032 else
1033 {
1034 int multiplier;
1035
1036 if (_ctk_css_parser_try (parser, "+", TRUE(!(0))))
1037 multiplier = 1;
1038 else if (_ctk_css_parser_try (parser, "-", TRUE(!(0))))
1039 multiplier = -1;
1040 else
1041 multiplier = 1;
1042
1043 if (_ctk_css_parser_try_int (parser, &a))
1044 {
1045 if (a < 0)
1046 {
1047 _ctk_css_parser_error (parser, "Expected an integer");
1048 if (selector)
1049 _ctk_css_selector_free (selector);
1050 return NULL((void*)0);
1051 }
1052 a *= multiplier;
1053 }
1054 else if (_ctk_css_parser_has_prefix (parser, "n"))
1055 {
1056 a = multiplier;
1057 }
1058 else
1059 {
1060 _ctk_css_parser_error (parser, "Expected an integer");
1061 if (selector)
1062 _ctk_css_selector_free (selector);
1063 return NULL((void*)0);
1064 }
1065
1066 if (_ctk_css_parser_try (parser, "n", TRUE(!(0))))
1067 {
1068 if (_ctk_css_parser_try (parser, "+", TRUE(!(0))))
1069 multiplier = 1;
1070 else if (_ctk_css_parser_try (parser, "-", TRUE(!(0))))
1071 multiplier = -1;
1072 else
1073 multiplier = 1;
1074
1075 if (_ctk_css_parser_try_int (parser, &b))
1076 {
1077 if (b < 0)
1078 {
1079 _ctk_css_parser_error (parser, "Expected an integer");
1080 if (selector)
1081 _ctk_css_selector_free (selector);
1082 return NULL((void*)0);
1083 }
1084 }
1085 else
1086 b = 0;
1087
1088 b *= multiplier;
1089 }
1090 else
1091 {
1092 b = a;
1093 a = 0;
1094 }
1095 }
1096
1097 if (!_ctk_css_parser_try (parser, ")", FALSE(0)))
1098 {
1099 _ctk_css_parser_error (parser, "Missing closing bracket for pseudo-class");
1100 if (selector)
1101 _ctk_css_selector_free (selector);
1102 return NULL((void*)0);
1103 }
1104
1105 selector = ctk_css_selector_new (negate ? &CTK_CSS_SELECTOR_NOT_PSEUDOCLASS_POSITION
1106 : &CTK_CSS_SELECTOR_PSEUDOCLASS_POSITION,
1107 selector);
1108 selector->position.type = type;
1109 selector->position.a = a;
1110 selector->position.b = b;
1111
1112 return selector;
1113}
1114
1115static CtkCssSelector *
1116parse_selector_pseudo_class (CtkCssParser *parser,
1117 CtkCssSelector *selector,
1118 gboolean negate)
1119{
1120 static const struct {
1121 const char *name;
1122 gboolean deprecated;
1123 CtkStateFlags state_flag;
1124 PositionType position_type;
1125 int position_a;
1126 int position_b;
1127 } pseudo_classes[] = {
1128 { .name = "first-child", .deprecated = 0, .state_flag = 0, .position_type = POSITION_FORWARD, .position_a = 0, .position_b = 1 },
1129 { .name = "last-child", .deprecated = 0, .state_flag = 0, .position_type = POSITION_BACKWARD, .position_a = 0, .position_b = 1 },
1130 { .name = "only-child", .deprecated = 0, .state_flag = 0, .position_type = POSITION_ONLY, .position_a = 0, .position_b = 0 },
1131 { .name = "sorted", .deprecated = 1, .state_flag = 0, .position_type = POSITION_SORTED, .position_a = 0, .position_b = 0 },
1132 { .name = "active", .deprecated = 0, .state_flag = CTK_STATE_FLAG_ACTIVE, },
1133 { .name = "prelight", .deprecated = 1, .state_flag = CTK_STATE_FLAG_PRELIGHT, },
1134 { .name = "hover", .deprecated = 0, .state_flag = CTK_STATE_FLAG_PRELIGHT, },
1135 { .name = "selected", .deprecated = 0, .state_flag = CTK_STATE_FLAG_SELECTED, },
1136 { .name = "insensitive", .deprecated = 1, .state_flag = CTK_STATE_FLAG_INSENSITIVE, },
1137 { .name = "disabled", .deprecated = 0, .state_flag = CTK_STATE_FLAG_INSENSITIVE, },
1138 { .name = "inconsistent", .deprecated = 1, .state_flag = CTK_STATE_FLAG_INCONSISTENT, },
1139 { .name = "indeterminate", .deprecated = 0, .state_flag = CTK_STATE_FLAG_INCONSISTENT, },
1140 { .name = "focused", .deprecated = 1, .state_flag = CTK_STATE_FLAG_FOCUSED, },
1141 { .name = "focus", .deprecated = 0, .state_flag = CTK_STATE_FLAG_FOCUSED, },
1142 { .name = "backdrop", .deprecated = 0, .state_flag = CTK_STATE_FLAG_BACKDROP, },
1143 { .name = "dir(ltr)", .deprecated = 0, .state_flag = CTK_STATE_FLAG_DIR_LTR, },
1144 { .name = "dir(rtl)", .deprecated = 0, .state_flag = CTK_STATE_FLAG_DIR_RTL, },
1145 { .name = "link", .deprecated = 0, .state_flag = CTK_STATE_FLAG_LINK, },
1146 { .name = "visited", .deprecated = 0, .state_flag = CTK_STATE_FLAG_VISITED, },
1147 { .name = "checked", .deprecated = 0, .state_flag = CTK_STATE_FLAG_CHECKED, },
1148 { .name = "drop(active)", .deprecated = 0, .state_flag = CTK_STATE_FLAG_DROP_ACTIVE, }
1149 };
1150
1151 guint i;
1152
1153 if (_ctk_css_parser_try (parser, "nth-child", FALSE(0)))
1154 return parse_selector_pseudo_class_nth_child (parser, selector, POSITION_FORWARD, negate);
1155 else if (_ctk_css_parser_try (parser, "nth-last-child", FALSE(0)))
1156 return parse_selector_pseudo_class_nth_child (parser, selector, POSITION_BACKWARD, negate);
1157
1158 for (i = 0; i < G_N_ELEMENTS (pseudo_classes)(sizeof (pseudo_classes) / sizeof ((pseudo_classes)[0])); i++)
1159 {
1160 if (_ctk_css_parser_try (parser, pseudo_classes[i].name, FALSE(0)))
1161 {
1162 if (pseudo_classes[i].state_flag)
1163 {
1164 selector = ctk_css_selector_new (negate ? &CTK_CSS_SELECTOR_NOT_PSEUDOCLASS_STATE
1165 : &CTK_CSS_SELECTOR_PSEUDOCLASS_STATE,
1166 selector);
1167 selector->state.state = pseudo_classes[i].state_flag;
1168 if (pseudo_classes[i].deprecated)
1169 {
1170 if (i + 1 < G_N_ELEMENTS (pseudo_classes)(sizeof (pseudo_classes) / sizeof ((pseudo_classes)[0])) &&
1171 pseudo_classes[i + 1].state_flag == pseudo_classes[i].state_flag)
1172 _ctk_css_parser_error_full (parser,
1173 CTK_CSS_PROVIDER_ERROR_DEPRECATED,
1174 "The :%s pseudo-class is deprecated. Use :%s instead.",
1175 pseudo_classes[i].name,
1176 pseudo_classes[i + 1].name);
1177 else
1178 _ctk_css_parser_error_full (parser,
1179 CTK_CSS_PROVIDER_ERROR_DEPRECATED,
1180 "The :%s pseudo-class is deprecated.",
1181 pseudo_classes[i].name);
1182 }
1183 }
1184 else
1185 {
1186 selector = ctk_css_selector_new (negate ? &CTK_CSS_SELECTOR_NOT_PSEUDOCLASS_POSITION
1187 : &CTK_CSS_SELECTOR_PSEUDOCLASS_POSITION,
1188 selector);
1189 selector->position.type = pseudo_classes[i].position_type;
1190 selector->position.a = pseudo_classes[i].position_a;
1191 selector->position.b = pseudo_classes[i].position_b;
1192 }
1193 return selector;
1194 }
1195 }
1196
1197 _ctk_css_parser_error (parser, "Invalid name of pseudo-class");
1198 if (selector)
1199 _ctk_css_selector_free (selector);
1200 return NULL((void*)0);
1201}
1202
1203static CtkCssSelector *
1204parse_selector_negation (CtkCssParser *parser,
1205 CtkCssSelector *selector)
1206{
1207 char *name;
1208
1209 name = _ctk_css_parser_try_ident (parser, FALSE(0));
1210 if (name)
1211 {
1212 selector = ctk_css_selector_new (&CTK_CSS_SELECTOR_NOT_NAME,
1213 selector);
1214 selector->name.name = g_intern_string (name);
1215 g_free (name);
1216 }
1217 else if (_ctk_css_parser_try (parser, "*", FALSE(0)))
1218 selector = ctk_css_selector_new (&CTK_CSS_SELECTOR_NOT_ANY, selector);
1219 else if (_ctk_css_parser_try (parser, "#", FALSE(0)))
1220 selector = parse_selector_id (parser, selector, TRUE(!(0)));
1221 else if (_ctk_css_parser_try (parser, ".", FALSE(0)))
1222 selector = parse_selector_class (parser, selector, TRUE(!(0)));
1223 else if (_ctk_css_parser_try (parser, ":", FALSE(0)))
1224 selector = parse_selector_pseudo_class (parser, selector, TRUE(!(0)));
1225 else
1226 {
1227 _ctk_css_parser_error (parser, "Not a valid selector for :not()");
1228 if (selector)
1229 _ctk_css_selector_free (selector);
1230 return NULL((void*)0);
1231 }
1232
1233 _ctk_css_parser_skip_whitespace (parser);
1234
1235 if (!_ctk_css_parser_try (parser, ")", FALSE(0)))
1236 {
1237 _ctk_css_parser_error (parser, "Missing closing bracket for :not()");
1238 if (selector)
1239 _ctk_css_selector_free (selector);
1240 return NULL((void*)0);
1241 }
1242
1243 return selector;
1244}
1245
1246static CtkCssSelector *
1247parse_simple_selector (CtkCssParser *parser,
1248 CtkCssSelector *selector)
1249{
1250 gboolean parsed_something = FALSE(0);
1251 char *name;
1252
1253 name = _ctk_css_parser_try_ident (parser, FALSE(0));
1254 if (name)
1255 {
1256 selector = ctk_css_selector_new (&CTK_CSS_SELECTOR_NAME,
1257 selector);
1258 selector->name.name = g_intern_string (name);
1259 g_free (name);
1260 parsed_something = TRUE(!(0));
1261 }
1262 else if (_ctk_css_parser_try (parser, "*", FALSE(0)))
1263 {
1264 selector = ctk_css_selector_new (&CTK_CSS_SELECTOR_ANY, selector);
1265 parsed_something = TRUE(!(0));
1266 }
1267
1268 do {
1269 if (_ctk_css_parser_try (parser, "#", FALSE(0)))
1270 selector = parse_selector_id (parser, selector, FALSE(0));
1271 else if (_ctk_css_parser_try (parser, ".", FALSE(0)))
1272 selector = parse_selector_class (parser, selector, FALSE(0));
1273 else if (_ctk_css_parser_try (parser, ":not(", TRUE(!(0))))
1274 selector = parse_selector_negation (parser, selector);
1275 else if (_ctk_css_parser_try (parser, ":", FALSE(0)))
1276 selector = parse_selector_pseudo_class (parser, selector, FALSE(0));
1277 else if (!parsed_something)
1278 {
1279 _ctk_css_parser_error (parser, "Expected a valid selector");
1280 if (selector)
1281 _ctk_css_selector_free (selector);
1282 return NULL((void*)0);
1283 }
1284 else
1285 break;
1286
1287 parsed_something = TRUE(!(0));
1288 }
1289 while (selector && !_ctk_css_parser_is_eof (parser));
1290
1291 _ctk_css_parser_skip_whitespace (parser);
1292
1293 return selector;
1294}
1295
1296CtkCssSelector *
1297_ctk_css_selector_parse (CtkCssParser *parser)
1298{
1299 CtkCssSelector *selector = NULL((void*)0);
1300
1301 while ((selector = parse_simple_selector (parser, selector)) &&
1302 !_ctk_css_parser_is_eof (parser) &&
1303 !_ctk_css_parser_begins_with (parser, ',') &&
1304 !_ctk_css_parser_begins_with (parser, '{'))
1305 {
1306 if (_ctk_css_parser_try (parser, "+", TRUE(!(0))))
1307 selector = ctk_css_selector_new (&CTK_CSS_SELECTOR_ADJACENT, selector);
1308 else if (_ctk_css_parser_try (parser, "~", TRUE(!(0))))
1309 selector = ctk_css_selector_new (&CTK_CSS_SELECTOR_SIBLING, selector);
1310 else if (_ctk_css_parser_try (parser, ">", TRUE(!(0))))
1311 selector = ctk_css_selector_new (&CTK_CSS_SELECTOR_CHILD, selector);
1312 else
1313 selector = ctk_css_selector_new (&CTK_CSS_SELECTOR_DESCENDANT, selector);
1314 }
1315
1316 return selector;
1317}
1318
1319void
1320_ctk_css_selector_free (CtkCssSelector *selector)
1321{
1322 g_return_if_fail (selector != NULL)do { if ((selector != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "selector != NULL"); return
; } } while (0)
;
1323
1324 g_free (selector);
1325}
1326
1327void
1328_ctk_css_selector_print (const CtkCssSelector *selector,
1329 GString * str)
1330{
1331 const CtkCssSelector *previous;
1332
1333 g_return_if_fail (selector != NULL)do { if ((selector != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "selector != NULL"); return
; } } while (0)
;
1334
1335 previous = ctk_css_selector_previous (selector);
1336 if (previous)
1337 _ctk_css_selector_print (previous, str);
1338
1339 selector->class->print (selector, str);
1340}
1341
1342char *
1343_ctk_css_selector_to_string (const CtkCssSelector *selector)
1344{
1345 GString *string;
1346
1347 g_return_val_if_fail (selector != NULL, NULL)do { if ((selector != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "selector != NULL"); return
(((void*)0)); } } while (0)
;
1348
1349 string = g_string_new (NULL((void*)0));
1350
1351 _ctk_css_selector_print (selector, string);
1352
1353 return g_string_free (string, FALSE)(__builtin_constant_p ((0)) ? (((0)) ? (g_string_free) ((string
), ((0))) : g_string_free_and_steal (string)) : (g_string_free
) ((string), ((0))))
;
1354}
1355
1356static gboolean
1357ctk_css_selector_foreach_match (const CtkCssSelector *selector,
1358 const CtkCssMatcher *matcher,
1359 gpointer unused G_GNUC_UNUSED__attribute__ ((__unused__)))
1360{
1361 selector = ctk_css_selector_previous (selector);
1362
1363 if (selector == NULL((void*)0))
1364 return TRUE(!(0));
1365
1366 if (!ctk_css_selector_match (selector, matcher))
1367 return FALSE(0);
1368
1369 return ctk_css_selector_foreach (selector, matcher, ctk_css_selector_foreach_match, NULL((void*)0));
1370}
1371
1372/**
1373 * _ctk_css_selector_matches:
1374 * @selector: the selector
1375 * @path: the path to check
1376 * @state: The state to match
1377 *
1378 * Checks if the @selector matches the given @path. If @length is
1379 * smaller than the number of elements in @path, it is assumed that
1380 * only the first @length element of @path are valid and the rest
1381 * does not exist. This is useful for doing parent matches for the
1382 * 'inherit' keyword.
1383 *
1384 * Returns: %TRUE if the selector matches @path
1385 **/
1386gboolean
1387_ctk_css_selector_matches (const CtkCssSelector *selector,
1388 const CtkCssMatcher *matcher)
1389{
1390
1391 g_return_val_if_fail (selector != NULL, FALSE)do { if ((selector != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "selector != NULL"); return
((0)); } } while (0)
;
1392 g_return_val_if_fail (matcher != NULL, FALSE)do { if ((matcher != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "matcher != NULL"); return
((0)); } } while (0)
;
1393
1394 if (!ctk_css_selector_match (selector, matcher))
1395 return FALSE(0);
1396
1397 return ctk_css_selector_foreach (selector, matcher, ctk_css_selector_foreach_match, NULL((void*)0));
1398}
1399
1400/* Computes specificity according to CSS 2.1.
1401 * The arguments must be initialized to 0 */
1402static void
1403_ctk_css_selector_get_specificity (const CtkCssSelector *selector,
1404 guint *ids,
1405 guint *classes,
1406 guint *elements)
1407{
1408 for (; selector; selector = ctk_css_selector_previous (selector))
1409 {
1410 selector->class->add_specificity (selector, ids, classes, elements);
1411 }
1412}
1413
1414int
1415_ctk_css_selector_compare (const CtkCssSelector *a,
1416 const CtkCssSelector *b)
1417{
1418 guint a_ids = 0, a_classes = 0, a_elements = 0;
1419 guint b_ids = 0, b_classes = 0, b_elements = 0;
1420 int compare;
1421
1422 _ctk_css_selector_get_specificity (a, &a_ids, &a_classes, &a_elements);
1423 _ctk_css_selector_get_specificity (b, &b_ids, &b_classes, &b_elements);
1424
1425 compare = a_ids - b_ids;
1426 if (compare)
1427 return compare;
1428
1429 compare = a_classes - b_classes;
1430 if (compare)
1431 return compare;
1432
1433 return a_elements - b_elements;
1434}
1435
1436CtkCssChange
1437_ctk_css_selector_get_change (const CtkCssSelector *selector)
1438{
1439 if (selector == NULL((void*)0))
1440 return 0;
1441
1442 return selector->class->get_change (selector, _ctk_css_selector_get_change (ctk_css_selector_previous (selector)));
1443}
1444
1445/******************** SelectorTree handling *****************/
1446
1447static GHashTable *
1448ctk_css_selectors_count_initial_init (void)
1449{
1450 return g_hash_table_new ((GHashFunc)ctk_css_selector_hash_one, (GEqualFunc)ctk_css_selector_equal);
1451}
1452
1453static void
1454ctk_css_selectors_count_initial (const CtkCssSelector *selector, GHashTable *hash_one)
1455{
1456 if (!selector->class->is_simple)
1457 {
1458 guint count = GPOINTER_TO_INT (g_hash_table_lookup (hash_one, selector))((gint) (glong) (g_hash_table_lookup (hash_one, selector)));
1459 g_hash_table_replace (hash_one, (gpointer)selector, GUINT_TO_POINTER (count + 1)((gpointer) (gulong) (count + 1)));
1460 return;
1461 }
1462
1463 for (;
1464 selector && selector->class->is_simple;
1465 selector = ctk_css_selector_previous (selector))
1466 {
1467 guint count = GPOINTER_TO_INT (g_hash_table_lookup (hash_one, selector))((gint) (glong) (g_hash_table_lookup (hash_one, selector)));
1468 g_hash_table_replace (hash_one, (gpointer)selector, GUINT_TO_POINTER (count + 1)((gpointer) (gulong) (count + 1)));
1469 }
1470}
1471
1472static gboolean
1473ctk_css_selectors_has_initial_selector (const CtkCssSelector *selector, const CtkCssSelector *initial)
1474{
1475 if (!selector->class->is_simple)
1476 return ctk_css_selector_equal (selector, initial);
1477
1478 for (;
1479 selector && selector->class->is_simple;
1480 selector = ctk_css_selector_previous (selector))
1481 {
1482 if (ctk_css_selector_equal (selector, initial))
1483 return TRUE(!(0));
1484 }
1485
1486 return FALSE(0);
1487}
1488
1489static CtkCssSelector *
1490ctk_css_selectors_skip_initial_selector (CtkCssSelector *selector, const CtkCssSelector *initial)
1491{
1492 CtkCssSelector *found;
1493 CtkCssSelector tmp;
1494
1495 /* If the initial simple selector is not first, move it there so we can skip it
1496 without losing any other selectors */
1497 if (!ctk_css_selector_equal (selector, initial))
1498 {
1499 for (found = selector; found && found->class->is_simple; found = (CtkCssSelector *)ctk_css_selector_previous (found))
1500 {
1501 if (ctk_css_selector_equal (found, initial))
1502 break;
1503 }
1504
1505 g_assert (found != NULL && found->class->is_simple)do { if (found != ((void*)0) && found->class->is_simple
) ; else g_assertion_message_expr ("Ctk", "ctkcssselector.c",
1505, ((const char*) (__func__)), "found != NULL && found->class->is_simple"
); } while (0)
;
1506
1507 tmp = *found;
1508 *found = *selector;
1509 *selector = tmp;
1510 }
1511
1512 return (CtkCssSelector *)ctk_css_selector_previous (selector);
1513}
1514
1515static gboolean
1516ctk_css_selector_tree_match_foreach (const CtkCssSelector *selector,
1517 const CtkCssMatcher *matcher,
1518 gpointer res)
1519{
1520 const CtkCssSelectorTree *tree = (const CtkCssSelectorTree *) selector;
1521 const CtkCssSelectorTree *prev;
1522
1523 if (!ctk_css_selector_match (selector, matcher))
1524 return FALSE(0);
1525
1526 ctk_css_selector_tree_found_match (tree, res);
1527
1528 for (prev = ctk_css_selector_tree_get_previous (tree);
1529 prev != NULL((void*)0);
1530 prev = ctk_css_selector_tree_get_sibling (prev))
1531 ctk_css_selector_foreach (&prev->selector, matcher, ctk_css_selector_tree_match_foreach, res);
1532
1533 return FALSE(0);
1534}
1535
1536GPtrArray *
1537_ctk_css_selector_tree_match_all (const CtkCssSelectorTree *tree,
1538 const CtkCssMatcher *matcher)
1539{
1540 GPtrArray *array = NULL((void*)0);
1541
1542 for (; tree != NULL((void*)0);
1543 tree = ctk_css_selector_tree_get_sibling (tree))
1544 ctk_css_selector_foreach (&tree->selector, matcher, ctk_css_selector_tree_match_foreach, &array);
1545
1546 return array;
1547}
1548
1549/* When checking for changes via the tree we need to know if a rule further
1550 down the tree matched, because if so we need to add "our bit" to the
1551 Change. For instance in a a match like *.class:active we'll
1552 get a tree that first checks :active, if that matches we continue down
1553 to the tree, and if we get a match we add CHANGE_CLASS. However, the
1554 end of the tree where we have a match is an ANY which doesn't actually
1555 modify the change, so we don't know if we have a match or not. We fix
1556 this by setting CTK_CSS_CHANGE_GOT_MATCH which lets us guarantee
1557 that change != 0 on any match. */
1558#define CTK_CSS_CHANGE_GOT_MATCH(1ULL << 62) CTK_CSS_CHANGE_RESERVED_BIT(1ULL << 62)
1559
1560static CtkCssChange
1561ctk_css_selector_tree_collect_change (const CtkCssSelectorTree *tree)
1562{
1563 CtkCssChange change = 0;
1564 const CtkCssSelectorTree *prev;
1565
1566 for (prev = ctk_css_selector_tree_get_previous (tree);
1567 prev != NULL((void*)0);
1568 prev = ctk_css_selector_tree_get_sibling (prev))
1569 change |= ctk_css_selector_tree_collect_change (prev);
1570
1571 change = tree->selector.class->get_change (&tree->selector, change);
1572
1573 return change;
1574}
1575
1576static CtkCssChange
1577ctk_css_selector_tree_get_change (const CtkCssSelectorTree *tree,
1578 const CtkCssMatcher *matcher)
1579{
1580 CtkCssChange change = 0;
1581 const CtkCssSelectorTree *prev;
1582
1583 if (!ctk_css_selector_match (&tree->selector, matcher))
1584 return 0;
1585
1586 if (!tree->selector.class->is_simple)
1587 return ctk_css_selector_tree_collect_change (tree) | CTK_CSS_CHANGE_GOT_MATCH(1ULL << 62);
1588
1589 for (prev = ctk_css_selector_tree_get_previous (tree);
1590 prev != NULL((void*)0);
1591 prev = ctk_css_selector_tree_get_sibling (prev))
1592 change |= ctk_css_selector_tree_get_change (prev, matcher);
1593
1594 if (change || ctk_css_selector_tree_get_matches (tree))
1595 change = tree->selector.class->get_change (&tree->selector, change & ~CTK_CSS_CHANGE_GOT_MATCH(1ULL << 62)) | CTK_CSS_CHANGE_GOT_MATCH(1ULL << 62);
1596
1597 return change;
1598}
1599
1600CtkCssChange
1601_ctk_css_selector_tree_get_change_all (const CtkCssSelectorTree *tree,
1602 const CtkCssMatcher *matcher)
1603{
1604 CtkCssChange change;
1605
1606 change = 0;
1607
1608 /* no need to foreach here because we abort for non-simple selectors */
1609 for (; tree != NULL((void*)0);
1610 tree = ctk_css_selector_tree_get_sibling (tree))
1611 change |= ctk_css_selector_tree_get_change (tree, matcher);
1612
1613 /* Never return reserved bit set */
1614 return change & ~CTK_CSS_CHANGE_RESERVED_BIT(1ULL << 62);
1615}
1616
1617#ifdef PRINT_TREE
1618static void
1619_ctk_css_selector_tree_print (const CtkCssSelectorTree *tree, GString *str, char *prefix)
1620{
1621 gboolean first = TRUE(!(0));
1622 int len, i;
1623
1624 for (; tree != NULL((void*)0); tree = ctk_css_selector_tree_get_sibling (tree), first = FALSE(0))
1625 {
1626 if (!first)
1627 g_string_append (str, prefix)(__builtin_constant_p (prefix) ? __extension__ ({ const char *
const __val = (prefix); g_string_append_len_inline (str, __val
, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !(__val
))) : (gssize) -1); }) : g_string_append_len_inline (str, prefix
, (gssize) -1))
;
1628
1629 if (first)
1630 {
1631 if (ctk_css_selector_tree_get_sibling (tree))
1632 g_string_append (str, "─┬─")(__builtin_constant_p ("─┬─") ? __extension__ ({ const char
* const __val = ("─┬─"); g_string_append_len_inline (str
, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !
(__val))) : (gssize) -1); }) : g_string_append_len_inline (str
, "─┬─", (gssize) -1))
;
1633 else
1634 g_string_append (str, "───")(__builtin_constant_p ("───") ? __extension__ ({ const char
* const __val = ("───"); g_string_append_len_inline (str
, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !
(__val))) : (gssize) -1); }) : g_string_append_len_inline (str
, "───", (gssize) -1))
;
1635 }
1636 else
1637 {
1638 if (ctk_css_selector_tree_get_sibling (tree))
1639 g_string_append (str, " ├─")(__builtin_constant_p (" ├─") ? __extension__ ({ const char
* const __val = (" ├─"); g_string_append_len_inline (str
, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !
(__val))) : (gssize) -1); }) : g_string_append_len_inline (str
, " ├─", (gssize) -1))
;
1640 else
1641 g_string_append (str, " └─")(__builtin_constant_p (" └─") ? __extension__ ({ const char
* const __val = (" └─"); g_string_append_len_inline (str
, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !
(__val))) : (gssize) -1); }) : g_string_append_len_inline (str
, " └─", (gssize) -1))
;
1642 }
1643
1644 len = str->len;
1645 tree->selector.class->print (&tree->selector, str);
1646 len = str->len - len;
1647
1648 if (ctk_css_selector_tree_get_previous (tree))
1649 {
1650 GString *prefix2 = g_string_new (prefix);
1651
1652 if (ctk_css_selector_tree_get_sibling (tree))
1653 g_string_append (prefix2, " │ ")(__builtin_constant_p (" │ ") ? __extension__ ({ const char
* const __val = (" │ "); g_string_append_len_inline (prefix2
, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !
(__val))) : (gssize) -1); }) : g_string_append_len_inline (prefix2
, " │ ", (gssize) -1))
;
1654 else
1655 g_string_append (prefix2, " ")(__builtin_constant_p (" ") ? __extension__ ({ const char *
const __val = (" "); g_string_append_len_inline (prefix2, __val
, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !(__val
))) : (gssize) -1); }) : g_string_append_len_inline (prefix2,
" ", (gssize) -1))
;
1656 for (i = 0; i < len; i++)
1657 g_string_append_c (prefix2, ' ')g_string_append_c_inline (prefix2, ' ');
1658
1659 _ctk_css_selector_tree_print (ctk_css_selector_tree_get_previous (tree), str, prefix2->str);
1660 g_string_free (prefix2, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(prefix2), ((!(0)))) : g_string_free_and_steal (prefix2)) : (
g_string_free) ((prefix2), ((!(0)))))
;
1661 }
1662 else
1663 g_string_append (str, "\n")(__builtin_constant_p ("\n") ? __extension__ ({ const char * const
__val = ("\n"); g_string_append_len_inline (str, __val, (__val
!= ((void*)0)) ? (gssize) strlen (((__val) + !(__val))) : (gssize
) -1); }) : g_string_append_len_inline (str, "\n", (gssize) -
1))
;
1664 }
1665}
1666#endif
1667
1668void
1669_ctk_css_selector_tree_match_print (const CtkCssSelectorTree *tree,
1670 GString *str)
1671{
1672 const CtkCssSelectorTree *iter;
1673
1674 g_return_if_fail (tree != NULL)do { if ((tree != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "tree != NULL"); return;
} } while (0)
;
1675
1676 /* print name and * selector before others */
1677 for (iter = tree;
1678 iter && iter->selector.class->is_simple;
1679 iter = ctk_css_selector_tree_get_parent (iter))
1680 {
1681 if (iter->selector.class == &CTK_CSS_SELECTOR_NAME ||
1682 iter->selector.class == &CTK_CSS_SELECTOR_ANY)
1683 {
1684 iter->selector.class->print (&iter->selector, str);
1685 }
1686 }
1687 /* now print other simple selectors */
1688 for (iter = tree;
1689 iter && iter->selector.class->is_simple;
1690 iter = ctk_css_selector_tree_get_parent (iter))
1691 {
1692 if (iter->selector.class != &CTK_CSS_SELECTOR_NAME &&
1693 iter->selector.class != &CTK_CSS_SELECTOR_ANY)
1694 {
1695 iter->selector.class->print (&iter->selector, str);
1696 }
1697 }
1698
1699 /* now if there's a combinator, print that one */
1700 if (iter != NULL((void*)0))
1701 {
1702 iter->selector.class->print (&iter->selector, str);
1703 tree = ctk_css_selector_tree_get_parent (iter);
1704 if (tree)
1705 _ctk_css_selector_tree_match_print (tree, str);
1706 }
1707}
1708
1709void
1710_ctk_css_selector_tree_free (CtkCssSelectorTree *tree)
1711{
1712 if (tree == NULL((void*)0))
1713 return;
1714
1715 g_free (tree);
1716}
1717
1718
1719typedef struct {
1720 gpointer match;
1721 CtkCssSelector *current_selector;
1722 CtkCssSelectorTree **selector_match;
1723} CtkCssSelectorRuleSetInfo;
1724
1725static CtkCssSelectorTree *
1726get_tree (GByteArray *array, gint32 offset)
1727{
1728 return (CtkCssSelectorTree *) (array->data + offset);
1729}
1730
1731static CtkCssSelectorTree *
1732alloc_tree (GByteArray *array, gint32 *offset)
1733{
1734 CtkCssSelectorTree tree = { .selector = { NULL((void*)0) } };
1735
1736 *offset = array->len;
1737 g_byte_array_append (array, (guint8 *)&tree, sizeof (CtkCssSelectorTree));
1738 return get_tree (array, *offset);
1739}
1740
1741static gint32
1742subdivide_infos (GByteArray *array, GList *infos, gint32 parent_offset)
1743{
1744 GHashTable *ht;
1745 GList *l;
1746 GList *matched;
1747 GList *remaining;
1748 gint32 tree_offset;
1749 CtkCssSelectorTree *tree;
1750 CtkCssSelectorRuleSetInfo *info;
1751 CtkCssSelector max_selector;
1752 GHashTableIter iter;
1753 guint max_count;
1754 gpointer key, value;
1755 GPtrArray *exact_matches;
1756 gint32 res;
1757
1758 if (infos == NULL((void*)0))
1759 return CTK_CSS_SELECTOR_TREE_EMPTY_OFFSET((gint32) 0x7fffffff);
1760
1761 ht = ctk_css_selectors_count_initial_init ();
1762
1763 for (l = infos; l != NULL((void*)0); l = l->next)
1764 {
1765 info = l->data;
1766 ctk_css_selectors_count_initial (info->current_selector, ht);
1767 }
1768
1769 /* Pick the selector with highest count, and use as decision on this level
1770 as that makes it possible to skip the largest amount of checks later */
1771
1772 max_count = 0;
1773
1774 g_hash_table_iter_init (&iter, ht);
1775 while (g_hash_table_iter_next (&iter, &key, &value))
1776 {
1777 CtkCssSelector *selector = key;
1778 if (GPOINTER_TO_UINT (value)((guint) (gulong) (value)) > max_count ||
1779 (GPOINTER_TO_UINT (value)((guint) (gulong) (value)) == max_count &&
1780 ctk_css_selector_compare_one (selector, &max_selector) < 0))
1781 {
1782 max_count = GPOINTER_TO_UINT (value)((guint) (gulong) (value));
1783 max_selector = *selector;
1784 }
1785 }
1786
1787 matched = NULL((void*)0);
1788 remaining = NULL((void*)0);
1789
1790 tree = alloc_tree (array, &tree_offset);
1791 tree->parent_offset = parent_offset;
1792 tree->selector = max_selector;
1793
1794 exact_matches = NULL((void*)0);
1795 for (l = infos; l != NULL((void*)0); l = l->next)
1796 {
1797 info = l->data;
1798
1799 if (ctk_css_selectors_has_initial_selector (info->current_selector, &max_selector))
1800 {
1801 info->current_selector = ctk_css_selectors_skip_initial_selector (info->current_selector, &max_selector);
1802 if (info->current_selector == NULL((void*)0))
1803 {
1804 /* Matches current node */
1805 if (exact_matches == NULL((void*)0))
1806 exact_matches = g_ptr_array_new ();
1807 g_ptr_array_add (exact_matches, info->match);
1808 if (info->selector_match != NULL((void*)0))
1809 *info->selector_match = GUINT_TO_POINTER (tree_offset)((gpointer) (gulong) (tree_offset));
1810 }
1811 else
1812 matched = g_list_prepend (matched, info);
1813 }
1814 else
1815 {
1816 remaining = g_list_prepend (remaining, info);
1817 }
1818 }
1819
1820 if (exact_matches)
1821 {
1822 g_ptr_array_add (exact_matches, NULL((void*)0)); /* Null terminate */
1823 res = array->len;
1824 g_byte_array_append (array, (guint8 *)exact_matches->pdata,
1825 exact_matches->len * sizeof (gpointer));
1826 g_ptr_array_free (exact_matches, TRUE(!(0)));
1827 }
1828 else
1829 res = CTK_CSS_SELECTOR_TREE_EMPTY_OFFSET((gint32) 0x7fffffff);
1830 get_tree (array, tree_offset)->matches_offset = res;
1831
1832 res = subdivide_infos (array, matched, tree_offset);
1833 get_tree (array, tree_offset)->previous_offset = res;
1834
1835 res = subdivide_infos (array, remaining, parent_offset);
1836 get_tree (array, tree_offset)->sibling_offset = res;
1837
1838 g_list_free (matched);
1839 g_list_free (remaining);
1840 g_hash_table_unref (ht);
1841
1842 return tree_offset;
1843}
1844
1845struct _CtkCssSelectorTreeBuilder {
1846 GList *infos;
1847};
1848
1849CtkCssSelectorTreeBuilder *
1850_ctk_css_selector_tree_builder_new (void)
1851{
1852 return g_new0 (CtkCssSelectorTreeBuilder, 1)((CtkCssSelectorTreeBuilder *) g_malloc0_n ((1), sizeof (CtkCssSelectorTreeBuilder
)))
;
1853}
1854
1855void
1856_ctk_css_selector_tree_builder_free (CtkCssSelectorTreeBuilder *builder)
1857{
1858 g_list_free_full (builder->infos, g_free);
1859 g_free (builder);
1860}
1861
1862void
1863_ctk_css_selector_tree_builder_add (CtkCssSelectorTreeBuilder *builder,
1864 CtkCssSelector *selectors,
1865 CtkCssSelectorTree **selector_match,
1866 gpointer match)
1867{
1868 CtkCssSelectorRuleSetInfo *info = g_new0 (CtkCssSelectorRuleSetInfo, 1)((CtkCssSelectorRuleSetInfo *) g_malloc0_n ((1), sizeof (CtkCssSelectorRuleSetInfo
)))
;
1869
1870 info->match = match;
1871 info->current_selector = selectors;
1872 info->selector_match = selector_match;
1873 builder->infos = g_list_prepend (builder->infos, info);
1874}
1875
1876/* Convert all offsets to node-relative */
1877static void
1878fixup_offsets (CtkCssSelectorTree *tree, guint8 *data)
1879{
1880 while (tree != NULL((void*)0))
1881 {
1882 if (tree->parent_offset != CTK_CSS_SELECTOR_TREE_EMPTY_OFFSET((gint32) 0x7fffffff))
1883 tree->parent_offset -= ((guint8 *)tree - data);
1884
1885 if (tree->previous_offset != CTK_CSS_SELECTOR_TREE_EMPTY_OFFSET((gint32) 0x7fffffff))
1886 tree->previous_offset -= ((guint8 *)tree - data);
1887
1888 if (tree->sibling_offset != CTK_CSS_SELECTOR_TREE_EMPTY_OFFSET((gint32) 0x7fffffff))
1889 tree->sibling_offset -= ((guint8 *)tree - data);
1890
1891 if (tree->matches_offset != CTK_CSS_SELECTOR_TREE_EMPTY_OFFSET((gint32) 0x7fffffff))
1892 tree->matches_offset -= ((guint8 *)tree - data);
1893
1894 fixup_offsets ((CtkCssSelectorTree *)ctk_css_selector_tree_get_previous (tree), data);
1895
1896 tree = (CtkCssSelectorTree *)ctk_css_selector_tree_get_sibling (tree);
1897 }
1898}
1899
1900CtkCssSelectorTree *
1901_ctk_css_selector_tree_builder_build (CtkCssSelectorTreeBuilder *builder)
1902{
1903 CtkCssSelectorTree *tree;
1904 GByteArray *array;
1905 guint8 *data;
1906 guint len;
1907 GList *l;
1908 CtkCssSelectorRuleSetInfo *info;
1909
1910 array = g_byte_array_new ();
1911 subdivide_infos (array, builder->infos, CTK_CSS_SELECTOR_TREE_EMPTY_OFFSET((gint32) 0x7fffffff));
1912
1913 len = array->len;
1914 data = g_byte_array_free (array, FALSE(0));
1915
1916 /* shrink to final size */
1917 data = g_realloc (data, len);
1918
1919 tree = (CtkCssSelectorTree *)data;
1920
1921 fixup_offsets (tree, data);
1922
1923 /* Convert offsets to final pointers */
1924 for (l = builder->infos; l != NULL((void*)0); l = l->next)
1925 {
1926 info = l->data;
1927 if (info->selector_match)
1928 *info->selector_match = (CtkCssSelectorTree *)(data + GPOINTER_TO_UINT (*info->selector_match)((guint) (gulong) (*info->selector_match)));
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption
1929 }
1930
1931#ifdef PRINT_TREE
1932 {
1933 GString *s = g_string_new ("");
1934 _ctk_css_selector_tree_print (tree, s, "");
1935 g_print ("%s", s->str);
1936 g_string_free (s, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(s), ((!(0)))) : g_string_free_and_steal (s)) : (g_string_free
) ((s), ((!(0)))))
;
1937 }
1938#endif
1939
1940 return tree;
1941}