Bug Summary

File:ctk/ctkcssprovider.c
Warning:line 1844, column 7
Value stored to 'length' is never read

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 ctkcssprovider.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-172619-43637-1 -x c ctkcssprovider.c
1/* CTK - The GIMP Toolkit
2 * Copyright (C) 2010 Carlos Garnacho <carlosg@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 <string.h>
21#include <stdlib.h>
22
23#include <gdk-pixbuf/gdk-pixbuf.h>
24#include <cairo-gobject.h>
25
26#include "ctkcssproviderprivate.h"
27
28#include "ctkbitmaskprivate.h"
29#include "ctkcssarrayvalueprivate.h"
30#include "ctkcsscolorvalueprivate.h"
31#include "ctkcsskeyframesprivate.h"
32#include "ctkcssparserprivate.h"
33#include "ctkcsssectionprivate.h"
34#include "ctkcssselectorprivate.h"
35#include "ctkcssshorthandpropertyprivate.h"
36#include "ctkcssstylefuncsprivate.h"
37#include "ctksettingsprivate.h"
38#include "ctkstyleprovider.h"
39#include "ctkstylecontextprivate.h"
40#include "ctkstylepropertyprivate.h"
41#include "ctkstyleproviderprivate.h"
42#include "ctkwidgetpath.h"
43#include "ctkbindings.h"
44#include "ctkmarshalers.h"
45#include "ctkprivate.h"
46#include "ctkintl.h"
47#include "ctkutilsprivate.h"
48#include "ctkversion.h"
49
50/**
51 * SECTION:ctkcssprovider
52 * @Short_description: CSS-like styling for widgets
53 * @Title: CtkCssProvider
54 * @See_also: #CtkStyleContext, #CtkStyleProvider
55 *
56 * CtkCssProvider is an object implementing the #CtkStyleProvider interface.
57 * It is able to parse [CSS-like][css-overview] input in order to style widgets.
58 *
59 * An application can make CTK+ parse a specific CSS style sheet by calling
60 * ctk_css_provider_load_from_file() or ctk_css_provider_load_from_resource()
61 * and adding the provider with ctk_style_context_add_provider() or
62 * ctk_style_context_add_provider_for_screen().
63
64 * In addition, certain files will be read when CTK+ is initialized. First, the
65 * file `$XDG_CONFIG_HOME/ctk-3.0/ctk.css` is loaded if it exists. Then, CTK+
66 * loads the first existing file among
67 * `XDG_DATA_HOME/themes/THEME/ctk-VERSION/ctk.css`,
68 * `$HOME/.themes/THEME/ctk-VERSION/ctk.css`,
69 * `$XDG_DATA_DIRS/themes/THEME/ctk-VERSION/ctk.css` and
70 * `DATADIR/share/themes/THEME/ctk-VERSION/ctk.css`, where `THEME` is the name of
71 * the current theme (see the #CtkSettings:ctk-theme-name setting), `DATADIR`
72 * is the prefix configured when CTK+ was compiled (unless overridden by the
73 * `CTK_DATA_PREFIX` environment variable), and `VERSION` is the CTK+ version number.
74 * If no file is found for the current version, CTK+ tries older versions all the
75 * way back to 3.0.
76 *
77 * In the same way, CTK+ tries to load a ctk-keys.css file for the current
78 * key theme, as defined by #CtkSettings:ctk-key-theme-name.
79 */
80
81
82typedef struct CtkCssRuleset CtkCssRuleset;
83typedef struct _CtkCssScanner CtkCssScanner;
84typedef struct _PropertyValue PropertyValue;
85typedef struct _WidgetPropertyValue WidgetPropertyValue;
86typedef enum ParserScope ParserScope;
87typedef enum ParserSymbol ParserSymbol;
88
89struct _PropertyValue {
90 CtkCssStyleProperty *property;
91 CtkCssValue *value;
92 CtkCssSection *section;
93};
94
95struct _WidgetPropertyValue {
96 WidgetPropertyValue *next;
97 char *name;
98 char *value;
99
100 CtkCssSection *section;
101};
102
103struct CtkCssRuleset
104{
105 CtkCssSelector *selector;
106 CtkCssSelectorTree *selector_match;
107 WidgetPropertyValue *widget_style;
108 PropertyValue *styles;
109 CtkBitmask *set_styles;
110 guint n_styles;
111 guint owns_styles : 1;
112 guint owns_widget_style : 1;
113};
114
115struct _CtkCssScanner
116{
117 CtkCssProvider *provider;
118 CtkCssParser *parser;
119 CtkCssSection *section;
120 CtkCssScanner *parent;
121 GSList *state;
122};
123
124struct _CtkCssProviderPrivate
125{
126 GScanner *scanner;
127
128 GHashTable *symbolic_colors;
129 GHashTable *keyframes;
130
131 GArray *rulesets;
132 CtkCssSelectorTree *tree;
133 GResource *resource;
134 gchar *path;
135};
136
137enum {
138 PARSING_ERROR,
139 LAST_SIGNAL
140};
141
142static gboolean ctk_keep_css_sections = FALSE(0);
143
144static guint css_provider_signals[LAST_SIGNAL] = { 0 };
145
146static void ctk_css_provider_finalize (GObject *object);
147static void ctk_css_style_provider_iface_init (CtkStyleProviderIface *iface);
148static void ctk_css_style_provider_private_iface_init (CtkStyleProviderPrivateInterface *iface);
149static void widget_property_value_list_free (WidgetPropertyValue *head);
150static void ctk_css_style_provider_emit_error (CtkStyleProviderPrivate *provider,
151 CtkCssSection *section,
152 const GError *error);
153
154static gboolean
155ctk_css_provider_load_internal (CtkCssProvider *css_provider,
156 CtkCssScanner *scanner,
157 GFile *file,
158 const char *data,
159 GError **error);
160
161GQuark
162ctk_css_provider_error_quark (void)
163{
164 return g_quark_from_static_string ("ctk-css-provider-error-quark");
165}
166
167G_DEFINE_TYPE_EXTENDED (CtkCssProvider, ctk_css_provider, G_TYPE_OBJECT, 0,static void ctk_css_provider_init (CtkCssProvider *self); static
void ctk_css_provider_class_init (CtkCssProviderClass *klass
); static GType ctk_css_provider_get_type_once (void); static
gpointer ctk_css_provider_parent_class = ((void*)0); static gint
CtkCssProvider_private_offset; static void ctk_css_provider_class_intern_init
(gpointer klass) { ctk_css_provider_parent_class = g_type_class_peek_parent
(klass); if (CtkCssProvider_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CtkCssProvider_private_offset); ctk_css_provider_class_init
((CtkCssProviderClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer ctk_css_provider_get_instance_private
(CtkCssProvider *self) { return (((gpointer) ((guint8*) (self
) + (glong) (CtkCssProvider_private_offset)))); } GType ctk_css_provider_get_type
(void) { static GType static_g_define_type_id = 0; if ((__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); (void) (
0 ? (gpointer) * (&static_g_define_type_id) : ((void*)0))
; (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= ctk_css_provider_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType ctk_css_provider_get_type_once (
void) { GType g_define_type_id = g_type_register_static_simple
(((GType) ((20) << (2))), g_intern_static_string ("CtkCssProvider"
), sizeof (CtkCssProviderClass), (GClassInitFunc)(void (*)(void
)) ctk_css_provider_class_intern_init, sizeof (CtkCssProvider
), (GInstanceInitFunc)(void (*)(void)) ctk_css_provider_init,
(GTypeFlags) 0); { {{ CtkCssProvider_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CtkCssProviderPrivate)); } { const
GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) ctk_css_style_provider_iface_init, ((void*)
0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (ctk_style_provider_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) ctk_css_style_provider_private_iface_init, (
(void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (_ctk_style_provider_private_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
168 G_ADD_PRIVATE (CtkCssProvider)static void ctk_css_provider_init (CtkCssProvider *self); static
void ctk_css_provider_class_init (CtkCssProviderClass *klass
); static GType ctk_css_provider_get_type_once (void); static
gpointer ctk_css_provider_parent_class = ((void*)0); static gint
CtkCssProvider_private_offset; static void ctk_css_provider_class_intern_init
(gpointer klass) { ctk_css_provider_parent_class = g_type_class_peek_parent
(klass); if (CtkCssProvider_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CtkCssProvider_private_offset); ctk_css_provider_class_init
((CtkCssProviderClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer ctk_css_provider_get_instance_private
(CtkCssProvider *self) { return (((gpointer) ((guint8*) (self
) + (glong) (CtkCssProvider_private_offset)))); } GType ctk_css_provider_get_type
(void) { static GType static_g_define_type_id = 0; if ((__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); (void) (
0 ? (gpointer) * (&static_g_define_type_id) : ((void*)0))
; (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= ctk_css_provider_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType ctk_css_provider_get_type_once (
void) { GType g_define_type_id = g_type_register_static_simple
(((GType) ((20) << (2))), g_intern_static_string ("CtkCssProvider"
), sizeof (CtkCssProviderClass), (GClassInitFunc)(void (*)(void
)) ctk_css_provider_class_intern_init, sizeof (CtkCssProvider
), (GInstanceInitFunc)(void (*)(void)) ctk_css_provider_init,
(GTypeFlags) 0); { {{ CtkCssProvider_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CtkCssProviderPrivate)); } { const
GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) ctk_css_style_provider_iface_init, ((void*)
0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (ctk_style_provider_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) ctk_css_style_provider_private_iface_init, (
(void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (_ctk_style_provider_private_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
169 G_IMPLEMENT_INTERFACE (CTK_TYPE_STYLE_PROVIDER,static void ctk_css_provider_init (CtkCssProvider *self); static
void ctk_css_provider_class_init (CtkCssProviderClass *klass
); static GType ctk_css_provider_get_type_once (void); static
gpointer ctk_css_provider_parent_class = ((void*)0); static gint
CtkCssProvider_private_offset; static void ctk_css_provider_class_intern_init
(gpointer klass) { ctk_css_provider_parent_class = g_type_class_peek_parent
(klass); if (CtkCssProvider_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CtkCssProvider_private_offset); ctk_css_provider_class_init
((CtkCssProviderClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer ctk_css_provider_get_instance_private
(CtkCssProvider *self) { return (((gpointer) ((guint8*) (self
) + (glong) (CtkCssProvider_private_offset)))); } GType ctk_css_provider_get_type
(void) { static GType static_g_define_type_id = 0; if ((__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); (void) (
0 ? (gpointer) * (&static_g_define_type_id) : ((void*)0))
; (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= ctk_css_provider_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType ctk_css_provider_get_type_once (
void) { GType g_define_type_id = g_type_register_static_simple
(((GType) ((20) << (2))), g_intern_static_string ("CtkCssProvider"
), sizeof (CtkCssProviderClass), (GClassInitFunc)(void (*)(void
)) ctk_css_provider_class_intern_init, sizeof (CtkCssProvider
), (GInstanceInitFunc)(void (*)(void)) ctk_css_provider_init,
(GTypeFlags) 0); { {{ CtkCssProvider_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CtkCssProviderPrivate)); } { const
GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) ctk_css_style_provider_iface_init, ((void*)
0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (ctk_style_provider_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) ctk_css_style_provider_private_iface_init, (
(void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (_ctk_style_provider_private_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
170 ctk_css_style_provider_iface_init)static void ctk_css_provider_init (CtkCssProvider *self); static
void ctk_css_provider_class_init (CtkCssProviderClass *klass
); static GType ctk_css_provider_get_type_once (void); static
gpointer ctk_css_provider_parent_class = ((void*)0); static gint
CtkCssProvider_private_offset; static void ctk_css_provider_class_intern_init
(gpointer klass) { ctk_css_provider_parent_class = g_type_class_peek_parent
(klass); if (CtkCssProvider_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CtkCssProvider_private_offset); ctk_css_provider_class_init
((CtkCssProviderClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer ctk_css_provider_get_instance_private
(CtkCssProvider *self) { return (((gpointer) ((guint8*) (self
) + (glong) (CtkCssProvider_private_offset)))); } GType ctk_css_provider_get_type
(void) { static GType static_g_define_type_id = 0; if ((__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); (void) (
0 ? (gpointer) * (&static_g_define_type_id) : ((void*)0))
; (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= ctk_css_provider_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType ctk_css_provider_get_type_once (
void) { GType g_define_type_id = g_type_register_static_simple
(((GType) ((20) << (2))), g_intern_static_string ("CtkCssProvider"
), sizeof (CtkCssProviderClass), (GClassInitFunc)(void (*)(void
)) ctk_css_provider_class_intern_init, sizeof (CtkCssProvider
), (GInstanceInitFunc)(void (*)(void)) ctk_css_provider_init,
(GTypeFlags) 0); { {{ CtkCssProvider_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CtkCssProviderPrivate)); } { const
GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) ctk_css_style_provider_iface_init, ((void*)
0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (ctk_style_provider_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) ctk_css_style_provider_private_iface_init, (
(void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (_ctk_style_provider_private_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
171 G_IMPLEMENT_INTERFACE (CTK_TYPE_STYLE_PROVIDER_PRIVATE,static void ctk_css_provider_init (CtkCssProvider *self); static
void ctk_css_provider_class_init (CtkCssProviderClass *klass
); static GType ctk_css_provider_get_type_once (void); static
gpointer ctk_css_provider_parent_class = ((void*)0); static gint
CtkCssProvider_private_offset; static void ctk_css_provider_class_intern_init
(gpointer klass) { ctk_css_provider_parent_class = g_type_class_peek_parent
(klass); if (CtkCssProvider_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CtkCssProvider_private_offset); ctk_css_provider_class_init
((CtkCssProviderClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer ctk_css_provider_get_instance_private
(CtkCssProvider *self) { return (((gpointer) ((guint8*) (self
) + (glong) (CtkCssProvider_private_offset)))); } GType ctk_css_provider_get_type
(void) { static GType static_g_define_type_id = 0; if ((__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); (void) (
0 ? (gpointer) * (&static_g_define_type_id) : ((void*)0))
; (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= ctk_css_provider_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType ctk_css_provider_get_type_once (
void) { GType g_define_type_id = g_type_register_static_simple
(((GType) ((20) << (2))), g_intern_static_string ("CtkCssProvider"
), sizeof (CtkCssProviderClass), (GClassInitFunc)(void (*)(void
)) ctk_css_provider_class_intern_init, sizeof (CtkCssProvider
), (GInstanceInitFunc)(void (*)(void)) ctk_css_provider_init,
(GTypeFlags) 0); { {{ CtkCssProvider_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CtkCssProviderPrivate)); } { const
GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) ctk_css_style_provider_iface_init, ((void*)
0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (ctk_style_provider_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) ctk_css_style_provider_private_iface_init, (
(void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (_ctk_style_provider_private_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
172 ctk_css_style_provider_private_iface_init))static void ctk_css_provider_init (CtkCssProvider *self); static
void ctk_css_provider_class_init (CtkCssProviderClass *klass
); static GType ctk_css_provider_get_type_once (void); static
gpointer ctk_css_provider_parent_class = ((void*)0); static gint
CtkCssProvider_private_offset; static void ctk_css_provider_class_intern_init
(gpointer klass) { ctk_css_provider_parent_class = g_type_class_peek_parent
(klass); if (CtkCssProvider_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CtkCssProvider_private_offset); ctk_css_provider_class_init
((CtkCssProviderClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer ctk_css_provider_get_instance_private
(CtkCssProvider *self) { return (((gpointer) ((guint8*) (self
) + (glong) (CtkCssProvider_private_offset)))); } GType ctk_css_provider_get_type
(void) { static GType static_g_define_type_id = 0; if ((__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); (void) (
0 ? (gpointer) * (&static_g_define_type_id) : ((void*)0))
; (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= ctk_css_provider_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType ctk_css_provider_get_type_once (
void) { GType g_define_type_id = g_type_register_static_simple
(((GType) ((20) << (2))), g_intern_static_string ("CtkCssProvider"
), sizeof (CtkCssProviderClass), (GClassInitFunc)(void (*)(void
)) ctk_css_provider_class_intern_init, sizeof (CtkCssProvider
), (GInstanceInitFunc)(void (*)(void)) ctk_css_provider_init,
(GTypeFlags) 0); { {{ CtkCssProvider_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CtkCssProviderPrivate)); } { const
GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) ctk_css_style_provider_iface_init, ((void*)
0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (ctk_style_provider_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) ctk_css_style_provider_private_iface_init, (
(void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (_ctk_style_provider_private_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
;
173
174static void
175ctk_css_provider_parsing_error (CtkCssProvider *provider,
176 CtkCssSection *section,
177 const GError *error)
178{
179 /* Only emit a warning when we have no error handlers. This is our
180 * default handlers. And in this case erroneous CSS files are a bug
181 * and should be fixed.
182 * Note that these warnings can also be triggered by a broken theme
183 * that people installed from some weird location on the internets.
184 */
185 if (!g_signal_has_handler_pending (provider,
186 css_provider_signals[PARSING_ERROR],
187 0,
188 TRUE(!(0))))
189 {
190 char *s = _ctk_css_section_to_string (section);
191
192 g_warning ("Theme parsing error: %s: %s",
193 s,
194 error->message);
195
196 g_free (s);
197 }
198}
199
200/* This is exported privately for use in CtkInspector.
201 * It is the callers responsibility to reparse the current theme.
202 */
203void
204ctk_css_provider_set_keep_css_sections (void)
205{
206 ctk_keep_css_sections = TRUE(!(0));
207}
208
209static void
210ctk_css_provider_class_init (CtkCssProviderClass *klass)
211{
212 GObjectClass *object_class = G_OBJECT_CLASS (klass)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((klass)), (((GType) ((20) << (2))))))))
;
213
214 if (g_getenv ("CTK_CSS_DEBUG"))
215 ctk_css_provider_set_keep_css_sections ();
216
217 /**
218 * CtkCssProvider::parsing-error:
219 * @provider: the provider that had a parsing error
220 * @section: section the error happened in
221 * @error: The parsing error
222 *
223 * Signals that a parsing error occurred. the @path, @line and @position
224 * describe the actual location of the error as accurately as possible.
225 *
226 * Parsing errors are never fatal, so the parsing will resume after
227 * the error. Errors may however cause parts of the given
228 * data or even all of it to not be parsed at all. So it is a useful idea
229 * to check that the parsing succeeds by connecting to this signal.
230 *
231 * Note that this signal may be emitted at any time as the css provider
232 * may opt to defer parsing parts or all of the input to a later time
233 * than when a loading function was called.
234 */
235 css_provider_signals[PARSING_ERROR] =
236 g_signal_new (I_("parsing-error")g_intern_static_string ("parsing-error"),
237 G_TYPE_FROM_CLASS (object_class)(((GTypeClass*) (object_class))->g_type),
238 G_SIGNAL_RUN_LAST,
239 G_STRUCT_OFFSET (CtkCssProviderClass, parsing_error)((glong) __builtin_offsetof(CtkCssProviderClass, parsing_error
))
,
240 NULL((void*)0), NULL((void*)0),
241 _ctk_marshal_VOID__BOXED_BOXED,
242 G_TYPE_NONE((GType) ((1) << (2))), 2, CTK_TYPE_CSS_SECTION(ctk_css_section_get_type ()), G_TYPE_ERROR(g_error_get_type ()));
243
244 object_class->finalize = ctk_css_provider_finalize;
245
246 klass->parsing_error = ctk_css_provider_parsing_error;
247}
248
249static void
250ctk_css_ruleset_init_copy (CtkCssRuleset *new,
251 CtkCssRuleset *ruleset,
252 CtkCssSelector *selector)
253{
254 memcpy (new, ruleset, sizeof (CtkCssRuleset));
255
256 new->selector = selector;
257 /* First copy takes over ownership */
258 if (ruleset->owns_styles)
259 ruleset->owns_styles = FALSE(0);
260 if (ruleset->owns_widget_style)
261 ruleset->owns_widget_style = FALSE(0);
262 if (new->set_styles)
263 new->set_styles = _ctk_bitmask_copy (new->set_styles);
264}
265
266static void
267ctk_css_ruleset_clear (CtkCssRuleset *ruleset)
268{
269 if (ruleset->owns_styles)
270 {
271 guint i;
272
273 for (i = 0; i < ruleset->n_styles; i++)
274 {
275 _ctk_css_value_unref (ruleset->styles[i].value);
276 ruleset->styles[i].value = NULL((void*)0);
277 if (ruleset->styles[i].section)
278 ctk_css_section_unref (ruleset->styles[i].section);
279 }
280 g_free (ruleset->styles);
281 }
282 if (ruleset->set_styles)
283 _ctk_bitmask_free (ruleset->set_styles);
284 if (ruleset->owns_widget_style)
285 widget_property_value_list_free (ruleset->widget_style);
286 if (ruleset->selector)
287 _ctk_css_selector_free (ruleset->selector);
288
289 memset (ruleset, 0, sizeof (CtkCssRuleset));
290}
291
292static WidgetPropertyValue *
293widget_property_value_new (char *name, CtkCssSection *section)
294{
295 WidgetPropertyValue *value;
296
297 value = g_slice_new0 (WidgetPropertyValue)((WidgetPropertyValue*) g_slice_alloc0 (sizeof (WidgetPropertyValue
)))
;
298
299 value->name = name;
300 if (ctk_keep_css_sections)
301 value->section = ctk_css_section_ref (section);
302
303 return value;
304}
305
306static void
307widget_property_value_free (WidgetPropertyValue *value)
308{
309 g_free (value->value);
310 g_free (value->name);
311 if (value->section)
312 ctk_css_section_unref (value->section);
313
314 g_slice_free (WidgetPropertyValue, value)do { if (1) g_slice_free1 (sizeof (WidgetPropertyValue), (value
)); else (void) ((WidgetPropertyValue*) 0 == (value)); } while
(0)
;
315}
316
317static void
318widget_property_value_list_free (WidgetPropertyValue *head)
319{
320 WidgetPropertyValue *l, *next;
321 for (l = head; l != NULL((void*)0); l = next)
322 {
323 next = l->next;
324 widget_property_value_free (l);
325 }
326}
327
328static WidgetPropertyValue *
329widget_property_value_list_remove_name (WidgetPropertyValue *head, const char *name)
330{
331 WidgetPropertyValue *l, **last;
332
333 last = &head;
334
335 for (l = head; l != NULL((void*)0); l = l->next)
336 {
337 if (strcmp (l->name, name) == 0)
338 {
339 *last = l->next;
340 widget_property_value_free (l);
341 break;
342 }
343
344 last = &l->next;
345 }
346
347 return head;
348}
349
350static void
351ctk_css_ruleset_add_style (CtkCssRuleset *ruleset,
352 char *name,
353 WidgetPropertyValue *value)
354{
355 value->next = widget_property_value_list_remove_name (ruleset->widget_style, name);
356 ruleset->widget_style = value;
357 ruleset->owns_widget_style = TRUE(!(0));
358}
359
360static void
361ctk_css_ruleset_add (CtkCssRuleset *ruleset,
362 CtkCssStyleProperty *property,
363 CtkCssValue *value,
364 CtkCssSection *section)
365{
366 guint i;
367
368 g_return_if_fail (ruleset->owns_styles || ruleset->n_styles == 0)do { if ((ruleset->owns_styles || ruleset->n_styles == 0
)) { } else { g_return_if_fail_warning ("Ctk", ((const char*)
(__func__)), "ruleset->owns_styles || ruleset->n_styles == 0"
); return; } } while (0)
;
369
370 if (ruleset->set_styles == NULL((void*)0))
371 ruleset->set_styles = _ctk_bitmask_new ();
372
373 ruleset->set_styles = _ctk_bitmask_set (ruleset->set_styles,
374 _ctk_css_style_property_get_id (property),
375 TRUE(!(0)));
376
377 ruleset->owns_styles = TRUE(!(0));
378
379 for (i = 0; i < ruleset->n_styles; i++)
380 {
381 if (ruleset->styles[i].property == property)
382 {
383 _ctk_css_value_unref (ruleset->styles[i].value);
384 ruleset->styles[i].value = NULL((void*)0);
385 if (ruleset->styles[i].section)
386 ctk_css_section_unref (ruleset->styles[i].section);
387 break;
388 }
389 }
390 if (i == ruleset->n_styles)
391 {
392 ruleset->n_styles++;
393 ruleset->styles = g_realloc (ruleset->styles, ruleset->n_styles * sizeof (PropertyValue));
394 ruleset->styles[i].value = NULL((void*)0);
395 ruleset->styles[i].property = property;
396 }
397
398 ruleset->styles[i].value = value;
399 if (ctk_keep_css_sections)
400 ruleset->styles[i].section = ctk_css_section_ref (section);
401 else
402 ruleset->styles[i].section = NULL((void*)0);
403}
404
405static void
406ctk_css_scanner_destroy (CtkCssScanner *scanner)
407{
408 if (scanner->section)
409 ctk_css_section_unref (scanner->section);
410 g_object_unref (scanner->provider);
411 _ctk_css_parser_free (scanner->parser);
412
413 g_slice_free (CtkCssScanner, scanner)do { if (1) g_slice_free1 (sizeof (CtkCssScanner), (scanner))
; else (void) ((CtkCssScanner*) 0 == (scanner)); } while (0)
;
414}
415
416static void
417ctk_css_style_provider_emit_error (CtkStyleProviderPrivate *provider,
418 CtkCssSection *section,
419 const GError *error)
420{
421 g_signal_emit (provider, css_provider_signals[PARSING_ERROR], 0, section, error);
422}
423
424static void
425ctk_css_provider_emit_error (CtkCssProvider *provider,
426 CtkCssScanner *scanner,
427 const GError *error)
428{
429 ctk_css_style_provider_emit_error (CTK_STYLE_PROVIDER_PRIVATE (provider)((((CtkStyleProviderPrivate*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((provider)), ((_ctk_style_provider_private_get_type
()))))))
,
430 scanner ? scanner->section : NULL((void*)0),
431 error);
432}
433
434static void
435ctk_css_scanner_parser_error (CtkCssParser *parser G_GNUC_UNUSED__attribute__ ((__unused__)),
436 const GError *error,
437 gpointer user_data)
438{
439 CtkCssScanner *scanner = user_data;
440
441 ctk_css_provider_emit_error (scanner->provider, scanner, error);
442}
443
444static CtkCssScanner *
445ctk_css_scanner_new (CtkCssProvider *provider,
446 CtkCssScanner *parent,
447 CtkCssSection *section,
448 GFile *file,
449 const gchar *text)
450{
451 CtkCssScanner *scanner;
452
453 scanner = g_slice_new0 (CtkCssScanner)((CtkCssScanner*) g_slice_alloc0 (sizeof (CtkCssScanner)));
454
455 g_object_ref (provider)((__typeof__ (provider)) (g_object_ref) (provider));
456 scanner->provider = provider;
457 scanner->parent = parent;
458 if (section)
459 scanner->section = ctk_css_section_ref (section);
460
461 scanner->parser = _ctk_css_parser_new (text,
462 file,
463 ctk_css_scanner_parser_error,
464 scanner);
465
466 return scanner;
467}
468
469static gboolean
470ctk_css_scanner_would_recurse (CtkCssScanner *scanner,
471 GFile *file)
472{
473 while (scanner)
474 {
475 GFile *parser_file = _ctk_css_parser_get_file (scanner->parser);
476 if (parser_file && g_file_equal (parser_file, file))
477 return TRUE(!(0));
478
479 scanner = scanner->parent;
480 }
481
482 return FALSE(0);
483}
484
485static void
486ctk_css_scanner_push_section (CtkCssScanner *scanner,
487 CtkCssSectionType section_type)
488{
489 CtkCssSection *section;
490
491 section = _ctk_css_section_new (scanner->section,
492 section_type,
493 scanner->parser);
494
495 if (scanner->section)
496 ctk_css_section_unref (scanner->section);
497 scanner->section = section;
498}
499
500static void
501ctk_css_scanner_pop_section (CtkCssScanner *scanner,
502 CtkCssSectionType check_type)
503{
504 CtkCssSection *parent;
505
506 g_assert (ctk_css_section_get_section_type (scanner->section) == check_type)do { if (ctk_css_section_get_section_type (scanner->section
) == check_type) ; else g_assertion_message_expr ("Ctk", "ctkcssprovider.c"
, 506, ((const char*) (__func__)), "ctk_css_section_get_section_type (scanner->section) == check_type"
); } while (0)
;
507
508 parent = ctk_css_section_get_parent (scanner->section);
509 if (parent)
510 ctk_css_section_ref (parent);
511
512 _ctk_css_section_end (scanner->section);
513 ctk_css_section_unref (scanner->section);
514
515 scanner->section = parent;
516}
517
518static void
519ctk_css_provider_init (CtkCssProvider *css_provider)
520{
521 CtkCssProviderPrivate *priv;
522
523 priv = css_provider->priv = ctk_css_provider_get_instance_private (css_provider);
524
525 priv->rulesets = g_array_new (FALSE(0), FALSE(0), sizeof (CtkCssRuleset));
526
527 priv->symbolic_colors = g_hash_table_new_full (g_str_hash, g_str_equal,
528 (GDestroyNotify) g_free,
529 (GDestroyNotify) _ctk_css_value_unref);
530 priv->keyframes = g_hash_table_new_full (g_str_hash, g_str_equal,
531 (GDestroyNotify) g_free,
532 (GDestroyNotify) _ctk_css_keyframes_unref);
533}
534
535static void
536verify_tree_match_results (CtkCssProvider *provider G_GNUC_UNUSED__attribute__ ((__unused__)),
537 const CtkCssMatcher *matcher G_GNUC_UNUSED__attribute__ ((__unused__)),
538 GPtrArray *tree_rules G_GNUC_UNUSED__attribute__ ((__unused__)))
539{
540#ifdef VERIFY_TREE
541 CtkCssProviderPrivate *priv = provider->priv;
542 CtkCssRuleset *ruleset;
543 gboolean should_match;
544 int i, j;
545
546 for (i = 0; i < priv->rulesets->len; i++)
547 {
548 gboolean found = FALSE(0);
549
550 ruleset = &g_array_index (priv->rulesets, CtkCssRuleset, i)(((CtkCssRuleset*) (void *) (priv->rulesets)->data) [(i
)])
;
551
552 for (j = 0; j < tree_rules->len; j++)
553 {
554 if (ruleset == tree_rules->pdata[j])
555 {
556 found = TRUE(!(0));
557 break;
558 }
559 }
560 should_match = _ctk_css_selector_matches (ruleset->selector, matcher);
561 if (found != !!should_match)
562 {
563 g_error ("expected rule '%s' to %s, but it %s",
564 _ctk_css_selector_to_string (ruleset->selector),
565 should_match ? "match" : "not match",
566 found ? "matched" : "didn't match");
567 }
568 }
569#endif
570}
571
572static void
573verify_tree_get_change_results (CtkCssProvider *provider G_GNUC_UNUSED__attribute__ ((__unused__)),
574 const CtkCssMatcher *matcher G_GNUC_UNUSED__attribute__ ((__unused__)),
575 CtkCssChange change G_GNUC_UNUSED__attribute__ ((__unused__)))
576{
577#ifdef VERIFY_TREE
578 {
579 CtkCssChange verify_change = 0;
580 GPtrArray *tree_rules;
581 int i;
582
583 tree_rules = _ctk_css_selector_tree_match_all (provider->priv->tree, matcher);
584 if (tree_rules)
585 {
586 verify_tree_match_results (provider, matcher, tree_rules);
587
588 for (i = tree_rules->len - 1; i >= 0; i--)
589 {
590 CtkCssRuleset *ruleset;
591
592 ruleset = tree_rules->pdata[i];
593
594 verify_change |= _ctk_css_selector_get_change (ruleset->selector);
595 }
596
597 g_ptr_array_free (tree_rules, TRUE(!(0)));
598 }
599
600 if (change != verify_change)
601 {
602 GString *s;
603
604 s = g_string_new ("");
605 g_string_append (s, "expected change ")(__builtin_constant_p ("expected change ") ? __extension__ ({
const char * const __val = ("expected change "); g_string_append_len_inline
(s, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val)
+ !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(s, "expected change ", (gssize) -1))
;
606 ctk_css_change_print (verify_change, s);
607 g_string_append (s, ", but it was ")(__builtin_constant_p (", but it was ") ? __extension__ ({ const
char * const __val = (", but it was "); g_string_append_len_inline
(s, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val)
+ !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(s, ", but it was ", (gssize) -1))
;
608 ctk_css_change_print (change, s);
609 if ((change & ~verify_change) != 0)
610 {
611 g_string_append (s, ", unexpectedly set: ")(__builtin_constant_p (", unexpectedly set: ") ? __extension__
({ const char * const __val = (", unexpectedly set: "); g_string_append_len_inline
(s, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val)
+ !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(s, ", unexpectedly set: ", (gssize) -1))
;
612 ctk_css_change_print (change & ~verify_change, s);
613 }
614 if ((~change & verify_change) != 0)
615 {
616 g_string_append_printf (s, ", unexpectedly not set: ");
617 ctk_css_change_print (~change & verify_change, s);
618 }
619 g_warning (s->str);
620 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)))))
;
621 }
622 }
623#endif
624}
625
626
627static gboolean
628ctk_css_provider_get_style_property (CtkStyleProvider *provider,
629 CtkWidgetPath *path,
630 CtkStateFlags state,
631 GParamSpec *pspec,
632 GValue *value)
633{
634 CtkCssProvider *css_provider = CTK_CSS_PROVIDER (provider)((((CtkCssProvider*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((provider)), ((ctk_css_provider_get_type ()))))))
;
635 CtkCssProviderPrivate *priv = css_provider->priv;
636 WidgetPropertyValue *val;
637 GPtrArray *tree_rules;
638 CtkCssMatcher matcher;
639 gboolean found = FALSE(0);
640 gchar *prop_name;
641 gint i;
642
643 if (state == ctk_widget_path_iter_get_state (path, -1))
644 {
645 ctk_widget_path_ref (path);
646 }
647 else
648 {
649 path = ctk_widget_path_copy (path);
650 ctk_widget_path_iter_set_state (path, -1, state);
651 }
652
653 if (!_ctk_css_matcher_init (&matcher, path, NULL((void*)0)))
654 {
655 ctk_widget_path_unref (path);
656 return FALSE(0);
657 }
658
659 tree_rules = _ctk_css_selector_tree_match_all (priv->tree, &matcher);
660 if (tree_rules)
661 {
662 verify_tree_match_results (css_provider, &matcher, tree_rules);
663
664 prop_name = g_strdup_printf ("-%s-%s",
665 g_type_name (pspec->owner_type),
666 pspec->name);
667
668 for (i = tree_rules->len - 1; i >= 0; i--)
669 {
670 CtkCssRuleset *ruleset = tree_rules->pdata[i];
671
672 if (ruleset->widget_style == NULL((void*)0))
673 continue;
674
675 for (val = ruleset->widget_style; val != NULL((void*)0); val = val->next)
676 {
677 if (strcmp (val->name, prop_name) == 0)
678 {
679 CtkCssScanner *scanner;
680
681 scanner = ctk_css_scanner_new (css_provider,
682 NULL((void*)0),
683 val->section,
684 val->section != NULL((void*)0) ? ctk_css_section_get_file (val->section) : NULL((void*)0),
685 val->value);
686 if (!val->section)
687 ctk_css_scanner_push_section (scanner, CTK_CSS_SECTION_VALUE);
688 found = _ctk_css_style_funcs_parse_value (value, scanner->parser);
689 if (!val->section)
690 ctk_css_scanner_pop_section (scanner, CTK_CSS_SECTION_VALUE);
691 ctk_css_scanner_destroy (scanner);
692 break;
693 }
694 }
695
696 if (found)
697 break;
698 }
699
700 g_free (prop_name);
701 g_ptr_array_free (tree_rules, TRUE(!(0)));
702 }
703
704 ctk_widget_path_unref (path);
705
706 return found;
707}
708
709static void
710ctk_css_style_provider_iface_init (CtkStyleProviderIface *iface)
711{
712 iface->get_style_property = ctk_css_provider_get_style_property;
713}
714
715static CtkCssValue *
716ctk_css_style_provider_get_color (CtkStyleProviderPrivate *provider,
717 const char *name)
718{
719 CtkCssProvider *css_provider = CTK_CSS_PROVIDER (provider)((((CtkCssProvider*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((provider)), ((ctk_css_provider_get_type ()))))))
;
720
721 return g_hash_table_lookup (css_provider->priv->symbolic_colors, name);
722}
723
724static CtkCssKeyframes *
725ctk_css_style_provider_get_keyframes (CtkStyleProviderPrivate *provider,
726 const char *name)
727{
728 CtkCssProvider *css_provider = CTK_CSS_PROVIDER (provider)((((CtkCssProvider*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((provider)), ((ctk_css_provider_get_type ()))))))
;
729
730 return g_hash_table_lookup (css_provider->priv->keyframes, name);
731}
732
733static void
734ctk_css_style_provider_lookup (CtkStyleProviderPrivate *provider,
735 const CtkCssMatcher *matcher,
736 CtkCssLookup *lookup,
737 CtkCssChange *change)
738{
739 CtkCssProvider *css_provider;
740 CtkCssProviderPrivate *priv;
741 CtkCssRuleset *ruleset;
742 guint j;
743 int i;
744 GPtrArray *tree_rules;
745
746 css_provider = CTK_CSS_PROVIDER (provider)((((CtkCssProvider*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((provider)), ((ctk_css_provider_get_type ()))))))
;
747 priv = css_provider->priv;
748
749 tree_rules = _ctk_css_selector_tree_match_all (priv->tree, matcher);
750 if (tree_rules)
751 {
752 verify_tree_match_results (css_provider, matcher, tree_rules);
753
754 for (i = tree_rules->len - 1; i >= 0; i--)
755 {
756 ruleset = tree_rules->pdata[i];
757
758 if (ruleset->styles == NULL((void*)0))
759 continue;
760
761 if (!_ctk_bitmask_intersects (_ctk_css_lookup_get_missing (lookup),
762 ruleset->set_styles))
763 continue;
764
765 for (j = 0; j < ruleset->n_styles; j++)
766 {
767 CtkCssStyleProperty *prop = ruleset->styles[j].property;
768 guint id = _ctk_css_style_property_get_id (prop);
769
770 if (!_ctk_css_lookup_is_missing (lookup, id))
771 continue;
772
773 _ctk_css_lookup_set (lookup,
774 id,
775 ruleset->styles[j].section,
776 ruleset->styles[j].value);
777 }
778
779 if (_ctk_bitmask_is_empty (_ctk_css_lookup_get_missing (lookup)))
780 break;
781 }
782
783 g_ptr_array_free (tree_rules, TRUE(!(0)));
784 }
785
786 if (change)
787 {
788 CtkCssMatcher change_matcher;
789
790 _ctk_css_matcher_superset_init (&change_matcher, matcher, CTK_CSS_CHANGE_NAME(1ULL << 1) | CTK_CSS_CHANGE_CLASS(1ULL << 0));
791
792 *change = _ctk_css_selector_tree_get_change_all (priv->tree, &change_matcher);
793 verify_tree_get_change_results (css_provider, &change_matcher, *change);
794 }
795}
796
797static void
798ctk_css_style_provider_private_iface_init (CtkStyleProviderPrivateInterface *iface)
799{
800 iface->get_color = ctk_css_style_provider_get_color;
801 iface->get_keyframes = ctk_css_style_provider_get_keyframes;
802 iface->lookup = ctk_css_style_provider_lookup;
803 iface->emit_error = ctk_css_style_provider_emit_error;
804}
805
806static void
807ctk_css_provider_finalize (GObject *object)
808{
809 CtkCssProvider *css_provider;
810 CtkCssProviderPrivate *priv;
811 guint i;
812
813 css_provider = CTK_CSS_PROVIDER (object)((((CtkCssProvider*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((ctk_css_provider_get_type ()))))))
;
814 priv = css_provider->priv;
815
816 for (i = 0; i < priv->rulesets->len; i++)
817 ctk_css_ruleset_clear (&g_array_index (priv->rulesets, CtkCssRuleset, i)(((CtkCssRuleset*) (void *) (priv->rulesets)->data) [(i
)])
);
818
819 g_array_free (priv->rulesets, TRUE(!(0)));
820 _ctk_css_selector_tree_free (priv->tree);
821
822 g_hash_table_destroy (priv->symbolic_colors);
823 g_hash_table_destroy (priv->keyframes);
824
825 if (priv->resource)
826 {
827 g_resources_unregister (priv->resource);
828 g_resource_unref (priv->resource);
829 priv->resource = NULL((void*)0);
830 }
831
832 g_free (priv->path);
833
834 G_OBJECT_CLASS (ctk_css_provider_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_css_provider_parent_class)), (((GType) ((20) <<
(2))))))))
->finalize (object);
835}
836
837/**
838 * ctk_css_provider_new:
839 *
840 * Returns a newly created #CtkCssProvider.
841 *
842 * Returns: A new #CtkCssProvider
843 **/
844CtkCssProvider *
845ctk_css_provider_new (void)
846{
847 return g_object_new (CTK_TYPE_CSS_PROVIDER(ctk_css_provider_get_type ()), NULL((void*)0));
848}
849
850static void
851ctk_css_provider_take_error (CtkCssProvider *provider,
852 CtkCssScanner *scanner,
853 GError *error)
854{
855 ctk_css_provider_emit_error (provider, scanner, error);
856 g_error_free (error);
857}
858
859static void
860ctk_css_provider_error_literal (CtkCssProvider *provider,
861 CtkCssScanner *scanner,
862 GQuark domain,
863 gint code,
864 const char *message)
865{
866 ctk_css_provider_take_error (provider,
867 scanner,
868 g_error_new_literal (domain, code, message));
869}
870
871static void
872ctk_css_provider_error (CtkCssProvider *provider,
873 CtkCssScanner *scanner,
874 GQuark domain,
875 gint code,
876 const char *format,
877 ...) G_GNUC_PRINTF (5, 6)__attribute__((__format__ (__printf__, 5, 6)));
878static void
879ctk_css_provider_error (CtkCssProvider *provider,
880 CtkCssScanner *scanner,
881 GQuark domain,
882 gint code,
883 const char *format,
884 ...)
885{
886 GError *error;
887 va_list args;
888
889 ctk_internal_return_if_fail (CTK_IS_CSS_PROVIDER (provider))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((provider)); GType __t = ((ctk_css_provider_get_type ()))
; gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class
&& __inst->g_class->g_type == __t) __r = (!(0)
); else __r = g_type_check_instance_is_a (__inst, __t); __r; }
)))))) { } else { g_return_if_fail_warning ("Ctk", ((const char
*) (__func__)), "(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ((provider)); GType __t = ((ctk_css_provider_get_type ())); gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; }))))"
); return; } } while (0)
;
890 ctk_internal_return_if_fail (scanner != NULL)do { if ((scanner != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "scanner != ((void*)0)")
; return; } } while (0)
;
891
892 va_start (args, format)__builtin_va_start(args, format);
893 error = g_error_new_valist (domain, code, format, args);
894 va_end (args)__builtin_va_end(args);
895
896 ctk_css_provider_take_error (provider, scanner, error);
897}
898
899static void
900ctk_css_provider_invalid_token (CtkCssProvider *provider,
901 CtkCssScanner *scanner,
902 const char *expected)
903{
904 ctk_css_provider_error (provider,
905 scanner,
906 CTK_CSS_PROVIDER_ERROR(ctk_css_provider_error_quark ()),
907 CTK_CSS_PROVIDER_ERROR_SYNTAX,
908 "expected %s", expected);
909}
910
911static void
912css_provider_commit (CtkCssProvider *css_provider,
913 GSList *selectors,
914 CtkCssRuleset *ruleset)
915{
916 CtkCssProviderPrivate *priv;
917 GSList *l;
918
919 priv = css_provider->priv;
920
921 if (ruleset->styles == NULL((void*)0) && ruleset->widget_style == NULL((void*)0))
922 {
923 g_slist_free_full (selectors, (GDestroyNotify) _ctk_css_selector_free);
924 return;
925 }
926
927 for (l = selectors; l; l = l->next)
928 {
929 CtkCssRuleset new;
930
931 ctk_css_ruleset_init_copy (&new, ruleset, l->data);
932
933 g_array_append_val (priv->rulesets, new)g_array_append_vals (priv->rulesets, &(new), 1);
934 }
935
936 g_slist_free (selectors);
937}
938
939static void
940ctk_css_provider_reset (CtkCssProvider *css_provider)
941{
942 CtkCssProviderPrivate *priv;
943 guint i;
944
945 priv = css_provider->priv;
946
947 if (priv->resource)
948 {
949 g_resources_unregister (priv->resource);
950 g_resource_unref (priv->resource);
951 priv->resource = NULL((void*)0);
952 }
953
954 if (priv->path)
955 {
956 g_free (priv->path);
957 priv->path = NULL((void*)0);
958 }
959
960 g_hash_table_remove_all (priv->symbolic_colors);
961 g_hash_table_remove_all (priv->keyframes);
962
963 for (i = 0; i < priv->rulesets->len; i++)
964 ctk_css_ruleset_clear (&g_array_index (priv->rulesets, CtkCssRuleset, i)(((CtkCssRuleset*) (void *) (priv->rulesets)->data) [(i
)])
);
965 g_array_set_size (priv->rulesets, 0);
966 _ctk_css_selector_tree_free (priv->tree);
967 priv->tree = NULL((void*)0);
968
969}
970
971static void
972ctk_css_provider_propagate_error (CtkCssProvider *provider G_GNUC_UNUSED__attribute__ ((__unused__)),
973 CtkCssSection *section,
974 const GError *error,
975 GError **propagate_to)
976{
977
978 char *s;
979
980 /* don't fail for deprecations */
981 if (g_error_matches (error, CTK_CSS_PROVIDER_ERROR(ctk_css_provider_error_quark ()), CTK_CSS_PROVIDER_ERROR_DEPRECATED))
982 {
983 s = _ctk_css_section_to_string (section);
984 g_warning ("Theme parsing error: %s: %s", s, error->message);
985 g_free (s);
986 return;
987 }
988
989 /* we already set an error. And we'd like to keep the first one */
990 if (*propagate_to)
991 return;
992
993 *propagate_to = g_error_copy (error);
994 if (section)
995 {
996 s = _ctk_css_section_to_string (section);
997 g_prefix_error (propagate_to, "%s", s);
998 g_free (s);
999 }
1000}
1001
1002static gboolean
1003parse_import (CtkCssScanner *scanner)
1004{
1005 GFile *file;
1006
1007 ctk_css_scanner_push_section (scanner, CTK_CSS_SECTION_IMPORT);
1008
1009 if (!_ctk_css_parser_try (scanner->parser, "@import", TRUE(!(0))))
1010 {
1011 ctk_css_scanner_pop_section (scanner, CTK_CSS_SECTION_IMPORT);
1012 return FALSE(0);
1013 }
1014
1015 if (_ctk_css_parser_is_string (scanner->parser))
1016 {
1017 char *uri;
1018
1019 uri = _ctk_css_parser_read_string (scanner->parser);
1020 file = _ctk_css_parser_get_file_for_path (scanner->parser, uri);
1021 g_free (uri);
1022 }
1023 else
1024 {
1025 file = _ctk_css_parser_read_url (scanner->parser);
1026 }
1027
1028 if (file == NULL((void*)0))
1029 {
1030 _ctk_css_parser_resync (scanner->parser, TRUE(!(0)), 0);
1031 ctk_css_scanner_pop_section (scanner, CTK_CSS_SECTION_IMPORT);
1032 return TRUE(!(0));
1033 }
1034
1035 if (!_ctk_css_parser_try (scanner->parser, ";", FALSE(0)))
1036 {
1037 ctk_css_provider_invalid_token (scanner->provider, scanner, "semicolon");
1038 _ctk_css_parser_resync (scanner->parser, TRUE(!(0)), 0);
1039 }
1040 else if (ctk_css_scanner_would_recurse (scanner, file))
1041 {
1042 char *path = g_file_get_path (file);
1043 ctk_css_provider_error (scanner->provider,
1044 scanner,
1045 CTK_CSS_PROVIDER_ERROR(ctk_css_provider_error_quark ()),
1046 CTK_CSS_PROVIDER_ERROR_IMPORT,
1047 "Loading '%s' would recurse",
1048 path);
1049 g_free (path);
1050 }
1051 else
1052 {
1053 ctk_css_provider_load_internal (scanner->provider,
1054 scanner,
1055 file,
1056 NULL((void*)0),
1057 NULL((void*)0));
1058 }
1059
1060 g_object_unref (file);
1061
1062 ctk_css_scanner_pop_section (scanner, CTK_CSS_SECTION_IMPORT);
1063 _ctk_css_parser_skip_whitespace (scanner->parser);
1064
1065 return TRUE(!(0));
1066}
1067
1068static gboolean
1069parse_color_definition (CtkCssScanner *scanner)
1070{
1071 CtkCssValue *color;
1072 char *name;
1073
1074 ctk_css_scanner_push_section (scanner, CTK_CSS_SECTION_COLOR_DEFINITION);
1075
1076 if (!_ctk_css_parser_try (scanner->parser, "@define-color", TRUE(!(0))))
1077 {
1078 ctk_css_scanner_pop_section (scanner, CTK_CSS_SECTION_COLOR_DEFINITION);
1079 return FALSE(0);
1080 }
1081
1082 name = _ctk_css_parser_try_name (scanner->parser, TRUE(!(0)));
1083 if (name == NULL((void*)0))
1084 {
1085 ctk_css_provider_error_literal (scanner->provider,
1086 scanner,
1087 CTK_CSS_PROVIDER_ERROR(ctk_css_provider_error_quark ()),
1088 CTK_CSS_PROVIDER_ERROR_SYNTAX,
1089 "Not a valid color name");
1090 _ctk_css_parser_resync (scanner->parser, TRUE(!(0)), 0);
1091 ctk_css_scanner_pop_section (scanner, CTK_CSS_SECTION_COLOR_DEFINITION);
1092 return TRUE(!(0));
1093 }
1094
1095 color = _ctk_css_color_value_parse (scanner->parser);
1096 if (color == NULL((void*)0))
1097 {
1098 g_free (name);
1099 _ctk_css_parser_resync (scanner->parser, TRUE(!(0)), 0);
1100 ctk_css_scanner_pop_section (scanner, CTK_CSS_SECTION_COLOR_DEFINITION);
1101 return TRUE(!(0));
1102 }
1103
1104 if (!_ctk_css_parser_try (scanner->parser, ";", TRUE(!(0))))
1105 {
1106 g_free (name);
1107 _ctk_css_value_unref (color);
1108 ctk_css_provider_error_literal (scanner->provider,
1109 scanner,
1110 CTK_CSS_PROVIDER_ERROR(ctk_css_provider_error_quark ()),
1111 CTK_CSS_PROVIDER_ERROR_SYNTAX,
1112 "Missing semicolon at end of color definition");
1113 _ctk_css_parser_resync (scanner->parser, TRUE(!(0)), 0);
1114
1115 ctk_css_scanner_pop_section (scanner, CTK_CSS_SECTION_COLOR_DEFINITION);
1116 return TRUE(!(0));
1117 }
1118
1119 g_hash_table_insert (scanner->provider->priv->symbolic_colors, name, color);
1120
1121 ctk_css_scanner_pop_section (scanner, CTK_CSS_SECTION_COLOR_DEFINITION);
1122 return TRUE(!(0));
1123}
1124
1125static gboolean
1126parse_binding_set (CtkCssScanner *scanner)
1127{
1128 CtkBindingSet *binding_set;
1129 char *name;
1130
1131 ctk_css_scanner_push_section (scanner, CTK_CSS_SECTION_BINDING_SET);
1132
1133 if (!_ctk_css_parser_try (scanner->parser, "@binding-set", TRUE(!(0))))
1134 {
1135 ctk_css_scanner_pop_section (scanner, CTK_CSS_SECTION_BINDING_SET);
1136 return FALSE(0);
1137 }
1138
1139 name = _ctk_css_parser_try_ident (scanner->parser, TRUE(!(0)));
1140 if (name == NULL((void*)0))
1141 {
1142 ctk_css_provider_error_literal (scanner->provider,
1143 scanner,
1144 CTK_CSS_PROVIDER_ERROR(ctk_css_provider_error_quark ()),
1145 CTK_CSS_PROVIDER_ERROR_SYNTAX,
1146 "Expected name for binding set");
1147 _ctk_css_parser_resync (scanner->parser, TRUE(!(0)), 0);
1148 goto skip_semicolon;
1149 }
1150
1151 binding_set = ctk_binding_set_find (name);
1152 if (!binding_set)
1153 {
1154 binding_set = ctk_binding_set_new (name);
1155 binding_set->parsed = TRUE(!(0));
1156 }
1157 g_free (name);
1158
1159 if (!_ctk_css_parser_try (scanner->parser, "{", TRUE(!(0))))
1160 {
1161 ctk_css_provider_error_literal (scanner->provider,
1162 scanner,
1163 CTK_CSS_PROVIDER_ERROR(ctk_css_provider_error_quark ()),
1164 CTK_CSS_PROVIDER_ERROR_SYNTAX,
1165 "Expected '{' for binding set");
1166 _ctk_css_parser_resync (scanner->parser, TRUE(!(0)), 0);
1167 goto skip_semicolon;
1168 }
1169
1170 while (!_ctk_css_parser_is_eof (scanner->parser) &&
1171 !_ctk_css_parser_begins_with (scanner->parser, '}'))
1172 {
1173 name = _ctk_css_parser_read_value (scanner->parser);
1174 if (name == NULL((void*)0))
1175 {
1176 _ctk_css_parser_resync (scanner->parser, TRUE(!(0)), '}');
1177 continue;
1178 }
1179
1180 if (ctk_binding_entry_add_signal_from_string (binding_set, name) != G_TOKEN_NONE)
1181 {
1182 ctk_css_provider_error_literal (scanner->provider,
1183 scanner,
1184 CTK_CSS_PROVIDER_ERROR(ctk_css_provider_error_quark ()),
1185 CTK_CSS_PROVIDER_ERROR_SYNTAX,
1186 "Failed to parse binding set.");
1187 }
1188
1189 g_free (name);
1190
1191 if (!_ctk_css_parser_try (scanner->parser, ";", TRUE(!(0))))
1192 {
1193 if (!_ctk_css_parser_begins_with (scanner->parser, '}') &&
1194 !_ctk_css_parser_is_eof (scanner->parser))
1195 {
1196 ctk_css_provider_error_literal (scanner->provider,
1197 scanner,
1198 CTK_CSS_PROVIDER_ERROR(ctk_css_provider_error_quark ()),
1199 CTK_CSS_PROVIDER_ERROR_SYNTAX,
1200 "Expected semicolon");
1201 _ctk_css_parser_resync (scanner->parser, TRUE(!(0)), '}');
1202 }
1203 }
1204 }
1205
1206 if (!_ctk_css_parser_try (scanner->parser, "}", TRUE(!(0))))
1207 {
1208 ctk_css_provider_error_literal (scanner->provider,
1209 scanner,
1210 CTK_CSS_PROVIDER_ERROR(ctk_css_provider_error_quark ()),
1211 CTK_CSS_PROVIDER_ERROR_SYNTAX,
1212 "expected '}' after declarations");
1213 if (!_ctk_css_parser_is_eof (scanner->parser))
1214 _ctk_css_parser_resync (scanner->parser, FALSE(0), 0);
1215 }
1216
1217skip_semicolon:
1218 if (_ctk_css_parser_begins_with (scanner->parser, ';'))
1219 {
1220 ctk_css_provider_error_literal (scanner->provider,
1221 scanner,
1222 CTK_CSS_PROVIDER_ERROR(ctk_css_provider_error_quark ()),
1223 CTK_CSS_PROVIDER_ERROR_DEPRECATED,
1224 "Nonstandard semicolon at end of binding set");
1225 _ctk_css_parser_try (scanner->parser, ";", TRUE(!(0)));
1226 }
1227
1228 ctk_css_scanner_pop_section (scanner, CTK_CSS_SECTION_BINDING_SET);
1229
1230 return TRUE(!(0));
1231}
1232
1233static gboolean
1234parse_keyframes (CtkCssScanner *scanner)
1235{
1236 CtkCssKeyframes *keyframes;
1237 char *name;
1238
1239 ctk_css_scanner_push_section (scanner, CTK_CSS_SECTION_KEYFRAMES);
1240
1241 if (!_ctk_css_parser_try (scanner->parser, "@keyframes", TRUE(!(0))))
1242 {
1243 ctk_css_scanner_pop_section (scanner, CTK_CSS_SECTION_KEYFRAMES);
1244 return FALSE(0);
1245 }
1246
1247 name = _ctk_css_parser_try_ident (scanner->parser, TRUE(!(0)));
1248 if (name == NULL((void*)0))
1249 {
1250 ctk_css_provider_error_literal (scanner->provider,
1251 scanner,
1252 CTK_CSS_PROVIDER_ERROR(ctk_css_provider_error_quark ()),
1253 CTK_CSS_PROVIDER_ERROR_SYNTAX,
1254 "Expected name for keyframes");
1255 _ctk_css_parser_resync (scanner->parser, TRUE(!(0)), 0);
1256 goto exit;
1257 }
1258
1259 if (!_ctk_css_parser_try (scanner->parser, "{", TRUE(!(0))))
1260 {
1261 ctk_css_provider_error_literal (scanner->provider,
1262 scanner,
1263 CTK_CSS_PROVIDER_ERROR(ctk_css_provider_error_quark ()),
1264 CTK_CSS_PROVIDER_ERROR_SYNTAX,
1265 "Expected '{' for keyframes");
1266 _ctk_css_parser_resync (scanner->parser, TRUE(!(0)), 0);
1267 g_free (name);
1268 goto exit;
1269 }
1270
1271 keyframes = _ctk_css_keyframes_parse (scanner->parser);
1272 if (keyframes == NULL((void*)0))
1273 {
1274 _ctk_css_parser_resync (scanner->parser, TRUE(!(0)), '}');
1275 g_free (name);
1276 goto exit;
1277 }
1278
1279 g_hash_table_insert (scanner->provider->priv->keyframes, name, keyframes);
1280
1281 if (!_ctk_css_parser_try (scanner->parser, "}", TRUE(!(0))))
1282 {
1283 ctk_css_provider_error_literal (scanner->provider,
1284 scanner,
1285 CTK_CSS_PROVIDER_ERROR(ctk_css_provider_error_quark ()),
1286 CTK_CSS_PROVIDER_ERROR_SYNTAX,
1287 "expected '}' after declarations");
1288 if (!_ctk_css_parser_is_eof (scanner->parser))
1289 _ctk_css_parser_resync (scanner->parser, FALSE(0), 0);
1290 }
1291
1292exit:
1293 ctk_css_scanner_pop_section (scanner, CTK_CSS_SECTION_KEYFRAMES);
1294
1295 return TRUE(!(0));
1296}
1297
1298static void
1299parse_at_keyword (CtkCssScanner *scanner)
1300{
1301 if (parse_import (scanner))
1302 return;
1303 if (parse_color_definition (scanner))
1304 return;
1305 if (parse_binding_set (scanner))
1306 return;
1307 if (parse_keyframes (scanner))
1308 return;
1309
1310 else
1311 {
1312 ctk_css_provider_error_literal (scanner->provider,
1313 scanner,
1314 CTK_CSS_PROVIDER_ERROR(ctk_css_provider_error_quark ()),
1315 CTK_CSS_PROVIDER_ERROR_SYNTAX,
1316 "unknown @ rule");
1317 _ctk_css_parser_resync (scanner->parser, TRUE(!(0)), 0);
1318 }
1319}
1320
1321static GSList *
1322parse_selector_list (CtkCssScanner *scanner)
1323{
1324 GSList *selectors = NULL((void*)0);
1325
1326 ctk_css_scanner_push_section (scanner, CTK_CSS_SECTION_SELECTOR);
1327
1328 do {
1329 CtkCssSelector *select = _ctk_css_selector_parse (scanner->parser);
1330
1331 if (select == NULL((void*)0))
1332 {
1333 g_slist_free_full (selectors, (GDestroyNotify) _ctk_css_selector_free);
1334 _ctk_css_parser_resync (scanner->parser, FALSE(0), 0);
1335 ctk_css_scanner_pop_section (scanner, CTK_CSS_SECTION_SELECTOR);
1336 return NULL((void*)0);
1337 }
1338
1339 selectors = g_slist_prepend (selectors, select);
1340 }
1341 while (_ctk_css_parser_try (scanner->parser, ",", TRUE(!(0))));
1342
1343 ctk_css_scanner_pop_section (scanner, CTK_CSS_SECTION_SELECTOR);
1344
1345 return selectors;
1346}
1347
1348static gboolean
1349name_is_style_property (const char *name)
1350{
1351 if (name[0] != '-')
1352 return FALSE(0);
1353
1354 if (g_str_has_prefix (name, "-ctk-")(__builtin_constant_p ("-ctk-")? __extension__ ({ const char *
const __str = (name); const char * const __prefix = ("-ctk-"
); gboolean __result = (0); if (__str == ((void*)0) || __prefix
== ((void*)0)) __result = (g_str_has_prefix) (__str, __prefix
); else { const size_t __str_len = strlen (((__str) + !(__str
))); const size_t __prefix_len = strlen (((__prefix) + !(__prefix
))); if (__str_len >= __prefix_len) __result = memcmp (((__str
) + !(__str)), ((__prefix) + !(__prefix)), __prefix_len) == 0
; } __result; }) : (g_str_has_prefix) (name, "-ctk-") )
)
1355 return FALSE(0);
1356
1357 return TRUE(!(0));
1358}
1359
1360static void
1361warn_if_deprecated (CtkCssScanner *scanner,
1362 const gchar *name)
1363{
1364 gchar *n = NULL((void*)0);
1365 gchar *p;
1366 const gchar *type_name;
1367 const gchar *property_name;
1368 GType type;
1369 GTypeClass *class = NULL((void*)0);
1370 GParamSpec *pspec;
1371
1372 n = g_strdup (name)g_strdup_inline (name);
1373
1374 /* skip initial - */
1375 type_name = n + 1;
1376
1377 p = strchr (type_name, '-');
1378 if (!p)
1379 goto out;
1380
1381 p[0] = '\0';
1382 property_name = p + 1;
1383
1384 type = g_type_from_name (type_name);
1385 if (type == G_TYPE_INVALID((GType) ((0) << (2))) ||
1386 !g_type_is_a (type, CTK_TYPE_WIDGET)((type) == ((ctk_widget_get_type ())) || (g_type_is_a) ((type
), ((ctk_widget_get_type ()))))
)
1387 goto out;
1388
1389 class = g_type_class_ref (type);
1390 pspec = ctk_widget_class_find_style_property (CTK_WIDGET_CLASS (class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((class)), ((ctk_widget_get_type ()))))))
, property_name);
1391 if (!pspec)
1392 goto out;
1393
1394 if (!(pspec->flags & G_PARAM_DEPRECATED))
1395 goto out;
1396
1397 _ctk_css_parser_error_full (scanner->parser,
1398 CTK_CSS_PROVIDER_ERROR_DEPRECATED,
1399 "The style property %s:%s is deprecated and shouldn't be "
1400 "used anymore. It will be removed in a future version",
1401 g_type_name (pspec->owner_type), pspec->name);
1402
1403out:
1404 g_free (n);
1405 if (class)
1406 g_type_class_unref (class);
1407}
1408
1409static void
1410parse_declaration (CtkCssScanner *scanner,
1411 CtkCssRuleset *ruleset)
1412{
1413 CtkStyleProperty *property;
1414 char *name;
1415
1416 ctk_css_scanner_push_section (scanner, CTK_CSS_SECTION_DECLARATION);
1417
1418 name = _ctk_css_parser_try_ident (scanner->parser, TRUE(!(0)));
1419 if (name == NULL((void*)0))
1420 goto check_for_semicolon;
1421
1422 property = _ctk_style_property_lookup (name);
1423 if (property == NULL((void*)0) && !name_is_style_property (name))
1424 {
1425 ctk_css_provider_error (scanner->provider,
1426 scanner,
1427 CTK_CSS_PROVIDER_ERROR(ctk_css_provider_error_quark ()),
1428 CTK_CSS_PROVIDER_ERROR_NAME,
1429 "'%s' is not a valid property name",
1430 name);
1431 _ctk_css_parser_resync (scanner->parser, TRUE(!(0)), '}');
1432 g_free (name);
1433 ctk_css_scanner_pop_section (scanner, CTK_CSS_SECTION_DECLARATION);
1434 return;
1435 }
1436
1437 if (property != NULL((void*)0) && strcmp (name, property->name) != 0)
1438 {
1439 ctk_css_provider_error (scanner->provider,
1440 scanner,
1441 CTK_CSS_PROVIDER_ERROR(ctk_css_provider_error_quark ()),
1442 CTK_CSS_PROVIDER_ERROR_DEPRECATED,
1443 "The '%s' property has been renamed to '%s'",
1444 name, property->name);
1445 }
1446 else if (strcmp (name, "engine") == 0)
1447 {
1448 ctk_css_provider_error (scanner->provider,
1449 scanner,
1450 CTK_CSS_PROVIDER_ERROR(ctk_css_provider_error_quark ()),
1451 CTK_CSS_PROVIDER_ERROR_DEPRECATED,
1452 "The '%s' property is ignored",
1453 name);
1454 }
1455
1456 if (!_ctk_css_parser_try (scanner->parser, ":", TRUE(!(0))))
1457 {
1458 ctk_css_provider_invalid_token (scanner->provider, scanner, "':'");
1459 _ctk_css_parser_resync (scanner->parser, TRUE(!(0)), '}');
1460 g_free (name);
1461 ctk_css_scanner_pop_section (scanner, CTK_CSS_SECTION_DECLARATION);
1462 return;
1463 }
1464
1465 if (property)
1466 {
1467 CtkCssValue *value;
1468
1469 g_free (name);
1470
1471 ctk_css_scanner_push_section (scanner, CTK_CSS_SECTION_VALUE);
1472
1473 value = _ctk_style_property_parse_value (property,
1474 scanner->parser);
1475
1476 if (value == NULL((void*)0))
1477 {
1478 _ctk_css_parser_resync (scanner->parser, TRUE(!(0)), '}');
1479 ctk_css_scanner_pop_section (scanner, CTK_CSS_SECTION_VALUE);
1480 ctk_css_scanner_pop_section (scanner, CTK_CSS_SECTION_DECLARATION);
1481 return;
1482 }
1483
1484 if (!_ctk_css_parser_begins_with (scanner->parser, ';') &&
1485 !_ctk_css_parser_begins_with (scanner->parser, '}') &&
1486 !_ctk_css_parser_is_eof (scanner->parser))
1487 {
1488 ctk_css_provider_error (scanner->provider,
1489 scanner,
1490 CTK_CSS_PROVIDER_ERROR(ctk_css_provider_error_quark ()),
1491 CTK_CSS_PROVIDER_ERROR_SYNTAX,
1492 "Junk at end of value for %s", property->name);
1493 _ctk_css_parser_resync (scanner->parser, TRUE(!(0)), '}');
1494 ctk_css_scanner_pop_section (scanner, CTK_CSS_SECTION_VALUE);
1495 ctk_css_scanner_pop_section (scanner, CTK_CSS_SECTION_DECLARATION);
1496 return;
1497 }
1498
1499 if (CTK_IS_CSS_SHORTHAND_PROPERTY (property)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
property); GType __t = ((_ctk_css_shorthand_property_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))
)
1500 {
1501 CtkCssShorthandProperty *shorthand = CTK_CSS_SHORTHAND_PROPERTY (property)((((CtkCssShorthandProperty*) (void *) g_type_check_instance_cast
((GTypeInstance*) (property), ((_ctk_css_shorthand_property_get_type
()))))))
;
1502 guint i;
1503
1504 for (i = 0; i < _ctk_css_shorthand_property_get_n_subproperties (shorthand); i++)
1505 {
1506 CtkCssStyleProperty *child = _ctk_css_shorthand_property_get_subproperty (shorthand, i);
1507 CtkCssValue *sub = _ctk_css_array_value_get_nth (value, i);
1508
1509 ctk_css_ruleset_add (ruleset, child, _ctk_css_value_ref (sub), scanner->section);
1510 }
1511
1512 _ctk_css_value_unref (value);
1513 }
1514 else if (CTK_IS_CSS_STYLE_PROPERTY (property)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
property); GType __t = ((_ctk_css_style_property_get_type ())
); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))
)
1515 {
1516 ctk_css_ruleset_add (ruleset, CTK_CSS_STYLE_PROPERTY (property)((((CtkCssStyleProperty*) (void *) g_type_check_instance_cast
((GTypeInstance*) (property), ((_ctk_css_style_property_get_type
()))))))
, value, scanner->section);
1517 }
1518 else
1519 {
1520 g_assert_not_reached ()do { g_assertion_message_expr ("Ctk", "ctkcssprovider.c", 1520
, ((const char*) (__func__)), ((void*)0)); } while (0)
;
1521 _ctk_css_value_unref (value);
1522 }
1523
1524
1525 ctk_css_scanner_pop_section (scanner, CTK_CSS_SECTION_VALUE);
1526 }
1527 else if (name_is_style_property (name))
1528 {
1529 char *value_str;
1530
1531 warn_if_deprecated (scanner, name);
1532
1533 ctk_css_scanner_push_section (scanner, CTK_CSS_SECTION_VALUE);
1534
1535 value_str = _ctk_css_parser_read_value (scanner->parser);
1536 if (value_str)
1537 {
1538 WidgetPropertyValue *val;
1539
1540 val = widget_property_value_new (name, scanner->section);
1541 val->value = value_str;
1542
1543 ctk_css_ruleset_add_style (ruleset, name, val);
1544 }
1545 else
1546 {
1547 _ctk_css_parser_resync (scanner->parser, TRUE(!(0)), '}');
1548 ctk_css_scanner_pop_section (scanner, CTK_CSS_SECTION_VALUE);
1549 ctk_css_scanner_pop_section (scanner, CTK_CSS_SECTION_DECLARATION);
1550 return;
1551 }
1552
1553 ctk_css_scanner_pop_section (scanner, CTK_CSS_SECTION_VALUE);
1554 }
1555 else
1556 g_free (name);
1557
1558check_for_semicolon:
1559 ctk_css_scanner_pop_section (scanner, CTK_CSS_SECTION_DECLARATION);
1560
1561 if (!_ctk_css_parser_try (scanner->parser, ";", TRUE(!(0))))
1562 {
1563 if (!_ctk_css_parser_begins_with (scanner->parser, '}') &&
1564 !_ctk_css_parser_is_eof (scanner->parser))
1565 {
1566 ctk_css_provider_error_literal (scanner->provider,
1567 scanner,
1568 CTK_CSS_PROVIDER_ERROR(ctk_css_provider_error_quark ()),
1569 CTK_CSS_PROVIDER_ERROR_SYNTAX,
1570 "Expected semicolon");
1571 _ctk_css_parser_resync (scanner->parser, TRUE(!(0)), '}');
1572 }
1573 }
1574}
1575
1576static void
1577parse_declarations (CtkCssScanner *scanner,
1578 CtkCssRuleset *ruleset)
1579{
1580 while (!_ctk_css_parser_is_eof (scanner->parser) &&
1581 !_ctk_css_parser_begins_with (scanner->parser, '}'))
1582 {
1583 parse_declaration (scanner, ruleset);
1584 }
1585}
1586
1587static void
1588parse_ruleset (CtkCssScanner *scanner)
1589{
1590 GSList *selectors;
1591 CtkCssRuleset ruleset = { 0, };
1592
1593 ctk_css_scanner_push_section (scanner, CTK_CSS_SECTION_RULESET);
1594
1595 selectors = parse_selector_list (scanner);
1596 if (selectors == NULL((void*)0))
1597 {
1598 ctk_css_scanner_pop_section (scanner, CTK_CSS_SECTION_RULESET);
1599 return;
1600 }
1601
1602 if (!_ctk_css_parser_try (scanner->parser, "{", TRUE(!(0))))
1603 {
1604 ctk_css_provider_error_literal (scanner->provider,
1605 scanner,
1606 CTK_CSS_PROVIDER_ERROR(ctk_css_provider_error_quark ()),
1607 CTK_CSS_PROVIDER_ERROR_SYNTAX,
1608 "expected '{' after selectors");
1609 _ctk_css_parser_resync (scanner->parser, FALSE(0), 0);
1610 g_slist_free_full (selectors, (GDestroyNotify) _ctk_css_selector_free);
1611 ctk_css_scanner_pop_section (scanner, CTK_CSS_SECTION_RULESET);
1612 return;
1613 }
1614
1615 parse_declarations (scanner, &ruleset);
1616
1617 if (!_ctk_css_parser_try (scanner->parser, "}", TRUE(!(0))))
1618 {
1619 ctk_css_provider_error_literal (scanner->provider,
1620 scanner,
1621 CTK_CSS_PROVIDER_ERROR(ctk_css_provider_error_quark ()),
1622 CTK_CSS_PROVIDER_ERROR_SYNTAX,
1623 "expected '}' after declarations");
1624 if (!_ctk_css_parser_is_eof (scanner->parser))
1625 {
1626 _ctk_css_parser_resync (scanner->parser, FALSE(0), 0);
1627 g_slist_free_full (selectors, (GDestroyNotify) _ctk_css_selector_free);
1628 ctk_css_ruleset_clear (&ruleset);
1629 ctk_css_scanner_pop_section (scanner, CTK_CSS_SECTION_RULESET);
1630 }
1631 }
1632
1633 css_provider_commit (scanner->provider, selectors, &ruleset);
1634 ctk_css_ruleset_clear (&ruleset);
1635 ctk_css_scanner_pop_section (scanner, CTK_CSS_SECTION_RULESET);
1636}
1637
1638static void
1639parse_statement (CtkCssScanner *scanner)
1640{
1641 if (_ctk_css_parser_begins_with (scanner->parser, '@'))
1642 parse_at_keyword (scanner);
1643 else
1644 parse_ruleset (scanner);
1645}
1646
1647static void
1648parse_stylesheet (CtkCssScanner *scanner)
1649{
1650 ctk_css_scanner_push_section (scanner, CTK_CSS_SECTION_DOCUMENT);
1651
1652 _ctk_css_parser_skip_whitespace (scanner->parser);
1653
1654 while (!_ctk_css_parser_is_eof (scanner->parser))
1655 {
1656 if (_ctk_css_parser_try (scanner->parser, "<!--", TRUE(!(0))) ||
1657 _ctk_css_parser_try (scanner->parser, "-->", TRUE(!(0))))
1658 continue;
1659
1660 parse_statement (scanner);
1661 }
1662
1663 ctk_css_scanner_pop_section (scanner, CTK_CSS_SECTION_DOCUMENT);
1664}
1665
1666static int
1667ctk_css_provider_compare_rule (gconstpointer a_,
1668 gconstpointer b_)
1669{
1670 const CtkCssRuleset *a = (const CtkCssRuleset *) a_;
1671 const CtkCssRuleset *b = (const CtkCssRuleset *) b_;
1672 int compare;
1673
1674 compare = _ctk_css_selector_compare (a->selector, b->selector);
1675 if (compare != 0)
1676 return compare;
1677
1678 return 0;
1679}
1680
1681static void
1682ctk_css_provider_postprocess (CtkCssProvider *css_provider)
1683{
1684 CtkCssProviderPrivate *priv = css_provider->priv;
1685 CtkCssSelectorTreeBuilder *builder;
1686 guint i;
1687
1688 g_array_sort (priv->rulesets, ctk_css_provider_compare_rule);
1689
1690 builder = _ctk_css_selector_tree_builder_new ();
1691 for (i = 0; i < priv->rulesets->len; i++)
1692 {
1693 CtkCssRuleset *ruleset;
1694
1695 ruleset = &g_array_index (priv->rulesets, CtkCssRuleset, i)(((CtkCssRuleset*) (void *) (priv->rulesets)->data) [(i
)])
;
1696
1697 _ctk_css_selector_tree_builder_add (builder,
1698 ruleset->selector,
1699 &ruleset->selector_match,
1700 ruleset);
1701 }
1702
1703 priv->tree = _ctk_css_selector_tree_builder_build (builder);
1704 _ctk_css_selector_tree_builder_free (builder);
1705
1706#ifndef VERIFY_TREE
1707 for (i = 0; i < priv->rulesets->len; i++)
1708 {
1709 CtkCssRuleset *ruleset;
1710
1711 ruleset = &g_array_index (priv->rulesets, CtkCssRuleset, i)(((CtkCssRuleset*) (void *) (priv->rulesets)->data) [(i
)])
;
1712
1713 _ctk_css_selector_free (ruleset->selector);
1714 ruleset->selector = NULL((void*)0);
1715 }
1716#endif
1717}
1718
1719static gboolean
1720ctk_css_provider_load_internal (CtkCssProvider *css_provider,
1721 CtkCssScanner *parent,
1722 GFile *file,
1723 const char *text,
1724 GError **error)
1725{
1726 GBytes *free_bytes = NULL((void*)0);
1727 CtkCssScanner *scanner;
1728 gulong error_handler;
1729
1730 if (error)
1731 error_handler = g_signal_connect (css_provider,g_signal_connect_data ((css_provider), ("parsing-error"), (((
GCallback) (ctk_css_provider_propagate_error))), (error), ((void
*)0), (GConnectFlags) 0)
1732 "parsing-error",g_signal_connect_data ((css_provider), ("parsing-error"), (((
GCallback) (ctk_css_provider_propagate_error))), (error), ((void
*)0), (GConnectFlags) 0)
1733 G_CALLBACK (ctk_css_provider_propagate_error),g_signal_connect_data ((css_provider), ("parsing-error"), (((
GCallback) (ctk_css_provider_propagate_error))), (error), ((void
*)0), (GConnectFlags) 0)
1734 error)g_signal_connect_data ((css_provider), ("parsing-error"), (((
GCallback) (ctk_css_provider_propagate_error))), (error), ((void
*)0), (GConnectFlags) 0)
;
1735 else
1736 error_handler = 0; /* silence gcc */
1737
1738 if (text == NULL((void*)0))
1739 {
1740 GError *load_error = NULL((void*)0);
1741
1742 free_bytes = ctk_file_load_bytes (file, NULL((void*)0), &load_error);
1743
1744 if (free_bytes != NULL((void*)0))
1745 {
1746 text = g_bytes_get_data (free_bytes, NULL((void*)0));
1747 }
1748 else
1749 {
1750 if (parent == NULL((void*)0))
1751 {
1752 scanner = ctk_css_scanner_new (css_provider,
1753 NULL((void*)0),
1754 NULL((void*)0),
1755 file,
1756 "");
1757
1758 ctk_css_scanner_push_section (scanner, CTK_CSS_SECTION_DOCUMENT);
1759 }
1760 else
1761 scanner = parent;
1762
1763 ctk_css_provider_error (css_provider,
1764 scanner,
1765 CTK_CSS_PROVIDER_ERROR(ctk_css_provider_error_quark ()),
1766 CTK_CSS_PROVIDER_ERROR_IMPORT,
1767 "Failed to import: %s",
1768 load_error->message);
1769
1770 if (parent == NULL((void*)0))
1771 {
1772 ctk_css_scanner_pop_section (scanner, CTK_CSS_SECTION_DOCUMENT);
1773
1774 ctk_css_scanner_destroy (scanner);
1775 }
1776 }
1777 }
1778
1779 if (text)
1780 {
1781 scanner = ctk_css_scanner_new (css_provider,
1782 parent,
1783 parent ? parent->section : NULL((void*)0),
1784 file,
1785 text);
1786
1787 parse_stylesheet (scanner);
1788
1789 ctk_css_scanner_destroy (scanner);
1790
1791 if (parent == NULL((void*)0))
1792 ctk_css_provider_postprocess (css_provider);
1793 }
1794
1795 if (free_bytes)
1796 g_bytes_unref (free_bytes);
1797
1798 if (error)
1799 {
1800 g_signal_handler_disconnect (css_provider, error_handler);
1801
1802 if (*error)
1803 {
1804 /* We clear all contents from the provider for backwards compat reasons */
1805 ctk_css_provider_reset (css_provider);
1806 return FALSE(0);
1807 }
1808 }
1809
1810 return TRUE(!(0));
1811}
1812
1813/**
1814 * ctk_css_provider_load_from_data:
1815 * @css_provider: a #CtkCssProvider
1816 * @data: (array length=length) (element-type guint8): CSS data loaded in memory
1817 * @length: the length of @data in bytes, or -1 for NUL terminated strings. If
1818 * @length is not -1, the code will assume it is not NUL terminated and will
1819 * potentially do a copy.
1820 * @error: (out) (allow-none): return location for a #GError, or %NULL
1821 *
1822 * Loads @data into @css_provider, and by doing so clears any previously loaded
1823 * information.
1824 *
1825 * Returns: %TRUE. The return value is deprecated and %FALSE will only be
1826 * returned for backwards compatibility reasons if an @error is not
1827 * %NULL and a loading error occurred. To track errors while loading
1828 * CSS, connect to the #CtkCssProvider::parsing-error signal.
1829 **/
1830gboolean
1831ctk_css_provider_load_from_data (CtkCssProvider *css_provider,
1832 const gchar *data,
1833 gssize length,
1834 GError **error)
1835{
1836 char *free_data;
1837 gboolean ret;
1838
1839 g_return_val_if_fail (CTK_IS_CSS_PROVIDER (css_provider), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((css_provider)); GType __t = ((ctk_css_provider_get_type (
))); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_CSS_PROVIDER (css_provider)"); return
((0)); } } while (0)
;
1840 g_return_val_if_fail (data != NULL, FALSE)do { if ((data != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "data != NULL"); return (
(0)); } } while (0)
;
1841
1842 if (length < 0)
1843 {
1844 length = strlen (data);
Value stored to 'length' is never read
1845 free_data = NULL((void*)0);
1846 }
1847 else
1848 {
1849 free_data = g_strndup (data, length);
1850 data = free_data;
1851 }
1852
1853 ctk_css_provider_reset (css_provider);
1854
1855 ret = ctk_css_provider_load_internal (css_provider, NULL((void*)0), NULL((void*)0), data, error);
1856
1857 g_free (free_data);
1858
1859 _ctk_style_provider_private_changed (CTK_STYLE_PROVIDER_PRIVATE (css_provider)((((CtkStyleProviderPrivate*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((css_provider)), ((_ctk_style_provider_private_get_type
()))))))
);
1860
1861 return ret;
1862}
1863
1864/**
1865 * ctk_css_provider_load_from_file:
1866 * @css_provider: a #CtkCssProvider
1867 * @file: #GFile pointing to a file to load
1868 * @error: (out) (allow-none): return location for a #GError, or %NULL
1869 *
1870 * Loads the data contained in @file into @css_provider, making it
1871 * clear any previously loaded information.
1872 *
1873 * Returns: %TRUE. The return value is deprecated and %FALSE will only be
1874 * returned for backwards compatibility reasons if an @error is not
1875 * %NULL and a loading error occurred. To track errors while loading
1876 * CSS, connect to the #CtkCssProvider::parsing-error signal.
1877 **/
1878gboolean
1879ctk_css_provider_load_from_file (CtkCssProvider *css_provider,
1880 GFile *file,
1881 GError **error)
1882{
1883 gboolean success;
1884
1885 g_return_val_if_fail (CTK_IS_CSS_PROVIDER (css_provider), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((css_provider)); GType __t = ((ctk_css_provider_get_type (
))); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_CSS_PROVIDER (css_provider)"); return
((0)); } } while (0)
;
1886 g_return_val_if_fail (G_IS_FILE (file), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = ((g_file_get_type ())); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "G_IS_FILE (file)"); return ((0)); } } while (0)
;
1887
1888 ctk_css_provider_reset (css_provider);
1889
1890 success = ctk_css_provider_load_internal (css_provider, NULL((void*)0), file, NULL((void*)0), error);
1891
1892 _ctk_style_provider_private_changed (CTK_STYLE_PROVIDER_PRIVATE (css_provider)((((CtkStyleProviderPrivate*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((css_provider)), ((_ctk_style_provider_private_get_type
()))))))
);
1893
1894 return success;
1895}
1896
1897/**
1898 * ctk_css_provider_load_from_path:
1899 * @css_provider: a #CtkCssProvider
1900 * @path: the path of a filename to load, in the GLib filename encoding
1901 * @error: (out) (allow-none): return location for a #GError, or %NULL
1902 *
1903 * Loads the data contained in @path into @css_provider, making it clear
1904 * any previously loaded information.
1905 *
1906 * Returns: %TRUE. The return value is deprecated and %FALSE will only be
1907 * returned for backwards compatibility reasons if an @error is not
1908 * %NULL and a loading error occurred. To track errors while loading
1909 * CSS, connect to the #CtkCssProvider::parsing-error signal.
1910 **/
1911gboolean
1912ctk_css_provider_load_from_path (CtkCssProvider *css_provider,
1913 const gchar *path,
1914 GError **error)
1915{
1916 GFile *file;
1917 gboolean result;
1918
1919 g_return_val_if_fail (CTK_IS_CSS_PROVIDER (css_provider), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((css_provider)); GType __t = ((ctk_css_provider_get_type (
))); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_CSS_PROVIDER (css_provider)"); return
((0)); } } while (0)
;
1920 g_return_val_if_fail (path != NULL, FALSE)do { if ((path != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "path != NULL"); return (
(0)); } } while (0)
;
1921
1922 file = g_file_new_for_path (path);
1923
1924 result = ctk_css_provider_load_from_file (css_provider, file, error);
1925
1926 g_object_unref (file);
1927
1928 return result;
1929}
1930
1931/**
1932 * ctk_css_provider_load_from_resource:
1933 * @css_provider: a #CtkCssProvider
1934 * @resource_path: a #GResource resource path
1935 *
1936 * Loads the data contained in the resource at @resource_path into
1937 * the #CtkCssProvider, clearing any previously loaded information.
1938 *
1939 * To track errors while loading CSS, connect to the
1940 * #CtkCssProvider::parsing-error signal.
1941 *
1942 * Since: 3.16
1943 */
1944void
1945ctk_css_provider_load_from_resource (CtkCssProvider *css_provider,
1946 const gchar *resource_path)
1947{
1948 GFile *file;
1949 gchar *uri, *escaped;
1950
1951 g_return_if_fail (CTK_IS_CSS_PROVIDER (css_provider))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((css_provider)); GType __t = ((ctk_css_provider_get_type (
))); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_CSS_PROVIDER (css_provider)"); return
; } } while (0)
;
1952 g_return_if_fail (resource_path != NULL)do { if ((resource_path != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "resource_path != NULL")
; return; } } while (0)
;
1953
1954 escaped = g_uri_escape_string (resource_path,
1955 G_URI_RESERVED_CHARS_ALLOWED_IN_PATH"!$&'()*+,;=" ":@" "/", FALSE(0));
1956 uri = g_strconcat ("resource://", escaped, NULL((void*)0));
1957 g_free (escaped);
1958
1959 file = g_file_new_for_uri (uri);
1960 g_free (uri);
1961
1962 ctk_css_provider_load_from_file (css_provider, file, NULL((void*)0));
1963
1964 g_object_unref (file);
1965}
1966
1967/**
1968 * ctk_css_provider_get_default:
1969 *
1970 * Returns the provider containing the style settings used as a
1971 * fallback for all widgets.
1972 *
1973 * Returns: (transfer none): The provider used for fallback styling.
1974 * This memory is owned by CTK+, and you must not free it.
1975 *
1976 * Deprecated: 3.24: Use ctk_css_provider_new() instead.
1977 **/
1978CtkCssProvider *
1979ctk_css_provider_get_default (void)
1980{
1981 static CtkCssProvider *provider;
1982
1983 if (G_UNLIKELY (!provider)(!provider))
1984 {
1985 provider = ctk_css_provider_new ();
1986 }
1987
1988 return provider;
1989}
1990
1991gchar *
1992_ctk_get_theme_dir (void)
1993{
1994 const gchar *var;
1995
1996 var = g_getenv ("CTK_DATA_PREFIX");
1997 if (var == NULL((void*)0))
1998 var = _ctk_get_data_prefix ();
1999 return g_build_filename (var, "share", "themes", NULL((void*)0));
2000}
2001
2002/* Return the path that this providers ctk.css was loaded from,
2003 * if it is part of a theme, otherwise NULL.
2004 */
2005const gchar *
2006_ctk_css_provider_get_theme_dir (CtkCssProvider *provider)
2007{
2008 return provider->priv->path;
2009}
2010
2011#if (CTK_MINOR_VERSION(25) % 2)
2012#define MINOR (CTK_MINOR_VERSION(25) + 1)
2013#else
2014#define MINOR CTK_MINOR_VERSION(25)
2015#endif
2016
2017/*
2018 * Look for
2019 * $dir/$subdir/ctk-3.16/ctk-$variant.css
2020 * $dir/$subdir/ctk-3.14/ctk-$variant.css
2021 * ...
2022 * $dir/$subdir/ctk-3.0/ctk-$variant.css
2023 * and return the first found file.
2024 * We don't check versions before 3.14,
2025 * since those CTK+ versions didn't have
2026 * the versioned loading mechanism.
2027 */
2028static gchar *
2029_ctk_css_find_theme_dir (const gchar *dir,
2030 const gchar *subdir,
2031 const gchar *name,
2032 const gchar *variant)
2033{
2034 gchar *file;
2035 gchar *base;
2036 gchar *subsubdir;
2037 gint i;
2038 gchar *path;
2039
2040 if (variant)
2041 file = g_strconcat ("ctk-", variant, ".css", NULL((void*)0));
2042 else
2043 file = g_strdup ("ctk.css")g_strdup_inline ("ctk.css");
2044
2045 if (subdir)
2046 base = g_build_filename (dir, subdir, name, NULL((void*)0));
2047 else
2048 base = g_build_filename (dir, name, NULL((void*)0));
2049
2050 for (i = MINOR; i >= 0; i = i - 2)
2051 {
2052 if (i < 14)
2053 i = 0;
2054
2055 subsubdir = g_strdup_printf ("ctk-3.%d", i);
2056 path = g_build_filename (base, subsubdir, file, NULL((void*)0));
2057 g_free (subsubdir);
2058
2059 if (g_file_test (path, G_FILE_TEST_EXISTS))
2060 break;
2061
2062 g_free (path);
2063 path = NULL((void*)0);
2064 }
2065
2066 g_free (file);
2067 g_free (base);
2068
2069 return path;
2070}
2071
2072#undef MINOR
2073
2074static gchar *
2075_ctk_css_find_theme (const gchar *name,
2076 const gchar *variant)
2077{
2078 gchar *path;
2079 const char *const *dirs;
2080 int i;
2081 char *dir;
2082
2083 /* First look in the user's data directory */
2084 path = _ctk_css_find_theme_dir (g_get_user_data_dir (), "themes", name, variant);
2085 if (path)
2086 return path;
2087
2088 /* Next look in the user's home directory */
2089 path = _ctk_css_find_theme_dir (g_get_home_dir (), ".themes", name, variant);
2090 if (path)
2091 return path;
2092
2093 /* Look in system data directories */
2094 dirs = g_get_system_data_dirs ();
2095 for (i = 0; dirs[i]; i++)
2096 {
2097 path = _ctk_css_find_theme_dir (dirs[i], "themes", name, variant);
2098 if (path)
2099 return path;
2100 }
2101
2102 /* Finally, try in the default theme directory */
2103 dir = _ctk_get_theme_dir ();
2104 path = _ctk_css_find_theme_dir (dir, NULL((void*)0), name, variant);
2105 g_free (dir);
2106
2107 return path;
2108}
2109
2110/**
2111 * _ctk_css_provider_load_named:
2112 * @provider: a #CtkCssProvider
2113 * @name: A theme name
2114 * @variant: (allow-none): variant to load, for example, "dark", or
2115 * %NULL for the default
2116 *
2117 * Loads a theme from the usual theme paths. The actual process of
2118 * finding the theme might change between releases, but it is
2119 * guaranteed that this function uses the same mechanism to load the
2120 * theme than CTK uses for loading its own theme.
2121 **/
2122void
2123_ctk_css_provider_load_named (CtkCssProvider *provider,
2124 const gchar *name,
2125 const gchar *variant)
2126{
2127 gchar *path;
2128 gchar *resource_path;
2129
2130 g_return_if_fail (CTK_IS_CSS_PROVIDER (provider))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((provider)); GType __t = ((ctk_css_provider_get_type ()))
; gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class
&& __inst->g_class->g_type == __t) __r = (!(0)
); else __r = g_type_check_instance_is_a (__inst, __t); __r; }
)))))) { } else { g_return_if_fail_warning ("Ctk", ((const char
*) (__func__)), "CTK_IS_CSS_PROVIDER (provider)"); return; } }
while (0)
;
2131 g_return_if_fail (name != NULL)do { if ((name != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "name != NULL"); return;
} } while (0)
;
2132
2133 ctk_css_provider_reset (provider);
2134
2135 /* try loading the resource for the theme. This is mostly meant for built-in
2136 * themes.
2137 */
2138 if (variant)
2139 resource_path = g_strdup_printf ("/org/ctk/libctk/theme/%s/ctk-%s.css", name, variant);
2140 else
2141 resource_path = g_strdup_printf ("/org/ctk/libctk/theme/%s/ctk.css", name);
2142
2143 if (g_resources_get_info (resource_path, 0, NULL((void*)0), NULL((void*)0), NULL((void*)0)))
2144 {
2145 ctk_css_provider_load_from_resource (provider, resource_path);
2146 g_free (resource_path);
2147 return;
2148 }
2149 g_free (resource_path);
2150
2151 /* Next try looking for files in the various theme directories. */
2152 path = _ctk_css_find_theme (name, variant);
2153 if (path)
2154 {
2155 char *dir, *resource_file;
2156 GResource *resource;
2157
2158 dir = g_path_get_dirname (path);
2159 resource_file = g_build_filename (dir, "ctk.gresource", NULL((void*)0));
2160 resource = g_resource_load (resource_file, NULL((void*)0));
2161 g_free (resource_file);
2162
2163 if (resource != NULL((void*)0))
2164 g_resources_register (resource);
2165
2166 ctk_css_provider_load_from_path (provider, path, NULL((void*)0));
2167
2168 /* Only set this after load, as load_from_path will clear it */
2169 provider->priv->resource = resource;
2170 provider->priv->path = dir;
2171
2172 g_free (path);
2173 }
2174 else
2175 {
2176 /* Things failed! Fall back! Fall back! */
2177
2178 if (variant)
2179 {
2180 /* If there was a variant, try without */
2181 _ctk_css_provider_load_named (provider, name, NULL((void*)0));
2182 }
2183 else
2184 {
2185 /* Worst case, fall back to the default */
2186 g_return_if_fail (!g_str_equal (name, DEFAULT_THEME_NAME))do { if ((!(strcmp ((const char *) (name), (const char *) ("Advaita"
)) == 0))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "!g_str_equal (name, DEFAULT_THEME_NAME)"
); return; } } while (0)
; /* infloop protection */
2187 _ctk_css_provider_load_named (provider, DEFAULT_THEME_NAME"Advaita", NULL((void*)0));
2188 }
2189 }
2190}
2191
2192/**
2193 * ctk_css_provider_get_named:
2194 * @name: A theme name
2195 * @variant: (allow-none): variant to load, for example, "dark", or
2196 * %NULL for the default
2197 *
2198 * Loads a theme from the usual theme paths
2199 *
2200 * Returns: (transfer none): a #CtkCssProvider with the theme loaded.
2201 * This memory is owned by CTK+, and you must not free it.
2202 */
2203CtkCssProvider *
2204ctk_css_provider_get_named (const gchar *name,
2205 const gchar *variant)
2206{
2207 static GHashTable *themes = NULL((void*)0);
2208 CtkCssProvider *provider;
2209 gchar *key;
2210
2211 if (variant == NULL((void*)0))
2212 key = g_strdup (name)g_strdup_inline (name);
2213 else
2214 key = g_strconcat (name, "-", variant, NULL((void*)0));
2215 if (G_UNLIKELY (!themes)(!themes))
2216 themes = g_hash_table_new (g_str_hash, g_str_equal);
2217
2218 provider = g_hash_table_lookup (themes, key);
2219
2220 if (!provider)
2221 {
2222 provider = ctk_css_provider_new ();
2223 _ctk_css_provider_load_named (provider, name, variant);
2224 g_hash_table_insert (themes, g_strdup (key)g_strdup_inline (key), provider);
2225 }
2226
2227 g_free (key);
2228
2229 return provider;
2230}
2231
2232static int
2233compare_properties (gconstpointer a, gconstpointer b, gpointer style)
2234{
2235 const guint *ua = a;
2236 const guint *ub = b;
2237 PropertyValue *styles = style;
2238
2239 return strcmp (_ctk_style_property_get_name (CTK_STYLE_PROPERTY (styles[*ua].property)((((CtkStyleProperty*) (void *) g_type_check_instance_cast ((
GTypeInstance*) (styles[*ua].property), ((_ctk_style_property_get_type
()))))))
),
2240 _ctk_style_property_get_name (CTK_STYLE_PROPERTY (styles[*ub].property)((((CtkStyleProperty*) (void *) g_type_check_instance_cast ((
GTypeInstance*) (styles[*ub].property), ((_ctk_style_property_get_type
()))))))
));
2241}
2242
2243static int
2244compare_names (gconstpointer a, gconstpointer b)
2245{
2246 const WidgetPropertyValue *aa = a;
2247 const WidgetPropertyValue *bb = b;
2248 return strcmp (aa->name, bb->name);
2249}
2250
2251static void
2252ctk_css_ruleset_print (const CtkCssRuleset *ruleset,
2253 GString *str)
2254{
2255 GList *values, *walk;
2256 WidgetPropertyValue *widget_value;
2257 guint i;
2258
2259 _ctk_css_selector_tree_match_print (ruleset->selector_match, str);
2260
2261 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))
;
2262
2263 if (ruleset->styles)
2264 {
2265 guint *sorted = g_new (guint, ruleset->n_styles)((guint *) g_malloc_n ((ruleset->n_styles), sizeof (guint)
))
;
2266
2267 for (i = 0; i < ruleset->n_styles; i++)
2268 sorted[i] = i;
2269
2270 /* so the output is identical for identical selector styles */
2271 g_qsort_with_data (sorted, ruleset->n_styles, sizeof (guint), compare_properties, ruleset->styles);
2272
2273 for (i = 0; i < ruleset->n_styles; i++)
2274 {
2275 PropertyValue *prop = &ruleset->styles[sorted[i]];
2276 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))
;
2277 g_string_append (str, _ctk_style_property_get_name (CTK_STYLE_PROPERTY (prop->property)))(__builtin_constant_p (_ctk_style_property_get_name (((((CtkStyleProperty
*) (void *) g_type_check_instance_cast ((GTypeInstance*) (prop
->property), ((_ctk_style_property_get_type ())))))))) ? __extension__
({ const char * const __val = (_ctk_style_property_get_name (
((((CtkStyleProperty*) (void *) g_type_check_instance_cast ((
GTypeInstance*) (prop->property), ((_ctk_style_property_get_type
())))))))); g_string_append_len_inline (str, __val, (__val !=
((void*)0)) ? (gssize) strlen (((__val) + !(__val))) : (gssize
) -1); }) : g_string_append_len_inline (str, _ctk_style_property_get_name
(((((CtkStyleProperty*) (void *) g_type_check_instance_cast (
(GTypeInstance*) (prop->property), ((_ctk_style_property_get_type
()))))))), (gssize) -1))
;
2278 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))
;
2279 _ctk_css_value_print (prop->value, str);
2280 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))
;
2281 }
2282
2283 g_free (sorted);
2284 }
2285
2286 if (ruleset->widget_style)
2287 {
2288 values = NULL((void*)0);
2289 for (widget_value = ruleset->widget_style; widget_value != NULL((void*)0); widget_value = widget_value->next)
2290 values = g_list_prepend (values, widget_value);
2291
2292 /* so the output is identical for identical selector styles */
2293 values = g_list_sort (values, compare_names);
2294
2295 for (walk = values; walk; walk = walk->next)
2296 {
2297 widget_value = walk->data;
2298
2299 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))
;
2300 g_string_append (str, widget_value->name)(__builtin_constant_p (widget_value->name) ? __extension__
({ const char * const __val = (widget_value->name); g_string_append_len_inline
(str, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val
) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(str, widget_value->name, (gssize) -1))
;
2301 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))
;
2302 g_string_append (str, widget_value->value)(__builtin_constant_p (widget_value->value) ? __extension__
({ const char * const __val = (widget_value->value); g_string_append_len_inline
(str, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val
) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(str, widget_value->value, (gssize) -1))
;
2303 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))
;
2304 }
2305
2306 g_list_free (values);
2307 }
2308
2309 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))
;
2310}
2311
2312static void
2313ctk_css_provider_print_colors (GHashTable *colors,
2314 GString *str)
2315{
2316 GList *keys, *walk;
2317
2318 keys = g_hash_table_get_keys (colors);
2319 /* so the output is identical for identical styles */
2320 keys = g_list_sort (keys, (GCompareFunc) strcmp);
2321
2322 for (walk = keys; walk; walk = walk->next)
2323 {
2324 const char *name = walk->data;
2325 CtkCssValue *color = g_hash_table_lookup (colors, (gpointer) name);
2326
2327 g_string_append (str, "@define-color ")(__builtin_constant_p ("@define-color ") ? __extension__ ({ const
char * const __val = ("@define-color "); g_string_append_len_inline
(str, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val
) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(str, "@define-color ", (gssize) -1))
;
2328 g_string_append (str, name)(__builtin_constant_p (name) ? __extension__ ({ const char * const
__val = (name); g_string_append_len_inline (str, __val, (__val
!= ((void*)0)) ? (gssize) strlen (((__val) + !(__val))) : (gssize
) -1); }) : g_string_append_len_inline (str, name, (gssize) -
1))
;
2329 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
))
;
2330 _ctk_css_value_print (color, str);
2331 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))
;
2332 }
2333
2334 g_list_free (keys);
2335}
2336
2337static void
2338ctk_css_provider_print_keyframes (GHashTable *keyframes,
2339 GString *str)
2340{
2341 GList *keys, *walk;
2342
2343 keys = g_hash_table_get_keys (keyframes);
2344 /* so the output is identical for identical styles */
2345 keys = g_list_sort (keys, (GCompareFunc) strcmp);
2346
2347 for (walk = keys; walk; walk = walk->next)
2348 {
2349 const char *name = walk->data;
2350 CtkCssKeyframes *keyframe = g_hash_table_lookup (keyframes, (gpointer) name);
2351
2352 if (str->len > 0)
2353 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))
;
2354 g_string_append (str, "@keyframes ")(__builtin_constant_p ("@keyframes ") ? __extension__ ({ const
char * const __val = ("@keyframes "); g_string_append_len_inline
(str, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val
) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(str, "@keyframes ", (gssize) -1))
;
2355 g_string_append (str, name)(__builtin_constant_p (name) ? __extension__ ({ const char * const
__val = (name); g_string_append_len_inline (str, __val, (__val
!= ((void*)0)) ? (gssize) strlen (((__val) + !(__val))) : (gssize
) -1); }) : g_string_append_len_inline (str, name, (gssize) -
1))
;
2356 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))
;
2357 _ctk_css_keyframes_print (keyframe, str);
2358 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))
;
2359 }
2360
2361 g_list_free (keys);
2362}
2363
2364/**
2365 * ctk_css_provider_to_string:
2366 * @provider: the provider to write to a string
2367 *
2368 * Converts the @provider into a string representation in CSS
2369 * format.
2370 *
2371 * Using ctk_css_provider_load_from_data() with the return value
2372 * from this function on a new provider created with
2373 * ctk_css_provider_new() will basically create a duplicate of
2374 * this @provider.
2375 *
2376 * Returns: a new string representing the @provider.
2377 *
2378 * Since: 3.2
2379 **/
2380char *
2381ctk_css_provider_to_string (CtkCssProvider *provider)
2382{
2383 CtkCssProviderPrivate *priv;
2384 GString *str;
2385 guint i;
2386
2387 g_return_val_if_fail (CTK_IS_CSS_PROVIDER (provider), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((provider)); GType __t = ((ctk_css_provider_get_type ()))
; gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class
&& __inst->g_class->g_type == __t) __r = (!(0)
); else __r = g_type_check_instance_is_a (__inst, __t); __r; }
)))))) { } else { g_return_if_fail_warning ("Ctk", ((const char
*) (__func__)), "CTK_IS_CSS_PROVIDER (provider)"); return (((
void*)0)); } } while (0)
;
2388
2389 priv = provider->priv;
2390
2391 str = g_string_new ("");
2392
2393 ctk_css_provider_print_colors (priv->symbolic_colors, str);
2394 ctk_css_provider_print_keyframes (priv->keyframes, str);
2395
2396 for (i = 0; i < priv->rulesets->len; i++)
2397 {
2398 if (str->len != 0)
2399 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))
;
2400 ctk_css_ruleset_print (&g_array_index (priv->rulesets, CtkCssRuleset, i)(((CtkCssRuleset*) (void *) (priv->rulesets)->data) [(i
)])
, str);
2401 }
2402
2403 return g_string_free (str, FALSE)(__builtin_constant_p ((0)) ? (((0)) ? (g_string_free) ((str)
, ((0))) : g_string_free_and_steal (str)) : (g_string_free) (
(str), ((0))))
;
2404}
2405