Add get_interfaces, and fetch interface/stateset over the wire if needed
[platform/upstream/at-spi2-core.git] / atspi / atspi-accessible.c
1 /*
2  * AT-SPI - Assistive Technology Service Provider Interface
3  * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
4  *
5  * Copyright 2001, 2002 Sun Microsystems Inc.,
6  * Copyright 2001, 2002 Ximian, Inc.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23
24 #include "atspi-private.h"
25 #include <string.h>
26
27 static void
28 atspi_action_interface_init (AtspiAction *action)
29 {
30 }
31
32 static void
33 atspi_collection_interface_init (AtspiCollection *component)
34 {
35 }
36
37 static void
38 atspi_component_interface_init (AtspiComponent *component)
39 {
40 }
41
42 atspi_editable_text_interface_init (AtspiEditableText *editable_text)
43 {
44 }
45
46 static void
47 atspi_image_interface_init (AtspiImage *image)
48 {
49 }
50
51 static void
52 atspi_selection_interface_init (AtspiSelection *selection)
53 {
54 }
55
56 static void
57 atspi_table_interface_init (AtspiTable *table)
58 {
59 }
60
61 static void
62 atspi_text_interface_init (AtspiText *text)
63 {
64 }
65
66 static void
67 atspi_value_interface_init (AtspiValue *value)
68 {
69 }
70
71 G_DEFINE_TYPE_WITH_CODE (AtspiAccessible, atspi_accessible, ATSPI_TYPE_OBJECT,
72                          G_IMPLEMENT_INTERFACE (ATSPI_TYPE_ACTION, atspi_action_interface_init)
73                          G_IMPLEMENT_INTERFACE (ATSPI_TYPE_COLLECTION, atspi_collection_interface_init)
74                          G_IMPLEMENT_INTERFACE (ATSPI_TYPE_COMPONENT, atspi_component_interface_init)
75                          G_IMPLEMENT_INTERFACE (ATSPI_TYPE_EDITABLE_TEXT, atspi_editable_text_interface_init)
76                          G_IMPLEMENT_INTERFACE (ATSPI_TYPE_IMAGE, atspi_image_interface_init)
77                          G_IMPLEMENT_INTERFACE (ATSPI_TYPE_SELECTION, atspi_selection_interface_init)
78                          G_IMPLEMENT_INTERFACE (ATSPI_TYPE_TABLE, atspi_table_interface_init)
79                          G_IMPLEMENT_INTERFACE (ATSPI_TYPE_TEXT, atspi_text_interface_init)
80                          G_IMPLEMENT_INTERFACE (ATSPI_TYPE_VALUE, atspi_value_interface_init))
81
82 static void
83 atspi_accessible_init (AtspiAccessible *accessible)
84 {
85 }
86
87 static void
88 atspi_accessible_finalize (GObject *obj)
89 {
90   /*AtspiAccessible *accessible = ATSPI_ACCESSIBLE (obj); */
91
92   /* TODO: Unref parent/children, etc. */
93 }
94
95 static void
96 atspi_accessible_class_init (AtspiAccessibleClass *klass)
97 {
98   GObjectClass *object_class = G_OBJECT_CLASS (klass);
99
100   object_class->finalize = atspi_accessible_finalize;
101 }
102
103 /* TODO: Generate following from spec? */
104 static const char *role_names [] =
105 {
106   "invalid",
107   "accel-label",
108   "alert",
109   "animation",
110   "arrow",
111   "calendar",
112   "canvas",
113   "check-box",
114   "check-menu-item",
115   "color-chooser",
116   "column-header",
117   "combo-box",
118   "date-editor",
119   "desktop-icon",
120   "desktop-frame",
121   "dial",
122   "dialog",
123   "directory-pane",
124   "drawing-area",
125   "file-chooser",
126   "filler",
127   "font-chooser",
128   "frame",
129   "glass-pane",
130   "html-container",
131   "icon",
132   "image",
133   "internalframe",
134   "label",
135   "layered-pane",
136   "list",
137   "list-item",
138   "menu",
139   "menu-bar",
140   "menu-item",
141   "option-pane",
142   "page-tab",
143   "page-tab-list",
144   "panel",
145   "password-text",
146   "popup-menu",
147   "progress-bar",
148   "push-button",
149   "radio-button",
150   "radio-menu-item",
151   "root-pane",
152   "row-header",
153   "scroll-bar",
154   "scroll-pane",
155   "separator",
156   "slider",
157   "spin-button",
158   "split-pane",
159   "statusbar",
160   "table",
161   "table-cell",
162   "table-column-header",
163   "table-row-header",
164   "tear-off-menu-item",
165   "terminal",
166   "text",
167   "toggle-button",
168   "tool-bar",
169   "tool-tip",
170   "tree",
171   "tree-table",
172   "unknown",
173   "viewport",
174   "window",
175   NULL,
176   "header",
177   "fooler",
178   "paragraph",
179   "ruler",
180   "application",
181   "autocomplete",
182   "editbar",
183   "embedded",
184   "entry",
185   "chart",
186   "caption",
187   "document_frame",
188   "heading",
189   "page",
190   "section",
191   "form",
192   "redundant object",
193   "link",
194   "input method window"
195 };
196
197 #define MAX_ROLES (sizeof (role_names) / sizeof (char *))
198
199 /**
200  * atspi_role_get_name
201  * @role: an #AtspiAccessibleRole object to query.
202  *
203  * Get a localizeable string that indicates the name of an #AtspiAccessibleRole.
204  * <em>DEPRECATED.</em>
205  *
206  * Returns: a localizable string name for an #AtspiAccessibleRole enumerated type.
207  **/
208 gchar *
209 atspi_role_get_name (AtspiRole role)
210 {
211   if (role < MAX_ROLES && role_names [(int) role])
212     {
213       return g_strdup (role_names [(int) role]);
214     }
215   else
216     {
217       return g_strdup ("");
218     }
219 }
220
221 /**
222  * atspi_accessible_get_name:
223  * @obj: a pointer to the #AtspiAccessible object on which to operate.
224  *
225  * Get the name of an #AtspiAccessible object.
226  *
227  * Returns: a UTF-8 string indicating the name of the #AtspiAccessible object.
228  * or NULL on exception
229  **/
230 gchar *
231 atspi_accessible_get_name (AtspiAccessible *obj, GError **error)
232 {
233   g_return_val_if_fail (obj != NULL, NULL);
234   if (!(obj->cached_properties & ATSPI_CACHE_NAME))
235   {
236     if (!_atspi_dbus_get_property (obj, atspi_interface_accessible, "Name", error,
237                                    "s", &obj->name))
238       return NULL;
239     obj->cached_properties |= ATSPI_CACHE_NAME;
240   }
241   return g_strdup (obj->name);
242 }
243
244 /**
245  * atspi_accessible_get_description:
246  * @obj: a pointer to the #AtspiAccessible object on which to operate.
247  *
248  * Get the description of an #AtspiAccessible object.
249  *
250  * Returns: a UTF-8 string describing the #AtspiAccessible object.
251  * or NULL on exception
252  **/
253 gchar *
254 atspi_accessible_get_description (AtspiAccessible *obj, GError **error)
255 {
256   g_return_val_if_fail (obj != NULL, NULL);
257
258   if (!(obj->cached_properties & ATSPI_CACHE_DESCRIPTION))
259   {
260     if (!_atspi_dbus_call (obj, atspi_interface_accessible, "GetDescription", NULL, "=>s", &obj->description))
261       return NULL;
262     obj->cached_properties |= ATSPI_CACHE_DESCRIPTION;
263   }
264   return g_strdup (obj->description);
265 }
266
267 const char *str_parent = "Parent";
268
269 /**
270  * atspi_accessible_get_parent:
271  * @obj: a pointer to the #AtspiAccessible object to query.
272  *
273  * Get an #AtspiAccessible object's parent container.
274  *
275  * Returns: (transfer full): a pointer to the #AtspiAccessible object which
276  *          contains the given #AtspiAccessible instance, or NULL if the @obj
277  *          has no parent container.
278  *
279  **/
280 AtspiAccessible *
281 atspi_accessible_get_parent (AtspiAccessible *obj, GError **error)
282 {
283   g_return_val_if_fail (obj != NULL, NULL);
284
285   if (!(obj->cached_properties & ATSPI_CACHE_PARENT))
286   {
287     DBusMessage *message, *reply;
288     DBusMessageIter iter, iter_variant;
289     message = dbus_message_new_method_call (obj->parent.app->bus_name,
290                                             obj->parent.path,
291                                             DBUS_INTERFACE_PROPERTIES, "Get");
292     if (!message)
293       return NULL;
294     dbus_message_append_args (message, DBUS_TYPE_STRING, &atspi_interface_accessible,
295                                DBUS_TYPE_STRING, &str_parent,
296                               DBUS_TYPE_INVALID);
297     reply = _atspi_dbus_send_with_reply_and_block (message);
298     if (!reply ||
299        (strcmp (dbus_message_get_signature (reply), "v") != 0))
300       return NULL;
301     dbus_message_iter_init (reply, &iter);
302     dbus_message_iter_recurse (&iter, &iter_variant);
303     obj->accessible_parent = _atspi_dbus_return_accessible_from_iter (&iter_variant);
304     dbus_message_unref (reply);
305     obj->cached_properties |= ATSPI_CACHE_PARENT;
306   }
307   if (!obj->accessible_parent)
308     return NULL;
309   return g_object_ref (obj->accessible_parent);
310 }
311
312 /**
313  * atspi_accessible_get_child_count:
314  * @obj: a pointer to the #AtspiAccessible object on which to operate.
315  *
316  * Get the number of children contained by an #AtspiAccessible object.
317  *
318  * Returns: a #long indicating the number of #AtspiAccessible children
319  *          contained by an #AtspiAccessible object. or -1 on exception
320  *
321  **/
322 gint
323 atspi_accessible_get_child_count (AtspiAccessible *obj, GError *error)
324 {
325   g_return_val_if_fail (obj != NULL, -1);
326
327   /* TODO: MANAGES_DESCENDANTS */
328   return g_list_length (obj->children);
329 }
330
331 /**
332  * atspi_accessible_get_child_at_index:
333  * @obj: a pointer to the #AtspiAccessible object on which to operate.
334  * @child_index: a #long indicating which child is specified.
335  *
336  * Get the #AtspiAccessible child of an #AtspiAccessible object at a given index.
337  *
338  * Returns: (transfer full): a pointer to the #AtspiAccessible child object at
339  * index @child_index. or NULL on exception
340  **/
341 AtspiAccessible *
342 atspi_accessible_get_child_at_index (AtspiAccessible *obj,
343                             gint    child_index,
344                             GError **error)
345 {
346   AtspiAccessible *child;
347
348   g_return_val_if_fail (obj != NULL, NULL);
349
350   /* TODO: ManagesDescendants */
351   child = g_list_nth_data (obj->children, child_index);
352   if (!child)
353     return NULL;
354   return g_object_ref (child);
355 }
356
357 /**
358  * atspi_accessible_get_index_in_parent
359  * @obj: a pointer to the #AtspiAccessible object on which to operate.
360  *
361  * Get the index of an #AtspiAccessible object in its containing #AtspiAccessible.
362  *
363  * Returns: a #glong indicating the index of the #AtspiAccessible object
364  *          in its parent (i.e. containing) #AtspiAccessible instance,
365  *          or -1 if @obj has no containing parent or on exception.
366  **/
367 gint
368 atspi_accessible_get_index_in_parent (AtspiAccessible *obj, GError **error)
369 {
370   GList *l;
371   gint i = 0;
372
373   g_return_val_if_fail (obj != NULL, -1);
374   if (!obj->accessible_parent) return -1;
375   l = obj->accessible_parent->children;
376   while (l)
377   {
378     if (l->data == obj) return i;
379     l = g_list_next (l);
380     i++;
381   }
382   return -1;
383 }
384
385 typedef struct
386 {
387   dbus_uint32_t type;
388   GArray *targets;
389 } Accessibility_Relation;
390
391 /**
392  * atspi_accessible_get_relation_set:
393  * @obj: a pointer to the #AtspiAccessible object on which to operate.
394  *
395  * Get the set of #AtspiRelation objects which describe this #AtspiAccessible object's
396  *       relationships with other #AtspiAccessible objects.
397  *
398  * Returns: (element-type AtspiAccessible*) (transfer full): an array of
399  *          #AtspiAccessibleRelation pointers. or NULL on exception
400  **/
401 GArray *
402 atspi_accessible_get_relation_set (AtspiAccessible *obj, GError **error)
403 {
404   DBusMessage *reply;
405   DBusMessageIter iter, iter_array;
406   GArray *ret;
407
408   g_return_val_if_fail (obj != NULL, NULL);
409
410   reply = _atspi_dbus_call_partial (obj, atspi_interface_accessible, "GetRelationSet", error, "");
411   _ATSPI_DBUS_CHECK_SIG (reply, "a(ua(so))", NULL);
412
413   ret = g_array_new (TRUE, TRUE, sizeof (AtspiRelation *));
414   dbus_message_iter_init (reply, &iter);
415   dbus_message_iter_recurse (&iter, &iter_array);
416   while (dbus_message_iter_get_arg_type (&iter_array) != DBUS_TYPE_INVALID)
417   {
418     GArray *new_array;
419     AtspiRelation *relation;
420     relation = _atspi_relation_new_from_iter (&iter_array);
421     new_array = g_array_append_val (ret, relation);
422     if (new_array)
423       ret = new_array;
424     dbus_message_iter_next (&iter_array);
425   }
426   return ret;
427 }
428
429 /**
430  * atspi_accessible_get_role:
431  * @obj: a pointer to the #AtspiAccessible object on which to operate.
432  *
433  * Get the UI role of an #AtspiAccessible object.
434  * A UTF-8 string describing this role can be obtained via atspi_accessible_getRoleName ().
435  *
436  * Returns: the #AtspiRole of the object.
437  *
438  **/
439 AtspiRole
440 atspi_accessible_get_role (AtspiAccessible *obj, GError **error)
441 {
442   g_return_val_if_fail (obj != NULL, ATSPI_ROLE_INVALID);
443
444   if (!(obj->cached_properties & ATSPI_CACHE_ROLE))
445   {
446     dbus_uint32_t role;
447     /* TODO: Make this a property */
448     if (_atspi_dbus_call (obj, atspi_interface_accessible, "GetRole", NULL, "=>u", &role))
449     {
450       obj->cached_properties |= ATSPI_CACHE_ROLE;
451       obj->role = role;
452     }
453   }
454   return obj->role;
455 }
456
457 /**
458  * atspi_accessible_get_role_name:
459  * @obj: a pointer to the #AtspiAccessible object on which to operate.
460  *
461  * Get a UTF-8 string describing the role this object plays in the UI.
462  * This method will return useful values for roles that fall outside the
463  * enumeration used in atspi_accessible_getRole ().
464  *
465  * Returns: a UTF-8 string specifying the role of this #AtspiAccessible object.
466  *
467  **/
468 gchar *
469 atspi_accessible_get_role_name (AtspiAccessible *obj, GError **error)
470 {
471   char *retval = NULL;
472
473   g_return_val_if_fail (obj != NULL, g_strdup ("invalid"));
474
475   _atspi_dbus_call (obj, atspi_interface_accessible, "GetRoleName", error, "=>s", &retval);
476
477   return retval;
478 }
479
480 /**
481  * atspi_accessible_get_localized_role_name:
482  * @obj: a pointer to the #AtspiAccessible object on which to operate.
483  *
484  * Get a UTF-8 string describing the (localized) role this object plays in the UI.
485  * This method will return useful values for roles that fall outside the
486  * enumeration used in atspi_accessible_getRole ().
487  *
488  * Returns: a UTF-8 string specifying the role of this #AtspiAccessible object.
489  *
490  **/
491 gchar *
492 atspi_accessible_get_localized_role_name (AtspiAccessible *obj, GError **error)
493 {
494   char *retval = NULL;
495
496   g_return_val_if_fail (obj != NULL, g_strdup ("invalid"));
497
498   _atspi_dbus_call (obj, atspi_interface_accessible, "GetLocalizedRoleName", error, "=>s", &retval);
499
500   return retval;
501 }
502
503 /**
504  * atspi_accessible_get_state_set:
505  * @obj: a pointer to the #AtspiAccessible object on which to operate.
506  *
507  * Gets the current state of an object.
508  *
509  * Returns: (transfer full): a pointer to an #AtspiStateSet representing the
510  *          object's current state.
511  **/
512 AtspiStateSet *
513 atspi_accessible_get_state_set (AtspiAccessible *obj)
514 {
515   if (!(obj->cached_properties & ATSPI_CACHE_STATES))
516   {
517     DBusMessage *reply;
518     DBusMessageIter iter;
519     reply = _atspi_dbus_call_partial (obj, atspi_interface_accessible,
520                                       "GetState", NULL, "");
521     _ATSPI_DBUS_CHECK_SIG (reply, "au", NULL);
522     dbus_message_iter_init (reply, &iter);
523     _atspi_dbus_set_state (obj, &iter);
524     dbus_message_unref (reply);
525   }
526
527   return g_object_ref (obj->states);
528 }
529
530 /**
531  * atspi_accessible_get_attributes:
532  * @obj: The #AtspiAccessible being queried.
533  *
534  * Get the #AttributeSet representing any assigned 
535  * name-value pair attributes or annotations for this object.
536  * For typographic, textual, or textually-semantic attributes, see
537  * atspi_text_get_attributes instead.
538  *
539  * Returns: (element-type gchar* gchar*) (transfer full): The name-value-pair
540  *          attributes assigned to this object.
541  */
542 GHashTable *
543 atspi_accessible_get_attributes (AtspiAccessible *obj, GError **error)
544 {
545   DBusMessage *message;
546   GHashTable *ret;
547
548     g_return_val_if_fail (obj != NULL, NULL);
549
550   message = _atspi_dbus_call_partial (obj, atspi_interface_accessible, "GetAttributes", error, "");
551   ret = _atspi_dbus_hash_from_message (message);
552   dbus_message_unref (message);
553   return ret;
554 }
555
556 /**
557  * atspi_accessible_get_attributes_as_array:
558  * @obj: The #AtspiAccessible being queried.
559  *
560  * Get the #AttributeSet representing any assigned 
561  * name-value pair attributes or annotations for this object.
562  * For typographic, textual, or textually-semantic attributes, see
563  * atspi_text_get_attributes_as_array instead.
564  *
565  * Returns: (element-type gchar*) (transfer full): The name-value-pair
566  *          attributes assigned to this object.
567  */
568 GArray *
569 atspi_accessible_get_attributes_as_array (AtspiAccessible *obj, GError **error)
570 {
571   DBusMessage *message;
572   GArray *ret;
573
574     g_return_val_if_fail (obj != NULL, NULL);
575
576   message = _atspi_dbus_call_partial (obj, atspi_interface_accessible, "GetAttributes", error, "");
577   ret = _atspi_dbus_attribute_array_from_message (message);
578   if (message)
579     dbus_message_unref (message);
580   return ret;
581 }
582
583 /**
584  * atspi_accessible_get_application:
585  * @obj: The #AtspiAccessible being queried.
586  *
587  * Get the containing #AtspiApplication for an object.
588  *
589  * Returns: (transfer full): the containing AtspiApplication instance for
590  *          this object.
591  */
592 AtspiAccessible *
593 atspi_accessible_get_application (AtspiAccessible *obj, GError **error)
594 {
595   AtspiAccessible *parent;
596
597   for (;;)
598   {
599     parent = atspi_accessible_get_parent (obj, NULL);
600     if (!parent || parent == obj ||
601         atspi_accessible_get_role (parent, NULL) == ATSPI_ROLE_DESKTOP_FRAME)
602     return g_object_ref (obj);
603     obj = parent;
604   }
605 }
606
607 /* Applicatio-specific methods */
608
609 /**
610  * atspi_accessible_get_toolkit_name:
611  * @obj: a pointer to the #AtspiAccessible object on which to operate.
612  *
613  * Get the toolkit for a #AtspiAccessible object.
614  * Only works on application root objects.
615  *
616  * Returns: a UTF-8 string indicating the toolkit name for the #AtspiAccessible object.
617  * or NULL on exception
618  **/
619 gchar *
620 atspi_accessible_get_toolkit_name (AtspiAccessible *obj, GError **error)
621 {
622   gchar *ret = NULL;
623
624   g_return_val_if_fail (obj != NULL, NULL);
625
626   if (!_atspi_dbus_get_property (obj, atspi_interface_application, "ToolkitName", error, "s", &ret))
627       return NULL;
628   return g_strdup (ret);
629 }
630
631 /**
632  * atspi_accessible_get_toolkit_version:
633  * @obj: a pointer to the #AtspiAccessible object on which to operate.
634  *
635  * Get the toolkit version for a #AtspiAccessible object.
636  * Only works on application root objects.
637  *
638  * Returns: a UTF-8 string indicating the toolkit ersion for the #AtspiAccessible object.
639  * or NULL on exception
640  **/
641 gchar *
642 atspi_accessible_get_toolkit_version (AtspiAccessible *obj, GError **error)
643 {
644   gchar *ret = NULL;
645
646   g_return_val_if_fail (obj != NULL, NULL);
647
648   if (!_atspi_dbus_get_property (obj, atspi_interface_application, "ToolkitVersion", error, "s", &ret))
649       return NULL;
650   return g_strdup (ret);
651 }
652 /* Interface query methods */
653
654 /**
655  * atspi_accessible_is_action:
656  * @obj: a pointer to the #AtspiAccessible instance to query.
657  *
658  * Query whether the specified #AtspiAccessible implements #AtspiAction.
659  *
660  * Returns: #TRUE if @obj implements the #AtspiAction interface,
661  *          #FALSE otherwise.
662  **/
663 gboolean
664 atspi_accessible_is_action (AtspiAccessible *obj)
665 {
666   return _atspi_accessible_is_a (obj,
667                               atspi_interface_action);
668 }
669
670 /**
671  * atspi_accessible_is_application:
672  * @obj: a pointer to the #AtspiAccessible instance to query.
673  *
674  * Query whether the specified #AtspiAccessible implements #AtspiApplication.
675  *
676  * Returns: #TRUE if @obj implements the #AtspiApplication interface,
677  *          #FALSE otherwise.
678  **/
679 gboolean
680 atspi_accessible_is_application (AtspiAccessible *obj)
681 {
682   return _atspi_accessible_is_a (obj,
683                               atspi_interface_application);
684 }
685
686 /**                      
687  * atspi_accessible_is_collection:                                                                                                                                                                          * @obj: a pointer to the #AtspiAccessible instance to query.                                                                                                                                          
688  *                          
689  * Query whether the specified #AtspiAccessible implements #AtspiCollection.    
690  * Returns: #TRUE if @obj implements the #AtspiCollection interface,                                                                                                               
691  *          #FALSE otherwise.
692  **/
693 gboolean
694 atspi_accessible_is_collection (AtspiAccessible *obj)
695 {
696 #if 0
697      g_warning ("Collections not implemented");
698      return _atspi_accessible_is_a (obj,
699                               atspi_interface_collection);
700 #else
701      return FALSE;
702 #endif
703 }
704
705 /**
706  * atspi_accessible_is_component:
707  * @obj: a pointer to the #AtspiAccessible instance to query.
708  *
709  * Query whether the specified #AtspiAccessible implements #AtspiComponent.
710  *
711  * Returns: #TRUE if @obj implements the #AtspiComponent interface,
712  *          #FALSE otherwise.
713  **/
714 gboolean
715 atspi_accessible_is_component (AtspiAccessible *obj)
716 {
717   return _atspi_accessible_is_a (obj,
718                               atspi_interface_component);
719 }
720
721 /**
722  * atspi_accessible_is_document:
723  * @obj: a pointer to the #AtspiAccessible instance to query.
724  *
725  * Query whether the specified #AtspiAccessible implements #AtspiDocument.
726  *
727  * Returns: #TRUE if @obj implements the #AtspiDocument interface,
728  *          #FALSE otherwise.
729  **/
730 gboolean
731 atspi_accessible_is_document (AtspiAccessible *obj)
732 {
733   return _atspi_accessible_is_a (obj,
734                               atspi_interface_document);
735 }
736
737 /**
738  * atspi_accessible_is_editable_text:
739  * @obj: a pointer to the #AtspiAccessible instance to query.
740  *
741  * Query whether the specified #AtspiAccessible implements #AtspiEditableText.
742  *
743  * Returns: #TRUE if @obj implements the #AtspiEditableText interface,
744  *          #FALSE otherwise.
745  **/
746 gboolean
747 atspi_accessible_is_editable_text (AtspiAccessible *obj)
748 {
749   return _atspi_accessible_is_a (obj,
750                               atspi_interface_editable_text);
751 }
752                                                                                                                                                                         
753 /**
754  * atspi_accessible_is_hypertext:
755  * @obj: a pointer to the #AtspiAccessible instance to query.
756  *
757  * Query whether the specified #AtspiAccessible implements #AtspiHypertext.
758  *
759  * Returns: #TRUE if @obj implements the #AtspiHypertext interface,
760  *          #FALSE otherwise.
761  **/
762 gboolean
763 atspi_accessible_is_hypertext (AtspiAccessible *obj)
764 {
765   return _atspi_accessible_is_a (obj,
766                               atspi_interface_hypertext);
767 }
768
769 /**
770  * atspi_accessible_is_image:
771  * @obj: a pointer to the #AtspiAccessible instance to query.
772  *
773  * Query whether the specified #AtspiAccessible implements #AtspiImage.
774  *
775  * Returns: #TRUE if @obj implements the #AtspiImage interface,
776  *          #FALSE otherwise.
777 **/
778 gboolean
779 atspi_accessible_is_image (AtspiAccessible *obj)
780 {
781   return _atspi_accessible_is_a (obj,
782                               atspi_interface_image);
783 }
784
785 /**
786  * atspi_accessible_is_selection:
787  * @obj: a pointer to the #AtspiAccessible instance to query.
788  *
789  * Query whether the specified #AtspiAccessible implements #AtspiSelection.
790  *
791  * Returns: #TRUE if @obj implements the #AtspiSelection interface,
792  *          #FALSE otherwise.
793 **/
794 gboolean
795 atspi_accessible_is_selection (AtspiAccessible *obj)
796 {
797   return _atspi_accessible_is_a (obj,
798                               atspi_interface_selection);
799 }
800
801 /**
802  * atspi_accessible_is_table:
803  * @obj: a pointer to the #AtspiAccessible instance to query.
804  *
805  * Query whether the specified #AtspiAccessible implements #AtspiTable.
806  *
807  * Returns: #TRUE if @obj implements the #AtspiTable interface,
808  *          #FALSE otherwise.
809 **/
810 gboolean
811 atspi_accessible_is_table (AtspiAccessible *obj)
812 {
813   return _atspi_accessible_is_a (obj,
814                               atspi_interface_table);
815 }
816
817 /**
818  * atspi_accessible_is_streamable_content:
819  * @obj: a pointer to the #AtspiAccessible instance to query.
820  *
821  * Query whether the specified #AtspiAccessible implements
822  *          #AtspiStreamableContent.
823  *
824  * Returns: #TRUE if @obj implements the #AtspiStreamableContent interface,
825  *          #FALSE otherwise.
826 **/
827 gboolean
828 atspi_accessible_is_streamable_content (AtspiAccessible *obj)
829 {
830 #if 0
831   return _atspi_accessible_is_a (obj,
832                               atspi_interface_streamable_content);
833 #else
834   g_warning ("Streamable content not implemented");
835   return FALSE;
836 #endif
837 }
838
839 /**
840  * atspi_accessible_is_text:
841  * @obj: a pointer to the #AtspiAccessible instance to query.
842  *
843  * Query whether the specified #AtspiAccessible implements #AtspiText.
844  *
845  * Returns: #TRUE if @obj implements the #AtspiText interface,
846  *          #FALSE otherwise.
847 **/
848 gboolean
849 atspi_accessible_is_text (AtspiAccessible *obj)
850 {
851   return _atspi_accessible_is_a (obj,
852                               atspi_interface_text);
853 }
854
855 /**
856  * atspi_accessible_is_value:
857  * @obj: a pointer to the #AtspiAccessible instance to query.
858  *
859  * Query whether the specified #AtspiAccessible implements #AtspiValue.
860  *
861  * Returns: #TRUE if @obj implements the #AtspiValue interface,
862  *          #FALSE otherwise.
863 **/
864 gboolean
865 atspi_accessible_is_value (AtspiAccessible *obj)
866 {
867   return _atspi_accessible_is_a (obj,
868                               atspi_interface_value);
869 }
870
871 /**
872  * atspi_accessible_get_action:
873  * @obj: a pointer to the #AtspiAccessible instance to query.
874  *
875  * Get the #AtspiAction interface for an #AtspiAccessible.
876  *
877  * Returns: (transfer full): a pointer to an #AtspiAction interface
878  *          instance, or NULL if @obj does not implement #AtspiAction.
879  **/
880 AtspiAction *
881 atspi_accessible_get_action (AtspiAccessible *accessible)
882 {
883   return (_atspi_accessible_is_a (accessible, atspi_interface_action) ?
884           g_object_ref (ATSPI_ACTION (accessible)) : NULL);  
885 }
886
887 /**
888  * atspi_accessible_get_collection:
889  * @obj: a pointer to the #AtspiAccessible instance to query.
890  *
891  * Get the #AtspiCollection interface for an #AtspiAccessible.
892  *
893  * Returns: (transfer full): a pointer to an #AtspiCollection interface
894  *          instance, or NULL if @obj does not implement #AtspiCollection.
895  **/
896 AtspiCollection *
897 atspi_accessible_get_collection (AtspiAccessible *accessible)
898 {
899   return (_atspi_accessible_is_a (accessible, atspi_interface_collection) ?
900           g_object_ref (ATSPI_COLLECTION (accessible)) : NULL);  
901 }
902
903 /**
904  * atspi_accessible_get_component:
905  * @obj: a pointer to the #AtspiAccessible instance to query.
906  *
907  * Get the #AtspiComponent interface for an #AtspiAccessible.
908  *
909  * Returns: (transfer full): a pointer to an #AtspiComponent interface
910  *          instance, or NULL if @obj does not implement #AtspiComponent.
911  **/
912 AtspiComponent *
913 atspi_accessible_get_component (AtspiAccessible *obj)
914 {
915   return (_atspi_accessible_is_a (obj, atspi_interface_component) ?
916           g_object_ref (ATSPI_COMPONENT (obj)) : NULL);
917 }
918
919 /**
920  * atspi_accessible_get_document:
921  * @obj: a pointer to the #AtspiAccessible instance to query.
922  *
923  * Get the #AtspiDocument interface for an #AtspiAccessible.
924  *
925  * Returns: (transfer full): a pointer to an #AtspiDocument interface
926  *          instance, or NULL if @obj does not implement #AtspiDocument.
927  **/
928 AtspiDocument *
929 atspi_accessible_get_document (AtspiAccessible *accessible)
930 {
931   return (_atspi_accessible_is_a (accessible, atspi_interface_document) ?
932           g_object_ref (ATSPI_DOCUMENT (accessible)) : NULL);  
933 }
934
935 /**
936  * atspi_accessible_get_editable_text:
937  * @obj: a pointer to the #AtspiAccessible instance to query.
938  *
939  * Get the #AtspiEditableText interface for an #AtspiAccessible.
940  *
941  * Returns: (transfer full): a pointer to an #AtspiEditableText interface
942  *          instance, or NULL if @obj does not implement #AtspiEditableText.
943  **/
944 AtspiEditableText *
945 atspi_accessible_get_editable_text (AtspiAccessible *accessible)
946 {
947   return (_atspi_accessible_is_a (accessible, atspi_interface_editable_text) ?
948           g_object_ref (ATSPI_EDITABLE_TEXT (accessible)) : NULL);  
949 }
950
951 /**
952  * atspi_accessible_get_hypertext:
953  * @obj: a pointer to the #AtspiAccessible instance to query.
954  *
955  * Get the #AtspiHypertext interface for an #AtspiAccessible.
956  *
957  * Returns: (transfer full): a pointer to an #AtspiHypertext interface
958  *          instance, or NULL if @obj does not implement #AtspiHypertext.
959  **/
960 AtspiHypertext *
961 atspi_accessible_get_hypertext (AtspiAccessible *accessible)
962 {
963   return (_atspi_accessible_is_a (accessible, atspi_interface_hypertext) ?
964           g_object_ref (ATSPI_HYPERTEXT (accessible)) : NULL);  
965 }
966
967 /**
968  * atspi_accessible_get_image:
969  * @obj: a pointer to the #AtspiAccessible instance to query.
970  *
971  * Get the #AtspiImage interface for an #AtspiAccessible.
972  *
973  * Returns: (transfer full): a pointer to an #AtspiImage interface instance, or
974  *          NULL if @obj does not implement #AtspiImage.
975  **/
976 AtspiImage *
977 atspi_accessible_get_image (AtspiAccessible *accessible)
978 {
979   return (_atspi_accessible_is_a (accessible, atspi_interface_image) ?
980           g_object_ref (ATSPI_IMAGE (accessible)) : NULL);  
981 }
982
983 /**
984  * atspi_accessible_get_selection:
985  * @obj: a pointer to the #AtspiAccessible instance to query.
986  *
987  * Get the #AtspiSelection interface for an #AtspiAccessible.
988  *
989  * Returns: (transfer full): a pointer to an #AtspiSelection interface
990  *          instance, or NULL if @obj does not implement #AtspiSelection.
991  **/
992 AtspiSelection *
993 atspi_accessible_get_selection (AtspiAccessible *accessible)
994 {
995   return (_atspi_accessible_is_a (accessible, atspi_interface_selection) ?
996           g_object_ref (ATSPI_SELECTION (accessible)) : NULL);  
997 }
998
999 #if 0
1000 /**
1001  * atspi_accessible_get_streamable_content:
1002  * @obj: a pointer to the #AtspiAccessible instance to query.
1003  *
1004  * Get the #AtspiStreamableContent interface for an #AtspiAccessible.
1005  *
1006  * Returns: (transfer full): a pointer to an #AtspiStreamableContent interface
1007  *          instance, or NULL if @obj does not implement #AtspiStreamableContent.
1008  **/
1009 AtspiStreamableContent *
1010 atspi_accessible_get_streamable_content (AtspiAccessible *accessible)
1011 {
1012   return (_atspi_accessible_is_a (accessible, atspi_interface_streamable_content) ?
1013           accessible : NULL);  
1014 }
1015 #endif
1016
1017 /**
1018  * atspi_accessible_get_table:
1019  * @obj: a pointer to the #AtspiAccessible instance to query.
1020  *
1021  * Get the #AtspiTable interface for an #AtspiAccessible.
1022  *
1023  * Returns: (transfer full): a pointer to an #AtspiTable interface instance, or
1024  *          NULL if @obj does not implement #AtspiTable.
1025  **/
1026 AtspiTable *
1027 atspi_accessible_get_table (AtspiAccessible *obj)
1028 {
1029   return (_atspi_accessible_is_a (obj, atspi_interface_table) ?
1030           g_object_ref (ATSPI_TABLE (obj)) : NULL);  
1031 }
1032
1033 /**
1034  * atspi_accessible_get_text:
1035  * @obj: a pointer to the #AtspiAccessible instance to query.
1036  *
1037  * Get the #AtspiTable interface for an #AtspiAccessible.
1038  *
1039  * Returns: (transfer full): a pointer to an #AtspiText interface instance, or
1040  *          NULL if @obj does not implement #AtspiTable.
1041  **/
1042 AtspiText *
1043 atspi_accessible_get_text (AtspiAccessible *obj)
1044 {
1045   return (_atspi_accessible_is_a (obj, atspi_interface_text) ?
1046           g_object_ref (ATSPI_TEXT (obj)) : NULL);
1047 }
1048
1049 /**
1050  * atspi_accessible_get_value:
1051  * @obj: a pointer to the #AtspiAccessible instance to query.
1052  *
1053  * Get the #AtspiTable interface for an #AtspiAccessible.
1054  *
1055  * Returns: (transfer full): a pointer to an #AtspiValue interface instance, or
1056  *          NULL if @obj does not implement #AtspiValue.
1057  **/
1058 AtspiValue *
1059 atspi_accessible_get_value (AtspiAccessible *accessible)
1060 {
1061   return (_atspi_accessible_is_a (accessible, atspi_interface_value) ?
1062           g_object_ref (ATSPI_VALUE (accessible)) : NULL);  
1063 }
1064
1065 #if 0
1066 static gboolean
1067 cspi_init_relation_type_table (AccessibleRelationType *relation_type_table)
1068 {
1069   int i;
1070   for (i = 0; i < Accessibility_RELATION_LAST_DEFINED; ++i)
1071     {
1072       relation_type_table [i] = SPI_RELATION_NULL;
1073     }
1074   relation_type_table [Accessibility_RELATION_NULL] = SPI_RELATION_NULL;
1075   relation_type_table [Accessibility_RELATION_LABEL_FOR] = SPI_RELATION_LABEL_FOR;
1076   relation_type_table [Accessibility_RELATION_LABELLED_BY] = SPI_RELATION_LABELED_BY;
1077   relation_type_table [Accessibility_RELATION_CONTROLLER_FOR] = SPI_RELATION_CONTROLLER_FOR;
1078   relation_type_table [Accessibility_RELATION_CONTROLLED_BY] = SPI_RELATION_CONTROLLED_BY;
1079   relation_type_table [Accessibility_RELATION_MEMBER_OF] = SPI_RELATION_MEMBER_OF;
1080   relation_type_table [Accessibility_RELATION_TOOLTIP_FOR] = SPI_RELATION_NULL;
1081   relation_type_table [Accessibility_RELATION_NODE_CHILD_OF] = SPI_RELATION_NODE_CHILD_OF;
1082   relation_type_table [Accessibility_RELATION_EXTENDED] = SPI_RELATION_EXTENDED;
1083   relation_type_table [Accessibility_RELATION_FLOWS_TO] = SPI_RELATION_FLOWS_TO;
1084   relation_type_table [Accessibility_RELATION_FLOWS_FROM] = SPI_RELATION_FLOWS_FROM;
1085   relation_type_table [Accessibility_RELATION_SUBWINDOW_OF] = SPI_RELATION_SUBWINDOW_OF;
1086   relation_type_table [Accessibility_RELATION_EMBEDS] = SPI_RELATION_EMBEDS;
1087   relation_type_table [Accessibility_RELATION_EMBEDDED_BY] = SPI_RELATION_EMBEDDED_BY;
1088   relation_type_table [Accessibility_RELATION_POPUP_FOR] = SPI_RELATION_POPUP_FOR;
1089   relation_type_table [Accessibility_RELATION_PARENT_WINDOW_OF] = SPI_RELATION_PARENT_WINDOW_OF;
1090   relation_type_table [Accessibility_RELATION_DESCRIBED_BY] = SPI_RELATION_DESCRIBED_BY;
1091   relation_type_table [Accessibility_RELATION_DESCRIPTION_FOR] = SPI_RELATION_DESCRIPTION_FOR;
1092   return TRUE;
1093 }
1094
1095 static AccessibleRelationType
1096 cspi_relation_type_from_spi_relation_type (Accessibility_RelationType type)
1097 {
1098   /* array is sized according to IDL RelationType because IDL RelationTypes are the index */    
1099   static AccessibleRelationType cspi_relation_type_table [Accessibility_RELATION_LAST_DEFINED];
1100   static gboolean is_initialized = FALSE;
1101   AccessibleRelationType cspi_type;
1102   if (!is_initialized)
1103     {
1104       is_initialized = cspi_init_relation_type_table (cspi_relation_type_table);            
1105     }
1106   if (type >= 0 && type < Accessibility_RELATION_LAST_DEFINED)
1107     {
1108       cspi_type = cspi_relation_type_table [type];          
1109     }
1110   else
1111     {
1112       cspi_type = SPI_RELATION_NULL;
1113     }
1114   return cspi_type; 
1115 }
1116 /**
1117  * AccessibleRelation_getRelationType:
1118  * @obj: a pointer to the #AtspiAccessibleRelation object to query.
1119  *
1120  * Get the type of relationship represented by an #AtspiAccessibleRelation.
1121  *
1122  * Returns: an #AtspiAccessibleRelationType indicating the type of relation
1123  *         encapsulated in this #AtspiAccessibleRelation object.
1124  *
1125  **/
1126 AccessibleRelationType
1127 AccessibleRelation_getRelationType (AccessibleRelation *obj)
1128 {
1129   cspi_return_val_if_fail (obj, SPI_RELATION_NULL);
1130   return cspi_relation_type_from_spi_relation_type (obj->type);
1131 }
1132
1133 /**
1134  * AccessibleRelation_getNTargets:
1135  * @obj: a pointer to the #AtspiAccessibleRelation object to query.
1136  *
1137  * Get the number of objects which this relationship has as its
1138  *       target objects (the subject is the #AtspiAccessible from which this
1139  *       #AtspiAccessibleRelation originated).
1140  *
1141  * Returns: a short integer indicating how many target objects which the
1142  *       originating #AtspiAccessible object has the #AtspiAccessibleRelation
1143  *       relationship with.
1144  **/
1145 int
1146 AccessibleRelation_getNTargets (AccessibleRelation *obj)
1147 {
1148   cspi_return_val_if_fail (obj, -1);
1149   return obj->targets->len;
1150 }
1151
1152 /**
1153  * AccessibleRelation_getTarget:
1154  * @obj: a pointer to the #AtspiAccessibleRelation object to query.
1155  * @i: a (zero-index) integer indicating which (of possibly several) target is requested.
1156  *
1157  * Get the @i-th target of a specified #AtspiAccessibleRelation relationship.
1158  *
1159  * Returns: an #AtspiAccessible which is the @i-th object with which the
1160  *      originating #AtspiAccessible has relationship specified in the
1161  *      #AtspiAccessibleRelation object.
1162  *
1163  **/
1164 Accessible *
1165 AccessibleRelation_getTarget (AccessibleRelation *obj, int i)
1166 {
1167   cspi_return_val_if_fail (obj, NULL);
1168
1169   if (i < 0 || i >= obj->targets->len) return NULL;
1170   return cspi_object_add (
1171                          g_array_index (obj->targets, Accessible *, i));
1172 }
1173
1174 /**
1175  * AccessibleStateSet_ref:
1176  * @obj: a pointer to the #AtspiAccessibleStateSet object on which to operate.
1177  *
1178  * Increment the reference count for an #AtspiAccessibleStateSet object.
1179  *
1180  **/
1181 void
1182 AccessibleStateSet_ref (AccessibleStateSet *obj)
1183 {
1184   spi_state_set_cache_ref (obj);
1185 }
1186
1187 /**
1188  * AccessibleStateSet_unref:
1189  * @obj: a pointer to the #AtspiAccessibleStateSet object on which to operate.
1190  *
1191  * Decrement the reference count for an #AtspiAccessibleStateSet object.
1192  *
1193  **/
1194 void
1195 AccessibleStateSet_unref (AccessibleStateSet *obj)
1196 {
1197   spi_state_set_cache_unref (obj);
1198 }
1199
1200 static Accessibility_StateType
1201 spi_state_to_dbus (AccessibleState state)
1202 {
1203 #define MAP_STATE(a) \
1204   case SPI_STATE_##a: \
1205     return Accessibility_STATE_##a
1206
1207   switch (state)
1208     {
1209       MAP_STATE (INVALID);
1210       MAP_STATE (ACTIVE);
1211       MAP_STATE (ARMED);
1212       MAP_STATE (BUSY);
1213       MAP_STATE (CHECKED);
1214       MAP_STATE (DEFUNCT);
1215       MAP_STATE (EDITABLE);
1216       MAP_STATE (ENABLED);
1217       MAP_STATE (EXPANDABLE);
1218       MAP_STATE (EXPANDED);
1219       MAP_STATE (FOCUSABLE);
1220       MAP_STATE (FOCUSED);
1221       MAP_STATE (HORIZONTAL);
1222       MAP_STATE (ICONIFIED);
1223       MAP_STATE (MODAL);
1224       MAP_STATE (MULTI_LINE);
1225       MAP_STATE (MULTISELECTABLE);
1226       MAP_STATE (OPAQUE);
1227       MAP_STATE (PRESSED);
1228       MAP_STATE (RESIZABLE);
1229       MAP_STATE (SELECTABLE);
1230       MAP_STATE (SELECTED);
1231       MAP_STATE (SENSITIVE);
1232       MAP_STATE (SHOWING);
1233       MAP_STATE (SINGLE_LINE);
1234       MAP_STATE (STALE);
1235       MAP_STATE (TRANSIENT);
1236       MAP_STATE (VERTICAL);
1237       MAP_STATE (VISIBLE);
1238       MAP_STATE (MANAGES_DESCENDANTS);
1239       MAP_STATE (INDETERMINATE);
1240       MAP_STATE (TRUNCATED);
1241       MAP_STATE (REQUIRED);
1242       MAP_STATE (INVALID_ENTRY);
1243       MAP_STATE (SUPPORTS_AUTOCOMPLETION);
1244       MAP_STATE (SELECTABLE_TEXT);
1245       MAP_STATE (IS_DEFAULT);
1246       MAP_STATE (VISITED);
1247     default:
1248       return Accessibility_STATE_INVALID;
1249   }
1250 #undef MAP_STATE
1251 }             
1252
1253 /**
1254  * AccessibleStateSet_contains:
1255  * @obj: a pointer to the #AtspiAccessibleStateSet object on which to operate.
1256  * @state: an #AtspiAccessibleState for which the specified #AtspiAccessibleStateSet
1257  *       will be queried.
1258  *
1259  * Determine whether a given #AtspiAccessibleStateSet includes a given state; that is,
1260  *       whether @state is true for the stateset in question.
1261  *
1262  * Returns: #TRUE if @state is true/included in the given #AtspiAccessibleStateSet,
1263  *          otherwise #FALSE.
1264  *
1265  **/
1266 gboolean
1267 AccessibleStateSet_contains (AccessibleStateSet *obj,
1268                              AccessibleState state)
1269 {
1270   return spi_state_set_cache_contains (obj, spi_state_to_dbus (state));
1271 }
1272
1273 /**
1274  * AccessibleStateSet_add:
1275  * @obj: a pointer to the #AtspiAccessibleStateSet object on which to operate.
1276  * @state: an #AtspiAccessibleState to be added to the specified #AtspiAccessibleStateSet
1277  *
1278  * Add a particular #AtspiAccessibleState to an #AtspiAccessibleStateSet (i.e. set the
1279  *       given state to #TRUE in the stateset.
1280  *
1281  **/
1282 void
1283 AccessibleStateSet_add (AccessibleStateSet *obj,
1284                         AccessibleState state)
1285 {
1286   spi_state_set_cache_add (obj, spi_state_to_dbus (state));
1287 }
1288
1289 /**
1290  * AccessibleStateSet_remove:
1291  * @obj: a pointer to the #AtspiAccessibleStateSet object on which to operate.
1292  * @state: an #AtspiAccessibleState to be removed from the specified #AtspiAccessibleStateSet
1293  *
1294  * Remove a particular #AtspiAccessibleState to an #AtspiAccessibleStateSet (i.e. set the
1295  *       given state to #FALSE in the stateset.)
1296  *
1297  **/
1298 void
1299 AccessibleStateSet_remove (AccessibleStateSet *obj,
1300                            AccessibleState state)
1301 {
1302   spi_state_set_cache_remove (obj, spi_state_to_dbus (state));
1303 }
1304
1305 /**
1306  * AccessibleStateSet_equals:
1307  * @obj: a pointer to the first #AtspiAccessibleStateSet object on which to operate.
1308  * @obj2: a pointer to the second #AtspiAccessibleStateSet object on which to operate.
1309  *
1310  * Determine whether two instances of #AtspiAccessibleStateSet are equivalent (i.e.
1311  *         consist of the same #AtspiAccessibleStates).  Useful for checking multiple
1312  *         state variables at once; construct the target state then compare against it.
1313  *
1314  * @see AccessibleStateSet_compare().
1315  *
1316  * Returns: #TRUE if the two #AtspiAccessibleStateSets are equivalent,
1317  *          otherwise #FALSE.
1318  *
1319  **/
1320 gboolean
1321 AccessibleStateSet_equals (AccessibleStateSet *obj,
1322                            AccessibleStateSet *obj2)
1323 {
1324   gboolean   eq;
1325   AtkStateSet *cmp;
1326
1327   if (obj == obj2)
1328     {
1329       return TRUE;
1330     }
1331
1332   cmp = spi_state_set_cache_xor (obj, obj2);
1333   eq = spi_state_set_cache_is_empty (cmp);
1334   spi_state_set_cache_unref (cmp);
1335
1336   return eq;
1337 }
1338
1339 /**
1340  * AccessibleStateSet_compare:
1341  * @obj: a pointer to the first #AtspiAccessibleStateSet object on which to operate.
1342  * @obj2: a pointer to the second #AtspiAccessibleStateSet object on which to operate.
1343  *
1344  * Determine the differences between two instances of #AtspiAccessibleStateSet.
1345  * Not Yet Implemented.
1346  *.
1347  * @see AccessibleStateSet_equals().
1348  *
1349  * Returns: an #AtspiAccessibleStateSet object containing all states contained on one of
1350  *          the two sets but not the other.
1351  *
1352  **/
1353 AccessibleStateSet *
1354 AccessibleStateSet_compare (AccessibleStateSet *obj,
1355                             AccessibleStateSet *obj2)
1356 {
1357   return spi_state_set_cache_xor (obj, obj2);
1358 }
1359
1360 /**
1361  * AccessibleStateSet_isEmpty:
1362  * @obj: a pointer to the #AtspiAccessibleStateSet object on which to operate.
1363  *
1364  * Determine whether a given #AtspiAccessibleStateSet is the empty set.
1365  *
1366  * Returns: #TRUE if the given #AtspiAccessibleStateSet contains no (true) states,
1367  *          otherwise #FALSE.
1368  *
1369  **/
1370 gboolean
1371 AccessibleStateSet_isEmpty (AccessibleStateSet *obj)
1372 {
1373   return spi_state_set_cache_is_empty (obj);
1374 }
1375 #endif
1376
1377 gboolean
1378 _atspi_accessible_is_a (AtspiAccessible *accessible,
1379                       const char *interface_name)
1380 {
1381   int n;
1382
1383   if (accessible == NULL)
1384     {
1385       return FALSE;
1386     }
1387
1388   if (!(accessible->cached_properties & ATSPI_CACHE_INTERFACES))
1389   {
1390     DBusMessage *reply;
1391     DBusMessageIter iter;
1392     reply = _atspi_dbus_call_partial (accessible, atspi_interface_accessible,
1393                                       "GetInterfaces", NULL, "");
1394     _ATSPI_DBUS_CHECK_SIG (reply, "as", FALSE);
1395     dbus_message_iter_init (reply, &iter);
1396     _atspi_dbus_set_interfaces (accessible, &iter);
1397     dbus_message_unref (reply);
1398   }
1399
1400   n = _atspi_get_iface_num (interface_name);
1401   if (n == -1) return FALSE;
1402   return (gboolean) ((accessible->interfaces & (1 << n))? TRUE: FALSE);
1403 }
1404
1405 static void
1406 append_const_val (GArray *array, const gchar *val)
1407 {
1408   gchar *dup = g_strdup (val);
1409
1410   if (dup)
1411     g_array_append_val (array, dup);
1412 }
1413
1414 /**
1415  * atspi_accessible_get_interfaces:
1416  *
1417  * #obj: The #AtspiAccessible to query.
1418  *
1419  * Returns: (element-type gchar*) (transfer full): A #GArray of strings
1420  *          describing the interfaces supported by the object.  Interfaces are
1421  *          denoted in short-hand (ie, "Component", "Text", etc.)
1422  **/
1423 GArray *
1424 atspi_accessible_get_interfaces (AtspiAccessible *obj)
1425 {
1426   GArray *ret = g_array_new (TRUE, TRUE, sizeof (gchar *));
1427
1428   if (!ret)
1429     return NULL;
1430
1431   g_return_val_if_fail (obj != NULL, NULL);
1432
1433   if (atspi_accessible_is_action (obj))
1434     append_const_val (ret, "Action");
1435   if (atspi_accessible_is_collection (obj))
1436     append_const_val (ret, "Collection");
1437   if (atspi_accessible_is_component (obj))
1438     append_const_val (ret, "Component");
1439   if (atspi_accessible_is_document (obj))
1440     append_const_val (ret, "Document");
1441   if (atspi_accessible_is_editable_text (obj))
1442     append_const_val (ret, "EditableText");
1443   if (atspi_accessible_is_hypertext (obj))
1444     append_const_val (ret, "Hypertext");
1445   if (atspi_accessible_is_image (obj))
1446     append_const_val (ret, "Image");
1447   if (atspi_accessible_is_selection (obj))
1448     append_const_val (ret, "Selection");
1449   if (atspi_accessible_is_table (obj))
1450     append_const_val (ret, "Table");
1451   if (atspi_accessible_is_text (obj))
1452     append_const_val (ret, "Text");
1453   if (atspi_accessible_is_value (obj))
1454     append_const_val (ret, "Value");
1455
1456   return ret;
1457 }
1458
1459 /* TODO: Move to a finalizer */
1460 static void
1461 cspi_object_destroyed (AtspiAccessible *accessible)
1462 {
1463   gboolean cached;
1464   AtspiEvent e;
1465
1466   /* TODO: Only fire if object not already marked defunct */
1467   memset (&e, 0, sizeof (e));
1468   e.type = "object:state-change:defunct";
1469   e.source = accessible;
1470   e.detail1 = 1;
1471   e.detail2 = 0;
1472   _atspi_send_event (&e);
1473
1474     g_free (accessible->parent.path);
1475
1476     if (accessible->states)
1477       g_object_unref (accessible->states);
1478     g_free (accessible->description);
1479     g_free (accessible->name);
1480 }
1481
1482 AtspiAccessible *
1483 atspi_accessible_new (AtspiApplication *app, const gchar *path)
1484 {
1485   AtspiAccessible *accessible;
1486   
1487   accessible = g_object_new (ATSPI_TYPE_ACCESSIBLE, NULL);
1488   g_return_val_if_fail (accessible != NULL, NULL);
1489
1490   accessible->parent.app = g_object_ref (app);
1491   accessible->parent.path = g_strdup (path);
1492
1493   return accessible;
1494 }