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