1/* gtkaccessiblevalue.c: Accessible value
2 *
3 * Copyright 2020 GNOME Foundation
4 *
5 * SPDX-License-Identifier: LGPL-2.1-or-later
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 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 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 */
20
21/*< private >
22 * GtkAccessibleValue:
23 *
24 * GtkAccessibleValue is a reference counted, generic container for values used
25 * to represent the state and properties of a `GtkAccessible` implementation.
26 *
27 * There are two kinds of accessible value types:
28 *
29 * - hard coded, static values; GTK owns them, and their contents, and are
30 * guaranteed to exist for the duration of the application's life time
31 * - dynamic values; the accessible state owns the value and their contents,
32 * and they can be allocated and freed
33 *
34 * Typically, the former type of values is used for boolean, tristate, and
35 * token value; the latter is used for numbers, strings, and token lists.
36 *
37 * For more information on the types of values, see the [WAI-ARIA](https://www.w3.org/WAI/PF/aria/states_and_properties#propcharacteristic_value)
38 * reference.
39 */
40
41#include "config.h"
42
43#include "gtkaccessiblevalueprivate.h"
44
45#include "gtkaccessible.h"
46#include "gtkbuilderprivate.h"
47#include "gtkenums.h"
48#include "gtktypebuiltins.h"
49
50#include <math.h>
51#include <float.h>
52#include <errno.h>
53
54G_DEFINE_QUARK (gtk-accessible-value-error-quark, gtk_accessible_value_error)
55
56G_DEFINE_BOXED_TYPE (GtkAccessibleValue, gtk_accessible_value,
57 gtk_accessible_value_ref,
58 gtk_accessible_value_unref)
59
60/*< private >
61 * gtk_accessible_value_alloc:
62 * @value_class: a `GtkAccessibleValueClass` structure
63 *
64 * Allocates a new `GtkAccessibleValue` subclass using @value_class as the
65 * type definition.
66 *
67 * Returns: (transfer full): the newly allocated `GtkAccessibleValue`
68 */
69GtkAccessibleValue *
70gtk_accessible_value_alloc (const GtkAccessibleValueClass *value_class)
71{
72 g_return_val_if_fail (value_class != NULL, NULL);
73 g_return_val_if_fail (value_class->instance_size >= sizeof (GtkAccessibleValue), NULL);
74
75 GtkAccessibleValue *res = g_malloc0 (n_bytes: value_class->instance_size);
76
77 /* We do not use grefcount, here, because we want to have statically
78 * allocated GtkAccessibleValue subclasses, and those cannot be initialized
79 * with g_ref_count_init()
80 */
81 res->ref_count = 1;
82 res->value_class = value_class;
83
84 if (res->value_class->init != NULL)
85 res->value_class->init (res);
86
87 return res;
88}
89
90/*< private >
91 * gtk_accessible_value_ref:
92 * @self: a `GtkAccessibleValue`
93 *
94 * Acquires a reference on the given `GtkAccessibleValue`.
95 *
96 * Returns: (transfer full): the value, with an additional reference
97 */
98GtkAccessibleValue *
99gtk_accessible_value_ref (GtkAccessibleValue *self)
100{
101 g_return_val_if_fail (self != NULL, NULL);
102
103 self->ref_count += 1;
104
105 return self;
106}
107
108/*< private >
109 * gtk_accessible_value_unref:
110 * @self: (transfer full): a `GtkAccessibleValue`
111 *
112 * Releases a reference on the given `GtkAccessibleValue`.
113 */
114void
115gtk_accessible_value_unref (GtkAccessibleValue *self)
116{
117 g_return_if_fail (self != NULL);
118
119 self->ref_count -= 1;
120 if (self->ref_count == 0)
121 {
122 if (self->value_class->finalize != NULL)
123 self->value_class->finalize (self);
124
125 g_free (mem: self);
126 }
127}
128
129/*< private >
130 * gtk_accessible_value_print:
131 * @self: a `GtkAccessibleValue`
132 * @buffer: a `GString`
133 *
134 * Prints the contents of a `GtkAccessibleValue` into the given @buffer.
135 */
136void
137gtk_accessible_value_print (const GtkAccessibleValue *self,
138 GString *buffer)
139{
140 g_return_if_fail (self != NULL);
141 g_return_if_fail (buffer != NULL);
142
143 if (self->value_class->print != NULL)
144 self->value_class->print (self, buffer);
145}
146
147/*< private >
148 * gtk_accessible_value_to_string:
149 * @self: a `GtkAccessibleValue`
150 *
151 * Fills a string with the contents of the given `GtkAccessibleValue`.
152 *
153 * Returns: (transfer full): a string with the contents of the value
154 */
155char *
156gtk_accessible_value_to_string (const GtkAccessibleValue *self)
157{
158 g_return_val_if_fail (self != NULL, NULL);
159
160 GString *buffer = g_string_new (NULL);
161
162 gtk_accessible_value_print (self, buffer);
163
164 return g_string_free (string: buffer, FALSE);
165}
166
167/*< private >
168 * gtk_accessible_value_equal:
169 * @value_a: (nullable): the first `GtkAccessibleValue`
170 * @value_b: (nullable): the second `GtkAccessibleValue`
171 *
172 * Checks whether @value_a and @value_b are equal.
173 *
174 * This function is %NULL-safe.
175 *
176 * Returns: %TRUE if the given `GtkAccessibleValue` instances are equal,
177 * and %FALSE otherwise
178 */
179gboolean
180gtk_accessible_value_equal (const GtkAccessibleValue *value_a,
181 const GtkAccessibleValue *value_b)
182{
183 if (value_a == value_b)
184 return TRUE;
185
186 if (value_a == NULL || value_b == NULL)
187 return FALSE;
188
189 if (value_a->value_class != value_b->value_class)
190 return FALSE;
191
192 if (value_a->value_class->equal == NULL)
193 return FALSE;
194
195 return value_a->value_class->equal (value_a, value_b);
196}
197
198/* {{{ Basic allocated types */
199
200typedef struct {
201 GtkAccessibleValue parent;
202
203 int value;
204} GtkIntAccessibleValue;
205
206static gboolean
207gtk_int_accessible_value_equal (const GtkAccessibleValue *value_a,
208 const GtkAccessibleValue *value_b)
209{
210 const GtkIntAccessibleValue *self_a = (GtkIntAccessibleValue *) value_a;
211 const GtkIntAccessibleValue *self_b = (GtkIntAccessibleValue *) value_b;
212
213 return self_a->value == self_b->value;
214}
215
216static void
217gtk_int_accessible_value_print (const GtkAccessibleValue *value,
218 GString *buffer)
219{
220 const GtkIntAccessibleValue *self = (GtkIntAccessibleValue *) value;
221
222 g_string_append_printf (string: buffer, format: "%d", self->value);
223}
224
225static const GtkAccessibleValueClass GTK_INT_ACCESSIBLE_VALUE = {
226 .type = GTK_ACCESSIBLE_VALUE_TYPE_INTEGER,
227 .type_name = "GtkIntAccessibleValue",
228 .instance_size = sizeof (GtkIntAccessibleValue),
229 .equal = gtk_int_accessible_value_equal,
230 .print = gtk_int_accessible_value_print,
231};
232
233GtkAccessibleValue *
234gtk_int_accessible_value_new (int value)
235{
236 GtkAccessibleValue *res = gtk_accessible_value_alloc (value_class: &GTK_INT_ACCESSIBLE_VALUE);
237
238 /* XXX: Possible optimization: statically allocate the first N values
239 * and hand out references to them, instead of dynamically
240 * allocating a new GtkAccessibleValue instance. Needs some profiling
241 * to figure out the common integer values used by large applications
242 */
243 GtkIntAccessibleValue *self = (GtkIntAccessibleValue *) res;
244 self->value = value;
245
246 return res;
247}
248
249int
250gtk_int_accessible_value_get (const GtkAccessibleValue *value)
251{
252 GtkIntAccessibleValue *self = (GtkIntAccessibleValue *) value;
253
254 g_return_val_if_fail (value != NULL, 0);
255 g_return_val_if_fail (value->value_class == &GTK_INT_ACCESSIBLE_VALUE, 0);
256
257 return self->value;
258}
259
260typedef struct {
261 GtkAccessibleValue parent;
262
263 double value;
264} GtkNumberAccessibleValue;
265
266static gboolean
267gtk_number_accessible_value_equal (const GtkAccessibleValue *value_a,
268 const GtkAccessibleValue *value_b)
269{
270 const GtkNumberAccessibleValue *self_a = (GtkNumberAccessibleValue *) value_a;
271 const GtkNumberAccessibleValue *self_b = (GtkNumberAccessibleValue *) value_b;
272
273 return G_APPROX_VALUE (self_a->value, self_b->value, 0.001);
274}
275
276static void
277gtk_number_accessible_value_print (const GtkAccessibleValue *value,
278 GString *buffer)
279{
280 const GtkNumberAccessibleValue *self = (GtkNumberAccessibleValue *) value;
281
282 g_string_append_printf (string: buffer, format: "%g", self->value);
283}
284
285static const GtkAccessibleValueClass GTK_NUMBER_ACCESSIBLE_VALUE = {
286 .type = GTK_ACCESSIBLE_VALUE_TYPE_NUMBER,
287 .type_name = "GtkNumberAccessibleValue",
288 .instance_size = sizeof (GtkNumberAccessibleValue),
289 .equal = gtk_number_accessible_value_equal,
290 .print = gtk_number_accessible_value_print,
291};
292
293GtkAccessibleValue *
294gtk_number_accessible_value_new (double value)
295{
296 GtkAccessibleValue *res = gtk_accessible_value_alloc (value_class: &GTK_NUMBER_ACCESSIBLE_VALUE);
297
298 GtkNumberAccessibleValue *self = (GtkNumberAccessibleValue *) res;
299 self->value = value;
300
301 return res;
302}
303
304double
305gtk_number_accessible_value_get (const GtkAccessibleValue *value)
306{
307 GtkNumberAccessibleValue *self = (GtkNumberAccessibleValue *) value;
308
309 g_return_val_if_fail (value != NULL, 0);
310 g_return_val_if_fail (value->value_class == &GTK_NUMBER_ACCESSIBLE_VALUE, 0);
311
312 return self->value;
313}
314
315typedef struct {
316 GtkAccessibleValue parent;
317
318 char *value;
319 gsize length;
320} GtkStringAccessibleValue;
321
322static void
323gtk_string_accessible_value_finalize (GtkAccessibleValue *value)
324{
325 GtkStringAccessibleValue *self = (GtkStringAccessibleValue *) value;
326
327 g_free (mem: self->value);
328}
329
330static gboolean
331gtk_string_accessible_value_equal (const GtkAccessibleValue *value_a,
332 const GtkAccessibleValue *value_b)
333{
334 const GtkStringAccessibleValue *self_a = (GtkStringAccessibleValue *) value_a;
335 const GtkStringAccessibleValue *self_b = (GtkStringAccessibleValue *) value_b;
336
337 if (self_a->length != self_b->length)
338 return FALSE;
339
340 return g_strcmp0 (str1: self_a->value, str2: self_b->value) == 0;
341}
342
343static void
344gtk_string_accessible_value_print (const GtkAccessibleValue *value,
345 GString *buffer)
346{
347 const GtkStringAccessibleValue *self = (GtkStringAccessibleValue *) value;
348
349 g_string_append (string: buffer, val: self->value);
350}
351
352static const GtkAccessibleValueClass GTK_STRING_ACCESSIBLE_VALUE = {
353 .type = GTK_ACCESSIBLE_VALUE_TYPE_STRING,
354 .type_name = "GtkStringAccessibleValue",
355 .instance_size = sizeof (GtkStringAccessibleValue),
356 .finalize = gtk_string_accessible_value_finalize,
357 .equal = gtk_string_accessible_value_equal,
358 .print = gtk_string_accessible_value_print,
359};
360
361GtkAccessibleValue *
362gtk_string_accessible_value_new (const char *str)
363{
364 GtkAccessibleValue *res = gtk_accessible_value_alloc (value_class: &GTK_STRING_ACCESSIBLE_VALUE);
365
366 GtkStringAccessibleValue *self = (GtkStringAccessibleValue *) res;
367
368 self->value = g_strdup (str);
369 self->length = strlen (s: str);
370
371 return res;
372}
373
374const char *
375gtk_string_accessible_value_get (const GtkAccessibleValue *value)
376{
377 GtkStringAccessibleValue *self = (GtkStringAccessibleValue *) value;
378
379 g_return_val_if_fail (value != NULL, 0);
380 g_return_val_if_fail (value->value_class == &GTK_STRING_ACCESSIBLE_VALUE, 0);
381
382 return self->value;
383}
384
385typedef struct {
386 GtkAccessibleValue parent;
387
388 GtkAccessible *ref;
389} GtkReferenceAccessibleValue;
390
391static void
392remove_weak_ref (gpointer data,
393 GObject *old_reference)
394{
395 GtkReferenceAccessibleValue *self = data;
396
397 self->ref = NULL;
398}
399
400static void
401gtk_reference_accessible_value_finalize (GtkAccessibleValue *value)
402{
403 GtkReferenceAccessibleValue *self = (GtkReferenceAccessibleValue *) value;
404
405 if (self->ref != NULL)
406 g_object_weak_unref (G_OBJECT (self->ref), notify: remove_weak_ref, data: self);
407}
408
409static gboolean
410gtk_reference_accessible_value_equal (const GtkAccessibleValue *value_a,
411 const GtkAccessibleValue *value_b)
412{
413 const GtkReferenceAccessibleValue *self_a = (GtkReferenceAccessibleValue *) value_a;
414 const GtkReferenceAccessibleValue *self_b = (GtkReferenceAccessibleValue *) value_b;
415
416 return self_a->ref == self_b->ref;
417}
418
419static void
420gtk_reference_accessible_value_print (const GtkAccessibleValue *value,
421 GString *buffer)
422{
423 const GtkReferenceAccessibleValue *self = (GtkReferenceAccessibleValue *) value;
424
425 if (self->ref != NULL)
426 {
427 g_string_append_printf (string: buffer, format: "%s<%p>",
428 G_OBJECT_TYPE_NAME (self->ref),
429 self->ref);
430 }
431 else
432 {
433 g_string_append (string: buffer, val: "<null>");
434 }
435}
436
437static const GtkAccessibleValueClass GTK_REFERENCE_ACCESSIBLE_VALUE = {
438 .type = GTK_ACCESSIBLE_VALUE_TYPE_REFERENCE,
439 .type_name = "GtkReferenceAccessibleValue",
440 .instance_size = sizeof (GtkReferenceAccessibleValue),
441 .finalize = gtk_reference_accessible_value_finalize,
442 .equal = gtk_reference_accessible_value_equal,
443 .print = gtk_reference_accessible_value_print,
444};
445
446GtkAccessibleValue *
447gtk_reference_accessible_value_new (GtkAccessible *ref)
448{
449 g_return_val_if_fail (GTK_IS_ACCESSIBLE (ref), NULL);
450
451 GtkAccessibleValue *res = gtk_accessible_value_alloc (value_class: &GTK_REFERENCE_ACCESSIBLE_VALUE);
452
453 GtkReferenceAccessibleValue *self = (GtkReferenceAccessibleValue *) res;
454
455 self->ref = ref;
456 g_object_weak_ref (G_OBJECT (self->ref), notify: remove_weak_ref, data: self);
457
458 return res;
459}
460
461GtkAccessible *
462gtk_reference_accessible_value_get (const GtkAccessibleValue *value)
463{
464 GtkReferenceAccessibleValue *self = (GtkReferenceAccessibleValue *) value;
465
466 g_return_val_if_fail (value != NULL, 0);
467 g_return_val_if_fail (value->value_class == &GTK_REFERENCE_ACCESSIBLE_VALUE, 0);
468
469 return self->ref;
470}
471
472typedef struct {
473 GtkAccessibleValue parent;
474
475 GList *refs;
476} GtkReferenceListAccessibleValue;
477
478static void
479remove_weak_ref_from_list (gpointer data,
480 GObject *old_reference)
481{
482 GtkReferenceListAccessibleValue *self = data;
483
484 GList *item = g_list_find (list: self->refs, data: old_reference);
485
486 if (item != NULL)
487 {
488 self->refs = g_list_remove_link (list: self->refs, llink: item);
489 g_list_free (list: item);
490 }
491}
492
493static void
494gtk_reference_list_accessible_value_finalize (GtkAccessibleValue *value)
495{
496 GtkReferenceListAccessibleValue *self = (GtkReferenceListAccessibleValue *) value;
497
498 for (GList *l = self->refs; l != NULL; l = l->next)
499 {
500 if (l->data != NULL)
501 g_object_weak_unref (G_OBJECT (l->data), notify: remove_weak_ref_from_list, data: self);
502 }
503
504 g_list_free (list: self->refs);
505}
506
507static gboolean
508gtk_reference_list_accessible_value_equal (const GtkAccessibleValue *value_a,
509 const GtkAccessibleValue *value_b)
510{
511 const GtkReferenceListAccessibleValue *self_a = (GtkReferenceListAccessibleValue *) value_a;
512 const GtkReferenceListAccessibleValue *self_b = (GtkReferenceListAccessibleValue *) value_b;
513
514 if (g_list_length (list: self_a->refs) != g_list_length (list: self_b->refs))
515 return FALSE;
516
517 for (GList *l = self_a->refs; l != NULL; l = l->next)
518 {
519 if (g_list_find (list: self_b->refs, data: l->data) == NULL)
520 return FALSE;
521 }
522
523 return TRUE;
524}
525
526static void
527gtk_reference_list_accessible_value_print (const GtkAccessibleValue *value,
528 GString *buffer)
529{
530 const GtkReferenceListAccessibleValue *self = (GtkReferenceListAccessibleValue *) value;
531
532 if (self->refs == NULL)
533 {
534 g_string_append (string: buffer, val: "<null>");
535 return;
536 }
537
538 for (GList *l = self->refs; l != NULL; l = l->next)
539 {
540 g_string_append_printf (string: buffer, format: "%s<%p>",
541 G_OBJECT_TYPE_NAME (l->data),
542 l->data);
543 }
544}
545
546static const GtkAccessibleValueClass GTK_REFERENCE_LIST_ACCESSIBLE_VALUE = {
547 .type = GTK_ACCESSIBLE_VALUE_TYPE_REFERENCE_LIST,
548 .type_name = "GtkReferenceListAccessibleValue",
549 .instance_size = sizeof (GtkReferenceListAccessibleValue),
550 .finalize = gtk_reference_list_accessible_value_finalize,
551 .equal = gtk_reference_list_accessible_value_equal,
552 .print = gtk_reference_list_accessible_value_print,
553};
554
555/*< private >
556 * gtk_reference_list_accessible_value_new:
557 * @value: (element-type GtkAccessible) (transfer full): a list of accessible objects
558 *
559 * Creates a new `GtkAccessible` that stores a list of references
560 * to `GtkAccessible` objects.
561 *
562 * Returns: (transfer full): the newly created `GtkAccessible`
563 */
564GtkAccessibleValue *
565gtk_reference_list_accessible_value_new (GList *value)
566{
567 GtkAccessibleValue *res = gtk_accessible_value_alloc (value_class: &GTK_REFERENCE_LIST_ACCESSIBLE_VALUE);
568
569 GtkReferenceListAccessibleValue *self = (GtkReferenceListAccessibleValue *) res;
570
571 self->refs = value;
572 if (self->refs != NULL)
573 {
574 for (GList *l = self->refs; l != NULL; l = l->next)
575 g_object_weak_ref (object: l->data, notify: remove_weak_ref_from_list, data: self);
576 }
577
578 return res;
579}
580
581GList *
582gtk_reference_list_accessible_value_get (const GtkAccessibleValue *value)
583{
584 GtkReferenceListAccessibleValue *self = (GtkReferenceListAccessibleValue *) value;
585
586 g_return_val_if_fail (value != NULL, 0);
587 g_return_val_if_fail (value->value_class == &GTK_REFERENCE_LIST_ACCESSIBLE_VALUE, 0);
588
589 return self->refs;
590}
591
592/* }}} */
593
594/* {{{ Collection API */
595
596typedef enum {
597 GTK_ACCESSIBLE_COLLECT_INVALID = -1,
598
599 /* true/false */
600 GTK_ACCESSIBLE_COLLECT_BOOLEAN = 0,
601
602 /* true/false/mixed/undefined */
603 GTK_ACCESSIBLE_COLLECT_TRISTATE,
604
605 /* one token */
606 GTK_ACCESSIBLE_COLLECT_TOKEN,
607
608 /* integer number */
609 GTK_ACCESSIBLE_COLLECT_INTEGER,
610
611 /* real number */
612 GTK_ACCESSIBLE_COLLECT_NUMBER,
613
614 /* string */
615 GTK_ACCESSIBLE_COLLECT_STRING,
616
617 /* reference */
618 GTK_ACCESSIBLE_COLLECT_REFERENCE,
619
620 /* references list */
621 GTK_ACCESSIBLE_COLLECT_REFERENCE_LIST,
622
623 /* allows collecting GTK_ACCESSIBLE_VALUE_UNDEFINED; implied
624 * by GTK_ACCESSIBLE_COLLECT_TRISTATE
625 */
626 GTK_ACCESSIBLE_COLLECT_UNDEFINED = 1 << 16
627} GtkAccessibleCollectType;
628
629typedef struct {
630 int value;
631 GtkAccessibleCollectType ctype;
632 const char *name;
633
634 /* The constructor and getter will be derived by the
635 * @ctype field and by the collected value, except for the
636 * GTK_ACCESSIBLE_COLLECT_TOKEN collection type. You can
637 * override the default ones by filling out these two
638 * pointers
639 */
640 GCallback ctor;
641 GCallback getter;
642 GCallback parser;
643 GCallback init_value;
644} GtkAccessibleCollect;
645
646static const GtkAccessibleCollect collect_states[] = {
647 [GTK_ACCESSIBLE_STATE_BUSY] = {
648 .value = GTK_ACCESSIBLE_STATE_BUSY,
649 .ctype = GTK_ACCESSIBLE_COLLECT_BOOLEAN,
650 .name = "busy"
651 },
652 [GTK_ACCESSIBLE_STATE_CHECKED] = {
653 .value = GTK_ACCESSIBLE_STATE_CHECKED,
654 .ctype = GTK_ACCESSIBLE_COLLECT_TRISTATE,
655 .name = "checked"
656 },
657 [GTK_ACCESSIBLE_STATE_DISABLED] = {
658 .value = GTK_ACCESSIBLE_STATE_DISABLED,
659 .ctype = GTK_ACCESSIBLE_COLLECT_BOOLEAN,
660 .name = "disabled"
661 },
662 [GTK_ACCESSIBLE_STATE_EXPANDED] = {
663 .value = GTK_ACCESSIBLE_STATE_EXPANDED,
664 .ctype = GTK_ACCESSIBLE_COLLECT_BOOLEAN | GTK_ACCESSIBLE_COLLECT_UNDEFINED,
665 .name = "expanded"
666 },
667 [GTK_ACCESSIBLE_STATE_HIDDEN] = {
668 .value = GTK_ACCESSIBLE_STATE_HIDDEN,
669 .ctype = GTK_ACCESSIBLE_COLLECT_BOOLEAN,
670 .name = "hidden"
671 },
672 [GTK_ACCESSIBLE_STATE_INVALID] = {
673 .value = GTK_ACCESSIBLE_STATE_INVALID,
674 .ctype = GTK_ACCESSIBLE_COLLECT_TOKEN,
675 .name = "invalid",
676 .ctor = (GCallback) gtk_invalid_accessible_value_new,
677 .getter = (GCallback) gtk_invalid_accessible_value_get,
678 .parser = (GCallback) gtk_invalid_accessible_value_parse,
679 .init_value = (GCallback) gtk_invalid_accessible_value_init_value,
680 },
681 [GTK_ACCESSIBLE_STATE_PRESSED] = {
682 .value = GTK_ACCESSIBLE_STATE_PRESSED,
683 .ctype = GTK_ACCESSIBLE_COLLECT_TRISTATE,
684 .name = "pressed"
685 },
686 [GTK_ACCESSIBLE_STATE_SELECTED] = {
687 .value = GTK_ACCESSIBLE_STATE_SELECTED,
688 .ctype = GTK_ACCESSIBLE_COLLECT_BOOLEAN | GTK_ACCESSIBLE_COLLECT_UNDEFINED,
689 .name = "selected"
690 },
691};
692
693/* § 6.6.1 Widget attributes */
694static const GtkAccessibleCollect collect_props[] = {
695 [GTK_ACCESSIBLE_PROPERTY_AUTOCOMPLETE] = {
696 .value = GTK_ACCESSIBLE_PROPERTY_AUTOCOMPLETE,
697 .ctype = GTK_ACCESSIBLE_COLLECT_TOKEN,
698 .name = "autocomplete",
699 .ctor = (GCallback) gtk_autocomplete_accessible_value_new,
700 .getter = (GCallback) gtk_autocomplete_accessible_value_get,
701 .parser = (GCallback) gtk_autocomplete_accessible_value_parse,
702 .init_value = (GCallback) gtk_autocomplete_accessible_value_init_value,
703 },
704 [GTK_ACCESSIBLE_PROPERTY_DESCRIPTION] = {
705 .value = GTK_ACCESSIBLE_PROPERTY_DESCRIPTION,
706 .ctype = GTK_ACCESSIBLE_COLLECT_STRING,
707 .name = "description"
708 },
709 [GTK_ACCESSIBLE_PROPERTY_HAS_POPUP] = {
710 .value = GTK_ACCESSIBLE_PROPERTY_HAS_POPUP,
711 .ctype = GTK_ACCESSIBLE_COLLECT_BOOLEAN,
712 .name = "haspopup"
713 },
714 [GTK_ACCESSIBLE_PROPERTY_KEY_SHORTCUTS] = {
715 .value = GTK_ACCESSIBLE_PROPERTY_KEY_SHORTCUTS,
716 .ctype = GTK_ACCESSIBLE_COLLECT_STRING,
717 .name = "keyshortcuts"
718 },
719 [GTK_ACCESSIBLE_PROPERTY_LABEL] = {
720 .value = GTK_ACCESSIBLE_PROPERTY_LABEL,
721 .ctype = GTK_ACCESSIBLE_COLLECT_STRING,
722 .name = "label"
723 },
724 [GTK_ACCESSIBLE_PROPERTY_LEVEL] = {
725 .value = GTK_ACCESSIBLE_PROPERTY_LEVEL,
726 .ctype = GTK_ACCESSIBLE_COLLECT_INTEGER,
727 .name = "level"
728 },
729 [GTK_ACCESSIBLE_PROPERTY_MODAL] = {
730 .value = GTK_ACCESSIBLE_PROPERTY_MODAL,
731 .ctype = GTK_ACCESSIBLE_COLLECT_BOOLEAN,
732 .name = "modal"
733 },
734 [GTK_ACCESSIBLE_PROPERTY_MULTI_LINE] = {
735 .value = GTK_ACCESSIBLE_PROPERTY_MULTI_LINE,
736 .ctype = GTK_ACCESSIBLE_COLLECT_BOOLEAN,
737 .name = "multiline"
738 },
739 [GTK_ACCESSIBLE_PROPERTY_MULTI_SELECTABLE] = {
740 .value = GTK_ACCESSIBLE_PROPERTY_MULTI_SELECTABLE,
741 .ctype = GTK_ACCESSIBLE_COLLECT_BOOLEAN,
742 .name = "multiselectable"
743 },
744 /* "orientation" is a bit special; it maps to GtkOrientation, but it
745 * can also be "undefined". This means we need to override constructor
746 * and getter, in order to properly handle GTK_ACCESSIBLE_VALUE_UNDEFINED
747 */
748 [GTK_ACCESSIBLE_PROPERTY_ORIENTATION] = {
749 .value = GTK_ACCESSIBLE_PROPERTY_ORIENTATION,
750 .ctype = GTK_ACCESSIBLE_COLLECT_TOKEN | GTK_ACCESSIBLE_COLLECT_UNDEFINED,
751 .name = "orientation",
752 .ctor = (GCallback) gtk_orientation_accessible_value_new,
753 .getter = (GCallback) gtk_orientation_accessible_value_get,
754 .parser = (GCallback) gtk_orientation_accessible_value_parse,
755 .init_value = (GCallback) gtk_orientation_accessible_value_init_value,
756 },
757 [GTK_ACCESSIBLE_PROPERTY_PLACEHOLDER] = {
758 .value = GTK_ACCESSIBLE_PROPERTY_PLACEHOLDER,
759 .ctype = GTK_ACCESSIBLE_COLLECT_STRING,
760 .name = "placeholder"
761 },
762 [GTK_ACCESSIBLE_PROPERTY_READ_ONLY] = {
763 .value = GTK_ACCESSIBLE_PROPERTY_READ_ONLY,
764 .ctype = GTK_ACCESSIBLE_COLLECT_BOOLEAN,
765 .name = "readonly"
766 },
767 [GTK_ACCESSIBLE_PROPERTY_REQUIRED] = {
768 .value = GTK_ACCESSIBLE_PROPERTY_REQUIRED,
769 .ctype = GTK_ACCESSIBLE_COLLECT_BOOLEAN,
770 .name = "required"
771 },
772 [GTK_ACCESSIBLE_PROPERTY_ROLE_DESCRIPTION] = {
773 .value = GTK_ACCESSIBLE_PROPERTY_ROLE_DESCRIPTION,
774 .ctype = GTK_ACCESSIBLE_COLLECT_STRING,
775 .name = "roledescription"
776 },
777 [GTK_ACCESSIBLE_PROPERTY_SORT] = {
778 .value = GTK_ACCESSIBLE_PROPERTY_SORT,
779 .ctype = GTK_ACCESSIBLE_COLLECT_TOKEN,
780 .name = "sort",
781 .ctor = (GCallback) gtk_sort_accessible_value_new,
782 .getter = (GCallback) gtk_sort_accessible_value_get,
783 .parser = (GCallback) gtk_sort_accessible_value_parse,
784 .init_value = (GCallback) gtk_sort_accessible_value_init_value,
785 },
786 [GTK_ACCESSIBLE_PROPERTY_VALUE_MAX] = {
787 .value = GTK_ACCESSIBLE_PROPERTY_VALUE_MAX,
788 .ctype = GTK_ACCESSIBLE_COLLECT_NUMBER,
789 .name = "valuemax"
790 },
791 [GTK_ACCESSIBLE_PROPERTY_VALUE_MIN] = {
792 .value = GTK_ACCESSIBLE_PROPERTY_VALUE_MIN,
793 .ctype = GTK_ACCESSIBLE_COLLECT_NUMBER,
794 .name = "valuemin"
795 },
796 [GTK_ACCESSIBLE_PROPERTY_VALUE_NOW] = {
797 .value = GTK_ACCESSIBLE_PROPERTY_VALUE_NOW,
798 .ctype = GTK_ACCESSIBLE_COLLECT_NUMBER,
799 .name = "valuenow"
800 },
801 [GTK_ACCESSIBLE_PROPERTY_VALUE_TEXT] = {
802 .value = GTK_ACCESSIBLE_PROPERTY_VALUE_TEXT,
803 .ctype = GTK_ACCESSIBLE_COLLECT_STRING,
804 .name = "valuetext"
805 },
806};
807
808/* § 6.6.4 Relationship Attributes */
809static const GtkAccessibleCollect collect_rels[] = {
810 [GTK_ACCESSIBLE_RELATION_ACTIVE_DESCENDANT] = {
811 .value = GTK_ACCESSIBLE_RELATION_ACTIVE_DESCENDANT,
812 .ctype = GTK_ACCESSIBLE_COLLECT_REFERENCE,
813 .name = "activedescendant"
814 },
815 [GTK_ACCESSIBLE_RELATION_COL_COUNT] = {
816 .value = GTK_ACCESSIBLE_RELATION_COL_COUNT,
817 .ctype = GTK_ACCESSIBLE_COLLECT_INTEGER,
818 .name = "colcount"
819 },
820 [GTK_ACCESSIBLE_RELATION_COL_INDEX] = {
821 .value = GTK_ACCESSIBLE_RELATION_COL_INDEX,
822 .ctype = GTK_ACCESSIBLE_COLLECT_INTEGER,
823 .name = "colindex"
824 },
825 [GTK_ACCESSIBLE_RELATION_COL_INDEX_TEXT] = {
826 .value = GTK_ACCESSIBLE_RELATION_COL_INDEX_TEXT,
827 .ctype = GTK_ACCESSIBLE_COLLECT_STRING,
828 .name = "colindextext"
829 },
830 [GTK_ACCESSIBLE_RELATION_COL_SPAN] = {
831 .value = GTK_ACCESSIBLE_RELATION_COL_SPAN,
832 .ctype = GTK_ACCESSIBLE_COLLECT_INTEGER,
833 .name = "colspan"
834 },
835 [GTK_ACCESSIBLE_RELATION_CONTROLS] = {
836 .value = GTK_ACCESSIBLE_RELATION_CONTROLS,
837 .ctype = GTK_ACCESSIBLE_COLLECT_REFERENCE_LIST,
838 .name = "controls"
839 },
840 [GTK_ACCESSIBLE_RELATION_DESCRIBED_BY] = {
841 .value = GTK_ACCESSIBLE_RELATION_DESCRIBED_BY,
842 .ctype = GTK_ACCESSIBLE_COLLECT_REFERENCE_LIST,
843 .name = "describedby"
844 },
845 [GTK_ACCESSIBLE_RELATION_DETAILS] = {
846 .value = GTK_ACCESSIBLE_RELATION_DETAILS,
847 .ctype = GTK_ACCESSIBLE_COLLECT_REFERENCE_LIST,
848 .name = "details"
849 },
850 [GTK_ACCESSIBLE_RELATION_ERROR_MESSAGE] = {
851 .value = GTK_ACCESSIBLE_RELATION_ERROR_MESSAGE,
852 .ctype = GTK_ACCESSIBLE_COLLECT_REFERENCE,
853 .name = "errormessage"
854 },
855 [GTK_ACCESSIBLE_RELATION_FLOW_TO] = {
856 .value = GTK_ACCESSIBLE_RELATION_FLOW_TO,
857 .ctype = GTK_ACCESSIBLE_COLLECT_REFERENCE_LIST,
858 .name = "flowto"
859 },
860 [GTK_ACCESSIBLE_RELATION_LABELLED_BY] = {
861 .value = GTK_ACCESSIBLE_RELATION_LABELLED_BY,
862 .ctype = GTK_ACCESSIBLE_COLLECT_REFERENCE_LIST,
863 .name = "labelledby"
864 },
865 [GTK_ACCESSIBLE_RELATION_OWNS] = {
866 .value = GTK_ACCESSIBLE_RELATION_OWNS,
867 .ctype = GTK_ACCESSIBLE_COLLECT_REFERENCE_LIST,
868 .name = "owns"
869 },
870 [GTK_ACCESSIBLE_RELATION_POS_IN_SET] = {
871 .value = GTK_ACCESSIBLE_RELATION_POS_IN_SET,
872 .ctype = GTK_ACCESSIBLE_COLLECT_INTEGER,
873 .name = "posinset"
874 },
875 [GTK_ACCESSIBLE_RELATION_ROW_COUNT] = {
876 .value = GTK_ACCESSIBLE_RELATION_ROW_COUNT,
877 .ctype = GTK_ACCESSIBLE_COLLECT_INTEGER,
878 .name = "rowcount"
879 },
880 [GTK_ACCESSIBLE_RELATION_ROW_INDEX] = {
881 .value = GTK_ACCESSIBLE_RELATION_ROW_INDEX,
882 .ctype = GTK_ACCESSIBLE_COLLECT_INTEGER,
883 .name = "rowindex"
884 },
885 [GTK_ACCESSIBLE_RELATION_ROW_INDEX_TEXT] = {
886 .value = GTK_ACCESSIBLE_RELATION_ROW_INDEX_TEXT,
887 .ctype = GTK_ACCESSIBLE_COLLECT_STRING,
888 .name = "rowindextext"
889 },
890 [GTK_ACCESSIBLE_RELATION_ROW_SPAN] = {
891 .value = GTK_ACCESSIBLE_RELATION_ROW_SPAN,
892 .ctype = GTK_ACCESSIBLE_COLLECT_INTEGER,
893 .name = "rowspan"
894 },
895 [GTK_ACCESSIBLE_RELATION_SET_SIZE] = {
896 .value = GTK_ACCESSIBLE_RELATION_SET_SIZE,
897 .ctype = GTK_ACCESSIBLE_COLLECT_INTEGER,
898 .name = "posinset"
899 },
900};
901
902typedef GtkAccessibleValue * (* GtkAccessibleValueBooleanCtor) (gboolean value);
903typedef GtkAccessibleValue * (* GtkAccessibleValueIntCtor) (int value);
904typedef GtkAccessibleValue * (* GtkAccessibleValueTristateCtor) (int value);
905typedef GtkAccessibleValue * (* GtkAccessibleValueEnumCtor) (int value);
906typedef GtkAccessibleValue * (* GtkAccessibleValueNumberCtor) (double value);
907typedef GtkAccessibleValue * (* GtkAccessibleValueStringCtor) (const char *value);
908typedef GtkAccessibleValue * (* GtkAccessibleValueRefCtor) (GtkAccessible *value);
909typedef GtkAccessibleValue * (* GtkAccessibleValueRefListCtor) (GList *value);
910
911typedef GtkAccessibleValue * (* GtkAccessibleValueEnumParser) (const char *str,
912 gsize len,
913 GError **error);
914typedef void (* GtkAccessibleValueEnumInit) (GValue *value);
915
916/*< private >
917 * gtk_accessible_value_get_default_for_state:
918 * @state: a `GtkAccessibleState`
919 *
920 * Retrieves the `GtkAccessibleValue` that contains the default for the
921 * given @state.
922 *
923 * Returns: (transfer full): the `GtkAccessibleValue`
924 */
925GtkAccessibleValue *
926gtk_accessible_value_get_default_for_state (GtkAccessibleState state)
927{
928 const GtkAccessibleCollect *cstate = &collect_states[state];
929
930 g_return_val_if_fail (state <= GTK_ACCESSIBLE_STATE_SELECTED, NULL);
931
932 switch (cstate->value)
933 {
934 case GTK_ACCESSIBLE_STATE_BUSY:
935 case GTK_ACCESSIBLE_STATE_DISABLED:
936 case GTK_ACCESSIBLE_STATE_HIDDEN:
937 return gtk_boolean_accessible_value_new (FALSE);
938
939 case GTK_ACCESSIBLE_STATE_CHECKED:
940 case GTK_ACCESSIBLE_STATE_EXPANDED:
941 case GTK_ACCESSIBLE_STATE_PRESSED:
942 case GTK_ACCESSIBLE_STATE_SELECTED:
943 return gtk_undefined_accessible_value_new ();
944
945 case GTK_ACCESSIBLE_STATE_INVALID:
946 return gtk_invalid_accessible_value_new (value: GTK_ACCESSIBLE_INVALID_FALSE);
947
948 default:
949 g_critical ("Unknown value for accessible state “%s”", cstate->name);
950 break;
951 }
952
953 return NULL;
954}
955
956static GtkAccessibleValue *
957gtk_accessible_value_collect_valist (const GtkAccessibleCollect *cstate,
958 GError **error,
959 va_list *args)
960{
961 GtkAccessibleValue *res = NULL;
962 GtkAccessibleCollectType ctype = cstate->ctype;
963 gboolean collects_undef = (ctype & GTK_ACCESSIBLE_COLLECT_UNDEFINED) != 0;
964
965 ctype &= (GTK_ACCESSIBLE_COLLECT_UNDEFINED - 1);
966
967 /* Tristate values include "undefined" by definition */
968 if (ctype == GTK_ACCESSIBLE_COLLECT_TRISTATE)
969 collects_undef = TRUE;
970
971 switch (ctype)
972 {
973 case GTK_ACCESSIBLE_COLLECT_BOOLEAN:
974 {
975 if (collects_undef)
976 {
977 int value = va_arg (*args, int);
978
979 if (value == GTK_ACCESSIBLE_VALUE_UNDEFINED)
980 res = gtk_undefined_accessible_value_new ();
981 else
982 res = gtk_boolean_accessible_value_new (value: value == 0 ? FALSE : TRUE);
983 }
984 else
985 {
986 gboolean value = va_arg (*args, gboolean);
987
988 res = gtk_boolean_accessible_value_new (value);
989 }
990 }
991 break;
992
993 case GTK_ACCESSIBLE_COLLECT_TRISTATE:
994 {
995 int value = va_arg (*args, int);
996
997 if (collects_undef && value == GTK_ACCESSIBLE_VALUE_UNDEFINED)
998 res = gtk_undefined_accessible_value_new ();
999 else
1000 res = gtk_tristate_accessible_value_new (value);
1001 }
1002 break;
1003
1004 case GTK_ACCESSIBLE_COLLECT_TOKEN:
1005 {
1006 GtkAccessibleValueEnumCtor ctor =
1007 (GtkAccessibleValueEnumCtor) cstate->ctor;
1008
1009 int value = va_arg (*args, int);
1010
1011 if (collects_undef && value == GTK_ACCESSIBLE_VALUE_UNDEFINED)
1012 {
1013 res = gtk_undefined_accessible_value_new ();
1014 }
1015 else
1016 {
1017 /* Token collection requires a constructor */
1018 g_assert (ctor != NULL);
1019
1020 res = (* ctor) (value);
1021 }
1022
1023 if (res == NULL)
1024 {
1025 g_set_error (err: error, GTK_ACCESSIBLE_VALUE_ERROR,
1026 code: GTK_ACCESSIBLE_VALUE_ERROR_INVALID_TOKEN,
1027 format: "Invalid value for token attribute: %d",
1028 value);
1029 }
1030 }
1031 break;
1032
1033 case GTK_ACCESSIBLE_COLLECT_INTEGER:
1034 {
1035 GtkAccessibleValueEnumCtor ctor =
1036 (GtkAccessibleValueEnumCtor) cstate->ctor;
1037
1038 int value = va_arg (*args, int);
1039
1040 if (ctor == NULL)
1041 res = gtk_int_accessible_value_new (value);
1042 else
1043 res = (* ctor) (value);
1044 }
1045 break;
1046
1047 case GTK_ACCESSIBLE_COLLECT_NUMBER:
1048 {
1049 GtkAccessibleValueNumberCtor ctor =
1050 (GtkAccessibleValueNumberCtor) cstate->ctor;
1051
1052 double value = va_arg (*args, double);
1053
1054 if (isnan (value) || isinf (value))
1055 {
1056 g_set_error_literal (err: error, GTK_ACCESSIBLE_VALUE_ERROR,
1057 code: GTK_ACCESSIBLE_VALUE_ERROR_INVALID_VALUE,
1058 message: "Invalid numeric value");
1059 return NULL;
1060 }
1061
1062 if (ctor == NULL)
1063 res = gtk_number_accessible_value_new (value);
1064 else
1065 res = (* ctor) (value);
1066 }
1067 break;
1068
1069 case GTK_ACCESSIBLE_COLLECT_STRING:
1070 {
1071 GtkAccessibleValueStringCtor ctor =
1072 (GtkAccessibleValueStringCtor) cstate->ctor;
1073
1074 const char *value = va_arg (*args, char*);
1075
1076 if (ctor == NULL)
1077 {
1078 if (value != NULL)
1079 res = gtk_string_accessible_value_new (str: value);
1080 }
1081 else
1082 {
1083 res = (* ctor) (value);
1084 }
1085 }
1086 break;
1087
1088 case GTK_ACCESSIBLE_COLLECT_REFERENCE:
1089 {
1090 GtkAccessibleValueRefCtor ctor =
1091 (GtkAccessibleValueRefCtor) cstate->ctor;
1092
1093 gpointer value = va_arg (*args, gpointer);
1094
1095 if (value != NULL && !GTK_IS_ACCESSIBLE (ptr: value))
1096 {
1097 g_set_error_literal (err: error, GTK_ACCESSIBLE_VALUE_ERROR,
1098 code: GTK_ACCESSIBLE_VALUE_ERROR_INVALID_VALUE,
1099 message: "Reference does not implement GtkAccessible");
1100 return NULL;
1101 }
1102
1103 if (ctor == NULL)
1104 {
1105 if (value != NULL)
1106 res = gtk_reference_accessible_value_new (ref: value);
1107 else
1108 res = gtk_undefined_accessible_value_new ();
1109 }
1110 else
1111 {
1112 res = (* ctor) (value);
1113 }
1114 }
1115 break;
1116
1117 case GTK_ACCESSIBLE_COLLECT_REFERENCE_LIST:
1118 {
1119 GtkAccessibleValueRefListCtor ctor =
1120 (GtkAccessibleValueRefListCtor) cstate->ctor;
1121
1122 GtkAccessible *ref = va_arg (*args, gpointer);
1123 GList *value = NULL;
1124
1125 while (ref != NULL)
1126 {
1127 if (!GTK_IS_ACCESSIBLE (ptr: ref))
1128 {
1129 g_set_error (err: error, GTK_ACCESSIBLE_VALUE_ERROR,
1130 code: GTK_ACCESSIBLE_VALUE_ERROR_INVALID_VALUE,
1131 format: "Reference of type “%s” [%p] does not implement GtkAccessible",
1132 G_OBJECT_TYPE_NAME (ref), ref);
1133 return NULL;
1134 }
1135
1136 value = g_list_prepend (list: value, data: ref);
1137
1138 ref = va_arg (*args, gpointer);
1139 }
1140
1141 if (value == NULL)
1142 res = gtk_undefined_accessible_value_new ();
1143 else
1144 {
1145 value = g_list_reverse (list: value);
1146
1147 if (ctor == NULL)
1148 res = gtk_reference_list_accessible_value_new (value);
1149 else
1150 res = (* ctor) (value);
1151 }
1152 }
1153 break;
1154
1155 case GTK_ACCESSIBLE_COLLECT_UNDEFINED:
1156 case GTK_ACCESSIBLE_COLLECT_INVALID:
1157 default:
1158 g_assert_not_reached ();
1159 break;
1160 }
1161
1162 return res;
1163}
1164
1165static GtkAccessibleValue *
1166gtk_accessible_value_collect_value (const GtkAccessibleCollect *cstate,
1167 const GValue *value_,
1168 GError **error)
1169{
1170 GtkAccessibleValue *res = NULL;
1171 GtkAccessibleCollectType ctype = cstate->ctype;
1172 gboolean collects_undef = (ctype & GTK_ACCESSIBLE_COLLECT_UNDEFINED) != 0;
1173
1174 ctype &= (GTK_ACCESSIBLE_COLLECT_UNDEFINED - 1);
1175
1176 /* Tristate values include "undefined" by definition */
1177 if (ctype == GTK_ACCESSIBLE_COLLECT_TRISTATE)
1178 collects_undef = TRUE;
1179
1180 switch (ctype)
1181 {
1182 case GTK_ACCESSIBLE_COLLECT_BOOLEAN:
1183 {
1184 if (collects_undef)
1185 {
1186 int value = g_value_get_int (value: value_);
1187
1188 if (value == GTK_ACCESSIBLE_VALUE_UNDEFINED)
1189 res = gtk_undefined_accessible_value_new ();
1190 else
1191 res = gtk_boolean_accessible_value_new (value: value == 0 ? FALSE : TRUE);
1192 }
1193 else
1194 {
1195 gboolean value = g_value_get_boolean (value: value_);
1196
1197 res = gtk_boolean_accessible_value_new (value);
1198 }
1199 }
1200 break;
1201
1202 case GTK_ACCESSIBLE_COLLECT_TRISTATE:
1203 {
1204 int value = g_value_get_int (value: value_);
1205
1206 if (collects_undef && value == GTK_ACCESSIBLE_VALUE_UNDEFINED)
1207 res = gtk_undefined_accessible_value_new ();
1208 else
1209 res = gtk_tristate_accessible_value_new (value);
1210 }
1211 break;
1212
1213 case GTK_ACCESSIBLE_COLLECT_TOKEN:
1214 {
1215 GtkAccessibleValueEnumCtor ctor =
1216 (GtkAccessibleValueEnumCtor) cstate->ctor;
1217
1218 int value = g_value_get_int (value: value_);
1219
1220 if (collects_undef && value == GTK_ACCESSIBLE_VALUE_UNDEFINED)
1221 {
1222 res = gtk_undefined_accessible_value_new ();
1223 }
1224 else
1225 {
1226 /* Token collection requires a constructor */
1227 g_assert (ctor != NULL);
1228
1229 res = (* ctor) (value);
1230 }
1231
1232 if (res == NULL)
1233 {
1234 g_set_error (err: error, GTK_ACCESSIBLE_VALUE_ERROR,
1235 code: GTK_ACCESSIBLE_VALUE_ERROR_INVALID_TOKEN,
1236 format: "Invalid value for token attribute: %d",
1237 value);
1238 }
1239 }
1240 break;
1241
1242 case GTK_ACCESSIBLE_COLLECT_INTEGER:
1243 {
1244 GtkAccessibleValueEnumCtor ctor =
1245 (GtkAccessibleValueEnumCtor) cstate->ctor;
1246
1247 int value = g_value_get_int (value: value_);
1248
1249 if (ctor == NULL)
1250 res = gtk_int_accessible_value_new (value);
1251 else
1252 res = (* ctor) (value);
1253 }
1254 break;
1255
1256 case GTK_ACCESSIBLE_COLLECT_NUMBER:
1257 {
1258 GtkAccessibleValueNumberCtor ctor =
1259 (GtkAccessibleValueNumberCtor) cstate->ctor;
1260
1261 double value = g_value_get_double (value: value_);
1262
1263 if (isnan (value) || isinf (value))
1264 {
1265 g_set_error_literal (err: error, GTK_ACCESSIBLE_VALUE_ERROR,
1266 code: GTK_ACCESSIBLE_VALUE_ERROR_INVALID_VALUE,
1267 message: "Invalid numeric value");
1268 return NULL;
1269 }
1270
1271 if (ctor == NULL)
1272 res = gtk_number_accessible_value_new (value);
1273 else
1274 res = (* ctor) (value);
1275 }
1276 break;
1277
1278 case GTK_ACCESSIBLE_COLLECT_STRING:
1279 {
1280 GtkAccessibleValueStringCtor ctor =
1281 (GtkAccessibleValueStringCtor) cstate->ctor;
1282
1283 const char *value = g_value_get_string (value: value_);
1284
1285 if (ctor == NULL)
1286 {
1287 if (value != NULL)
1288 res = gtk_string_accessible_value_new (str: value);
1289 }
1290 else
1291 {
1292 res = (* ctor) (value);
1293 }
1294 }
1295 break;
1296
1297 case GTK_ACCESSIBLE_COLLECT_REFERENCE:
1298 {
1299 GtkAccessibleValueRefCtor ctor =
1300 (GtkAccessibleValueRefCtor) cstate->ctor;
1301
1302 gpointer value = g_value_get_object (value: value_);
1303
1304 if (value != NULL && !GTK_IS_ACCESSIBLE (ptr: value))
1305 {
1306 g_set_error_literal (err: error, GTK_ACCESSIBLE_VALUE_ERROR,
1307 code: GTK_ACCESSIBLE_VALUE_ERROR_INVALID_VALUE,
1308 message: "Reference does not implement GtkAccessible");
1309 return NULL;
1310 }
1311
1312 if (ctor == NULL)
1313 {
1314 if (value != NULL)
1315 res = gtk_reference_accessible_value_new (ref: value);
1316 }
1317 else
1318 {
1319 res = (* ctor) (value);
1320 }
1321 }
1322 break;
1323
1324 case GTK_ACCESSIBLE_COLLECT_REFERENCE_LIST:
1325 {
1326 GtkAccessibleValueRefListCtor ctor =
1327 (GtkAccessibleValueRefListCtor) cstate->ctor;
1328
1329 GList *value = g_value_get_pointer (value: value_);
1330
1331 if (ctor == NULL)
1332 {
1333 if (value != NULL)
1334 res = gtk_reference_list_accessible_value_new (value);
1335 }
1336 else
1337 {
1338 res = (* ctor) (value);
1339 }
1340 }
1341 break;
1342
1343 case GTK_ACCESSIBLE_COLLECT_UNDEFINED:
1344 case GTK_ACCESSIBLE_COLLECT_INVALID:
1345 default:
1346 g_assert_not_reached ();
1347 break;
1348 }
1349
1350 return res;
1351}
1352
1353static GtkAccessibleValue *
1354gtk_accessible_value_parse (const GtkAccessibleCollect *cstate,
1355 const char *str,
1356 gsize len,
1357 GError **error)
1358{
1359 GtkAccessibleValue *res = NULL;
1360 GtkAccessibleCollectType ctype = cstate->ctype;
1361 gboolean collects_undef = (ctype & GTK_ACCESSIBLE_COLLECT_UNDEFINED) != 0;
1362
1363 ctype &= (GTK_ACCESSIBLE_COLLECT_UNDEFINED - 1);
1364
1365 /* Tristate values include "undefined" by definition */
1366 if (ctype == GTK_ACCESSIBLE_COLLECT_TRISTATE)
1367 collects_undef = TRUE;
1368
1369 switch (ctype)
1370 {
1371 case GTK_ACCESSIBLE_COLLECT_BOOLEAN:
1372 {
1373 gboolean b;
1374
1375 if (collects_undef && strncmp (s1: str, s2: "undefined", n: 9) == 0)
1376 res = gtk_undefined_accessible_value_new ();
1377 else if (_gtk_builder_boolean_from_string (string: str, value: &b, error))
1378 res = gtk_boolean_accessible_value_new (value: b);
1379 }
1380 break;
1381
1382 case GTK_ACCESSIBLE_COLLECT_TRISTATE:
1383 {
1384 int value;
1385
1386 if (collects_undef && strncmp (s1: str, s2: "undefined", n: 9) == 0)
1387 res = gtk_undefined_accessible_value_new ();
1388 else if (_gtk_builder_enum_from_string (type: GTK_TYPE_ACCESSIBLE_TRISTATE, string: str, enum_value: &value, error))
1389 res = gtk_boolean_accessible_value_new (value);
1390 }
1391 break;
1392
1393 case GTK_ACCESSIBLE_COLLECT_TOKEN:
1394 {
1395 GtkAccessibleValueEnumParser parser =
1396 (GtkAccessibleValueEnumParser) cstate->parser;
1397
1398 if (collects_undef && strncmp (s1: str, s2: "undefined", n: 9) == 0)
1399 {
1400 res = gtk_undefined_accessible_value_new ();
1401 }
1402 else
1403 {
1404 /* Token collection requires a constructor */
1405 g_assert (parser != NULL);
1406
1407 res = (* parser) (str, len, error);
1408 }
1409 }
1410 break;
1411
1412 case GTK_ACCESSIBLE_COLLECT_INTEGER:
1413 {
1414 char *end = NULL;
1415 gint64 value = g_ascii_strtoll (nptr: str, endptr: &end, base: 10);
1416
1417 if (str == end)
1418 {
1419 int saved_errno = errno;
1420 g_set_error (err: error, GTK_ACCESSIBLE_VALUE_ERROR,
1421 code: GTK_ACCESSIBLE_VALUE_ERROR_INVALID_VALUE,
1422 format: "Invalid integer value “%s”: %s",
1423 str, g_strerror (errnum: saved_errno));
1424
1425 return NULL;
1426 }
1427 else
1428 res = gtk_int_accessible_value_new (value: (int) value);
1429 }
1430 break;
1431
1432 case GTK_ACCESSIBLE_COLLECT_NUMBER:
1433 {
1434 char *end = NULL;
1435 double value = g_ascii_strtod (nptr: str, endptr: &end);
1436
1437 if (str == end || isnan (value) || isinf (value))
1438 {
1439 g_set_error (err: error, GTK_ACCESSIBLE_VALUE_ERROR,
1440 code: GTK_ACCESSIBLE_VALUE_ERROR_INVALID_VALUE,
1441 format: "Invalid numeric value “%s”",
1442 str);
1443 return NULL;
1444 }
1445
1446 res = gtk_number_accessible_value_new (value);
1447 }
1448 break;
1449
1450 case GTK_ACCESSIBLE_COLLECT_STRING:
1451 {
1452 res = gtk_string_accessible_value_new (str);
1453 }
1454 break;
1455
1456 case GTK_ACCESSIBLE_COLLECT_REFERENCE:
1457 case GTK_ACCESSIBLE_COLLECT_REFERENCE_LIST:
1458 {
1459 /* We do not error out, to let the caller code deal
1460 * with the references themselves
1461 */
1462 res = NULL;
1463 }
1464 break;
1465
1466 case GTK_ACCESSIBLE_COLLECT_UNDEFINED:
1467 case GTK_ACCESSIBLE_COLLECT_INVALID:
1468 default:
1469 g_assert_not_reached ();
1470 break;
1471 }
1472
1473 return res;
1474}
1475
1476static void
1477gtk_accessible_attribute_init_value (const GtkAccessibleCollect *cstate,
1478 GValue *value)
1479{
1480 GtkAccessibleCollectType ctype = cstate->ctype;
1481 gboolean collects_undef = (ctype & GTK_ACCESSIBLE_COLLECT_UNDEFINED) != 0;
1482
1483 ctype &= (GTK_ACCESSIBLE_COLLECT_UNDEFINED - 1);
1484
1485 /* Tristate values include "undefined" by definition */
1486 if (ctype == GTK_ACCESSIBLE_COLLECT_TRISTATE)
1487 collects_undef = TRUE;
1488
1489 switch (ctype)
1490 {
1491 case GTK_ACCESSIBLE_COLLECT_BOOLEAN:
1492 {
1493 if (collects_undef)
1494 g_value_init (value, G_TYPE_INT);
1495 else
1496 g_value_init (value, G_TYPE_BOOLEAN);
1497 }
1498 break;
1499
1500 case GTK_ACCESSIBLE_COLLECT_TRISTATE:
1501 g_value_init (value, g_type: GTK_TYPE_ACCESSIBLE_TRISTATE);
1502 break;
1503
1504 case GTK_ACCESSIBLE_COLLECT_TOKEN:
1505 if (cstate->init_value != NULL)
1506 {
1507 GtkAccessibleValueEnumInit init_value =
1508 (GtkAccessibleValueEnumInit) cstate->init_value;
1509
1510 (* init_value) (value);
1511 }
1512 else
1513 g_value_init (value, G_TYPE_INT);
1514 break;
1515
1516 case GTK_ACCESSIBLE_COLLECT_INTEGER:
1517 g_value_init (value, G_TYPE_INT);
1518 break;
1519
1520 case GTK_ACCESSIBLE_COLLECT_NUMBER:
1521 g_value_init (value, G_TYPE_DOUBLE);
1522 break;
1523
1524 case GTK_ACCESSIBLE_COLLECT_STRING:
1525 g_value_init (value, G_TYPE_STRING);
1526 break;
1527
1528 case GTK_ACCESSIBLE_COLLECT_REFERENCE:
1529 g_value_init (value, GTK_TYPE_ACCESSIBLE);
1530 break;
1531
1532 case GTK_ACCESSIBLE_COLLECT_REFERENCE_LIST:
1533 g_value_init (value, G_TYPE_POINTER);
1534 break;
1535
1536 case GTK_ACCESSIBLE_COLLECT_UNDEFINED:
1537 case GTK_ACCESSIBLE_COLLECT_INVALID:
1538 default:
1539 g_assert_not_reached ();
1540 break;
1541 }
1542}
1543
1544/*< private >
1545 * gtk_accessible_value_collect_for_state:
1546 * @state: a `GtkAccessibleState`
1547 * @error: return location for a `GError`
1548 * @args: a `va_list` reference
1549 *
1550 * Collects and consumes the next item in the @args variadic arguments list,
1551 * and returns a `GtkAccessibleValue` for it.
1552 *
1553 * If the collection fails, @error is set and %NULL is returned.
1554 *
1555 * The returned value could be %NULL even on success, in which case the state
1556 * should be reset to its default value by the caller.
1557 *
1558 * Returns: (transfer full) (nullable): a `GtkAccessibleValue`
1559 */
1560GtkAccessibleValue *
1561gtk_accessible_value_collect_for_state (GtkAccessibleState state,
1562 GError **error,
1563 va_list *args)
1564{
1565 const GtkAccessibleCollect *cstate = &collect_states[state];
1566
1567 g_return_val_if_fail (state <= GTK_ACCESSIBLE_STATE_SELECTED, NULL);
1568
1569 return gtk_accessible_value_collect_valist (cstate, error, args);
1570}
1571
1572/*< private >
1573 * gtk_accessible_value_collect_for_state_value:
1574 * @state: a `GtkAccessibleState`
1575 * @value: a `GValue`
1576 * @error: return location for a `GError`
1577 *
1578 * Retrieves the value stored inside @value and returns a `GtkAccessibleValue`
1579 * for the given @state.
1580 *
1581 * If the collection fails, @error is set and %NULL is returned.
1582 *
1583 * The returned value could be %NULL even on success, in which case the state
1584 * should be reset to its default value by the caller.
1585 *
1586 * Returns: (transfer full) (nullable): a `GtkAccessibleValue`
1587 */
1588GtkAccessibleValue *
1589gtk_accessible_value_collect_for_state_value (GtkAccessibleState state,
1590 const GValue *value,
1591 GError **error)
1592{
1593 const GtkAccessibleCollect *cstate = &collect_states[state];
1594
1595 g_return_val_if_fail (state <= GTK_ACCESSIBLE_STATE_SELECTED, NULL);
1596
1597 return gtk_accessible_value_collect_value (cstate, value_: value, error);
1598}
1599
1600GtkAccessibleValue *
1601gtk_accessible_value_parse_for_state (GtkAccessibleState state,
1602 const char *str,
1603 gsize len,
1604 GError **error)
1605{
1606 const GtkAccessibleCollect *cstate = &collect_states[state];
1607
1608 g_return_val_if_fail (state <= GTK_ACCESSIBLE_STATE_SELECTED, NULL);
1609
1610 return gtk_accessible_value_parse (cstate, str, len, error);
1611}
1612
1613/**
1614 * gtk_accessible_state_init_value:
1615 * @state: a `GtkAccessibleState`
1616 * @value: an uninitialized `GValue`
1617 *
1618 * Initializes @value with the appropriate type for the @state.
1619 *
1620 * This function is mostly meant for language bindings, in conjunction
1621 * with gtk_accessible_update_relation_state().
1622 */
1623void
1624gtk_accessible_state_init_value (GtkAccessibleState state,
1625 GValue *value)
1626{
1627 const GtkAccessibleCollect *cstate = &collect_states[state];
1628
1629 g_return_if_fail (state <= GTK_ACCESSIBLE_STATE_SELECTED);
1630
1631 gtk_accessible_attribute_init_value (cstate, value);
1632}
1633
1634/*< private >
1635 * gtk_accessible_value_get_default_for_property:
1636 * @property: a `GtkAccessibleProperty`
1637 *
1638 * Retrieves the `GtkAccessibleValue` that contains the default for the
1639 * given @property.
1640 *
1641 * Returns: (transfer full): the `GtkAccessibleValue`
1642 */
1643GtkAccessibleValue *
1644gtk_accessible_value_get_default_for_property (GtkAccessibleProperty property)
1645{
1646 const GtkAccessibleCollect *cstate = &collect_props[property];
1647
1648 g_return_val_if_fail (property <= GTK_ACCESSIBLE_PROPERTY_VALUE_TEXT, NULL);
1649
1650 switch (cstate->value)
1651 {
1652 /* Boolean properties */
1653 case GTK_ACCESSIBLE_PROPERTY_HAS_POPUP:
1654 case GTK_ACCESSIBLE_PROPERTY_MODAL:
1655 case GTK_ACCESSIBLE_PROPERTY_MULTI_LINE:
1656 case GTK_ACCESSIBLE_PROPERTY_MULTI_SELECTABLE:
1657 case GTK_ACCESSIBLE_PROPERTY_READ_ONLY:
1658 case GTK_ACCESSIBLE_PROPERTY_REQUIRED:
1659 return gtk_boolean_accessible_value_new (FALSE);
1660
1661 /* Integer properties */
1662 case GTK_ACCESSIBLE_PROPERTY_LEVEL:
1663 return gtk_int_accessible_value_new (value: 0);
1664
1665 /* Number properties */
1666 case GTK_ACCESSIBLE_PROPERTY_VALUE_MAX:
1667 case GTK_ACCESSIBLE_PROPERTY_VALUE_MIN:
1668 case GTK_ACCESSIBLE_PROPERTY_VALUE_NOW:
1669 return gtk_number_accessible_value_new (value: 0);
1670
1671 /* String properties */
1672 case GTK_ACCESSIBLE_PROPERTY_DESCRIPTION:
1673 case GTK_ACCESSIBLE_PROPERTY_KEY_SHORTCUTS:
1674 case GTK_ACCESSIBLE_PROPERTY_LABEL:
1675 case GTK_ACCESSIBLE_PROPERTY_PLACEHOLDER:
1676 case GTK_ACCESSIBLE_PROPERTY_ROLE_DESCRIPTION:
1677 case GTK_ACCESSIBLE_PROPERTY_VALUE_TEXT:
1678 return gtk_undefined_accessible_value_new ();
1679
1680 /* Token properties */
1681 case GTK_ACCESSIBLE_PROPERTY_AUTOCOMPLETE:
1682 return gtk_autocomplete_accessible_value_new (value: GTK_ACCESSIBLE_AUTOCOMPLETE_NONE);
1683
1684 case GTK_ACCESSIBLE_PROPERTY_ORIENTATION:
1685 return gtk_undefined_accessible_value_new ();
1686
1687 case GTK_ACCESSIBLE_PROPERTY_SORT:
1688 return gtk_sort_accessible_value_new (value: GTK_ACCESSIBLE_SORT_NONE);
1689
1690 default:
1691 g_critical ("Unknown value for accessible property “%s”", cstate->name);
1692 break;
1693 }
1694
1695 return NULL;
1696}
1697
1698/*< private >
1699 * gtk_accessible_value_collect_for_property:
1700 * @property: a `GtkAccessibleProperty`
1701 * @error: return location for a `GError`
1702 * @args: a `va_list` reference
1703 *
1704 * Collects and consumes the next item in the @args variadic arguments list,
1705 * and returns a `GtkAccessibleValue` for it.
1706 *
1707 * If the collection fails, @error is set.
1708 *
1709 * Returns: (transfer full) (nullable): a `GtkAccessibleValue`
1710 */
1711GtkAccessibleValue *
1712gtk_accessible_value_collect_for_property (GtkAccessibleProperty property,
1713 GError **error,
1714 va_list *args)
1715{
1716 const GtkAccessibleCollect *cstate = &collect_props[property];
1717
1718 g_return_val_if_fail (property <= GTK_ACCESSIBLE_PROPERTY_VALUE_TEXT, NULL);
1719
1720 return gtk_accessible_value_collect_valist (cstate, error, args);
1721}
1722
1723/*< private >
1724 * gtk_accessible_value_collect_for_property_value:
1725 * @property: a `GtkAccessibleProperty`
1726 * @value: a `GValue`
1727 * @error: return location for a `GError`
1728 *
1729 * Retrieves the value stored inside @value and returns a `GtkAccessibleValue`
1730 * for the given @property.
1731 *
1732 * If the collection fails, @error is set.
1733 *
1734 * The returned value could be %NULL even on success, in which case the property
1735 * should be reset to its default value by the caller.
1736 *
1737 * Returns: (transfer full) (nullable): a `GtkAccessibleValue`
1738 */
1739GtkAccessibleValue *
1740gtk_accessible_value_collect_for_property_value (GtkAccessibleProperty property,
1741 const GValue *value,
1742 GError **error)
1743{
1744 const GtkAccessibleCollect *cstate = &collect_props[property];
1745
1746 g_return_val_if_fail (property <= GTK_ACCESSIBLE_PROPERTY_VALUE_TEXT, NULL);
1747
1748 return gtk_accessible_value_collect_value (cstate, value_: value, error);
1749}
1750
1751GtkAccessibleValue *
1752gtk_accessible_value_parse_for_property (GtkAccessibleProperty property,
1753 const char *str,
1754 gsize len,
1755 GError **error)
1756{
1757 const GtkAccessibleCollect *cstate = &collect_props[property];
1758
1759 g_return_val_if_fail (property <= GTK_ACCESSIBLE_PROPERTY_VALUE_TEXT, NULL);
1760
1761 return gtk_accessible_value_parse (cstate, str, len, error);
1762}
1763
1764/**
1765 * gtk_accessible_property_init_value:
1766 * @property: a `GtkAccessibleProperty`
1767 * @value: an uninitialized `GValue`
1768 *
1769 * Initializes @value with the appropriate type for the @property.
1770 *
1771 * This function is mostly meant for language bindings, in conjunction
1772 * with gtk_accessible_update_property_value().
1773 */
1774void
1775gtk_accessible_property_init_value (GtkAccessibleProperty property,
1776 GValue *value)
1777{
1778 const GtkAccessibleCollect *cstate = &collect_props[property];
1779
1780 g_return_if_fail (property <= GTK_ACCESSIBLE_PROPERTY_VALUE_TEXT);
1781
1782 gtk_accessible_attribute_init_value (cstate, value);
1783}
1784
1785/*< private >
1786 * gtk_accessible_value_get_default_for_relation:
1787 * @relation: a `GtkAccessibleRelation`
1788 *
1789 * Retrieves the `GtkAccessibleValue` that contains the default for the
1790 * given @relation.
1791 *
1792 * Returns: (transfer full): the `GtkAccessibleValue`
1793 */
1794GtkAccessibleValue *
1795gtk_accessible_value_get_default_for_relation (GtkAccessibleRelation relation)
1796{
1797 const GtkAccessibleCollect *cstate = &collect_rels[relation];
1798
1799 g_return_val_if_fail (relation <= GTK_ACCESSIBLE_RELATION_SET_SIZE, NULL);
1800
1801 switch (cstate->value)
1802 {
1803 /* References */
1804 case GTK_ACCESSIBLE_RELATION_ACTIVE_DESCENDANT:
1805 case GTK_ACCESSIBLE_RELATION_CONTROLS:
1806 case GTK_ACCESSIBLE_RELATION_DESCRIBED_BY:
1807 case GTK_ACCESSIBLE_RELATION_DETAILS:
1808 case GTK_ACCESSIBLE_RELATION_ERROR_MESSAGE:
1809 case GTK_ACCESSIBLE_RELATION_FLOW_TO:
1810 case GTK_ACCESSIBLE_RELATION_LABELLED_BY:
1811 case GTK_ACCESSIBLE_RELATION_OWNS:
1812 return gtk_undefined_accessible_value_new ();
1813
1814 /* Integers */
1815 case GTK_ACCESSIBLE_RELATION_COL_COUNT:
1816 case GTK_ACCESSIBLE_RELATION_COL_INDEX:
1817 case GTK_ACCESSIBLE_RELATION_COL_SPAN:
1818 case GTK_ACCESSIBLE_RELATION_POS_IN_SET:
1819 case GTK_ACCESSIBLE_RELATION_ROW_COUNT:
1820 case GTK_ACCESSIBLE_RELATION_ROW_INDEX:
1821 case GTK_ACCESSIBLE_RELATION_ROW_SPAN:
1822 case GTK_ACCESSIBLE_RELATION_SET_SIZE:
1823 return gtk_int_accessible_value_new (value: 0);
1824
1825 /* Strings */
1826 case GTK_ACCESSIBLE_RELATION_ROW_INDEX_TEXT:
1827 case GTK_ACCESSIBLE_RELATION_COL_INDEX_TEXT:
1828 return gtk_undefined_accessible_value_new ();
1829
1830 default:
1831 g_critical ("Unknown value for accessible property “%s”", cstate->name);
1832 break;
1833 }
1834
1835 return NULL;
1836}
1837
1838/*< private >
1839 * gtk_accessible_value_collect_for_relation:
1840 * @relation: a `GtkAccessibleRelation`
1841 * @error: return location for a `GError`
1842 * @args: a `va_list` reference
1843 *
1844 * Collects and consumes the next item in the @args variadic arguments list,
1845 * and returns a `GtkAccessibleValue` for it.
1846 *
1847 * If the collection fails, @error is set and %NULL is returned.
1848 *
1849 * The returned value could be %NULL even on success, in which case the relation
1850 * should be reset to its default value by the caller.
1851 *
1852 * Returns: (transfer full) (nullable): a `GtkAccessibleValue`
1853 */
1854GtkAccessibleValue *
1855gtk_accessible_value_collect_for_relation (GtkAccessibleRelation relation,
1856 GError **error,
1857 va_list *args)
1858{
1859 const GtkAccessibleCollect *cstate = &collect_rels[relation];
1860
1861 g_return_val_if_fail (relation <= GTK_ACCESSIBLE_RELATION_SET_SIZE, NULL);
1862
1863 return gtk_accessible_value_collect_valist (cstate, error, args);
1864}
1865
1866/*< private >
1867 * gtk_accessible_value_collect_for_relation_value:
1868 * @relation: a `GtkAccessibleRelation`
1869 * @value: a `GValue`
1870 * @error: return location for a `GError`
1871 *
1872 * Retrieves the value stored inside @value and returns a `GtkAccessibleValue`
1873 * for the given @relation.
1874 *
1875 * If the collection fails, @error is set and %NULL is returned.
1876 *
1877 * The returned value could be %NULL even on success, in which case the relation
1878 * should be reset to its default value by the caller.
1879 *
1880 * Returns: (transfer full) (nullable): a `GtkAccessibleValue`
1881 */
1882GtkAccessibleValue *
1883gtk_accessible_value_collect_for_relation_value (GtkAccessibleRelation relation,
1884 const GValue *value,
1885 GError **error)
1886{
1887 const GtkAccessibleCollect *cstate = &collect_rels[relation];
1888
1889 g_return_val_if_fail (relation <= GTK_ACCESSIBLE_RELATION_SET_SIZE, NULL);
1890
1891 return gtk_accessible_value_collect_value (cstate, value_: value, error);
1892}
1893
1894GtkAccessibleValue *
1895gtk_accessible_value_parse_for_relation (GtkAccessibleRelation relation,
1896 const char *str,
1897 gsize len,
1898 GError **error)
1899{
1900 const GtkAccessibleCollect *cstate = &collect_rels[relation];
1901
1902 g_return_val_if_fail (relation <= GTK_ACCESSIBLE_RELATION_SET_SIZE, NULL);
1903
1904 return gtk_accessible_value_parse (cstate, str, len, error);
1905}
1906
1907/**
1908 * gtk_accessible_relation_init_value:
1909 * @relation: a `GtkAccessibleRelation`
1910 * @value: an uninitialized `GValue`
1911 *
1912 * Initializes @value with the appropriate type for the @relation.
1913 *
1914 * This function is mostly meant for language bindings, in conjunction
1915 * with gtk_accessible_update_relation_value().
1916 */
1917void
1918gtk_accessible_relation_init_value (GtkAccessibleRelation relation,
1919 GValue *value)
1920{
1921 const GtkAccessibleCollect *cstate = &collect_rels[relation];
1922
1923 g_return_if_fail (relation <= GTK_ACCESSIBLE_RELATION_SET_SIZE);
1924
1925 gtk_accessible_attribute_init_value (cstate, value);
1926}
1927
1928/* }}} */
1929

source code of gtk/gtk/gtkaccessiblevalue.c