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