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