Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name ctkbuilder.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-171836-43636-1 -x c ctkbuilder.c
1/* CTK - The GIMP Toolkit
2 * Copyright (C) 1998-2002 James Henstridge <james@daa.com.au>
3 * Copyright (C) 2006-2007 Async Open Source,
4 * Johan Dahlin <jdahlin@async.com.br>,
5 * Henrique Romano <henrique@async.com.br>
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21/**
22 * SECTION:ctkbuilder
23 * @Short_description: Build an interface from an XML UI definition
24 * @Title: CtkBuilder
25 *
26 * A CtkBuilder is an auxiliary object that reads textual descriptions
27 * of a user interface and instantiates the described objects. To create
28 * a CtkBuilder from a user interface description, call
29 * ctk_builder_new_from_file(), ctk_builder_new_from_resource() or
30 * ctk_builder_new_from_string().
31 *
32 * In the (unusual) case that you want to add user interface
33 * descriptions from multiple sources to the same CtkBuilder you can
34 * call ctk_builder_new() to get an empty builder and populate it by
35 * (multiple) calls to ctk_builder_add_from_file(),
36 * ctk_builder_add_from_resource() or ctk_builder_add_from_string().
37 *
38 * A CtkBuilder holds a reference to all objects that it has constructed
39 * and drops these references when it is finalized. This finalization can
40 * cause the destruction of non-widget objects or widgets which are not
41 * contained in a toplevel window. For toplevel windows constructed by a
42 * builder, it is the responsibility of the user to call ctk_widget_destroy()
43 * to get rid of them and all the widgets they contain.
44 *
45 * The functions ctk_builder_get_object() and ctk_builder_get_objects()
46 * can be used to access the widgets in the interface by the names assigned
47 * to them inside the UI description. Toplevel windows returned by these
48 * functions will stay around until the user explicitly destroys them
49 * with ctk_widget_destroy(). Other widgets will either be part of a
50 * larger hierarchy constructed by the builder (in which case you should
51 * not have to worry about their lifecycle), or without a parent, in which
52 * case they have to be added to some container to make use of them.
53 * Non-widget objects need to be reffed with g_object_ref() to keep them
54 * beyond the lifespan of the builder.
55 *
56 * The function ctk_builder_connect_signals() and variants thereof can be
57 * used to connect handlers to the named signals in the description.
58 *
59 * # CtkBuilder UI Definitions # {#BUILDER-UI}
60 *
61 * CtkBuilder parses textual descriptions of user interfaces which are
62 * specified in an XML format which can be roughly described by the
63 * RELAX NG schema below. We refer to these descriptions as “CtkBuilder
64 * UI definitions” or just “UI definitions” if the context is clear.
65 * Do not confuse CtkBuilder UI Definitions with
66 * [CtkUIManager UI Definitions][XML-UI], which are more limited in scope.
67 * It is common to use `.ui` as the filename extension for files containing
68 * CtkBuilder UI definitions.
69 *
70 * [RELAX NG Compact Syntax](https://gitlab.gnome.org/GNOME/ctk/-/blob/ctk-3-24/ctk/ctkbuilder.rnc)
71 *
72 * The toplevel element is <interface>. It optionally takes a “domain”
73 * attribute, which will make the builder look for translated strings
74 * using dgettext() in the domain specified. This can also be done by
75 * calling ctk_builder_set_translation_domain() on the builder.
76 * Objects are described by <object> elements, which can contain
77 * <property> elements to set properties, <signal> elements which
78 * connect signals to handlers, and <child> elements, which describe
79 * child objects (most often widgets inside a container, but also e.g.
80 * actions in an action group, or columns in a tree model). A <child>
81 * element contains an <object> element which describes the child object.
82 * The target toolkit version(s) are described by <requires> elements,
83 * the “lib” attribute specifies the widget library in question (currently
84 * the only supported value is “ctk+”) and the “version” attribute specifies
85 * the target version in the form “<major>.<minor>”. The builder will error
86 * out if the version requirements are not met.
87 *
88 * Typically, the specific kind of object represented by an <object>
89 * element is specified by the “class” attribute. If the type has not
90 * been loaded yet, CTK+ tries to find the get_type() function from the
91 * class name by applying heuristics. This works in most cases, but if
92 * necessary, it is possible to specify the name of the get_type() function
93 * explictly with the "type-func" attribute. As a special case, CtkBuilder
94 * allows to use an object that has been constructed by a #CtkUIManager in
95 * another part of the UI definition by specifying the id of the #CtkUIManager
96 * in the “constructor” attribute and the name of the object in the “id”
97 * attribute.
98 *
99 * Objects may be given a name with the “id” attribute, which allows the
100 * application to retrieve them from the builder with ctk_builder_get_object().
101 * An id is also necessary to use the object as property value in other
102 * parts of the UI definition. CTK+ reserves ids starting and ending
103 * with ___ (3 underscores) for its own purposes.
104 *
105 * Setting properties of objects is pretty straightforward with the
106 * <property> element: the “name” attribute specifies the name of the
107 * property, and the content of the element specifies the value.
108 * If the “translatable” attribute is set to a true value, CTK+ uses
109 * gettext() (or dgettext() if the builder has a translation domain set)
110 * to find a translation for the value. This happens before the value
111 * is parsed, so it can be used for properties of any type, but it is
112 * probably most useful for string properties. It is also possible to
113 * specify a context to disambiguate short strings, and comments which
114 * may help the translators.
115 *
116 * CtkBuilder can parse textual representations for the most common
117 * property types: characters, strings, integers, floating-point numbers,
118 * booleans (strings like “TRUE”, “t”, “yes”, “y”, “1” are interpreted
119 * as %TRUE, strings like “FALSE”, “f”, “no”, “n”, “0” are interpreted
120 * as %FALSE), enumerations (can be specified by their name, nick or
121 * integer value), flags (can be specified by their name, nick, integer
122 * value, optionally combined with “|”, e.g. “CTK_VISIBLE|CTK_REALIZED”)
123 * and colors (in a format understood by cdk_rgba_parse()).
124 *
125 * GVariants can be specified in the format understood by g_variant_parse(),
126 * and pixbufs can be specified as a filename of an image file to load.
127 *
128 * Objects can be referred to by their name and by default refer to
129 * objects declared in the local xml fragment and objects exposed via
130 * ctk_builder_expose_object(). In general, CtkBuilder allows forward
131 * references to objects — declared in the local xml; an object doesn’t
132 * have to be constructed before it can be referred to. The exception
133 * to this rule is that an object has to be constructed before it can
134 * be used as the value of a construct-only property.
135 *
136 * It is also possible to bind a property value to another object's
137 * property value using the attributes
138 * "bind-source" to specify the source object of the binding,
139 * "bind-property" to specify the source property and optionally
140 * "bind-flags" to specify the binding flags.
141 * Internally builder implements this using GBinding objects.
142 * For more information see g_object_bind_property()
143 *
144 * Signal handlers are set up with the <signal> element. The “name”
145 * attribute specifies the name of the signal, and the “handler” attribute
146 * specifies the function to connect to the signal. By default, CTK+ tries
147 * to find the handler using g_module_symbol(), but this can be changed by
148 * passing a custom #CtkBuilderConnectFunc to
149 * ctk_builder_connect_signals_full(). The remaining attributes, “after”,
150 * “swapped” and “object”, have the same meaning as the corresponding
151 * parameters of the g_signal_connect_object() or
152 * g_signal_connect_data() functions. A “last_modification_time”
153 * attribute is also allowed, but it does not have a meaning to the
154 * builder.
155 *
156 * Sometimes it is necessary to refer to widgets which have implicitly
157 * been constructed by CTK+ as part of a composite widget, to set
158 * properties on them or to add further children (e.g. the @vbox of
159 * a #CtkDialog). This can be achieved by setting the “internal-child”
160 * property of the <child> element to a true value. Note that CtkBuilder
161 * still requires an <object> element for the internal child, even if it
162 * has already been constructed.
163 *
164 * A number of widgets have different places where a child can be added
165 * (e.g. tabs vs. page content in notebooks). This can be reflected in
166 * a UI definition by specifying the “type” attribute on a <child>
167 * The possible values for the “type” attribute are described in the
168 * sections describing the widget-specific portions of UI definitions.
169 *
170 * # A CtkBuilder UI Definition
171 *
172 * |[
173 * <interface>
174 * <object class="CtkDialog" id="dialog1">
175 * <child internal-child="vbox">
176 * <object class="CtkBox" id="vbox1">
177 * <property name="border-width">10</property>
178 * <child internal-child="action_area">
179 * <object class="CtkButtonBox" id="hbuttonbox1">
180 * <property name="border-width">20</property>
181 * <child>
182 * <object class="CtkButton" id="ok_button">
183 * <property name="label">ctk-ok</property>
184 * <property name="use-stock">TRUE</property>
185 * <signal name="clicked" handler="ok_button_clicked"/>
186 * </object>
187 * </child>
188 * </object>
189 * </child>
190 * </object>
191 * </child>
192 * </object>
193 * </interface>
194 * ]|
195 *
196 * Beyond this general structure, several object classes define their
197 * own XML DTD fragments for filling in the ANY placeholders in the DTD
198 * above. Note that a custom element in a <child> element gets parsed by
199 * the custom tag handler of the parent object, while a custom element in
200 * an <object> element gets parsed by the custom tag handler of the object.
201 *
202 * These XML fragments are explained in the documentation of the
203 * respective objects.
204 *
205 * Additionally, since 3.10 a special <template> tag has been added
206 * to the format allowing one to define a widget class’s components.
207 * See the [CtkWidget documentation][composite-templates] for details.
208 */
209
210#include "config.h"
211#include <errno(*__errno_location ()).h> /* errno */
212#include <stdlib.h>
213#include <string.h> /* strlen */
214
215#include "ctkbuilder.h"
216#include "ctkbuildable.h"
217#include "ctkbuilderprivate.h"
218#include "ctkdebug.h"
219#include "ctkmain.h"
220#include "ctkintl.h"
221#include "ctkprivate.h"
222#include "ctktypebuiltins.h"
223#include "ctkwindow.h"
224#include "ctkicontheme.h"
225#include "ctktestutils.h"
226#include "ctkstock.h"
227
228
229static void ctk_builder_class_init (CtkBuilderClass *klass);
230static void ctk_builder_init (CtkBuilder *builder);
231static void ctk_builder_finalize (GObject *object);
232static void ctk_builder_set_property (GObject *object,
233 guint prop_id,
234 const GValue *value,
235 GParamSpec *pspec);
236static void ctk_builder_get_property (GObject *object,
237 guint prop_id,
238 GValue *value,
239 GParamSpec *pspec);
240static GType ctk_builder_real_get_type_from_name (CtkBuilder *builder,
241 const gchar *type_name);
242
243enum {
244 PROP_0,
245 PROP_TRANSLATION_DOMAIN,
246 LAST_PROP
247};
248
249static GParamSpec *builder_props[LAST_PROP];
250
251struct _CtkBuilderPrivate
252{
253 gchar *domain;
254 GHashTable *objects;
255 GHashTable *callbacks;
256 GSList *delayed_properties;
257 GSList *signals;
258 GSList *bindings;
259 gchar *filename;
260 gchar *resource_prefix;
261 GType template_type;
262 CtkApplication *application;
263};
264
265G_DEFINE_TYPE_WITH_PRIVATE (CtkBuilder, ctk_builder, G_TYPE_OBJECT)static void ctk_builder_init (CtkBuilder *self); static void ctk_builder_class_init
(CtkBuilderClass *klass); static GType ctk_builder_get_type_once
(void); static gpointer ctk_builder_parent_class = ((void*)0
); static gint CtkBuilder_private_offset; static void ctk_builder_class_intern_init
(gpointer klass) { ctk_builder_parent_class = g_type_class_peek_parent
(klass); if (CtkBuilder_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CtkBuilder_private_offset); ctk_builder_class_init
((CtkBuilderClass*) klass); } __attribute__ ((__unused__)) static
inline gpointer ctk_builder_get_instance_private (CtkBuilder
*self) { return (((gpointer) ((guint8*) (self) + (glong) (CtkBuilder_private_offset
)))); } GType ctk_builder_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_builder_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_builder_get_type_once (void)
{ GType g_define_type_id = g_type_register_static_simple (((
GType) ((20) << (2))), g_intern_static_string ("CtkBuilder"
), sizeof (CtkBuilderClass), (GClassInitFunc)(void (*)(void))
ctk_builder_class_intern_init, sizeof (CtkBuilder), (GInstanceInitFunc
)(void (*)(void)) ctk_builder_init, (GTypeFlags) 0); { {{ CtkBuilder_private_offset
= g_type_add_instance_private (g_define_type_id, sizeof (CtkBuilderPrivate
)); };} } return g_define_type_id; }
266
267static void
268ctk_builder_class_init (CtkBuilderClass *klass)
269{
270 GObjectClass *gobject_class;
271
272 gobject_class = G_OBJECT_CLASS (klass)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((klass)), (((GType) ((20) << (2))))))))
;
273
274 gobject_class->finalize = ctk_builder_finalize;
275 gobject_class->set_property = ctk_builder_set_property;
276 gobject_class->get_property = ctk_builder_get_property;
277
278 klass->get_type_from_name = ctk_builder_real_get_type_from_name;
279
280 /**
281 * CtkBuilder:translation-domain:
282 *
283 * The translation domain used when translating property values that
284 * have been marked as translatable in interface descriptions.
285 * If the translation domain is %NULL, #CtkBuilder uses gettext(),
286 * otherwise g_dgettext().
287 *
288 * Since: 2.12
289 */
290 builder_props[PROP_TRANSLATION_DOMAIN] =
291 g_param_spec_string ("translation-domain",
292 P_("Translation Domain")g_dgettext("ctk30" "-properties","Translation Domain"),
293 P_("The translation domain used by gettext")g_dgettext("ctk30" "-properties","The translation domain used by gettext"
)
,
294 NULL((void*)0),
295 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB);
296
297 g_object_class_install_properties (gobject_class, LAST_PROP, builder_props);
298}
299
300static void
301ctk_builder_init (CtkBuilder *builder)
302{
303 builder->priv = ctk_builder_get_instance_private (builder);
304 builder->priv->domain = NULL((void*)0);
305 builder->priv->objects = g_hash_table_new_full (g_str_hash, g_str_equal,
306 g_free, g_object_unref);
307}
308
309
310/*
311 * GObject virtual methods
312 */
313
314static void
315ctk_builder_finalize (GObject *object)
316{
317 CtkBuilderPrivate *priv = CTK_BUILDER (object)((((CtkBuilder*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((ctk_builder_get_type ()))))))
->priv;
318
319 g_free (priv->domain);
320 g_free (priv->filename);
321 g_free (priv->resource_prefix);
322
323 g_hash_table_destroy (priv->objects);
324 if (priv->callbacks)
325 g_hash_table_destroy (priv->callbacks);
326
327 g_slist_free_full (priv->signals, (GDestroyNotify)_free_signal_info);
328
329 G_OBJECT_CLASS (ctk_builder_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_builder_parent_class)), (((GType) ((20) << (2)
)))))))
->finalize (object);
330}
331
332static void
333ctk_builder_set_property (GObject *object,
334 guint prop_id,
335 const GValue *value,
336 GParamSpec *pspec)
337{
338 CtkBuilder *builder = CTK_BUILDER (object)((((CtkBuilder*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((ctk_builder_get_type ()))))))
;
339
340 switch (prop_id)
341 {
342 case PROP_TRANSLATION_DOMAIN:
343 ctk_builder_set_translation_domain (builder, g_value_get_string (value));
344 break;
345 default:
346 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((prop_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "ctkbuilder.c", 346, ("property"), _glib__property_id, _glib__pspec
->name, g_type_name ((((((GTypeClass*) (((GTypeInstance*) (
_glib__pspec))->g_class))->g_type)))), (g_type_name (((
(((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class
))->g_type)))))); } while (0)
;
347 break;
348 }
349}
350
351static void
352ctk_builder_get_property (GObject *object,
353 guint prop_id,
354 GValue *value,
355 GParamSpec *pspec)
356{
357 CtkBuilder *builder = CTK_BUILDER (object)((((CtkBuilder*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((ctk_builder_get_type ()))))))
;
358
359 switch (prop_id)
360 {
361 case PROP_TRANSLATION_DOMAIN:
362 g_value_set_string (value, builder->priv->domain);
363 break;
364 default:
365 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((prop_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "ctkbuilder.c", 365, ("property"), _glib__property_id, _glib__pspec
->name, g_type_name ((((((GTypeClass*) (((GTypeInstance*) (
_glib__pspec))->g_class))->g_type)))), (g_type_name (((
(((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class
))->g_type)))))); } while (0)
;
366 break;
367 }
368}
369
370
371/*
372 * Try to map a type name to a _get_type function
373 * and call it, eg:
374 *
375 * CtkWindow -> ctk_window_get_type
376 * CtkHBox -> ctk_hbox_get_type
377 * CtkUIManager -> ctk_ui_manager_get_type
378 * GWeatherLocation -> gweather_location_get_type
379 *
380 * Keep in sync with testsuite/ctk/typename.c !
381 */
382static gchar *
383type_name_mangle (const gchar *name)
384{
385 GString *symbol_name = g_string_new ("");
386 gint i;
387
388 for (i = 0; name[i] != '\0'; i++)
389 {
390 /* skip if uppercase, first or previous is uppercase */
391 if ((name[i] == g_ascii_toupper (name[i]) &&
392 i > 0 && name[i-1] != g_ascii_toupper (name[i-1])) ||
393 (i > 2 && name[i] == g_ascii_toupper (name[i]) &&
394 name[i-1] == g_ascii_toupper (name[i-1]) &&
395 name[i-2] == g_ascii_toupper (name[i-2])))
396 g_string_append_c (symbol_name, '_')g_string_append_c_inline (symbol_name, '_');
397 g_string_append_c (symbol_name, g_ascii_tolower (name[i]))g_string_append_c_inline (symbol_name, g_ascii_tolower (name[
i]))
;
398 }
399 g_string_append (symbol_name, "_get_type")(__builtin_constant_p ("_get_type") ? __extension__ ({ const char
* const __val = ("_get_type"); g_string_append_len_inline (symbol_name
, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !
(__val))) : (gssize) -1); }) : g_string_append_len_inline (symbol_name
, "_get_type", (gssize) -1))
;
400
401 return g_string_free (symbol_name, FALSE)(__builtin_constant_p ((0)) ? (((0)) ? (g_string_free) ((symbol_name
), ((0))) : g_string_free_and_steal (symbol_name)) : (g_string_free
) ((symbol_name), ((0))))
;
402}
403
404static GType
405_ctk_builder_resolve_type_lazily (const gchar *name)
406{
407 static GModule *module = NULL((void*)0);
408 GTypeGetFunc func;
409 gchar *symbol;
410 GType gtype = G_TYPE_INVALID((GType) ((0) << (2)));
411
412 if (!module)
413 module = g_module_open (NULL((void*)0), 0);
414
415 symbol = type_name_mangle (name);
416
417 if (g_module_symbol (module, symbol, (gpointer)&func))
418 gtype = func ();
419
420 g_free (symbol);
421
422 return gtype;
423}
424
425/*
426 * CtkBuilder virtual methods
427 */
428
429static GType
430ctk_builder_real_get_type_from_name (CtkBuilder *builder G_GNUC_UNUSED__attribute__ ((__unused__)),
431 const gchar *type_name)
432{
433 GType gtype;
434
435 gtype = g_type_from_name (type_name);
436 if (gtype != G_TYPE_INVALID((GType) ((0) << (2))))
437 return gtype;
438
439 gtype = _ctk_builder_resolve_type_lazily (type_name);
440 if (gtype != G_TYPE_INVALID((GType) ((0) << (2))))
441 return gtype;
442
443 ctk_test_register_all_types ();
444 return g_type_from_name (type_name);
445}
446
447typedef struct
448{
449 gchar *object;
450 GParamSpec *pspec;
451 gchar *value;
452 gint line;
453 gint col;
454} DelayedProperty;
455
456typedef struct
457{
458 GPtrArray *names;
459 GArray *values;
460 guint len;
461} ObjectProperties;
462
463static ObjectProperties *
464object_properties_new (void)
465{
466 ObjectProperties *res = g_new (ObjectProperties, 1)((ObjectProperties *) g_malloc_n ((1), sizeof (ObjectProperties
)))
;
467
468 res->names = g_ptr_array_new ();
469
470 res->values = g_array_new (FALSE(0), FALSE(0), sizeof (GValue));
471 g_array_set_clear_func (res->values, (GDestroyNotify) g_value_unset);
472
473 res->len = 0;
474
475 return res;
476}
477
478static void
479object_properties_free (ObjectProperties *properties)
480{
481 if (properties == NULL((void*)0))
482 return;
483
484 g_ptr_array_unref (properties->names);
485 g_array_unref (properties->values);
486
487 g_free (properties);
488}
489
490static void
491object_properties_add (ObjectProperties *properties,
492 const char *name,
493 const GValue *value)
494{
495 g_ptr_array_add (properties->names, (char *) name);
496 g_array_append_vals (properties->values, value, 1);
497
498 g_assert (properties->names->len == properties->values->len)do { if (properties->names->len == properties->values
->len) ; else g_assertion_message_expr ("Ctk", "ctkbuilder.c"
, 498, ((const char*) (__func__)), "properties->names->len == properties->values->len"
); } while (0)
;
499
500 properties->len += 1;
501}
502
503static const char *
504object_properties_get_name (ObjectProperties *properties,
505 guint idx)
506{
507 return g_ptr_array_index (properties->names, idx)((properties->names)->pdata)[idx];
508}
509
510static GValue *
511object_properties_get_value (ObjectProperties *properties,
512 guint idx)
513{
514 return &g_array_index (properties->values, GValue, idx)(((GValue*) (void *) (properties->values)->data) [(idx)
])
;
515}
516
517static void
518ctk_builder_get_parameters (CtkBuilder *builder,
519 GType object_type,
520 const gchar *object_name,
521 GSList *properties,
522 GParamFlags filter_flags,
523 ObjectProperties **parameters,
524 ObjectProperties **filtered_parameters)
525{
526 GSList *l;
527 DelayedProperty *property;
528 GError *error = NULL((void*)0);
529
530 if (parameters)
531 *parameters = object_properties_new ();
532 if (filtered_parameters)
533 *filtered_parameters = object_properties_new ();
534
535 for (l = properties; l; l = l->next)
536 {
537 PropertyInfo *prop = (PropertyInfo*)l->data;
538 const char *property_name = g_intern_string (prop->pspec->name);
539 GValue property_value = G_VALUE_INIT{ 0, { { 0 } } };
540
541 if (G_IS_PARAM_SPEC_OBJECT (prop->pspec)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(prop->pspec)); GType __t = ((g_param_spec_types[19])); 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; }))))
&&
542 (G_PARAM_SPEC_VALUE_TYPE (prop->pspec)(((((GParamSpec*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((prop->pspec)), (((GType) ((19) << (2))))))))->
value_type)
!= GDK_TYPE_PIXBUF(gdk_pixbuf_get_type ())) &&
543 (G_PARAM_SPEC_VALUE_TYPE (prop->pspec)(((((GParamSpec*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((prop->pspec)), (((GType) ((19) << (2))))))))->
value_type)
!= G_TYPE_FILE(g_file_get_type ())))
544 {
545 GObject *object = g_hash_table_lookup (builder->priv->objects,
546 prop->text->str);
547
548 if (object)
549 {
550 g_value_init (&property_value, G_OBJECT_TYPE (object)(((((GTypeClass*) (((GTypeInstance*) (object))->g_class))->
g_type)))
);
551 g_value_set_object (&property_value, object);
552 }
553 else
554 {
555 if (prop->pspec->flags & G_PARAM_CONSTRUCT_ONLY)
556 {
557 g_warning ("Failed to get construct only property "
558 "%s of %s with value '%s'",
559 prop->pspec->name, object_name, prop->text->str);
560 continue;
561 }
562 /* Delay setting property */
563 property = g_slice_new (DelayedProperty)((DelayedProperty*) g_slice_alloc (sizeof (DelayedProperty)));
564 property->pspec = prop->pspec;
565 property->object = g_strdup (object_name)g_strdup_inline (object_name);
566 property->value = g_strdup (prop->text->str)g_strdup_inline (prop->text->str);
567 property->line = prop->line;
568 property->col = prop->col;
569 builder->priv->delayed_properties =
570 g_slist_prepend (builder->priv->delayed_properties, property);
571 continue;
572 }
573 }
574 else if (prop->bound && (!prop->text || prop->text->len == 0))
575 {
576 /* Ignore properties with a binding and no value since they are
577 * only there for to express the binding.
578 */
579 continue;
580 }
581 else if (!ctk_builder_value_from_string (builder, prop->pspec,
582 prop->text->str,
583 &property_value,
584 &error))
585 {
586 g_warning ("Failed to set property %s.%s to %s: %s",
587 g_type_name (object_type), prop->pspec->name, prop->text->str,
588 error->message);
589 g_error_free (error);
590 error = NULL((void*)0);
591 continue;
592 }
593
594 if (prop->pspec->flags & filter_flags)
595 {
596 if (filtered_parameters)
597 object_properties_add (*filtered_parameters, property_name, &property_value);
598 }
599 else
600 {
601 if (parameters)
602 object_properties_add (*parameters, property_name, &property_value);
603 }
604 }
605}
606
607static const gchar *
608object_get_name (GObject *object)
609{
610 if (CTK_IS_BUILDABLE (object)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(object)); GType __t = ((ctk_buildable_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; }))))
)
611 return ctk_buildable_get_name (CTK_BUILDABLE (object)((((CtkBuildable*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((ctk_buildable_get_type ()))))))
);
612 else
613 return g_object_get_data (object, "ctk-builder-name");
614}
615
616static GObject *
617ctk_builder_get_internal_child (CtkBuilder *builder,
618 ObjectInfo *info,
619 const gchar *childname,
620 GError **error)
621{
622 GObject *obj = NULL((void*)0);
623
624 while (!obj)
625 {
626 if (!info->parent)
627 break;
628
629 info = (ObjectInfo*)((ChildInfo*)info->parent)->parent;
630 if (!info)
631 break;
632
633 CTK_NOTE (BUILDER,do { if ((ctk_get_debug_flags () & CTK_DEBUG_BUILDER)) { g_message
("Trying to get internal child %s from %s", childname, object_get_name
(info->object)); }; } while (0)
634 g_message ("Trying to get internal child %s from %s",do { if ((ctk_get_debug_flags () & CTK_DEBUG_BUILDER)) { g_message
("Trying to get internal child %s from %s", childname, object_get_name
(info->object)); }; } while (0)
635 childname, object_get_name (info->object)))do { if ((ctk_get_debug_flags () & CTK_DEBUG_BUILDER)) { g_message
("Trying to get internal child %s from %s", childname, object_get_name
(info->object)); }; } while (0)
;
636
637 if (CTK_IS_BUILDABLE (info->object)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(info->object)); GType __t = ((ctk_buildable_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; }
))))
)
638 obj = ctk_buildable_get_internal_child (CTK_BUILDABLE (info->object)((((CtkBuildable*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((info->object)), ((ctk_buildable_get_type ()))))))
,
639 builder,
640 childname);
641 };
642
643 if (!obj)
644 {
645 g_set_error (error,
646 CTK_BUILDER_ERROR(ctk_builder_error_quark ()),
647 CTK_BUILDER_ERROR_INVALID_VALUE,
648 "Unknown internal child: %s", childname);
649 }
650 return obj;
651}
652
653static inline void
654object_set_name (GObject *object,
655 const gchar *name)
656{
657 if (CTK_IS_BUILDABLE (object)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(object)); GType __t = ((ctk_buildable_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; }))))
)
658 ctk_buildable_set_name (CTK_BUILDABLE (object)((((CtkBuildable*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((ctk_buildable_get_type ()))))))
, name);
659 else
660 g_object_set_data_full (object, "ctk-builder-name", g_strdup (name)g_strdup_inline (name), g_free);
661}
662
663void
664_ctk_builder_add_object (CtkBuilder *builder,
665 const gchar *id,
666 GObject *object)
667{
668 object_set_name (object, id);
669 g_hash_table_insert (builder->priv->objects, g_strdup (id)g_strdup_inline (id), g_object_ref (object)((__typeof__ (object)) (g_object_ref) (object)));
670}
671
672static void
673ctk_builder_take_bindings (CtkBuilder *builder,
674 GObject *target,
675 GSList *bindings)
676{
677 GSList *l;
678
679 for (l = bindings; l; l = l->next)
680 {
681 BindingInfo *info = l->data;
682 info->target = target;
683 }
684
685 builder->priv->bindings = g_slist_concat (builder->priv->bindings, bindings);
686}
687
688GObject *
689_ctk_builder_construct (CtkBuilder *builder,
690 ObjectInfo *info,
691 GError **error)
692{
693 ObjectProperties *parameters, *construct_parameters;
694 GObject *obj;
695 int i;
696 CtkBuildableIface *iface;
697 gboolean custom_set_property;
698 CtkBuildable *buildable;
699 GParamFlags param_filter_flags;
700
701 g_assert (info->type != G_TYPE_INVALID)do { if (info->type != ((GType) ((0) << (2)))) ; else
g_assertion_message_expr ("Ctk", "ctkbuilder.c", 701, ((const
char*) (__func__)), "info->type != G_TYPE_INVALID"); } while
(0)
;
702
703 if (builder->priv->template_type != 0 &&
704 g_type_is_a (info->type, builder->priv->template_type)((info->type) == (builder->priv->template_type) || (
g_type_is_a) ((info->type), (builder->priv->template_type
)))
)
705 {
706 g_set_error (error,
707 CTK_BUILDER_ERROR(ctk_builder_error_quark ()),
708 CTK_BUILDER_ERROR_OBJECT_TYPE_REFUSED,
709 "Refused to build object of type '%s' because it "
710 "conforms to the template type '%s', avoiding infinite recursion.",
711 g_type_name (info->type), g_type_name (builder->priv->template_type));
712 return NULL((void*)0);
713 }
714
715 /* If there is a manual constructor (like UIManager), or if this is a
716 * reference to an internal child, then we filter out construct-only
717 * and warn that they cannot be set.
718 *
719 * Otherwise if we are calling g_object_new_with_properties(), we want
720 * to pass both G_PARAM_CONSTRUCT and G_PARAM_CONSTRUCT_ONLY to the
721 * object's constructor.
722 *
723 * Passing all construct properties to g_object_new_with_properties()
724 * slightly improves performance as the construct properties will only
725 * be set once.
726 */
727 if (info->constructor ||
728 (info->parent && ((ChildInfo*)info->parent)->internal_child != NULL((void*)0)))
729 param_filter_flags = G_PARAM_CONSTRUCT_ONLY;
730 else
731 param_filter_flags = G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY;
732
733 ctk_builder_get_parameters (builder, info->type,
734 info->id,
735 info->properties,
736 param_filter_flags,
737 &parameters,
738 &construct_parameters);
739
740 if (info->constructor)
741 {
742 GObject *constructor;
743
744 constructor = g_hash_table_lookup (builder->priv->objects, info->constructor);
745 if (constructor == NULL((void*)0))
746 {
747 g_set_error (error,
748 CTK_BUILDER_ERROR(ctk_builder_error_quark ()),
749 CTK_BUILDER_ERROR_INVALID_VALUE,
750 "Unknown object constructor for %s: %s",
751 info->id,
752 info->constructor);
753 object_properties_free (parameters);
754 object_properties_free (construct_parameters);
755 return NULL((void*)0);
756 }
757 obj = ctk_buildable_construct_child (CTK_BUILDABLE (constructor)((((CtkBuildable*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((constructor)), ((ctk_buildable_get_type ()))))))
,
758 builder,
759 info->id);
760 g_assert (obj != NULL)do { if (obj != ((void*)0)) ; else g_assertion_message_expr (
"Ctk", "ctkbuilder.c", 760, ((const char*) (__func__)), "obj != NULL"
); } while (0)
;
761 if (construct_parameters->len)
762 g_warning ("Can't pass in construct-only parameters to %s", info->id);
763 }
764 else if (info->parent && ((ChildInfo*)info->parent)->internal_child != NULL((void*)0))
765 {
766 gchar *childname = ((ChildInfo*)info->parent)->internal_child;
767 obj = ctk_builder_get_internal_child (builder, info, childname, error);
768 if (!obj)
769 {
770 object_properties_free (parameters);
771 object_properties_free (construct_parameters);
772 return NULL((void*)0);
773 }
774 if (construct_parameters->len)
775 g_warning ("Can't pass in construct-only parameters to %s", childname);
776 g_object_ref (obj)((__typeof__ (obj)) (g_object_ref) (obj));
777 }
778 else
779 {
780 obj = g_object_new_with_properties (info->type,
781 construct_parameters->len,
782 (const char **) construct_parameters->names->pdata,
783 (GValue *) construct_parameters->values->data);
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption
784
785 /* No matter what, make sure we have a reference.
786 *
787 * If it's an initially unowned object, sink it.
788 * If it's not initially unowned then we have the reference already.
789 *
790 * In the case that this is a window it will be sunk already and
791 * this is effectively a call to g_object_ref(). That's what
792 * we want.
793 */
794 if (G_IS_INITIALLY_UNOWNED (obj)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(obj)); GType __t = ((g_initially_unowned_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; }))))
)
795 g_object_ref_sink (obj)((__typeof__ (obj)) (g_object_ref_sink) (obj));
796
797 CTK_NOTE (BUILDER,do { if ((ctk_get_debug_flags () & CTK_DEBUG_BUILDER)) { g_message
("created %s of type %s", info->id, g_type_name (info->
type)); }; } while (0)
798 g_message ("created %s of type %s", info->id, g_type_name (info->type)))do { if ((ctk_get_debug_flags () & CTK_DEBUG_BUILDER)) { g_message
("created %s of type %s", info->id, g_type_name (info->
type)); }; } while (0)
;
799 }
800
801 object_properties_free (construct_parameters);
802
803 custom_set_property = FALSE(0);
804 buildable = NULL((void*)0);
805 iface = NULL((void*)0);
806 if (CTK_IS_BUILDABLE (obj)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(obj)); GType __t = ((ctk_buildable_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; }))))
)
807 {
808 buildable = CTK_BUILDABLE (obj)((((CtkBuildable*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((obj)), ((ctk_buildable_get_type ()))))))
;
809 iface = CTK_BUILDABLE_GET_IFACE (obj)((((CtkBuildableIface*) g_type_interface_peek (((GTypeInstance
*) ((obj)))->g_class, ((ctk_buildable_get_type ()))))))
;
810 if (iface->set_buildable_property)
811 custom_set_property = TRUE(!(0));
812 }
813
814 /* We're going to set multiple properties in one go, so it's better
815 * to notify changes at the end
816 */
817 g_object_freeze_notify (obj);
818
819 for (i = 0; i < parameters->len; i++)
820 {
821 const char *name = object_properties_get_name (parameters, i);
822 const GValue *value = object_properties_get_value (parameters, i);
823
824 if (custom_set_property)
825 iface->set_buildable_property (buildable, builder, name, value);
826 else
827 g_object_set_property (obj, name, value);
828
829#ifdef G_ENABLE_DEBUG1
830 if (CTK_DEBUG_CHECK (BUILDER)(ctk_get_debug_flags () & CTK_DEBUG_BUILDER))
831 {
832 gchar *str = g_strdup_value_contents (value);
833 g_message ("set %s: %s = %s", info->id, name, str);
834 g_free (str);
835 }
836#endif
837 }
838
839 g_object_thaw_notify (obj);
840
841 object_properties_free (parameters);
842
843 if (info->bindings)
844 ctk_builder_take_bindings (builder, obj, info->bindings);
845
846 /* put it in the hash table. */
847 _ctk_builder_add_object (builder, info->id, obj);
848
849 /* we already own a reference to obj. */
850 g_object_unref (obj);
851
852 return obj;
853}
854
855void
856_ctk_builder_apply_properties (CtkBuilder *builder,
857 ObjectInfo *info,
858 GError **error G_GNUC_UNUSED__attribute__ ((__unused__)))
859{
860 ObjectProperties *parameters;
861 CtkBuildableIface *iface;
862 CtkBuildable *buildable;
863 gboolean custom_set_property;
864 gint i;
865
866 g_assert (info->object != NULL)do { if (info->object != ((void*)0)) ; else g_assertion_message_expr
("Ctk", "ctkbuilder.c", 866, ((const char*) (__func__)), "info->object != NULL"
); } while (0)
;
867 g_assert (info->type != G_TYPE_INVALID)do { if (info->type != ((GType) ((0) << (2)))) ; else
g_assertion_message_expr ("Ctk", "ctkbuilder.c", 867, ((const
char*) (__func__)), "info->type != G_TYPE_INVALID"); } while
(0)
;
868
869 /* Fetch all properties that are not construct-only */
870 ctk_builder_get_parameters (builder, info->type,
871 info->id,
872 info->properties,
873 G_PARAM_CONSTRUCT_ONLY,
874 &parameters, NULL((void*)0));
875
876 custom_set_property = FALSE(0);
877 buildable = NULL((void*)0);
878 iface = NULL((void*)0);
879 if (CTK_IS_BUILDABLE (info->object)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(info->object)); GType __t = ((ctk_buildable_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; }
))))
)
880 {
881 buildable = CTK_BUILDABLE (info->object)((((CtkBuildable*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((info->object)), ((ctk_buildable_get_type ()))))))
;
882 iface = CTK_BUILDABLE_GET_IFACE (info->object)((((CtkBuildableIface*) g_type_interface_peek (((GTypeInstance
*) ((info->object)))->g_class, ((ctk_buildable_get_type
()))))))
;
883 if (iface->set_buildable_property)
884 custom_set_property = TRUE(!(0));
885 }
886
887 g_object_freeze_notify (info->object);
888
889 for (i = 0; i < parameters->len; i++)
890 {
891 const char *name = object_properties_get_name (parameters, i);
892 const GValue *value = object_properties_get_value (parameters, i);
893 if (custom_set_property)
894 iface->set_buildable_property (buildable, builder, name, value);
895 else
896 g_object_set_property (info->object, name, value);
897
898#ifdef G_ENABLE_DEBUG1
899 if (CTK_DEBUG_CHECK (BUILDER)(ctk_get_debug_flags () & CTK_DEBUG_BUILDER))
900 {
901 gchar *str = g_strdup_value_contents (value);
902 g_message ("set %s: %s = %s", info->id, name, str);
903 g_free (str);
904 }
905#endif
906 }
907
908 g_object_thaw_notify (info->object);
909
910 object_properties_free (parameters);
911}
912
913void
914_ctk_builder_add (CtkBuilder *builder,
915 ChildInfo *child_info)
916{
917 GObject *object;
918 GObject *parent;
919
920 /* Internal children are already added
921 * Also prevent us from being called twice.
922 */
923 if (!child_info ||
924 child_info->internal_child ||
925 child_info->added)
926 return;
927
928 object = child_info->object;
929 if (!object)
930 return;
931
932 if (!child_info->parent)
933 {
934 g_warning ("%s: Not adding, No parent", object_get_name (object));
935 return;
936 }
937
938 g_assert (object != NULL)do { if (object != ((void*)0)) ; else g_assertion_message_expr
("Ctk", "ctkbuilder.c", 938, ((const char*) (__func__)), "object != NULL"
); } while (0)
;
939
940 parent = ((ObjectInfo*)child_info->parent)->object;
941 g_assert (CTK_IS_BUILDABLE (parent))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((parent)); GType __t = ((ctk_buildable_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_assertion_message_expr ("Ctk", "ctkbuilder.c", 941, ((const
char*) (__func__)), "CTK_IS_BUILDABLE (parent)"); } while (0
)
;
942
943 CTK_NOTE (BUILDER,do { if ((ctk_get_debug_flags () & CTK_DEBUG_BUILDER)) { g_message
("adding %s to %s", object_get_name (object), object_get_name
(parent)); }; } while (0)
944 g_message ("adding %s to %s", object_get_name (object), object_get_name (parent)))do { if ((ctk_get_debug_flags () & CTK_DEBUG_BUILDER)) { g_message
("adding %s to %s", object_get_name (object), object_get_name
(parent)); }; } while (0)
;
945
946 ctk_buildable_add_child (CTK_BUILDABLE (parent)((((CtkBuildable*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((parent)), ((ctk_buildable_get_type ()))))))
, builder, object,
947 child_info->type);
948
949 child_info->added = TRUE(!(0));
950}
951
952void
953_ctk_builder_add_signals (CtkBuilder *builder,
954 GSList *signals)
955{
956 builder->priv->signals = g_slist_concat (builder->priv->signals,
957 g_slist_copy (signals));
958}
959
960static void
961ctk_builder_apply_delayed_properties (CtkBuilder *builder)
962{
963 GSList *l, *props;
964
965 /* take the list over from the builder->priv.
966 *
967 * g_slist_reverse does not copy the list, so the list now
968 * belongs to us (and we free it at the end of this function).
969 */
970 props = g_slist_reverse (builder->priv->delayed_properties);
971 builder->priv->delayed_properties = NULL((void*)0);
972
973 for (l = props; l; l = l->next)
974 {
975 DelayedProperty *property = l->data;
976 GObject *object, *obj;
977
978 object = g_hash_table_lookup (builder->priv->objects, property->object);
979 g_assert (object != NULL)do { if (object != ((void*)0)) ; else g_assertion_message_expr
("Ctk", "ctkbuilder.c", 979, ((const char*) (__func__)), "object != NULL"
); } while (0)
;
980
981 obj = _ctk_builder_lookup_object (builder, property->value, property->line, property->col);
982 if (obj)
983 g_object_set (object, property->pspec->name, obj, NULL((void*)0));
984
985 g_free (property->value);
986 g_free (property->object);
987 g_slice_free (DelayedProperty, property)do { if (1) g_slice_free1 (sizeof (DelayedProperty), (property
)); else (void) ((DelayedProperty*) 0 == (property)); } while
(0)
;
988 }
989 g_slist_free (props);
990}
991
992static inline void
993free_binding_info (gpointer data,
994 gpointer user G_GNUC_UNUSED__attribute__ ((__unused__)))
995{
996 BindingInfo *info = data;
997
998 g_free (info->source);
999 g_free (info->source_property);
1000 g_slice_free (BindingInfo, data)do { if (1) g_slice_free1 (sizeof (BindingInfo), (data)); else
(void) ((BindingInfo*) 0 == (data)); } while (0)
;
1001}
1002
1003static inline void
1004ctk_builder_create_bindings (CtkBuilder *builder)
1005{
1006 GSList *l;
1007
1008 for (l = builder->priv->bindings; l; l = l->next)
1009 {
1010 BindingInfo *info = l->data;
1011 GObject *source;
1012
1013 source = _ctk_builder_lookup_object (builder, info->source, info->line, info->col);
1014 if (source)
1015 g_object_bind_property (source, info->source_property,
1016 info->target, info->target_pspec->name,
1017 info->flags);
1018
1019 free_binding_info (info, NULL((void*)0));
1020 }
1021
1022 g_slist_free (builder->priv->bindings);
1023 builder->priv->bindings = NULL((void*)0);
1024}
1025
1026void
1027_ctk_builder_finish (CtkBuilder *builder)
1028{
1029 ctk_builder_apply_delayed_properties (builder);
1030 ctk_builder_create_bindings (builder);
1031}
1032
1033/**
1034 * ctk_builder_new:
1035 *
1036 * Creates a new empty builder object.
1037 *
1038 * This function is only useful if you intend to make multiple calls
1039 * to ctk_builder_add_from_file(), ctk_builder_add_from_resource()
1040 * or ctk_builder_add_from_string() in order to merge multiple UI
1041 * descriptions into a single builder.
1042 *
1043 * Most users will probably want to use ctk_builder_new_from_file(),
1044 * ctk_builder_new_from_resource() or ctk_builder_new_from_string().
1045 *
1046 * Returns: a new (empty) #CtkBuilder object
1047 *
1048 * Since: 2.12
1049 **/
1050CtkBuilder *
1051ctk_builder_new (void)
1052{
1053 return g_object_new (CTK_TYPE_BUILDER(ctk_builder_get_type ()), NULL((void*)0));
1054}
1055
1056/**
1057 * ctk_builder_add_from_file:
1058 * @builder: a #CtkBuilder
1059 * @filename: the name of the file to parse
1060 * @error: (allow-none): return location for an error, or %NULL
1061 *
1062 * Parses a file containing a [CtkBuilder UI definition][BUILDER-UI]
1063 * and merges it with the current contents of @builder.
1064 *
1065 * Most users will probably want to use ctk_builder_new_from_file().
1066 *
1067 * If an error occurs, 0 will be returned and @error will be assigned a
1068 * #GError from the #CTK_BUILDER_ERROR, #G_MARKUP_ERROR or #G_FILE_ERROR
1069 * domain.
1070 *
1071 * It’s not really reasonable to attempt to handle failures of this
1072 * call. You should not use this function with untrusted files (ie:
1073 * files that are not part of your application). Broken #CtkBuilder
1074 * files can easily crash your program, and it’s possible that memory
1075 * was leaked leading up to the reported failure. The only reasonable
1076 * thing to do when an error is detected is to call g_error().
1077 *
1078 * Returns: A positive value on success, 0 if an error occurred
1079 *
1080 * Since: 2.12
1081 **/
1082guint
1083ctk_builder_add_from_file (CtkBuilder *builder,
1084 const gchar *filename,
1085 GError **error)
1086{
1087 gchar *buffer;
1088 gsize length;
1089 GError *tmp_error;
1090
1091 g_return_val_if_fail (CTK_IS_BUILDER (builder), 0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((builder)); GType __t = ((ctk_builder_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_BUILDER (builder)"); return (0); } } while (0)
;
1092 g_return_val_if_fail (filename != NULL, 0)do { if ((filename != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "filename != NULL"); return
(0); } } while (0)
;
1093 g_return_val_if_fail (error == NULL || *error == NULL, 0)do { if ((error == ((void*)0) || *error == ((void*)0))) { } else
{ g_return_if_fail_warning ("Ctk", ((const char*) (__func__)
), "error == NULL || *error == NULL"); return (0); } } while (
0)
;
1094
1095 tmp_error = NULL((void*)0);
1096
1097 if (!g_file_get_contents (filename, &buffer, &length, &tmp_error))
1098 {
1099 g_propagate_error (error, tmp_error);
1100 return 0;
1101 }
1102
1103 g_free (builder->priv->filename);
1104 g_free (builder->priv->resource_prefix);
1105 builder->priv->filename = g_strdup (filename)g_strdup_inline (filename);
1106 builder->priv->resource_prefix = NULL((void*)0);
1107
1108 _ctk_builder_parser_parse_buffer (builder, filename,
1109 buffer, length,
1110 NULL((void*)0),
1111 &tmp_error);
1112
1113 g_free (buffer);
1114
1115 if (tmp_error != NULL((void*)0))
1116 {
1117 g_propagate_error (error, tmp_error);
1118 return 0;
1119 }
1120
1121 return 1;
1122}
1123
1124/**
1125 * ctk_builder_add_objects_from_file:
1126 * @builder: a #CtkBuilder
1127 * @filename: the name of the file to parse
1128 * @object_ids: (array zero-terminated=1) (element-type utf8): nul-terminated array of objects to build
1129 * @error: (allow-none): return location for an error, or %NULL
1130 *
1131 * Parses a file containing a [CtkBuilder UI definition][BUILDER-UI]
1132 * building only the requested objects and merges
1133 * them with the current contents of @builder.
1134 *
1135 * Upon errors 0 will be returned and @error will be assigned a
1136 * #GError from the #CTK_BUILDER_ERROR, #G_MARKUP_ERROR or #G_FILE_ERROR
1137 * domain.
1138 *
1139 * If you are adding an object that depends on an object that is not
1140 * its child (for instance a #CtkTreeView that depends on its
1141 * #CtkTreeModel), you have to explicitly list all of them in @object_ids.
1142 *
1143 * Returns: A positive value on success, 0 if an error occurred
1144 *
1145 * Since: 2.14
1146 **/
1147guint
1148ctk_builder_add_objects_from_file (CtkBuilder *builder,
1149 const gchar *filename,
1150 gchar **object_ids,
1151 GError **error)
1152{
1153 gchar *buffer;
1154 gsize length;
1155 GError *tmp_error;
1156
1157 g_return_val_if_fail (CTK_IS_BUILDER (builder), 0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((builder)); GType __t = ((ctk_builder_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_BUILDER (builder)"); return (0); } } while (0)
;
1158 g_return_val_if_fail (filename != NULL, 0)do { if ((filename != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "filename != NULL"); return
(0); } } while (0)
;
1159 g_return_val_if_fail (object_ids != NULL && object_ids[0] != NULL, 0)do { if ((object_ids != ((void*)0) && object_ids[0] !=
((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "object_ids != NULL && object_ids[0] != NULL"
); return (0); } } while (0)
;
1160 g_return_val_if_fail (error == NULL || *error == NULL, 0)do { if ((error == ((void*)0) || *error == ((void*)0))) { } else
{ g_return_if_fail_warning ("Ctk", ((const char*) (__func__)
), "error == NULL || *error == NULL"); return (0); } } while (
0)
;
1161
1162 tmp_error = NULL((void*)0);
1163
1164 if (!g_file_get_contents (filename, &buffer, &length, &tmp_error))
1165 {
1166 g_propagate_error (error, tmp_error);
1167 return 0;
1168 }
1169
1170 g_free (builder->priv->filename);
1171 g_free (builder->priv->resource_prefix);
1172 builder->priv->filename = g_strdup (filename)g_strdup_inline (filename);
1173 builder->priv->resource_prefix = NULL((void*)0);
1174
1175 _ctk_builder_parser_parse_buffer (builder, filename,
1176 buffer, length,
1177 object_ids,
1178 &tmp_error);
1179
1180 g_free (buffer);
1181
1182 if (tmp_error != NULL((void*)0))
1183 {
1184 g_propagate_error (error, tmp_error);
1185 return 0;
1186 }
1187
1188 return 1;
1189}
1190
1191
1192/**
1193 * ctk_builder_extend_with_template:
1194 * @builder: a #CtkBuilder
1195 * @widget: the widget that is being extended
1196 * @template_type: the type that the template is for
1197 * @buffer: the string to parse
1198 * @length: the length of @buffer (may be -1 if @buffer is nul-terminated)
1199 * @error: (allow-none): return location for an error, or %NULL
1200 *
1201 * Main private entry point for building composite container
1202 * components from template XML.
1203 *
1204 * This is exported purely to let ctk-builder-tool validate
1205 * templates, applications have no need to call this function.
1206 *
1207 * Returns: A positive value on success, 0 if an error occurred
1208 */
1209guint
1210ctk_builder_extend_with_template (CtkBuilder *builder,
1211 CtkWidget *widget,
1212 GType template_type,
1213 const gchar *buffer,
1214 gsize length,
1215 GError **error)
1216{
1217 GError *tmp_error;
1218
1219 g_return_val_if_fail (CTK_IS_BUILDER (builder), 0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((builder)); GType __t = ((ctk_builder_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_BUILDER (builder)"); return (0); } } while (0)
;
1220 g_return_val_if_fail (CTK_IS_WIDGET (widget), 0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = ((ctk_widget_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_WIDGET (widget)"); return (0); } } while (0)
;
1221 g_return_val_if_fail (g_type_name (template_type) != NULL, 0)do { if ((g_type_name (template_type) != ((void*)0))) { } else
{ g_return_if_fail_warning ("Ctk", ((const char*) (__func__)
), "g_type_name (template_type) != NULL"); return (0); } } while
(0)
;
1222 g_return_val_if_fail (g_type_is_a (G_OBJECT_TYPE (widget), template_type), 0)do { if (((((((((GTypeClass*) (((GTypeInstance*) (widget))->
g_class))->g_type)))) == (template_type) || (g_type_is_a) (
((((((GTypeClass*) (((GTypeInstance*) (widget))->g_class))
->g_type)))), (template_type))))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "g_type_is_a (G_OBJECT_TYPE (widget), template_type)"
); return (0); } } while (0)
;
1223 g_return_val_if_fail (buffer && buffer[0], 0)do { if ((buffer && buffer[0])) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "buffer && buffer[0]"
); return (0); } } while (0)
;
1224
1225 tmp_error = NULL((void*)0);
1226
1227 g_free (builder->priv->filename);
1228 g_free (builder->priv->resource_prefix);
1229 builder->priv->filename = g_strdup (".")g_strdup_inline (".");
1230 builder->priv->resource_prefix = NULL((void*)0);
1231 builder->priv->template_type = template_type;
1232
1233 ctk_builder_expose_object (builder, g_type_name (template_type), G_OBJECT (widget)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), (((GType) ((20) << (2))))))))
);
1234 _ctk_builder_parser_parse_buffer (builder, "<input>",
1235 buffer, length,
1236 NULL((void*)0),
1237 &tmp_error);
1238
1239 if (tmp_error != NULL((void*)0))
1240 {
1241 g_propagate_error (error, tmp_error);
1242 return 0;
1243 }
1244
1245 return 1;
1246}
1247
1248/**
1249 * ctk_builder_add_from_resource:
1250 * @builder: a #CtkBuilder
1251 * @resource_path: the path of the resource file to parse
1252 * @error: (allow-none): return location for an error, or %NULL
1253 *
1254 * Parses a resource file containing a [CtkBuilder UI definition][BUILDER-UI]
1255 * and merges it with the current contents of @builder.
1256 *
1257 * Most users will probably want to use ctk_builder_new_from_resource().
1258 *
1259 * If an error occurs, 0 will be returned and @error will be assigned a
1260 * #GError from the #CTK_BUILDER_ERROR, #G_MARKUP_ERROR or #G_RESOURCE_ERROR
1261 * domain.
1262 *
1263 * It’s not really reasonable to attempt to handle failures of this
1264 * call. The only reasonable thing to do when an error is detected is
1265 * to call g_error().
1266 *
1267 * Returns: A positive value on success, 0 if an error occurred
1268 *
1269 * Since: 3.4
1270 **/
1271guint
1272ctk_builder_add_from_resource (CtkBuilder *builder,
1273 const gchar *resource_path,
1274 GError **error)
1275{
1276 GError *tmp_error;
1277 GBytes *data;
1278 char *filename_for_errors;
1279 char *slash;
1280
1281 g_return_val_if_fail (CTK_IS_BUILDER (builder), 0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((builder)); GType __t = ((ctk_builder_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_BUILDER (builder)"); return (0); } } while (0)
;
1282 g_return_val_if_fail (resource_path != NULL, 0)do { if ((resource_path != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "resource_path != NULL")
; return (0); } } while (0)
;
1283 g_return_val_if_fail (error == NULL || *error == NULL, 0)do { if ((error == ((void*)0) || *error == ((void*)0))) { } else
{ g_return_if_fail_warning ("Ctk", ((const char*) (__func__)
), "error == NULL || *error == NULL"); return (0); } } while (
0)
;
1284
1285 tmp_error = NULL((void*)0);
1286
1287 data = g_resources_lookup_data (resource_path, 0, &tmp_error);
1288 if (data == NULL((void*)0))
1289 {
1290 g_propagate_error (error, tmp_error);
1291 return 0;
1292 }
1293
1294 g_free (builder->priv->filename);
1295 g_free (builder->priv->resource_prefix);
1296 builder->priv->filename = g_strdup (".")g_strdup_inline (".");
1297
1298 slash = strrchr (resource_path, '/');
1299 if (slash != NULL((void*)0))
1300 builder->priv->resource_prefix =
1301 g_strndup (resource_path, slash - resource_path + 1);
1302 else
1303 builder->priv->resource_prefix =
1304 g_strdup ("/")g_strdup_inline ("/");
1305
1306 filename_for_errors = g_strconcat ("<resource>", resource_path, NULL((void*)0));
1307
1308 _ctk_builder_parser_parse_buffer (builder, filename_for_errors,
1309 g_bytes_get_data (data, NULL((void*)0)), g_bytes_get_size (data),
1310 NULL((void*)0),
1311 &tmp_error);
1312
1313 g_free (filename_for_errors);
1314 g_bytes_unref (data);
1315
1316 if (tmp_error != NULL((void*)0))
1317 {
1318 g_propagate_error (error, tmp_error);
1319 return 0;
1320 }
1321
1322 return 1;
1323}
1324
1325/**
1326 * ctk_builder_add_objects_from_resource:
1327 * @builder: a #CtkBuilder
1328 * @resource_path: the path of the resource file to parse
1329 * @object_ids: (array zero-terminated=1) (element-type utf8): nul-terminated array of objects to build
1330 * @error: (allow-none): return location for an error, or %NULL
1331 *
1332 * Parses a resource file containing a [CtkBuilder UI definition][BUILDER-UI]
1333 * building only the requested objects and merges
1334 * them with the current contents of @builder.
1335 *
1336 * Upon errors 0 will be returned and @error will be assigned a
1337 * #GError from the #CTK_BUILDER_ERROR, #G_MARKUP_ERROR or #G_RESOURCE_ERROR
1338 * domain.
1339 *
1340 * If you are adding an object that depends on an object that is not
1341 * its child (for instance a #CtkTreeView that depends on its
1342 * #CtkTreeModel), you have to explicitly list all of them in @object_ids.
1343 *
1344 * Returns: A positive value on success, 0 if an error occurred
1345 *
1346 * Since: 3.4
1347 **/
1348guint
1349ctk_builder_add_objects_from_resource (CtkBuilder *builder,
1350 const gchar *resource_path,
1351 gchar **object_ids,
1352 GError **error)
1353{
1354 GError *tmp_error;
1355 GBytes *data;
1356 char *filename_for_errors;
1357 char *slash;
1358
1359 g_return_val_if_fail (CTK_IS_BUILDER (builder), 0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((builder)); GType __t = ((ctk_builder_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_BUILDER (builder)"); return (0); } } while (0)
;
1360 g_return_val_if_fail (resource_path != NULL, 0)do { if ((resource_path != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "resource_path != NULL")
; return (0); } } while (0)
;
1361 g_return_val_if_fail (object_ids != NULL && object_ids[0] != NULL, 0)do { if ((object_ids != ((void*)0) && object_ids[0] !=
((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "object_ids != NULL && object_ids[0] != NULL"
); return (0); } } while (0)
;
1362 g_return_val_if_fail (error == NULL || *error == NULL, 0)do { if ((error == ((void*)0) || *error == ((void*)0))) { } else
{ g_return_if_fail_warning ("Ctk", ((const char*) (__func__)
), "error == NULL || *error == NULL"); return (0); } } while (
0)
;
1363
1364 tmp_error = NULL((void*)0);
1365
1366 data = g_resources_lookup_data (resource_path, 0, &tmp_error);
1367 if (data == NULL((void*)0))
1368 {
1369 g_propagate_error (error, tmp_error);
1370 return 0;
1371 }
1372
1373 g_free (builder->priv->filename);
1374 g_free (builder->priv->resource_prefix);
1375 builder->priv->filename = g_strdup (".")g_strdup_inline (".");
1376
1377 slash = strrchr (resource_path, '/');
1378 if (slash != NULL((void*)0))
1379 builder->priv->resource_prefix =
1380 g_strndup (resource_path, slash - resource_path + 1);
1381 else
1382 builder->priv->resource_prefix =
1383 g_strdup ("/")g_strdup_inline ("/");
1384
1385 filename_for_errors = g_strconcat ("<resource>", resource_path, NULL((void*)0));
1386
1387 _ctk_builder_parser_parse_buffer (builder, filename_for_errors,
1388 g_bytes_get_data (data, NULL((void*)0)), g_bytes_get_size (data),
1389 object_ids,
1390 &tmp_error);
1391 g_free (filename_for_errors);
1392 g_bytes_unref (data);
1393
1394 if (tmp_error != NULL((void*)0))
1395 {
1396 g_propagate_error (error, tmp_error);
1397 return 0;
1398 }
1399
1400 return 1;
1401}
1402
1403/**
1404 * ctk_builder_add_from_string:
1405 * @builder: a #CtkBuilder
1406 * @buffer: the string to parse
1407 * @length: the length of @buffer (may be -1 if @buffer is nul-terminated)
1408 * @error: (allow-none): return location for an error, or %NULL
1409 *
1410 * Parses a string containing a [CtkBuilder UI definition][BUILDER-UI]
1411 * and merges it with the current contents of @builder.
1412 *
1413 * Most users will probably want to use ctk_builder_new_from_string().
1414 *
1415 * Upon errors 0 will be returned and @error will be assigned a
1416 * #GError from the #CTK_BUILDER_ERROR, #G_MARKUP_ERROR or
1417 * #G_VARIANT_PARSE_ERROR domain.
1418 *
1419 * It’s not really reasonable to attempt to handle failures of this
1420 * call. The only reasonable thing to do when an error is detected is
1421 * to call g_error().
1422 *
1423 * Returns: A positive value on success, 0 if an error occurred
1424 *
1425 * Since: 2.12
1426 **/
1427guint
1428ctk_builder_add_from_string (CtkBuilder *builder,
1429 const gchar *buffer,
1430 gsize length,
1431 GError **error)
1432{
1433 GError *tmp_error;
1434
1435 g_return_val_if_fail (CTK_IS_BUILDER (builder), 0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((builder)); GType __t = ((ctk_builder_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_BUILDER (builder)"); return (0); } } while (0)
;
1436 g_return_val_if_fail (buffer != NULL, 0)do { if ((buffer != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "buffer != NULL"); return
(0); } } while (0)
;
1437 g_return_val_if_fail (error == NULL || *error == NULL, 0)do { if ((error == ((void*)0) || *error == ((void*)0))) { } else
{ g_return_if_fail_warning ("Ctk", ((const char*) (__func__)
), "error == NULL || *error == NULL"); return (0); } } while (
0)
;
1438
1439 tmp_error = NULL((void*)0);
1440
1441 g_free (builder->priv->filename);
1442 g_free (builder->priv->resource_prefix);
1443 builder->priv->filename = g_strdup (".")g_strdup_inline (".");
1444 builder->priv->resource_prefix = NULL((void*)0);
1445
1446 _ctk_builder_parser_parse_buffer (builder, "<input>",
1447 buffer, length,
1448 NULL((void*)0),
1449 &tmp_error);
1450 if (tmp_error != NULL((void*)0))
1451 {
1452 g_propagate_error (error, tmp_error);
1453 return 0;
1454 }
1455
1456 return 1;
1457}
1458
1459/**
1460 * ctk_builder_add_objects_from_string:
1461 * @builder: a #CtkBuilder
1462 * @buffer: the string to parse
1463 * @length: the length of @buffer (may be -1 if @buffer is nul-terminated)
1464 * @object_ids: (array zero-terminated=1) (element-type utf8): nul-terminated array of objects to build
1465 * @error: (allow-none): return location for an error, or %NULL
1466 *
1467 * Parses a string containing a [CtkBuilder UI definition][BUILDER-UI]
1468 * building only the requested objects and merges
1469 * them with the current contents of @builder.
1470 *
1471 * Upon errors 0 will be returned and @error will be assigned a
1472 * #GError from the #CTK_BUILDER_ERROR or #G_MARKUP_ERROR domain.
1473 *
1474 * If you are adding an object that depends on an object that is not
1475 * its child (for instance a #CtkTreeView that depends on its
1476 * #CtkTreeModel), you have to explicitly list all of them in @object_ids.
1477 *
1478 * Returns: A positive value on success, 0 if an error occurred
1479 *
1480 * Since: 2.14
1481 **/
1482guint
1483ctk_builder_add_objects_from_string (CtkBuilder *builder,
1484 const gchar *buffer,
1485 gsize length,
1486 gchar **object_ids,
1487 GError **error)
1488{
1489 GError *tmp_error;
1490
1491 g_return_val_if_fail (CTK_IS_BUILDER (builder), 0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((builder)); GType __t = ((ctk_builder_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_BUILDER (builder)"); return (0); } } while (0)
;
1492 g_return_val_if_fail (buffer != NULL, 0)do { if ((buffer != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "buffer != NULL"); return
(0); } } while (0)
;
1493 g_return_val_if_fail (object_ids != NULL && object_ids[0] != NULL, 0)do { if ((object_ids != ((void*)0) && object_ids[0] !=
((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "object_ids != NULL && object_ids[0] != NULL"
); return (0); } } while (0)
;
1494 g_return_val_if_fail (error == NULL || *error == NULL, 0)do { if ((error == ((void*)0) || *error == ((void*)0))) { } else
{ g_return_if_fail_warning ("Ctk", ((const char*) (__func__)
), "error == NULL || *error == NULL"); return (0); } } while (
0)
;
1495
1496 tmp_error = NULL((void*)0);
1497
1498 g_free (builder->priv->filename);
1499 g_free (builder->priv->resource_prefix);
1500 builder->priv->filename = g_strdup (".")g_strdup_inline (".");
1501 builder->priv->resource_prefix = NULL((void*)0);
1502
1503 _ctk_builder_parser_parse_buffer (builder, "<input>",
1504 buffer, length,
1505 object_ids,
1506 &tmp_error);
1507
1508 if (tmp_error != NULL((void*)0))
1509 {
1510 g_propagate_error (error, tmp_error);
1511 return 0;
1512 }
1513
1514 return 1;
1515}
1516
1517/**
1518 * ctk_builder_get_object:
1519 * @builder: a #CtkBuilder
1520 * @name: name of object to get
1521 *
1522 * Gets the object named @name. Note that this function does not
1523 * increment the reference count of the returned object.
1524 *
1525 * Returns: (nullable) (transfer none): the object named @name or %NULL if
1526 * it could not be found in the object tree.
1527 *
1528 * Since: 2.12
1529 **/
1530GObject *
1531ctk_builder_get_object (CtkBuilder *builder,
1532 const gchar *name)
1533{
1534 g_return_val_if_fail (CTK_IS_BUILDER (builder), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((builder)); GType __t = ((ctk_builder_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_BUILDER (builder)"); return (((void*)0)); } } while
(0)
;
1535 g_return_val_if_fail (name != NULL, NULL)do { if ((name != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "name != NULL"); return (
((void*)0)); } } while (0)
;
1536
1537 return g_hash_table_lookup (builder->priv->objects, name);
1538}
1539
1540/**
1541 * ctk_builder_get_objects:
1542 * @builder: a #CtkBuilder
1543 *
1544 * Gets all objects that have been constructed by @builder. Note that
1545 * this function does not increment the reference counts of the returned
1546 * objects.
1547 *
1548 * Returns: (element-type GObject) (transfer container): a newly-allocated #GSList containing all the objects
1549 * constructed by the #CtkBuilder instance. It should be freed by
1550 * g_slist_free()
1551 *
1552 * Since: 2.12
1553 **/
1554GSList *
1555ctk_builder_get_objects (CtkBuilder *builder)
1556{
1557 GSList *objects = NULL((void*)0);
1558 GObject *object;
1559 GHashTableIter iter;
1560
1561 g_return_val_if_fail (CTK_IS_BUILDER (builder), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((builder)); GType __t = ((ctk_builder_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_BUILDER (builder)"); return (((void*)0)); } } while
(0)
;
1562
1563 g_hash_table_iter_init (&iter, builder->priv->objects);
1564 while (g_hash_table_iter_next (&iter, NULL((void*)0), (gpointer *)&object))
1565 objects = g_slist_prepend (objects, object);
1566
1567 return g_slist_reverse (objects);
1568}
1569
1570/**
1571 * ctk_builder_set_translation_domain:
1572 * @builder: a #CtkBuilder
1573 * @domain: (allow-none): the translation domain or %NULL
1574 *
1575 * Sets the translation domain of @builder.
1576 * See #CtkBuilder:translation-domain.
1577 *
1578 * Since: 2.12
1579 **/
1580void
1581ctk_builder_set_translation_domain (CtkBuilder *builder,
1582 const gchar *domain)
1583{
1584 gchar *new_domain;
1585
1586 g_return_if_fail (CTK_IS_BUILDER (builder))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((builder)); GType __t = ((ctk_builder_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_BUILDER (builder)"); return; } } while (0)
;
1587
1588 new_domain = g_strdup (domain)g_strdup_inline (domain);
1589 g_free (builder->priv->domain);
1590 builder->priv->domain = new_domain;
1591
1592 g_object_notify_by_pspec (G_OBJECT (builder)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((builder)), (((GType) ((20) << (2))))))))
, builder_props[PROP_TRANSLATION_DOMAIN]);
1593}
1594
1595/**
1596 * ctk_builder_get_translation_domain:
1597 * @builder: a #CtkBuilder
1598 *
1599 * Gets the translation domain of @builder.
1600 *
1601 * Returns: the translation domain. This string is owned
1602 * by the builder object and must not be modified or freed.
1603 *
1604 * Since: 2.12
1605 **/
1606const gchar *
1607ctk_builder_get_translation_domain (CtkBuilder *builder)
1608{
1609 g_return_val_if_fail (CTK_IS_BUILDER (builder), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((builder)); GType __t = ((ctk_builder_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_BUILDER (builder)"); return (((void*)0)); } } while
(0)
;
1610
1611 return builder->priv->domain;
1612}
1613
1614/**
1615 * ctk_builder_expose_object:
1616 * @builder: a #CtkBuilder
1617 * @name: the name of the object exposed to the builder
1618 * @object: the object to expose
1619 *
1620 * Add @object to the @builder object pool so it can be referenced just like any
1621 * other object built by builder.
1622 *
1623 * Since: 3.8
1624 **/
1625void
1626ctk_builder_expose_object (CtkBuilder *builder,
1627 const gchar *name,
1628 GObject *object)
1629{
1630 g_return_if_fail (CTK_IS_BUILDER (builder))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((builder)); GType __t = ((ctk_builder_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_BUILDER (builder)"); return; } } while (0)
;
1631 g_return_if_fail (name && name[0])do { if ((name && name[0])) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "name && name[0]"
); return; } } while (0)
;
1632 g_return_if_fail (!g_hash_table_contains (builder->priv->objects, name))do { if ((!g_hash_table_contains (builder->priv->objects
, name))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "!g_hash_table_contains (builder->priv->objects, name)"
); return; } } while (0)
;
1633
1634 object_set_name (object, name);
1635 g_hash_table_insert (builder->priv->objects,
1636 g_strdup (name)g_strdup_inline (name),
1637 g_object_ref (object)((__typeof__ (object)) (g_object_ref) (object)));
1638}
1639
1640
1641typedef struct {
1642 GModule *module;
1643 gpointer data;
1644} ConnectArgs;
1645
1646static void
1647ctk_builder_connect_signals_default (CtkBuilder *builder,
1648 GObject *object,
1649 const gchar *signal_name,
1650 const gchar *handler_name,
1651 GObject *connect_object,
1652 GConnectFlags flags,
1653 gpointer user_data)
1654{
1655 GCallback func;
1656 ConnectArgs *args = (ConnectArgs*) user_data;
1657
1658 func = ctk_builder_lookup_callback_symbol (builder, handler_name);
1659
1660 if (!func)
1661 {
1662 /* Only error out for missing GModule support if we've not
1663 * found the symbols explicitly added with ctk_builder_add_callback_symbol()
1664 */
1665 if (args->module == NULL((void*)0))
1666 g_error ("ctk_builder_connect_signals() requires working GModule");
1667
1668 if (!g_module_symbol (args->module, handler_name, (gpointer)&func))
1669 {
1670 g_warning ("Could not find signal handler '%s'. Did you compile with -rdynamic?", handler_name);
1671 return;
1672 }
1673 }
1674
1675 if (connect_object)
1676 g_signal_connect_object (object, signal_name, func, connect_object, flags);
1677 else
1678 g_signal_connect_data (object, signal_name, func, args->data, NULL((void*)0), flags);
1679}
1680
1681
1682/**
1683 * ctk_builder_connect_signals:
1684 * @builder: a #CtkBuilder
1685 * @user_data: user data to pass back with all signals
1686 *
1687 * This method is a simpler variation of ctk_builder_connect_signals_full().
1688 * It uses symbols explicitly added to @builder with prior calls to
1689 * ctk_builder_add_callback_symbol(). In the case that symbols are not
1690 * explicitly added; it uses #GModule’s introspective features (by opening the module %NULL)
1691 * to look at the application’s symbol table. From here it tries to match
1692 * the signal handler names given in the interface description with
1693 * symbols in the application and connects the signals. Note that this
1694 * function can only be called once, subsequent calls will do nothing.
1695 *
1696 * Note that unless ctk_builder_add_callback_symbol() is called for
1697 * all signal callbacks which are referenced by the loaded XML, this
1698 * function will require that #GModule be supported on the platform.
1699 *
1700 * If you rely on #GModule support to lookup callbacks in the symbol table,
1701 * the following details should be noted:
1702 *
1703 * When compiling applications for Windows, you must declare signal callbacks
1704 * with #G_MODULE_EXPORT, or they will not be put in the symbol table.
1705 * On Linux and Unices, this is not necessary; applications should instead
1706 * be compiled with the -Wl,--export-dynamic CFLAGS, and linked against
1707 * gmodule-export-2.0.
1708 *
1709 * Since: 2.12
1710 **/
1711void
1712ctk_builder_connect_signals (CtkBuilder *builder,
1713 gpointer user_data)
1714{
1715 ConnectArgs args;
1716
1717 g_return_if_fail (CTK_IS_BUILDER (builder))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((builder)); GType __t = ((ctk_builder_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_BUILDER (builder)"); return; } } while (0)
;
1718
1719 args.data = user_data;
1720
1721 if (g_module_supported ())
1722 args.module = g_module_open (NULL((void*)0), G_MODULE_BIND_LAZY);
1723 else
1724 args.module = NULL((void*)0);
1725
1726 ctk_builder_connect_signals_full (builder,
1727 ctk_builder_connect_signals_default,
1728 &args);
1729 if (args.module)
1730 g_module_close (args.module);
1731}
1732
1733/**
1734 * CtkBuilderConnectFunc:
1735 * @builder: a #CtkBuilder
1736 * @object: object to connect a signal to
1737 * @signal_name: name of the signal
1738 * @handler_name: name of the handler
1739 * @connect_object: (nullable): a #GObject, if non-%NULL, use g_signal_connect_object()
1740 * @flags: #GConnectFlags to use
1741 * @user_data: user data
1742 *
1743 * This is the signature of a function used to connect signals. It is used
1744 * by the ctk_builder_connect_signals() and ctk_builder_connect_signals_full()
1745 * methods. It is mainly intended for interpreted language bindings, but
1746 * could be useful where the programmer wants more control over the signal
1747 * connection process. Note that this function can only be called once,
1748 * subsequent calls will do nothing.
1749 *
1750 * Since: 2.12
1751 */
1752
1753/**
1754 * ctk_builder_connect_signals_full:
1755 * @builder: a #CtkBuilder
1756 * @func: (scope call): the function used to connect the signals
1757 * @user_data: arbitrary data that will be passed to the connection function
1758 *
1759 * This function can be thought of the interpreted language binding
1760 * version of ctk_builder_connect_signals(), except that it does not
1761 * require GModule to function correctly.
1762 *
1763 * Since: 2.12
1764 */
1765void
1766ctk_builder_connect_signals_full (CtkBuilder *builder,
1767 CtkBuilderConnectFunc func,
1768 gpointer user_data)
1769{
1770 GSList *l;
1771 GObject *object;
1772 GObject *connect_object;
1773 GString *detailed_id = NULL((void*)0);
1774
1775 g_return_if_fail (CTK_IS_BUILDER (builder))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((builder)); GType __t = ((ctk_builder_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_BUILDER (builder)"); return; } } while (0)
;
1776 g_return_if_fail (func != NULL)do { if ((func != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "func != NULL"); return;
} } while (0)
;
1777
1778 if (!builder->priv->signals)
1779 return;
1780
1781 builder->priv->signals = g_slist_reverse (builder->priv->signals);
1782 for (l = builder->priv->signals; l; l = l->next)
1783 {
1784 SignalInfo *signal = (SignalInfo*)l->data;
1785 const gchar *signal_name;
1786
1787 g_assert (signal != NULL)do { if (signal != ((void*)0)) ; else g_assertion_message_expr
("Ctk", "ctkbuilder.c", 1787, ((const char*) (__func__)), "signal != NULL"
); } while (0)
;
1788 g_assert (signal->id != 0)do { if (signal->id != 0) ; else g_assertion_message_expr (
"Ctk", "ctkbuilder.c", 1788, ((const char*) (__func__)), "signal->id != 0"
); } while (0)
;
1789
1790 signal_name = g_signal_name (signal->id);
1791
1792 object = g_hash_table_lookup (builder->priv->objects,
1793 signal->object_name);
1794 g_assert (object != NULL)do { if (object != ((void*)0)) ; else g_assertion_message_expr
("Ctk", "ctkbuilder.c", 1794, ((const char*) (__func__)), "object != NULL"
); } while (0)
;
1795
1796 connect_object = NULL((void*)0);
1797
1798 if (signal->connect_object_name)
1799 {
1800 connect_object = g_hash_table_lookup (builder->priv->objects,
1801 signal->connect_object_name);
1802 if (!connect_object)
1803 g_warning ("Could not lookup object %s on signal %s of object %s",
1804 signal->connect_object_name, signal_name,
1805 signal->object_name);
1806 }
1807
1808 if (signal->detail)
1809 {
1810 if (detailed_id == NULL((void*)0))
1811 detailed_id = g_string_new ("");
1812
1813 g_string_printf (detailed_id, "%s::%s", signal_name,
1814 g_quark_to_string (signal->detail));
1815 signal_name = detailed_id->str;
1816 }
1817
1818 func (builder, object, signal_name, signal->handler,
1819 connect_object, signal->flags, user_data);
1820 }
1821
1822 g_slist_free_full (builder->priv->signals, (GDestroyNotify)_free_signal_info);
1823 builder->priv->signals = NULL((void*)0);
1824
1825 if (detailed_id)
1826 g_string_free (detailed_id, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(detailed_id), ((!(0)))) : g_string_free_and_steal (detailed_id
)) : (g_string_free) ((detailed_id), ((!(0)))))
;
1827}
1828
1829/**
1830 * ctk_builder_value_from_string:
1831 * @builder: a #CtkBuilder
1832 * @pspec: the #GParamSpec for the property
1833 * @string: the string representation of the value
1834 * @value: (out): the #GValue to store the result in
1835 * @error: (allow-none): return location for an error, or %NULL
1836 *
1837 * This function demarshals a value from a string. This function
1838 * calls g_value_init() on the @value argument, so it need not be
1839 * initialised beforehand.
1840 *
1841 * This function can handle char, uchar, boolean, int, uint, long,
1842 * ulong, enum, flags, float, double, string, #CdkColor, #CdkRGBA and
1843 * #CtkAdjustment type values. Support for #CtkWidget type values is
1844 * still to come.
1845 *
1846 * Upon errors %FALSE will be returned and @error will be assigned a
1847 * #GError from the #CTK_BUILDER_ERROR domain.
1848 *
1849 * Returns: %TRUE on success
1850 *
1851 * Since: 2.12
1852 */
1853gboolean
1854ctk_builder_value_from_string (CtkBuilder *builder,
1855 GParamSpec *pspec,
1856 const gchar *string,
1857 GValue *value,
1858 GError **error)
1859{
1860 g_return_val_if_fail (CTK_IS_BUILDER (builder), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((builder)); GType __t = ((ctk_builder_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_BUILDER (builder)"); return ((0)); } } while (0)
;
1861 g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE)do { if (((((g_type_check_instance_is_fundamentally_a ((GTypeInstance
*) ((pspec)), (((GType) ((19) << (2)))))))))) { } else {
g_return_if_fail_warning ("Ctk", ((const char*) (__func__)),
"G_IS_PARAM_SPEC (pspec)"); return ((0)); } } while (0)
;
1862 g_return_val_if_fail (string != NULL, FALSE)do { if ((string != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "string != NULL"); return
((0)); } } while (0)
;
1863 g_return_val_if_fail (value != NULL, FALSE)do { if ((value != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "value != NULL"); return
((0)); } } while (0)
;
1864 g_return_val_if_fail (error == NULL || *error == NULL, FALSE)do { if ((error == ((void*)0) || *error == ((void*)0))) { } else
{ g_return_if_fail_warning ("Ctk", ((const char*) (__func__)
), "error == NULL || *error == NULL"); return ((0)); } } while
(0)
;
1865
1866 /*
1867 * GParamSpecUnichar has the internal type G_TYPE_UINT,
1868 * so we cannot handle this in the switch, do it separately
1869 */
1870 if (G_IS_PARAM_SPEC_UNICHAR (pspec)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(pspec)); GType __t = ((g_param_spec_types[9])); 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; }))))
)
1871 {
1872 gunichar c;
1873 g_value_init (value, G_TYPE_UINT((GType) ((7) << (2))));
1874 c = g_utf8_get_char_validated (string, strlen (string));
1875 if (c != 0 && c != (gunichar)-1 && c != (gunichar)-2)
1876 g_value_set_uint (value, c);
1877 return TRUE(!(0));
1878 }
1879
1880 /*
1881 * GParamSpecVariant can specify a GVariantType which can help with
1882 * parsing, so we need to take care of that here.
1883 */
1884 if (G_IS_PARAM_SPEC_VARIANT (pspec)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(pspec)); GType __t = ((g_param_spec_types[22])); 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; }))))
)
1885 {
1886 GParamSpecVariant *variant_pspec = G_PARAM_SPEC_VARIANT (pspec)((((GParamSpecVariant*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((pspec)), ((g_param_spec_types[22]))))))
;
1887 const GVariantType *type;
1888 GVariant *variant;
1889
1890 g_value_init (value, G_TYPE_VARIANT((GType) ((21) << (2))));
1891
1892 /* The GVariant parser doesn't deal with indefinite types */
1893 if (g_variant_type_is_definite (variant_pspec->type))
1894 type = variant_pspec->type;
1895 else
1896 type = NULL((void*)0);
1897
1898 variant = g_variant_parse (type, string, NULL((void*)0), NULL((void*)0), error);
1899 if (variant == NULL((void*)0))
1900 return FALSE(0);
1901 g_value_take_variant (value, variant);
1902 return TRUE(!(0));
1903 }
1904
1905 return ctk_builder_value_from_string_type (builder,
1906 G_PARAM_SPEC_VALUE_TYPE (pspec)(((((GParamSpec*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((pspec)), (((GType) ((19) << (2))))))))->value_type
)
,
1907 string, value, error);
1908}
1909
1910/**
1911 * ctk_builder_value_from_string_type:
1912 * @builder: a #CtkBuilder
1913 * @type: the #GType of the value
1914 * @string: the string representation of the value
1915 * @value: (out): the #GValue to store the result in
1916 * @error: (allow-none): return location for an error, or %NULL
1917 *
1918 * Like ctk_builder_value_from_string(), this function demarshals
1919 * a value from a string, but takes a #GType instead of #GParamSpec.
1920 * This function calls g_value_init() on the @value argument, so it
1921 * need not be initialised beforehand.
1922 *
1923 * Upon errors %FALSE will be returned and @error will be assigned a
1924 * #GError from the #CTK_BUILDER_ERROR domain.
1925 *
1926 * Returns: %TRUE on success
1927 *
1928 * Since: 2.12
1929 */
1930gboolean
1931ctk_builder_value_from_string_type (CtkBuilder *builder,
1932 GType type,
1933 const gchar *string,
1934 GValue *value,
1935 GError **error)
1936{
1937 gboolean ret = TRUE(!(0));
1938
1939 g_return_val_if_fail (string != NULL, FALSE)do { if ((string != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "string != NULL"); return
((0)); } } while (0)
;
1940 g_return_val_if_fail (error == NULL || *error == NULL, FALSE)do { if ((error == ((void*)0) || *error == ((void*)0))) { } else
{ g_return_if_fail_warning ("Ctk", ((const char*) (__func__)
), "error == NULL || *error == NULL"); return ((0)); } } while
(0)
;
1941
1942 g_value_init (value, type);
1943
1944 switch (G_TYPE_FUNDAMENTAL (type)(g_type_fundamental (type)))
1945 {
1946 case G_TYPE_CHAR((GType) ((3) << (2))):
1947 g_value_set_schar (value, string[0]);
1948 break;
1949 case G_TYPE_UCHAR((GType) ((4) << (2))):
1950 g_value_set_uchar (value, (guchar)string[0]);
1951 break;
1952 case G_TYPE_BOOLEAN((GType) ((5) << (2))):
1953 {
1954 gboolean b;
1955
1956 if (!_ctk_builder_boolean_from_string (string, &b, error))
1957 {
1958 ret = FALSE(0);
1959 break;
1960 }
1961 g_value_set_boolean (value, b);
1962 break;
1963 }
1964 case G_TYPE_INT((GType) ((6) << (2))):
1965 case G_TYPE_LONG((GType) ((8) << (2))):
1966 case G_TYPE_INT64((GType) ((10) << (2))):
1967 {
1968 gint64 l;
1969 gchar *endptr = NULL((void*)0);
1970
1971 errno(*__errno_location ()) = 0;
1972 l = g_ascii_strtoll (string, &endptr, 0);
1973 if (errno(*__errno_location ()) || endptr == string)
1974 {
1975 g_set_error (error,
1976 CTK_BUILDER_ERROR(ctk_builder_error_quark ()),
1977 CTK_BUILDER_ERROR_INVALID_VALUE,
1978 "Could not parse integer '%s'",
1979 string);
1980 ret = FALSE(0);
1981 break;
1982 }
1983 if (G_VALUE_HOLDS_INT (value)(((__extension__ ({ const GValue *__val = (const GValue*) ((value
)); GType __t = (((GType) ((6) << (2)))); gboolean __r;
if (!__val) __r = (0); else if (__val->g_type == __t) __r
= (!(0)); else __r = g_type_check_value_holds (__val, __t); __r
; }))))
)
1984 g_value_set_int (value, l);
1985 else if (G_VALUE_HOLDS_LONG (value)(((__extension__ ({ const GValue *__val = (const GValue*) ((value
)); GType __t = (((GType) ((8) << (2)))); gboolean __r;
if (!__val) __r = (0); else if (__val->g_type == __t) __r
= (!(0)); else __r = g_type_check_value_holds (__val, __t); __r
; }))))
)
1986 g_value_set_long (value, l);
1987 else
1988 g_value_set_int64 (value, l);
1989 break;
1990 }
1991 case G_TYPE_UINT((GType) ((7) << (2))):
1992 case G_TYPE_ULONG((GType) ((9) << (2))):
1993 case G_TYPE_UINT64((GType) ((11) << (2))):
1994 {
1995 guint64 ul;
1996 gchar *endptr = NULL((void*)0);
1997 errno(*__errno_location ()) = 0;
1998 ul = g_ascii_strtoull (string, &endptr, 0);
1999 if (errno(*__errno_location ()) || endptr == string)
2000 {
2001 g_set_error (error,
2002 CTK_BUILDER_ERROR(ctk_builder_error_quark ()),
2003 CTK_BUILDER_ERROR_INVALID_VALUE,
2004 "Could not parse unsigned integer '%s'",
2005 string);
2006 ret = FALSE(0);
2007 break;
2008 }
2009 if (G_VALUE_HOLDS_UINT (value)(((__extension__ ({ const GValue *__val = (const GValue*) ((value
)); GType __t = (((GType) ((7) << (2)))); gboolean __r;
if (!__val) __r = (0); else if (__val->g_type == __t) __r
= (!(0)); else __r = g_type_check_value_holds (__val, __t); __r
; }))))
)
2010 g_value_set_uint (value, ul);
2011 else if (G_VALUE_HOLDS_ULONG (value)(((__extension__ ({ const GValue *__val = (const GValue*) ((value
)); GType __t = (((GType) ((9) << (2)))); gboolean __r;
if (!__val) __r = (0); else if (__val->g_type == __t) __r
= (!(0)); else __r = g_type_check_value_holds (__val, __t); __r
; }))))
)
2012 g_value_set_ulong (value, ul);
2013 else
2014 g_value_set_uint64 (value, ul);
2015 break;
2016 }
2017 case G_TYPE_ENUM((GType) ((12) << (2))):
2018 {
2019 gint enum_value;
2020 if (!_ctk_builder_enum_from_string (type, string, &enum_value, error))
2021 {
2022 ret = FALSE(0);
2023 break;
2024 }
2025 g_value_set_enum (value, enum_value);
2026 break;
2027 }
2028 case G_TYPE_FLAGS((GType) ((13) << (2))):
2029 {
2030 guint flags_value;
2031
2032 if (!_ctk_builder_flags_from_string (type, NULL((void*)0), string, &flags_value, error))
2033 {
2034 ret = FALSE(0);
2035 break;
2036 }
2037 g_value_set_flags (value, flags_value);
2038 break;
2039 }
2040 case G_TYPE_FLOAT((GType) ((14) << (2))):
2041 case G_TYPE_DOUBLE((GType) ((15) << (2))):
2042 {
2043 gdouble d;
2044 gchar *endptr = NULL((void*)0);
2045 errno(*__errno_location ()) = 0;
2046 d = g_ascii_strtod (string, &endptr);
2047 if (errno(*__errno_location ()) || endptr == string)
2048 {
2049 g_set_error (error,
2050 CTK_BUILDER_ERROR(ctk_builder_error_quark ()),
2051 CTK_BUILDER_ERROR_INVALID_VALUE,
2052 "Could not parse double '%s'",
2053 string);
2054 ret = FALSE(0);
2055 break;
2056 }
2057 if (G_VALUE_HOLDS_FLOAT (value)(((__extension__ ({ const GValue *__val = (const GValue*) ((value
)); GType __t = (((GType) ((14) << (2)))); gboolean __r
; if (!__val) __r = (0); else if (__val->g_type == __t) __r
= (!(0)); else __r = g_type_check_value_holds (__val, __t); __r
; }))))
)
2058 g_value_set_float (value, d);
2059 else
2060 g_value_set_double (value, d);
2061 break;
2062 }
2063 case G_TYPE_STRING((GType) ((16) << (2))):
2064 g_value_set_string (value, string);
2065 break;
2066 case G_TYPE_VARIANT((GType) ((21) << (2))):
2067 {
2068 GVariant *variant;
2069
2070 variant = g_variant_parse (NULL((void*)0), string, NULL((void*)0), NULL((void*)0), error);
2071 if (value != NULL((void*)0))
2072 g_value_take_variant (value, variant);
2073 else
2074 ret = FALSE(0);
2075 }
2076 break;
2077 case G_TYPE_BOXED((GType) ((18) << (2))):
2078 if (G_VALUE_HOLDS (value, g_type_from_name ("CdkColor"))(((__extension__ ({ const GValue *__val = (const GValue*) ((value
)); GType __t = ((g_type_from_name ("CdkColor"))); gboolean __r
; if (!__val) __r = (0); else if (__val->g_type == __t) __r
= (!(0)); else __r = g_type_check_value_holds (__val, __t); __r
; }))))
)
2079 {
2080 CdkColor color = { 0, };
2081
2082 if (cdk_color_parse (string, &color))
2083 g_value_set_boxed (value, &color);
2084 else
2085 {
2086 g_set_error (error,
2087 CTK_BUILDER_ERROR(ctk_builder_error_quark ()),
2088 CTK_BUILDER_ERROR_INVALID_VALUE,
2089 "Could not parse color '%s'",
2090 string);
2091 ret = FALSE(0);
2092 }
2093 }
2094 else if (G_VALUE_HOLDS (value, CDK_TYPE_RGBA)(((__extension__ ({ const GValue *__val = (const GValue*) ((value
)); GType __t = (((cdk_rgba_get_type ()))); gboolean __r; if (
!__val) __r = (0); else if (__val->g_type == __t) __r = (!
(0)); else __r = g_type_check_value_holds (__val, __t); __r; }
))))
)
2095 {
2096 CdkRGBA rgba = { 0 };
2097
2098 if (cdk_rgba_parse (&rgba, string))
2099 g_value_set_boxed (value, &rgba);
2100 else
2101 {
2102 g_set_error (error,
2103 CTK_BUILDER_ERROR(ctk_builder_error_quark ()),
2104 CTK_BUILDER_ERROR_INVALID_VALUE,
2105 "Could not parse RGBA color '%s'",
2106 string);
2107 ret = FALSE(0);
2108 }
2109 }
2110 else if (G_VALUE_HOLDS (value, G_TYPE_STRV)(((__extension__ ({ const GValue *__val = (const GValue*) ((value
)); GType __t = (((g_strv_get_type ()))); gboolean __r; if (!
__val) __r = (0); else if (__val->g_type == __t) __r = (!(
0)); else __r = g_type_check_value_holds (__val, __t); __r; }
))))
)
2111 {
2112 gchar **vector = g_strsplit (string, "\n", 0);
2113 g_value_take_boxed (value, vector);
2114 }
2115 else
2116 {
2117 g_set_error (error,
2118 CTK_BUILDER_ERROR(ctk_builder_error_quark ()),
2119 CTK_BUILDER_ERROR_INVALID_VALUE,
2120 "Could not parse '%s' as a %s",
2121 string, G_VALUE_TYPE_NAME (value)(g_type_name ((((GValue*) (value))->g_type))));
2122 ret = FALSE(0);
2123 }
2124 break;
2125 case G_TYPE_OBJECT((GType) ((20) << (2))):
2126 case G_TYPE_INTERFACE((GType) ((2) << (2))):
2127 if (G_VALUE_HOLDS (value, GDK_TYPE_PIXBUF)(((__extension__ ({ const GValue *__val = (const GValue*) ((value
)); GType __t = (((gdk_pixbuf_get_type ()))); gboolean __r; if
(!__val) __r = (0); else if (__val->g_type == __t) __r = (
!(0)); else __r = g_type_check_value_holds (__val, __t); __r;
}))))
)
2128 {
2129 gchar *filename;
2130 GError *tmp_error = NULL((void*)0);
2131 GdkPixbuf *pixbuf = NULL((void*)0);
2132
2133 if (g_hash_table_contains (builder->priv->objects, string))
2134 {
2135 g_set_error (error,
2136 CTK_BUILDER_ERROR(ctk_builder_error_quark ()),
2137 CTK_BUILDER_ERROR_INVALID_VALUE,
2138 "Could not load image '%s': "
2139 " '%s' is already used as object id",
2140 string, string);
2141 return FALSE(0);
2142 }
2143
2144 filename = _ctk_builder_get_resource_path (builder, string);
2145 if (filename != NULL((void*)0))
2146 {
2147 GInputStream *stream = g_resources_open_stream (filename, 0, &tmp_error);
2148 if (stream != NULL((void*)0))
2149 {
2150 pixbuf = gdk_pixbuf_new_from_stream (stream, NULL((void*)0), &tmp_error);
2151 g_object_unref (stream);
2152 }
2153 }
2154 else
2155 {
2156 filename = _ctk_builder_get_absolute_filename (builder, string);
2157 pixbuf = gdk_pixbuf_new_from_file (filename, &tmp_error);
2158 }
2159
2160 if (pixbuf == NULL((void*)0))
2161 {
2162 CtkIconTheme *theme;
2163
2164 g_warning ("Could not load image '%s': %s",
2165 string, tmp_error->message);
2166 g_error_free (tmp_error);
2167
2168 /* fall back to a missing image */
2169 theme = ctk_icon_theme_get_default ();
2170 pixbuf = ctk_icon_theme_load_icon (theme,
2171 "image-missing",
2172 16,
2173 CTK_ICON_LOOKUP_USE_BUILTIN,
2174 NULL((void*)0));
2175 }
2176
2177 if (pixbuf)
2178 {
2179 g_value_set_object (value, pixbuf);
2180 g_object_unref (G_OBJECT (pixbuf)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((pixbuf)), (((GType) ((20) << (2))))))))
);
2181 }
2182
2183 g_free (filename);
2184
2185 ret = TRUE(!(0));
2186 }
2187 else if (G_VALUE_HOLDS (value, G_TYPE_FILE)(((__extension__ ({ const GValue *__val = (const GValue*) ((value
)); GType __t = (((g_file_get_type ()))); gboolean __r; if (!
__val) __r = (0); else if (__val->g_type == __t) __r = (!(
0)); else __r = g_type_check_value_holds (__val, __t); __r; }
))))
)
2188 {
2189 GFile *file;
2190
2191 if (g_hash_table_contains (builder->priv->objects, string))
2192 {
2193 g_set_error (error,
2194 CTK_BUILDER_ERROR(ctk_builder_error_quark ()),
2195 CTK_BUILDER_ERROR_INVALID_VALUE,
2196 "Could not create file '%s': "
2197 " '%s' is already used as object id",
2198 string, string);
2199 return FALSE(0);
2200 }
2201
2202 file = g_file_new_for_uri (string);
2203 g_value_set_object (value, file);
2204 g_object_unref (G_OBJECT (file)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((file)), (((GType) ((20) << (2))))))))
);
2205
2206 ret = TRUE(!(0));
2207 }
2208 else
2209 ret = FALSE(0);
2210 break;
2211 default:
2212 ret = FALSE(0);
2213 break;
2214 }
2215
2216 /* Catch unassigned error for object types as well as any unsupported types.
2217 * While parsing CtkBuilder; object types are deserialized
2218 * without calling ctk_builder_value_from_string_type().
2219 */
2220 if (!ret && error && *error == NULL((void*)0))
2221 g_set_error (error,
2222 CTK_BUILDER_ERROR(ctk_builder_error_quark ()),
2223 CTK_BUILDER_ERROR_INVALID_VALUE,
2224 "Unsupported GType '%s'", g_type_name (type));
2225
2226 return ret;
2227}
2228
2229gboolean
2230_ctk_builder_enum_from_string (GType type,
2231 const gchar *string,
2232 gint *enum_value,
2233 GError **error)
2234{
2235 GEnumClass *eclass;
2236 GEnumValue *ev;
2237 gchar *endptr;
2238 gint value;
2239 gboolean ret;
2240
2241 g_return_val_if_fail (G_TYPE_IS_ENUM (type), FALSE)do { if ((((g_type_fundamental (type)) == ((GType) ((12) <<
(2)))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "G_TYPE_IS_ENUM (type)"); return ((0)); }
} while (0)
;
2242 g_return_val_if_fail (string != NULL, FALSE)do { if ((string != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "string != NULL"); return
((0)); } } while (0)
;
2243
2244 ret = TRUE(!(0));
2245
2246 endptr = NULL((void*)0);
2247 errno(*__errno_location ()) = 0;
2248 value = g_ascii_strtoull (string, &endptr, 0);
2249 if (errno(*__errno_location ()) == 0 && endptr != string) /* parsed a number */
2250 *enum_value = value;
2251 else
2252 {
2253 eclass = g_type_class_ref (type);
2254 ev = g_enum_get_value_by_name (eclass, string);
2255 if (!ev)
2256 ev = g_enum_get_value_by_nick (eclass, string);
2257
2258 if (ev)
2259 *enum_value = ev->value;
2260 else
2261 {
2262 g_set_error (error,
2263 CTK_BUILDER_ERROR(ctk_builder_error_quark ()),
2264 CTK_BUILDER_ERROR_INVALID_VALUE,
2265 "Could not parse enum: '%s'",
2266 string);
2267 ret = FALSE(0);
2268 }
2269
2270 g_type_class_unref (eclass);
2271 }
2272
2273 return ret;
2274}
2275
2276gboolean
2277_ctk_builder_flags_from_string (GType type,
2278 GFlagsValue *aliases,
2279 const gchar *string,
2280 guint *flags_value,
2281 GError **error)
2282{
2283 GFlagsClass *fclass;
2284 gchar *endptr, *prevptr;
2285 guint i, j, k, value;
2286 gchar *flagstr;
2287 GFlagsValue *fv;
2288 const gchar *flag;
2289 gunichar ch;
2290 gboolean eos, ret;
2291
2292 g_return_val_if_fail (G_TYPE_IS_FLAGS (type), FALSE)do { if ((((g_type_fundamental (type)) == ((GType) ((13) <<
(2)))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "G_TYPE_IS_FLAGS (type)"); return ((0));
} } while (0)
;
2293 g_return_val_if_fail (string != 0, FALSE)do { if ((string != 0)) { } else { g_return_if_fail_warning (
"Ctk", ((const char*) (__func__)), "string != 0"); return ((0
)); } } while (0)
;
2294
2295 ret = TRUE(!(0));
2296
2297 endptr = NULL((void*)0);
2298 errno(*__errno_location ()) = 0;
2299 value = g_ascii_strtoull (string, &endptr, 0);
2300 if (errno(*__errno_location ()) == 0 && endptr != string) /* parsed a number */
2301 *flags_value = value;
2302 else
2303 {
2304 fclass = g_type_class_ref (type);
2305
2306 flagstr = g_strdup (string)g_strdup_inline (string);
2307 for (value = i = j = 0; ; i++)
2308 {
2309
2310 eos = flagstr[i] == '\0';
2311
2312 if (!eos && flagstr[i] != '|')
2313 continue;
2314
2315 flag = &flagstr[j];
2316 endptr = &flagstr[i];
2317
2318 if (!eos)
2319 {
2320 flagstr[i++] = '\0';
2321 j = i;
2322 }
2323
2324 /* trim spaces */
2325 for (;;)
2326 {
2327 ch = g_utf8_get_char (flag);
2328 if (!g_unichar_isspace (ch))
2329 break;
2330 flag = g_utf8_next_char (flag)((flag) + g_utf8_skip[*(const guchar *)(flag)]);
2331 }
2332
2333 while (endptr > flag)
2334 {
2335 prevptr = g_utf8_prev_char (endptr);
2336 ch = g_utf8_get_char (prevptr);
2337 if (!g_unichar_isspace (ch))
2338 break;
2339 endptr = prevptr;
2340 }
2341
2342 if (endptr > flag)
2343 {
2344 *endptr = '\0';
2345
2346 fv = NULL((void*)0);
2347
2348 if (aliases)
2349 {
2350 for (k = 0; aliases[k].value_nick; k++)
2351 {
2352 if (g_ascii_strcasecmp (aliases[k].value_nick, flag) == 0)
2353 {
2354 fv = &aliases[k];
2355 break;
2356 }
2357 }
2358 }
2359
2360 if (!fv)
2361 fv = g_flags_get_value_by_name (fclass, flag);
2362
2363 if (!fv)
2364 fv = g_flags_get_value_by_nick (fclass, flag);
2365
2366 if (fv)
2367 value |= fv->value;
2368 else
2369 {
2370 g_set_error (error,
2371 CTK_BUILDER_ERROR(ctk_builder_error_quark ()),
2372 CTK_BUILDER_ERROR_INVALID_VALUE,
2373 "Unknown flag: '%s'",
2374 flag);
2375 ret = FALSE(0);
2376 break;
2377 }
2378 }
2379
2380 if (eos)
2381 {
2382 *flags_value = value;
2383 break;
2384 }
2385 }
2386
2387 g_free (flagstr);
2388
2389 g_type_class_unref (fclass);
2390 }
2391
2392 return ret;
2393}
2394
2395gboolean
2396_ctk_builder_boolean_from_string (const gchar *string,
2397 gboolean *value,
2398 GError **error)
2399{
2400 if (string[0] == '\0')
2401 goto error;
2402 else if (string[1] == '\0')
2403 {
2404 gchar c;
2405
2406 c = string[0];
2407 if (c == '1' ||
2408 c == 'y' || c == 't' ||
2409 c == 'Y' || c == 'T')
2410 *value = TRUE(!(0));
2411 else if (c == '0' ||
2412 c == 'n' || c == 'f' ||
2413 c == 'N' || c == 'F')
2414 *value = FALSE(0);
2415 else
2416 goto error;
2417 }
2418 else
2419 {
2420 if (g_ascii_strcasecmp (string, "true") == 0 ||
2421 g_ascii_strcasecmp (string, "yes") == 0)
2422 *value = TRUE(!(0));
2423 else if (g_ascii_strcasecmp (string, "false") == 0 ||
2424 g_ascii_strcasecmp (string, "no") == 0)
2425 *value = FALSE(0);
2426 else
2427 goto error;
2428 }
2429
2430 return TRUE(!(0));
2431
2432error:
2433 g_set_error (error,
2434 CTK_BUILDER_ERROR(ctk_builder_error_quark ()),
2435 CTK_BUILDER_ERROR_INVALID_VALUE,
2436 "Could not parse boolean '%s'",
2437 string);
2438 return FALSE(0);
2439}
2440
2441/**
2442 * ctk_builder_get_type_from_name:
2443 * @builder: a #CtkBuilder
2444 * @type_name: type name to lookup
2445 *
2446 * Looks up a type by name, using the virtual function that
2447 * #CtkBuilder has for that purpose. This is mainly used when
2448 * implementing the #CtkBuildable interface on a type.
2449 *
2450 * Returns: the #GType found for @type_name or #G_TYPE_INVALID
2451 * if no type was found
2452 *
2453 * Since: 2.12
2454 */
2455GType
2456ctk_builder_get_type_from_name (CtkBuilder *builder,
2457 const gchar *type_name)
2458{
2459 GType type;
2460
2461 g_return_val_if_fail (CTK_IS_BUILDER (builder), G_TYPE_INVALID)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((builder)); GType __t = ((ctk_builder_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_BUILDER (builder)"); return (((GType) ((0) <<
(2)))); } } while (0)
;
2462 g_return_val_if_fail (type_name != NULL, G_TYPE_INVALID)do { if ((type_name != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "type_name != NULL"); return
(((GType) ((0) << (2)))); } } while (0)
;
2463
2464 type = CTK_BUILDER_GET_CLASS (builder)((((CtkBuilderClass*) (((GTypeInstance*) ((builder)))->g_class
))))
->get_type_from_name (builder, type_name);
2465
2466 if (G_TYPE_IS_CLASSED (type)(g_type_test_flags ((type), G_TYPE_FLAG_CLASSED)))
2467 g_type_class_unref (g_type_class_ref (type));
2468
2469 return type;
2470}
2471
2472GQuark
2473ctk_builder_error_quark (void)
2474{
2475 return g_quark_from_static_string ("ctk-builder-error-quark");
2476}
2477
2478gchar *
2479_ctk_builder_get_resource_path (CtkBuilder *builder, const gchar *string)
2480{
2481 if (g_str_has_prefix (string, "resource:///")(__builtin_constant_p ("resource:///")? __extension__ ({ const
char * const __str = (string); const char * const __prefix =
("resource:///"); 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) (string, "resource:///"
) )
)
2482 return g_uri_unescape_string (string + 11, "/");
2483
2484 if (g_path_is_absolute (string) ||
2485 builder->priv->resource_prefix == NULL((void*)0))
2486 return NULL((void*)0);
2487
2488 return g_build_path ("/", builder->priv->resource_prefix, string, NULL((void*)0));
2489}
2490
2491gchar *
2492_ctk_builder_get_absolute_filename (CtkBuilder *builder,
2493 const gchar *string)
2494{
2495 gchar *filename;
2496 gchar *dirname = NULL((void*)0);
2497
2498 if (g_path_is_absolute (string))
2499 return g_strdup (string)g_strdup_inline (string);
2500
2501 if (builder->priv->filename &&
2502 strcmp (builder->priv->filename, ".") != 0)
2503 {
2504 dirname = g_path_get_dirname (builder->priv->filename);
2505
2506 if (strcmp (dirname, ".") == 0)
2507 {
2508 g_free (dirname);
2509 dirname = g_get_current_dir ();
2510 }
2511 }
2512 else
2513 dirname = g_get_current_dir ();
2514
2515 filename = g_build_filename (dirname, string, NULL((void*)0));
2516 g_free (dirname);
2517
2518 return filename;
2519}
2520
2521GType
2522_ctk_builder_get_template_type (CtkBuilder *builder)
2523{
2524 return builder->priv->template_type;
2525}
2526
2527/**
2528 * ctk_builder_add_callback_symbol:
2529 * @builder: a #CtkBuilder
2530 * @callback_name: The name of the callback, as expected in the XML
2531 * @callback_symbol: (scope async): The callback pointer
2532 *
2533 * Adds the @callback_symbol to the scope of @builder under the given @callback_name.
2534 *
2535 * Using this function overrides the behavior of ctk_builder_connect_signals()
2536 * for any callback symbols that are added. Using this method allows for better
2537 * encapsulation as it does not require that callback symbols be declared in
2538 * the global namespace.
2539 *
2540 * Since: 3.10
2541 */
2542void
2543ctk_builder_add_callback_symbol (CtkBuilder *builder,
2544 const gchar *callback_name,
2545 GCallback callback_symbol)
2546{
2547 g_return_if_fail (CTK_IS_BUILDER (builder))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((builder)); GType __t = ((ctk_builder_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_BUILDER (builder)"); return; } } while (0)
;
2548 g_return_if_fail (callback_name && callback_name[0])do { if ((callback_name && callback_name[0])) { } else
{ g_return_if_fail_warning ("Ctk", ((const char*) (__func__)
), "callback_name && callback_name[0]"); return; } } while
(0)
;
2549 g_return_if_fail (callback_symbol != NULL)do { if ((callback_symbol != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "callback_symbol != NULL"
); return; } } while (0)
;
2550
2551 if (!builder->priv->callbacks)
2552 builder->priv->callbacks = g_hash_table_new_full (g_str_hash, g_str_equal,
2553 g_free, NULL((void*)0));
2554
2555 g_hash_table_insert (builder->priv->callbacks, g_strdup (callback_name)g_strdup_inline (callback_name), callback_symbol);
2556}
2557
2558/**
2559 * ctk_builder_add_callback_symbols:
2560 * @builder: a #CtkBuilder
2561 * @first_callback_name: The name of the callback, as expected in the XML
2562 * @first_callback_symbol: (scope async): The callback pointer
2563 * @...: A list of callback name and callback symbol pairs terminated with %NULL
2564 *
2565 * A convenience function to add many callbacks instead of calling
2566 * ctk_builder_add_callback_symbol() for each symbol.
2567 *
2568 * Since: 3.10
2569 */
2570void
2571ctk_builder_add_callback_symbols (CtkBuilder *builder,
2572 const gchar *first_callback_name,
2573 GCallback first_callback_symbol,
2574 ...)
2575{
2576 va_list var_args;
2577 const gchar *callback_name;
2578 GCallback callback_symbol;
2579
2580 g_return_if_fail (CTK_IS_BUILDER (builder))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((builder)); GType __t = ((ctk_builder_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_BUILDER (builder)"); return; } } while (0)
;
2581 g_return_if_fail (first_callback_name && first_callback_name[0])do { if ((first_callback_name && first_callback_name[
0])) { } else { g_return_if_fail_warning ("Ctk", ((const char
*) (__func__)), "first_callback_name && first_callback_name[0]"
); return; } } while (0)
;
2582 g_return_if_fail (first_callback_symbol != NULL)do { if ((first_callback_symbol != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "first_callback_symbol != NULL"
); return; } } while (0)
;
2583
2584 callback_name = first_callback_name;
2585 callback_symbol = first_callback_symbol;
2586
2587 va_start (var_args, first_callback_symbol)__builtin_va_start(var_args, first_callback_symbol);
2588
2589 do {
2590
2591 ctk_builder_add_callback_symbol (builder, callback_name, callback_symbol);
2592
2593 callback_name = va_arg (var_args, const gchar*)__builtin_va_arg(var_args, const gchar*);
2594
2595 if (callback_name)
2596 callback_symbol = va_arg (var_args, GCallback)__builtin_va_arg(var_args, GCallback);
2597
2598 } while (callback_name != NULL((void*)0));
2599
2600 va_end (var_args)__builtin_va_end(var_args);
2601}
2602
2603/**
2604 * ctk_builder_lookup_callback_symbol: (skip)
2605 * @builder: a #CtkBuilder
2606 * @callback_name: The name of the callback
2607 *
2608 * Fetches a symbol previously added to @builder
2609 * with ctk_builder_add_callback_symbols()
2610 *
2611 * This function is intended for possible use in language bindings
2612 * or for any case that one might be cusomizing signal connections
2613 * using ctk_builder_connect_signals_full()
2614 *
2615 * Returns: (nullable): The callback symbol in @builder for @callback_name, or %NULL
2616 *
2617 * Since: 3.10
2618 */
2619GCallback
2620ctk_builder_lookup_callback_symbol (CtkBuilder *builder,
2621 const gchar *callback_name)
2622{
2623 g_return_val_if_fail (CTK_IS_BUILDER (builder), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((builder)); GType __t = ((ctk_builder_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_BUILDER (builder)"); return (((void*)0)); } } while
(0)
;
2624 g_return_val_if_fail (callback_name && callback_name[0], NULL)do { if ((callback_name && callback_name[0])) { } else
{ g_return_if_fail_warning ("Ctk", ((const char*) (__func__)
), "callback_name && callback_name[0]"); return (((void
*)0)); } } while (0)
;
2625
2626 if (!builder->priv->callbacks)
2627 return NULL((void*)0);
2628
2629 return g_hash_table_lookup (builder->priv->callbacks, callback_name);
2630}
2631
2632/**
2633 * ctk_builder_new_from_file:
2634 * @filename: filename of user interface description file
2635 *
2636 * Builds the [CtkBuilder UI definition][BUILDER-UI]
2637 * in the file @filename.
2638 *
2639 * If there is an error opening the file or parsing the description then
2640 * the program will be aborted. You should only ever attempt to parse
2641 * user interface descriptions that are shipped as part of your program.
2642 *
2643 * Returns: a #CtkBuilder containing the described interface
2644 *
2645 * Since: 3.10
2646 **/
2647CtkBuilder *
2648ctk_builder_new_from_file (const gchar *filename)
2649{
2650 GError *error = NULL((void*)0);
2651 CtkBuilder *builder;
2652
2653 builder = ctk_builder_new ();
2654 if (!ctk_builder_add_from_file (builder, filename, &error))
2655 g_error ("failed to add UI: %s", error->message);
2656
2657 return builder;
2658}
2659
2660/**
2661 * ctk_builder_new_from_resource:
2662 * @resource_path: a #GResource resource path
2663 *
2664 * Builds the [CtkBuilder UI definition][BUILDER-UI]
2665 * at @resource_path.
2666 *
2667 * If there is an error locating the resource or parsing the
2668 * description, then the program will be aborted.
2669 *
2670 * Returns: a #CtkBuilder containing the described interface
2671 *
2672 * Since: 3.10
2673 **/
2674CtkBuilder *
2675ctk_builder_new_from_resource (const gchar *resource_path)
2676{
2677 GError *error = NULL((void*)0);
2678 CtkBuilder *builder;
2679
2680 builder = ctk_builder_new ();
2681 if (!ctk_builder_add_from_resource (builder, resource_path, &error))
2682 g_error ("failed to add UI: %s", error->message);
2683
2684 return builder;
2685}
2686
2687/**
2688 * ctk_builder_new_from_string:
2689 * @string: a user interface (XML) description
2690 * @length: the length of @string, or -1
2691 *
2692 * Builds the user interface described by @string (in the
2693 * [CtkBuilder UI definition][BUILDER-UI] format).
2694 *
2695 * If @string is %NULL-terminated, then @length should be -1.
2696 * If @length is not -1, then it is the length of @string.
2697 *
2698 * If there is an error parsing @string then the program will be
2699 * aborted. You should not attempt to parse user interface description
2700 * from untrusted sources.
2701 *
2702 * Returns: a #CtkBuilder containing the interface described by @string
2703 *
2704 * Since: 3.10
2705 **/
2706CtkBuilder *
2707ctk_builder_new_from_string (const gchar *string,
2708 gssize length)
2709{
2710 GError *error = NULL((void*)0);
2711 CtkBuilder *builder;
2712
2713 builder = ctk_builder_new ();
2714 if (!ctk_builder_add_from_string (builder, string, length, &error))
2715 g_error ("failed to add UI: %s", error->message);
2716
2717 return builder;
2718}
2719
2720/**
2721 * ctk_builder_set_application:
2722 * @builder: a #CtkBuilder
2723 * @application: a #CtkApplication
2724 *
2725 * Sets the application associated with @builder.
2726 *
2727 * You only need this function if there is more than one #GApplication
2728 * in your process. @application cannot be %NULL.
2729 *
2730 * Since: 3.10
2731 **/
2732void
2733ctk_builder_set_application (CtkBuilder *builder,
2734 CtkApplication *application)
2735{
2736 g_return_if_fail (CTK_IS_BUILDER (builder))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((builder)); GType __t = ((ctk_builder_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_BUILDER (builder)"); return; } } while (0)
;
2737 g_return_if_fail (CTK_IS_APPLICATION (application))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((application)); GType __t = ((ctk_application_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_APPLICATION (application)"); return
; } } while (0)
;
2738
2739 if (builder->priv->application)
2740 g_object_unref (builder->priv->application);
2741
2742 builder->priv->application = g_object_ref (application)((__typeof__ (application)) (g_object_ref) (application));
2743}
2744
2745/**
2746 * ctk_builder_get_application:
2747 * @builder: a #CtkBuilder
2748 *
2749 * Gets the #CtkApplication associated with the builder.
2750 *
2751 * The #CtkApplication is used for creating action proxies as requested
2752 * from XML that the builder is loading.
2753 *
2754 * By default, the builder uses the default application: the one from
2755 * g_application_get_default(). If you want to use another application
2756 * for constructing proxies, use ctk_builder_set_application().
2757 *
2758 * Returns: (nullable) (transfer none): the application being used by the builder,
2759 * or %NULL
2760 *
2761 * Since: 3.10
2762 **/
2763CtkApplication *
2764ctk_builder_get_application (CtkBuilder *builder)
2765{
2766 g_return_val_if_fail (CTK_IS_BUILDER (builder), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((builder)); GType __t = ((ctk_builder_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_BUILDER (builder)"); return (((void*)0)); } } while
(0)
;
2767
2768 if (!builder->priv->application)
2769 {
2770 GApplication *application;
2771
2772 application = g_application_get_default ();
2773 if (application && CTK_IS_APPLICATION (application)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(application)); GType __t = ((ctk_application_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; }))))
)
2774 builder->priv->application = g_object_ref (CTK_APPLICATION (application))((__typeof__ (((((CtkApplication*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((application)), ((ctk_application_get_type
())))))))) (g_object_ref) (((((CtkApplication*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((application)), ((ctk_application_get_type
()))))))))
;
2775 }
2776
2777 return builder->priv->application;
2778}
2779
2780/*< private >
2781 * _ctk_builder_prefix_error:
2782 * @builder: a #CtkBuilder
2783 * @context: the #GMarkupParseContext
2784 * @error: an error
2785 *
2786 * Calls g_prefix_error() to prepend a filename:line:column marker
2787 * to the given error. The filename is taken from @builder, and
2788 * the line and column are obtained by calling
2789 * g_markup_parse_context_get_position().
2790 *
2791 * This is intended to be called on errors returned by
2792 * g_markup_collect_attributes() in a start_element vfunc.
2793 */
2794void
2795_ctk_builder_prefix_error (CtkBuilder *builder,
2796 GMarkupParseContext *context,
2797 GError **error)
2798{
2799 gint line, col;
2800
2801 g_markup_parse_context_get_position (context, &line, &col);
2802 g_prefix_error (error, "%s:%d:%d ", builder->priv->filename, line, col);
2803}
2804
2805/*< private >
2806 * _ctk_builder_error_unhandled_tag:
2807 * @builder: a #CtkBuilder
2808 * @context: the #GMarkupParseContext
2809 * @object: name of the object that is being handled
2810 * @element_name: name of the element whose start tag is being handled
2811 * @error: return location for the error
2812 *
2813 * Sets @error to a suitable error indicating that an @element_name
2814 * tag is not expected in the custom markup for @object.
2815 *
2816 * This is intended to be called in a start_element vfunc.
2817 */
2818void
2819_ctk_builder_error_unhandled_tag (CtkBuilder *builder,
2820 GMarkupParseContext *context,
2821 const gchar *object,
2822 const gchar *element_name,
2823 GError **error)
2824{
2825 gint line, col;
2826
2827 g_markup_parse_context_get_position (context, &line, &col);
2828 g_set_error (error,
2829 CTK_BUILDER_ERROR(ctk_builder_error_quark ()),
2830 CTK_BUILDER_ERROR_UNHANDLED_TAG,
2831 "%s:%d:%d Unsupported tag for %s: <%s>",
2832 builder->priv->filename, line, col,
2833 object, element_name);
2834}
2835
2836/*< private >
2837 * @builder: a #CtkBuilder
2838 * @context: the #GMarkupParseContext
2839 * @parent_name: the name of the expected parent element
2840 * @error: return location for an error
2841 *
2842 * Checks that the parent element of the currently handled
2843 * start tag is @parent_name and set @error if it isn't.
2844 *
2845 * This is intended to be called in start_element vfuncs to
2846 * ensure that element nesting is as intended.
2847 *
2848 * Returns: %TRUE if @parent_name is the parent element
2849 */
2850gboolean
2851_ctk_builder_check_parent (CtkBuilder *builder,
2852 GMarkupParseContext *context,
2853 const gchar *parent_name,
2854 GError **error)
2855{
2856 const GSList *stack;
2857 gint line, col;
2858 const gchar *parent;
2859 const gchar *element;
2860
2861 stack = g_markup_parse_context_get_element_stack (context);
2862
2863 element = (const gchar *)stack->data;
2864 parent = stack->next ? (const gchar *)stack->next->data : "";
2865
2866 if (g_str_equal (parent_name, parent)(strcmp ((const char *) (parent_name), (const char *) (parent
)) == 0)
||
2867 (g_str_equal (parent_name, "object")(strcmp ((const char *) (parent_name), (const char *) ("object"
)) == 0)
&& g_str_equal (parent, "template")(strcmp ((const char *) (parent), (const char *) ("template")
) == 0)
))
2868 return TRUE(!(0));
2869
2870 g_markup_parse_context_get_position (context, &line, &col);
2871 g_set_error (error,
2872 CTK_BUILDER_ERROR(ctk_builder_error_quark ()),
2873 CTK_BUILDER_ERROR_INVALID_TAG,
2874 "%s:%d:%d Can't use <%s> here",
2875 builder->priv->filename, line, col, element);
2876
2877 return FALSE(0);
2878}
2879
2880/*< private >
2881 * @builder: a #CtkBuilder
2882 * @name: object name to look up
2883 * @line: line number where @name was encountered
2884 * @col: column number where @name was encountered
2885 *
2886 * Looks up an object by name. Similar to ctk_builder_get_object(),
2887 * but sets an error if lookup fails during custom_tag_end,
2888 * custom_finished or parser_finished vfuncs.
2889 *
2890 * The reason for doing things this way is that these vfuncs don't
2891 * take a GError** parameter to return an error.
2892 *
2893 * Returns: the found object
2894 */
2895GObject *
2896_ctk_builder_lookup_object (CtkBuilder *builder,
2897 const gchar *name,
2898 gint line,
2899 gint col)
2900{
2901 GObject *obj;
2902 GError *error = NULL((void*)0);
2903
2904 obj = g_hash_table_lookup (builder->priv->objects, name);
2905 error = (GError *) g_object_get_data (G_OBJECT (builder)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((builder)), (((GType) ((20) << (2))))))))
, "lookup-error");
2906
2907 if (!obj && !error)
2908 {
2909 g_set_error (&error,
2910 CTK_BUILDER_ERROR(ctk_builder_error_quark ()), CTK_BUILDER_ERROR_INVALID_ID,
2911 "%s:%d:%d Object with ID %s not found",
2912 builder->priv->filename, line, col, name);
2913 g_object_set_data_full (G_OBJECT (builder)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((builder)), (((GType) ((20) << (2))))))))
, "lookup-error",
2914 error, (GDestroyNotify)g_error_free);
2915 }
2916
2917 return obj;
2918}
2919
2920/*< private >
2921 * _ctk_builder_lookup_failed:
2922 * @CtkBuilder: a #CtkBuilder
2923 * @error: return location for error
2924 *
2925 * Finds whether any object lookups have failed.
2926 *
2927 * Returns: %TRUE if @error has been set
2928 */
2929gboolean
2930_ctk_builder_lookup_failed (CtkBuilder *builder,
2931 GError **error)
2932{
2933 GError *lookup_error;
2934
2935 lookup_error = (GError*) g_object_steal_data (G_OBJECT (builder)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((builder)), (((GType) ((20) << (2))))))))
, "lookup-error");
2936 if (lookup_error)
2937 {
2938 g_propagate_error (error, lookup_error);
2939 return TRUE(!(0));
2940 }
2941
2942 return FALSE(0);
2943}