Various fixes
[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;
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   return g_object_ref (obj->states);
516 }
517
518 /**
519  * atspi_accessible_get_attributes:
520  * @obj: The #AtspiAccessible being queried.
521  *
522  * Get the #AttributeSet representing any assigned 
523  * name-value pair attributes or annotations for this object.
524  * For typographic, textual, or textually-semantic attributes, see
525  * atspi_text_get_attributes instead.
526  *
527  * Returns: (element-type gchar* gchar*) (transfer full): The name-value-pair
528  *          attributes assigned to this object.
529  */
530 GHashTable *
531 atspi_accessible_get_attributes (AtspiAccessible *obj, GError **error)
532 {
533   DBusMessage *message;
534   GHashTable *ret;
535
536     g_return_val_if_fail (obj != NULL, NULL);
537
538   message = _atspi_dbus_call_partial (obj, atspi_interface_accessible, "GetAttributes", error, "");
539   ret = _atspi_dbus_hash_from_message (message);
540   dbus_message_unref (message);
541   return ret;
542 }
543
544 /**
545  * atspi_accessible_get_attributes_as_array:
546  * @obj: The #AtspiAccessible being queried.
547  *
548  * Get the #AttributeSet representing any assigned 
549  * name-value pair attributes or annotations for this object.
550  * For typographic, textual, or textually-semantic attributes, see
551  * atspi_text_get_attributes_as_array instead.
552  *
553  * Returns: (element-type gchar*) (transfer full): The name-value-pair
554  *          attributes assigned to this object.
555  */
556 GArray *
557 atspi_accessible_get_attributes_as_array (AtspiAccessible *obj, GError **error)
558 {
559   DBusMessage *message;
560   GArray *ret;
561
562     g_return_val_if_fail (obj != NULL, NULL);
563
564   message = _atspi_dbus_call_partial (obj, atspi_interface_accessible, "GetAttributes", error, "");
565   ret = _atspi_dbus_attribute_array_from_message (message);
566   if (message)
567     dbus_message_unref (message);
568   return ret;
569 }
570
571 /**
572  * atspi_accessible_get_application:
573  * @obj: The #AtspiAccessible being queried.
574  *
575  * Get the containing #AtspiApplication for an object.
576  *
577  * Returns: (transfer full): the containing AtspiApplication instance for
578  *          this object.
579  */
580 AtspiAccessible *
581 atspi_accessible_get_application (AtspiAccessible *obj, GError **error)
582 {
583   AtspiAccessible *parent;
584
585   for (;;)
586   {
587     parent = atspi_accessible_get_parent (obj, NULL);
588     if (!parent || parent == obj ||
589         atspi_accessible_get_role (parent, NULL) == ATSPI_ROLE_DESKTOP_FRAME)
590     return g_object_ref (obj);
591     obj = parent;
592   }
593 }
594
595 /* Applicatio-specific methods */
596
597 /**
598  * atspi_accessible_get_toolkit_name:
599  * @obj: a pointer to the #AtspiAccessible object on which to operate.
600  *
601  * Get the toolkit for a #AtspiAccessible object.
602  * Only works on application root objects.
603  *
604  * Returns: a UTF-8 string indicating the toolkit name for the #AtspiAccessible object.
605  * or NULL on exception
606  **/
607 gchar *
608 atspi_accessible_get_toolkit_name (AtspiAccessible *obj, GError **error)
609 {
610   gchar *ret = NULL;
611
612   g_return_val_if_fail (obj != NULL, NULL);
613
614   if (!_atspi_dbus_get_property (obj, atspi_interface_application, "ToolkitName", error, "s", &ret))
615       return NULL;
616   return g_strdup (ret);
617 }
618
619 /**
620  * atspi_accessible_get_toolkit_version:
621  * @obj: a pointer to the #AtspiAccessible object on which to operate.
622  *
623  * Get the toolkit version for a #AtspiAccessible object.
624  * Only works on application root objects.
625  *
626  * Returns: a UTF-8 string indicating the toolkit ersion for the #AtspiAccessible object.
627  * or NULL on exception
628  **/
629 gchar *
630 atspi_accessible_get_toolkit_version (AtspiAccessible *obj, GError **error)
631 {
632   gchar *ret = NULL;
633
634   g_return_val_if_fail (obj != NULL, NULL);
635
636   if (!_atspi_dbus_get_property (obj, atspi_interface_application, "ToolkitVersion", error, "s", &ret))
637       return NULL;
638   return g_strdup (ret);
639 }
640 /* Interface query methods */
641
642 /**
643  * atspi_accessible_is_action:
644  * @obj: a pointer to the #AtspiAccessible instance to query.
645  *
646  * Query whether the specified #AtspiAccessible implements #AtspiAction.
647  *
648  * Returns: #TRUE if @obj implements the #AtspiAction interface,
649  *          #FALSE otherwise.
650  **/
651 gboolean
652 atspi_accessible_is_action (AtspiAccessible *obj)
653 {
654   return _atspi_accessible_is_a (obj,
655                               atspi_interface_action);
656 }
657
658 /**
659  * atspi_accessible_is_application:
660  * @obj: a pointer to the #AtspiAccessible instance to query.
661  *
662  * Query whether the specified #AtspiAccessible implements #AtspiApplication.
663  *
664  * Returns: #TRUE if @obj implements the #AtspiApplication interface,
665  *          #FALSE otherwise.
666  **/
667 gboolean
668 atspi_accessible_is_application (AtspiAccessible *obj)
669 {
670   return _atspi_accessible_is_a (obj,
671                               atspi_interface_application);
672 }
673
674 /**                      
675  * atspi_accessible_is_collection:                                                                                                                                                                          * @obj: a pointer to the #AtspiAccessible instance to query.                                                                                                                                          
676  *                          
677  * Query whether the specified #AtspiAccessible implements #AtspiCollection.    
678  * Returns: #TRUE if @obj implements the #AtspiCollection interface,                                                                                                               
679  *          #FALSE otherwise.
680  **/
681 gboolean
682 atspi_accessible_is_collection (AtspiAccessible *obj)
683 {
684 #if 0
685      g_warning ("Collections not implemented");
686      return _atspi_accessible_is_a (obj,
687                               atspi_interface_collection);
688 #else
689      return FALSE;
690 #endif
691 }
692
693 /**
694  * atspi_accessible_is_component:
695  * @obj: a pointer to the #AtspiAccessible instance to query.
696  *
697  * Query whether the specified #AtspiAccessible implements #AtspiComponent.
698  *
699  * Returns: #TRUE if @obj implements the #AtspiComponent interface,
700  *          #FALSE otherwise.
701  **/
702 gboolean
703 atspi_accessible_is_component (AtspiAccessible *obj)
704 {
705   return _atspi_accessible_is_a (obj,
706                               atspi_interface_component);
707 }
708
709 /**
710  * atspi_accessible_is_document:
711  * @obj: a pointer to the #AtspiAccessible instance to query.
712  *
713  * Query whether the specified #AtspiAccessible implements #AtspiDocument.
714  *
715  * Returns: #TRUE if @obj implements the #AtspiDocument interface,
716  *          #FALSE otherwise.
717  **/
718 gboolean
719 atspi_accessible_is_document (AtspiAccessible *obj)
720 {
721   return _atspi_accessible_is_a (obj,
722                               atspi_interface_document);
723 }
724
725 /**
726  * atspi_accessible_is_editable_text:
727  * @obj: a pointer to the #AtspiAccessible instance to query.
728  *
729  * Query whether the specified #AtspiAccessible implements #AtspiEditableText.
730  *
731  * Returns: #TRUE if @obj implements the #AtspiEditableText interface,
732  *          #FALSE otherwise.
733  **/
734 gboolean
735 atspi_accessible_is_editable_text (AtspiAccessible *obj)
736 {
737   return _atspi_accessible_is_a (obj,
738                               atspi_interface_editable_text);
739 }
740                                                                                                                                                                         
741 /**
742  * atspi_accessible_is_hypertext:
743  * @obj: a pointer to the #AtspiAccessible instance to query.
744  *
745  * Query whether the specified #AtspiAccessible implements #AtspiHypertext.
746  *
747  * Returns: #TRUE if @obj implements the #AtspiHypertext interface,
748  *          #FALSE otherwise.
749  **/
750 gboolean
751 atspi_accessible_is_hypertext (AtspiAccessible *obj)
752 {
753   return _atspi_accessible_is_a (obj,
754                               atspi_interface_hypertext);
755 }
756
757 /**
758  * atspi_accessible_is_image:
759  * @obj: a pointer to the #AtspiAccessible instance to query.
760  *
761  * Query whether the specified #AtspiAccessible implements #AtspiImage.
762  *
763  * Returns: #TRUE if @obj implements the #AtspiImage interface,
764  *          #FALSE otherwise.
765 **/
766 gboolean
767 atspi_accessible_is_image (AtspiAccessible *obj)
768 {
769   return _atspi_accessible_is_a (obj,
770                               atspi_interface_image);
771 }
772
773 /**
774  * atspi_accessible_is_selection:
775  * @obj: a pointer to the #AtspiAccessible instance to query.
776  *
777  * Query whether the specified #AtspiAccessible implements #AtspiSelection.
778  *
779  * Returns: #TRUE if @obj implements the #AtspiSelection interface,
780  *          #FALSE otherwise.
781 **/
782 gboolean
783 atspi_accessible_is_selection (AtspiAccessible *obj)
784 {
785   return _atspi_accessible_is_a (obj,
786                               atspi_interface_selection);
787 }
788
789 /**
790  * atspi_accessible_is_table:
791  * @obj: a pointer to the #AtspiAccessible instance to query.
792  *
793  * Query whether the specified #AtspiAccessible implements #AtspiTable.
794  *
795  * Returns: #TRUE if @obj implements the #AtspiTable interface,
796  *          #FALSE otherwise.
797 **/
798 gboolean
799 atspi_accessible_is_table (AtspiAccessible *obj)
800 {
801   return _atspi_accessible_is_a (obj,
802                               atspi_interface_table);
803 }
804
805 /**
806  * atspi_accessible_is_streamable_content:
807  * @obj: a pointer to the #AtspiAccessible instance to query.
808  *
809  * Query whether the specified #AtspiAccessible implements
810  *          #AtspiStreamableContent.
811  *
812  * Returns: #TRUE if @obj implements the #AtspiStreamableContent interface,
813  *          #FALSE otherwise.
814 **/
815 gboolean
816 atspi_accessible_is_streamable_content (AtspiAccessible *obj)
817 {
818 #if 0
819   return _atspi_accessible_is_a (obj,
820                               atspi_interface_streamable_content);
821 #else
822   g_warning ("Streamable content not implemented");
823   return FALSE;
824 #endif
825 }
826
827 /**
828  * atspi_accessible_is_text:
829  * @obj: a pointer to the #AtspiAccessible instance to query.
830  *
831  * Query whether the specified #AtspiAccessible implements #AtspiText.
832  *
833  * Returns: #TRUE if @obj implements the #AtspiText interface,
834  *          #FALSE otherwise.
835 **/
836 gboolean
837 atspi_accessible_is_text (AtspiAccessible *obj)
838 {
839   return _atspi_accessible_is_a (obj,
840                               atspi_interface_text);
841 }
842
843 /**
844  * atspi_accessible_is_value:
845  * @obj: a pointer to the #AtspiAccessible instance to query.
846  *
847  * Query whether the specified #AtspiAccessible implements #AtspiValue.
848  *
849  * Returns: #TRUE if @obj implements the #AtspiValue interface,
850  *          #FALSE otherwise.
851 **/
852 gboolean
853 atspi_accessible_is_value (AtspiAccessible *obj)
854 {
855   return _atspi_accessible_is_a (obj,
856                               atspi_interface_value);
857 }
858
859 /**
860  * atspi_accessible_get_action:
861  * @obj: a pointer to the #AtspiAccessible instance to query.
862  *
863  * Get the #AtspiAction interface for an #AtspiAccessible.
864  *
865  * Returns: (transfer full): a pointer to an #AtspiAction interface
866  *          instance, or NULL if @obj does not implement #AtspiAction.
867  **/
868 AtspiAction *
869 atspi_accessible_get_action (AtspiAccessible *accessible)
870 {
871   return (_atspi_accessible_is_a (accessible, atspi_interface_action) ?
872           g_object_ref (ATSPI_ACTION (accessible)) : NULL);  
873 }
874
875 /**
876  * atspi_accessible_get_collection:
877  * @obj: a pointer to the #AtspiAccessible instance to query.
878  *
879  * Get the #AtspiCollection interface for an #AtspiAccessible.
880  *
881  * Returns: (transfer full): a pointer to an #AtspiCollection interface
882  *          instance, or NULL if @obj does not implement #AtspiCollection.
883  **/
884 AtspiCollection *
885 atspi_accessible_get_collection (AtspiAccessible *accessible)
886 {
887   return (_atspi_accessible_is_a (accessible, atspi_interface_collection) ?
888           g_object_ref (ATSPI_COLLECTION (accessible)) : NULL);  
889 }
890
891 /**
892  * atspi_accessible_get_component:
893  * @obj: a pointer to the #AtspiAccessible instance to query.
894  *
895  * Get the #AtspiComponent interface for an #AtspiAccessible.
896  *
897  * Returns: (transfer full): a pointer to an #AtspiComponent interface
898  *          instance, or NULL if @obj does not implement #AtspiComponent.
899  **/
900 AtspiComponent *
901 atspi_accessible_get_component (AtspiAccessible *obj)
902 {
903   return (_atspi_accessible_is_a (obj, atspi_interface_component) ?
904           g_object_ref (ATSPI_COMPONENT (obj)) : NULL);
905 }
906
907 /**
908  * atspi_accessible_get_document:
909  * @obj: a pointer to the #AtspiAccessible instance to query.
910  *
911  * Get the #AtspiDocument interface for an #AtspiAccessible.
912  *
913  * Returns: (transfer full): a pointer to an #AtspiDocument interface
914  *          instance, or NULL if @obj does not implement #AtspiDocument.
915  **/
916 AtspiDocument *
917 atspi_accessible_get_document (AtspiAccessible *accessible)
918 {
919   return (_atspi_accessible_is_a (accessible, atspi_interface_document) ?
920           g_object_ref (ATSPI_DOCUMENT (accessible)) : NULL);  
921 }
922
923 /**
924  * atspi_accessible_get_editable_text:
925  * @obj: a pointer to the #AtspiAccessible instance to query.
926  *
927  * Get the #AtspiEditableText interface for an #AtspiAccessible.
928  *
929  * Returns: (transfer full): a pointer to an #AtspiEditableText interface
930  *          instance, or NULL if @obj does not implement #AtspiEditableText.
931  **/
932 AtspiEditableText *
933 atspi_accessible_get_editable_text (AtspiAccessible *accessible)
934 {
935   return (_atspi_accessible_is_a (accessible, atspi_interface_editable_text) ?
936           g_object_ref (ATSPI_EDITABLE_TEXT (accessible)) : NULL);  
937 }
938
939 /**
940  * atspi_accessible_get_hypertext:
941  * @obj: a pointer to the #AtspiAccessible instance to query.
942  *
943  * Get the #AtspiHypertext interface for an #AtspiAccessible.
944  *
945  * Returns: (transfer full): a pointer to an #AtspiHypertext interface
946  *          instance, or NULL if @obj does not implement #AtspiHypertext.
947  **/
948 AtspiHypertext *
949 atspi_accessible_get_hypertext (AtspiAccessible *accessible)
950 {
951   return (_atspi_accessible_is_a (accessible, atspi_interface_hypertext) ?
952           g_object_ref (ATSPI_HYPERTEXT (accessible)) : NULL);  
953 }
954
955 /**
956  * atspi_accessible_get_image:
957  * @obj: a pointer to the #AtspiAccessible instance to query.
958  *
959  * Get the #AtspiImage interface for an #AtspiAccessible.
960  *
961  * Returns: (transfer full): a pointer to an #AtspiImage interface instance, or
962  *          NULL if @obj does not implement #AtspiImage.
963  **/
964 AtspiImage *
965 atspi_accessible_get_image (AtspiAccessible *accessible)
966 {
967   return (_atspi_accessible_is_a (accessible, atspi_interface_image) ?
968           g_object_ref (ATSPI_IMAGE (accessible)) : NULL);  
969 }
970
971 /**
972  * atspi_accessible_get_selection:
973  * @obj: a pointer to the #AtspiAccessible instance to query.
974  *
975  * Get the #AtspiSelection interface for an #AtspiAccessible.
976  *
977  * Returns: (transfer full): a pointer to an #AtspiSelection interface
978  *          instance, or NULL if @obj does not implement #AtspiSelection.
979  **/
980 AtspiSelection *
981 atspi_accessible_get_selection (AtspiAccessible *accessible)
982 {
983   return (_atspi_accessible_is_a (accessible, atspi_interface_selection) ?
984           g_object_ref (ATSPI_SELECTION (accessible)) : NULL);  
985 }
986
987 #if 0
988 /**
989  * atspi_accessible_get_streamable_content:
990  * @obj: a pointer to the #AtspiAccessible instance to query.
991  *
992  * Get the #AtspiStreamableContent interface for an #AtspiAccessible.
993  *
994  * Returns: (transfer full): a pointer to an #AtspiStreamableContent interface
995  *          instance, or NULL if @obj does not implement #AtspiStreamableContent.
996  **/
997 AtspiStreamableContent *
998 atspi_accessible_get_streamable_content (AtspiAccessible *accessible)
999 {
1000   return (_atspi_accessible_is_a (accessible, atspi_interface_streamable_content) ?
1001           accessible : NULL);  
1002 }
1003 #endif
1004
1005 /**
1006  * atspi_accessible_get_table:
1007  * @obj: a pointer to the #AtspiAccessible instance to query.
1008  *
1009  * Get the #AtspiTable interface for an #AtspiAccessible.
1010  *
1011  * Returns: (transfer full): a pointer to an #AtspiTable interface instance, or
1012  *          NULL if @obj does not implement #AtspiTable.
1013  **/
1014 AtspiTable *
1015 atspi_accessible_get_table (AtspiAccessible *obj)
1016 {
1017   return (_atspi_accessible_is_a (obj, atspi_interface_table) ?
1018           g_object_ref (ATSPI_TABLE (obj)) : NULL);  
1019 }
1020
1021 /**
1022  * atspi_accessible_get_text:
1023  * @obj: a pointer to the #AtspiAccessible instance to query.
1024  *
1025  * Get the #AtspiTable interface for an #AtspiAccessible.
1026  *
1027  * Returns: (transfer full): a pointer to an #AtspiText interface instance, or
1028  *          NULL if @obj does not implement #AtspiTable.
1029  **/
1030 AtspiText *
1031 atspi_accessible_get_text (AtspiAccessible *obj)
1032 {
1033   return (_atspi_accessible_is_a (obj, atspi_interface_text) ?
1034           g_object_ref (ATSPI_TEXT (obj)) : NULL);
1035 }
1036
1037 /**
1038  * atspi_accessible_get_value:
1039  * @obj: a pointer to the #AtspiAccessible instance to query.
1040  *
1041  * Get the #AtspiTable interface for an #AtspiAccessible.
1042  *
1043  * Returns: (transfer full): a pointer to an #AtspiValue interface instance, or
1044  *          NULL if @obj does not implement #AtspiValue.
1045  **/
1046 AtspiValue *
1047 atspi_accessible_get_value (AtspiAccessible *accessible)
1048 {
1049   return (_atspi_accessible_is_a (accessible, atspi_interface_value) ?
1050           g_object_ref (ATSPI_VALUE (accessible)) : NULL);  
1051 }
1052
1053 #if 0
1054 static gboolean
1055 cspi_init_relation_type_table (AccessibleRelationType *relation_type_table)
1056 {
1057   int i;
1058   for (i = 0; i < Accessibility_RELATION_LAST_DEFINED; ++i)
1059     {
1060       relation_type_table [i] = SPI_RELATION_NULL;
1061     }
1062   relation_type_table [Accessibility_RELATION_NULL] = SPI_RELATION_NULL;
1063   relation_type_table [Accessibility_RELATION_LABEL_FOR] = SPI_RELATION_LABEL_FOR;
1064   relation_type_table [Accessibility_RELATION_LABELLED_BY] = SPI_RELATION_LABELED_BY;
1065   relation_type_table [Accessibility_RELATION_CONTROLLER_FOR] = SPI_RELATION_CONTROLLER_FOR;
1066   relation_type_table [Accessibility_RELATION_CONTROLLED_BY] = SPI_RELATION_CONTROLLED_BY;
1067   relation_type_table [Accessibility_RELATION_MEMBER_OF] = SPI_RELATION_MEMBER_OF;
1068   relation_type_table [Accessibility_RELATION_TOOLTIP_FOR] = SPI_RELATION_NULL;
1069   relation_type_table [Accessibility_RELATION_NODE_CHILD_OF] = SPI_RELATION_NODE_CHILD_OF;
1070   relation_type_table [Accessibility_RELATION_EXTENDED] = SPI_RELATION_EXTENDED;
1071   relation_type_table [Accessibility_RELATION_FLOWS_TO] = SPI_RELATION_FLOWS_TO;
1072   relation_type_table [Accessibility_RELATION_FLOWS_FROM] = SPI_RELATION_FLOWS_FROM;
1073   relation_type_table [Accessibility_RELATION_SUBWINDOW_OF] = SPI_RELATION_SUBWINDOW_OF;
1074   relation_type_table [Accessibility_RELATION_EMBEDS] = SPI_RELATION_EMBEDS;
1075   relation_type_table [Accessibility_RELATION_EMBEDDED_BY] = SPI_RELATION_EMBEDDED_BY;
1076   relation_type_table [Accessibility_RELATION_POPUP_FOR] = SPI_RELATION_POPUP_FOR;
1077   relation_type_table [Accessibility_RELATION_PARENT_WINDOW_OF] = SPI_RELATION_PARENT_WINDOW_OF;
1078   relation_type_table [Accessibility_RELATION_DESCRIBED_BY] = SPI_RELATION_DESCRIBED_BY;
1079   relation_type_table [Accessibility_RELATION_DESCRIPTION_FOR] = SPI_RELATION_DESCRIPTION_FOR;
1080   return TRUE;
1081 }
1082
1083 static AccessibleRelationType
1084 cspi_relation_type_from_spi_relation_type (Accessibility_RelationType type)
1085 {
1086   /* array is sized according to IDL RelationType because IDL RelationTypes are the index */    
1087   static AccessibleRelationType cspi_relation_type_table [Accessibility_RELATION_LAST_DEFINED];
1088   static gboolean is_initialized = FALSE;
1089   AccessibleRelationType cspi_type;
1090   if (!is_initialized)
1091     {
1092       is_initialized = cspi_init_relation_type_table (cspi_relation_type_table);            
1093     }
1094   if (type >= 0 && type < Accessibility_RELATION_LAST_DEFINED)
1095     {
1096       cspi_type = cspi_relation_type_table [type];          
1097     }
1098   else
1099     {
1100       cspi_type = SPI_RELATION_NULL;
1101     }
1102   return cspi_type; 
1103 }
1104 /**
1105  * AccessibleRelation_getRelationType:
1106  * @obj: a pointer to the #AtspiAccessibleRelation object to query.
1107  *
1108  * Get the type of relationship represented by an #AtspiAccessibleRelation.
1109  *
1110  * Returns: an #AtspiAccessibleRelationType indicating the type of relation
1111  *         encapsulated in this #AtspiAccessibleRelation object.
1112  *
1113  **/
1114 AccessibleRelationType
1115 AccessibleRelation_getRelationType (AccessibleRelation *obj)
1116 {
1117   cspi_return_val_if_fail (obj, SPI_RELATION_NULL);
1118   return cspi_relation_type_from_spi_relation_type (obj->type);
1119 }
1120
1121 /**
1122  * AccessibleRelation_getNTargets:
1123  * @obj: a pointer to the #AtspiAccessibleRelation object to query.
1124  *
1125  * Get the number of objects which this relationship has as its
1126  *       target objects (the subject is the #AtspiAccessible from which this
1127  *       #AtspiAccessibleRelation originated).
1128  *
1129  * Returns: a short integer indicating how many target objects which the
1130  *       originating #AtspiAccessible object has the #AtspiAccessibleRelation
1131  *       relationship with.
1132  **/
1133 int
1134 AccessibleRelation_getNTargets (AccessibleRelation *obj)
1135 {
1136   cspi_return_val_if_fail (obj, -1);
1137   return obj->targets->len;
1138 }
1139
1140 /**
1141  * AccessibleRelation_getTarget:
1142  * @obj: a pointer to the #AtspiAccessibleRelation object to query.
1143  * @i: a (zero-index) integer indicating which (of possibly several) target is requested.
1144  *
1145  * Get the @i-th target of a specified #AtspiAccessibleRelation relationship.
1146  *
1147  * Returns: an #AtspiAccessible which is the @i-th object with which the
1148  *      originating #AtspiAccessible has relationship specified in the
1149  *      #AtspiAccessibleRelation object.
1150  *
1151  **/
1152 Accessible *
1153 AccessibleRelation_getTarget (AccessibleRelation *obj, int i)
1154 {
1155   cspi_return_val_if_fail (obj, NULL);
1156
1157   if (i < 0 || i >= obj->targets->len) return NULL;
1158   return cspi_object_add (
1159                          g_array_index (obj->targets, Accessible *, i));
1160 }
1161
1162 /**
1163  * AccessibleStateSet_ref:
1164  * @obj: a pointer to the #AtspiAccessibleStateSet object on which to operate.
1165  *
1166  * Increment the reference count for an #AtspiAccessibleStateSet object.
1167  *
1168  **/
1169 void
1170 AccessibleStateSet_ref (AccessibleStateSet *obj)
1171 {
1172   spi_state_set_cache_ref (obj);
1173 }
1174
1175 /**
1176  * AccessibleStateSet_unref:
1177  * @obj: a pointer to the #AtspiAccessibleStateSet object on which to operate.
1178  *
1179  * Decrement the reference count for an #AtspiAccessibleStateSet object.
1180  *
1181  **/
1182 void
1183 AccessibleStateSet_unref (AccessibleStateSet *obj)
1184 {
1185   spi_state_set_cache_unref (obj);
1186 }
1187
1188 static Accessibility_StateType
1189 spi_state_to_dbus (AccessibleState state)
1190 {
1191 #define MAP_STATE(a) \
1192   case SPI_STATE_##a: \
1193     return Accessibility_STATE_##a
1194
1195   switch (state)
1196     {
1197       MAP_STATE (INVALID);
1198       MAP_STATE (ACTIVE);
1199       MAP_STATE (ARMED);
1200       MAP_STATE (BUSY);
1201       MAP_STATE (CHECKED);
1202       MAP_STATE (DEFUNCT);
1203       MAP_STATE (EDITABLE);
1204       MAP_STATE (ENABLED);
1205       MAP_STATE (EXPANDABLE);
1206       MAP_STATE (EXPANDED);
1207       MAP_STATE (FOCUSABLE);
1208       MAP_STATE (FOCUSED);
1209       MAP_STATE (HORIZONTAL);
1210       MAP_STATE (ICONIFIED);
1211       MAP_STATE (MODAL);
1212       MAP_STATE (MULTI_LINE);
1213       MAP_STATE (MULTISELECTABLE);
1214       MAP_STATE (OPAQUE);
1215       MAP_STATE (PRESSED);
1216       MAP_STATE (RESIZABLE);
1217       MAP_STATE (SELECTABLE);
1218       MAP_STATE (SELECTED);
1219       MAP_STATE (SENSITIVE);
1220       MAP_STATE (SHOWING);
1221       MAP_STATE (SINGLE_LINE);
1222       MAP_STATE (STALE);
1223       MAP_STATE (TRANSIENT);
1224       MAP_STATE (VERTICAL);
1225       MAP_STATE (VISIBLE);
1226       MAP_STATE (MANAGES_DESCENDANTS);
1227       MAP_STATE (INDETERMINATE);
1228       MAP_STATE (TRUNCATED);
1229       MAP_STATE (REQUIRED);
1230       MAP_STATE (INVALID_ENTRY);
1231       MAP_STATE (SUPPORTS_AUTOCOMPLETION);
1232       MAP_STATE (SELECTABLE_TEXT);
1233       MAP_STATE (IS_DEFAULT);
1234       MAP_STATE (VISITED);
1235     default:
1236       return Accessibility_STATE_INVALID;
1237   }
1238 #undef MAP_STATE
1239 }             
1240
1241 /**
1242  * AccessibleStateSet_contains:
1243  * @obj: a pointer to the #AtspiAccessibleStateSet object on which to operate.
1244  * @state: an #AtspiAccessibleState for which the specified #AtspiAccessibleStateSet
1245  *       will be queried.
1246  *
1247  * Determine whether a given #AtspiAccessibleStateSet includes a given state; that is,
1248  *       whether @state is true for the stateset in question.
1249  *
1250  * Returns: #TRUE if @state is true/included in the given #AtspiAccessibleStateSet,
1251  *          otherwise #FALSE.
1252  *
1253  **/
1254 gboolean
1255 AccessibleStateSet_contains (AccessibleStateSet *obj,
1256                              AccessibleState state)
1257 {
1258   return spi_state_set_cache_contains (obj, spi_state_to_dbus (state));
1259 }
1260
1261 /**
1262  * AccessibleStateSet_add:
1263  * @obj: a pointer to the #AtspiAccessibleStateSet object on which to operate.
1264  * @state: an #AtspiAccessibleState to be added to the specified #AtspiAccessibleStateSet
1265  *
1266  * Add a particular #AtspiAccessibleState to an #AtspiAccessibleStateSet (i.e. set the
1267  *       given state to #TRUE in the stateset.
1268  *
1269  **/
1270 void
1271 AccessibleStateSet_add (AccessibleStateSet *obj,
1272                         AccessibleState state)
1273 {
1274   spi_state_set_cache_add (obj, spi_state_to_dbus (state));
1275 }
1276
1277 /**
1278  * AccessibleStateSet_remove:
1279  * @obj: a pointer to the #AtspiAccessibleStateSet object on which to operate.
1280  * @state: an #AtspiAccessibleState to be removed from the specified #AtspiAccessibleStateSet
1281  *
1282  * Remove a particular #AtspiAccessibleState to an #AtspiAccessibleStateSet (i.e. set the
1283  *       given state to #FALSE in the stateset.)
1284  *
1285  **/
1286 void
1287 AccessibleStateSet_remove (AccessibleStateSet *obj,
1288                            AccessibleState state)
1289 {
1290   spi_state_set_cache_remove (obj, spi_state_to_dbus (state));
1291 }
1292
1293 /**
1294  * AccessibleStateSet_equals:
1295  * @obj: a pointer to the first #AtspiAccessibleStateSet object on which to operate.
1296  * @obj2: a pointer to the second #AtspiAccessibleStateSet object on which to operate.
1297  *
1298  * Determine whether two instances of #AtspiAccessibleStateSet are equivalent (i.e.
1299  *         consist of the same #AtspiAccessibleStates).  Useful for checking multiple
1300  *         state variables at once; construct the target state then compare against it.
1301  *
1302  * @see AccessibleStateSet_compare().
1303  *
1304  * Returns: #TRUE if the two #AtspiAccessibleStateSets are equivalent,
1305  *          otherwise #FALSE.
1306  *
1307  **/
1308 gboolean
1309 AccessibleStateSet_equals (AccessibleStateSet *obj,
1310                            AccessibleStateSet *obj2)
1311 {
1312   gboolean   eq;
1313   AtkStateSet *cmp;
1314
1315   if (obj == obj2)
1316     {
1317       return TRUE;
1318     }
1319
1320   cmp = spi_state_set_cache_xor (obj, obj2);
1321   eq = spi_state_set_cache_is_empty (cmp);
1322   spi_state_set_cache_unref (cmp);
1323
1324   return eq;
1325 }
1326
1327 /**
1328  * AccessibleStateSet_compare:
1329  * @obj: a pointer to the first #AtspiAccessibleStateSet object on which to operate.
1330  * @obj2: a pointer to the second #AtspiAccessibleStateSet object on which to operate.
1331  *
1332  * Determine the differences between two instances of #AtspiAccessibleStateSet.
1333  * Not Yet Implemented.
1334  *.
1335  * @see AccessibleStateSet_equals().
1336  *
1337  * Returns: an #AtspiAccessibleStateSet object containing all states contained on one of
1338  *          the two sets but not the other.
1339  *
1340  **/
1341 AccessibleStateSet *
1342 AccessibleStateSet_compare (AccessibleStateSet *obj,
1343                             AccessibleStateSet *obj2)
1344 {
1345   return spi_state_set_cache_xor (obj, obj2);
1346 }
1347
1348 /**
1349  * AccessibleStateSet_isEmpty:
1350  * @obj: a pointer to the #AtspiAccessibleStateSet object on which to operate.
1351  *
1352  * Determine whether a given #AtspiAccessibleStateSet is the empty set.
1353  *
1354  * Returns: #TRUE if the given #AtspiAccessibleStateSet contains no (true) states,
1355  *          otherwise #FALSE.
1356  *
1357  **/
1358 gboolean
1359 AccessibleStateSet_isEmpty (AccessibleStateSet *obj)
1360 {
1361   return spi_state_set_cache_is_empty (obj);
1362 }
1363 #endif
1364
1365 gboolean
1366 _atspi_accessible_is_a (AtspiAccessible *accessible,
1367                       const char *interface_name)
1368 {
1369   int n;
1370
1371   if (accessible == NULL)
1372     {
1373       return FALSE;
1374     }
1375
1376   n = _atspi_get_iface_num (interface_name);
1377   if (n == -1) return FALSE;
1378   return (gboolean) ((accessible->interfaces & (1 << n))? TRUE: FALSE);
1379 }
1380
1381 /* TODO: Move to a finalizer */
1382 static void
1383 cspi_object_destroyed (AtspiAccessible *accessible)
1384 {
1385   gboolean cached;
1386   AtspiEvent e;
1387
1388   /* TODO: Only fire if object not already marked defunct */
1389   memset (&e, 0, sizeof (e));
1390   e.type = "object:state-change:defunct";
1391   e.source = accessible;
1392   e.detail1 = 1;
1393   e.detail2 = 0;
1394   _atspi_send_event (&e);
1395
1396     g_free (accessible->parent.path);
1397
1398     if (accessible->states)
1399       g_object_unref (accessible->states);
1400     g_free (accessible->description);
1401     g_free (accessible->name);
1402 }
1403
1404 AtspiAccessible *
1405 atspi_accessible_new (AtspiApplication *app, const gchar *path)
1406 {
1407   AtspiAccessible *accessible;
1408   
1409   accessible = g_object_new (ATSPI_TYPE_ACCESSIBLE, NULL);
1410   g_return_val_if_fail (accessible != NULL, NULL);
1411
1412   accessible->parent.app = g_object_ref (app);
1413   accessible->parent.path = g_strdup (path);
1414
1415   return accessible;
1416 }