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