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