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