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