1c441e18b899002decc0e06e60707cf5eb6befa6
[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: (transfer full): the containing AtspiApplication instance for
484  *          this object.
485  */
486 AtspiAccessible *
487 atspi_accessible_get_host_application (AtspiAccessible *obj, GError **error)
488 {
489   while (obj->accessible_parent && atspi_accessible_get_role (obj->accessible_parent, NULL) != ATSPI_ROLE_DESKTOP_FRAME)
490     obj = obj->accessible_parent;
491   return g_object_ref (obj);
492 }
493
494 #if 0   // TODO: interfaces */
495 /* Interface query methods */
496
497 /**
498  * atspi_accessible_is_action:
499  * @obj: a pointer to the #AtspiAccessible instance to query.
500  *
501  * Query whether the specified #AtspiAccessible implements #AtspiAction.
502  *
503  * Returns: #TRUE if @obj implements the #AtspiAction interface,
504  *          #FALSE otherwise.
505  **/
506 gboolean
507 atspi_accessible_is_action (AtspiAccessible *obj)
508 {
509   return _atspi_accessible_is_a (obj,
510                               atspi_interface_action);
511 }
512
513 /**
514  * atspi_accessible_is_application:
515  * @obj: a pointer to the #AtspiAccessible instance to query.
516  *
517  * Query whether the specified #AtspiAccessible implements #AtspiApplication.
518  *
519  * Returns: #TRUE if @obj implements the #AtspiApplication interface,
520  *          #FALSE otherwise.
521  **/
522 gboolean
523 atspi_accessible_is_application (AtspiAccessible *obj)
524 {
525   return _atspi_accessible_is_a (obj,
526                               atspi_interface_application);
527 }
528
529 /**                      
530  * atspi_accessible_is_collection:                                                                                                                                                                          * @obj: a pointer to the #AtspiAccessible instance to query.                                                                                                                                          
531  *                          
532  * Query whether the specified #AtspiAccessible implements #AtspiCollection.    
533  * Returns: #TRUE if @obj implements the #AtspiCollection interface,                                                                                                               
534  *          #FALSE otherwise.
535  **/
536 gboolean
537 atspi_accessible_is_collection (AtspiAccessible *obj)
538 {
539 #if 0
540      g_warning ("Collections not implemented");
541      return _atspi_accessible_is_a (obj,
542                               atspi_interface_collection);
543 #else
544      return FALSE;
545 #endif
546 }
547
548 /**
549  * atspi_accessible_is_component:
550  * @obj: a pointer to the #AtspiAccessible instance to query.
551  *
552  * Query whether the specified #AtspiAccessible implements #AtspiComponent.
553  *
554  * Returns: #TRUE if @obj implements the #AtspiComponent interface,
555  *          #FALSE otherwise.
556  **/
557 gboolean
558 atspi_accessible_is_component (AtspiAccessible *obj)
559 {
560   return _atspi_accessible_is_a (obj,
561                               atspi_interface_component);
562 }
563
564 /**
565  * atspi_accessible_is_document:
566  * @obj: a pointer to the #AtspiAccessible instance to query.
567  *
568  * Query whether the specified #AtspiAccessible implements #AtspiDocument.
569  *
570  * Returns: #TRUE if @obj implements the #AtspiDocument interface,
571  *          #FALSE otherwise.
572  **/
573 gboolean
574 atspi_accessible_is_document (AtspiAccessible *obj)
575 {
576   return _atspi_accessible_is_a (obj,
577                               atspi_interface_document);
578 }
579
580 /**
581  * atspi_accessible_is_editable_text:
582  * @obj: a pointer to the #AtspiAccessible instance to query.
583  *
584  * Query whether the specified #AtspiAccessible implements #AtspiEditableText.
585  *
586  * Returns: #TRUE if @obj implements the #AtspiEditableText interface,
587  *          #FALSE otherwise.
588  **/
589 gboolean
590 atspi_accessible_is_editable_text (AtspiAccessible *obj)
591 {
592   return _atspi_accessible_is_a (obj,
593                               atspi_interface_editable_text);
594 }
595                                                                                                                                                                         
596 /**
597  * atspi_accessible_is_hypertext:
598  * @obj: a pointer to the #AtspiAccessible instance to query.
599  *
600  * Query whether the specified #AtspiAccessible implements #AtspiHypertext.
601  *
602  * Returns: #TRUE if @obj implements the #AtspiHypertext interface,
603  *          #FALSE otherwise.
604  **/
605 gboolean
606 atspi_accessible_is_hypertext (AtspiAccessible *obj)
607 {
608   return _atspi_accessible_is_a (obj,
609                               atspi_interface_hypertext);
610 }
611
612 /**
613  * atspi_accessible_is_image:
614  * @obj: a pointer to the #AtspiAccessible instance to query.
615  *
616  * Query whether the specified #AtspiAccessible implements #AtspiImage.
617  *
618  * Returns: #TRUE if @obj implements the #AtspiImage interface,
619  *          #FALSE otherwise.
620 **/
621 gboolean
622 atspi_accessible_is_image (AtspiAccessible *obj)
623 {
624   return _atspi_accessible_is_a (obj,
625                               atspi_interface_image);
626 }
627
628 /**
629  * atspi_accessible_is_selection:
630  * @obj: a pointer to the #AtspiAccessible instance to query.
631  *
632  * Query whether the specified #AtspiAccessible implements #AtspiSelection.
633  *
634  * Returns: #TRUE if @obj implements the #AtspiSelection interface,
635  *          #FALSE otherwise.
636 **/
637 gboolean
638 atspi_accessible_is_selection (AtspiAccessible *obj)
639 {
640   return _atspi_accessible_is_a (obj,
641                               atspi_interface_selection);
642 }
643
644 /**
645  * atspi_accessible_is_table:
646  * @obj: a pointer to the #AtspiAccessible instance to query.
647  *
648  * Query whether the specified #AtspiAccessible implements #AtspiTable.
649  *
650  * Returns: #TRUE if @obj implements the #AtspiTable interface,
651  *          #FALSE otherwise.
652 **/
653 gboolean
654 atspi_accessible_is_table (AtspiAccessible *obj)
655 {
656   return _atspi_accessible_is_a (obj,
657                               atspi_interface_table);
658 }
659
660 /**
661  * atspi_accessible_is_streamable_content:
662  * @obj: a pointer to the #AtspiAccessible instance to query.
663  *
664  * Query whether the specified #AtspiAccessible implements
665  *          #AtspiStreamableContent.
666  *
667  * Returns: #TRUE if @obj implements the #AtspiStreamableContent interface,
668  *          #FALSE otherwise.
669 **/
670 gboolean
671 atspi_accessible_is_streamable_content (AtspiAccessible *obj)
672 {
673 #if 0
674   return _atspi_accessible_is_a (obj,
675                               atspi_interface_streamable_content);
676 #else
677   g_warning ("Streamable content not implemented");
678   return FALSE;
679 #endif
680 }
681
682 /**
683  * atspi_accessible_is_text:
684  * @obj: a pointer to the #AtspiAccessible instance to query.
685  *
686  * Query whether the specified #AtspiAccessible implements #AtspiText.
687  *
688  * Returns: #TRUE if @obj implements the #AtspiText interface,
689  *          #FALSE otherwise.
690 **/
691 gboolean
692 atspi_accessible_is_text (AtspiAccessible *obj)
693 {
694   return _atspi_accessible_is_a (obj,
695                               atspi_interface_text);
696 }
697
698 /**
699  * atspi_accessible_is_value:
700  * @obj: a pointer to the #AtspiAccessible instance to query.
701  *
702  * Query whether the specified #AtspiAccessible implements #AtspiValue.
703  *
704  * Returns: #TRUE if @obj implements the #AtspiValue interface,
705  *          #FALSE otherwise.
706 **/
707 gboolean
708 atspi_accessible_is_value (AtspiAccessible *obj)
709 {
710   return _atspi_accessible_is_a (obj,
711                               atspi_interface_value);
712 }
713
714 /**
715  * atspi_accessible_get_application:
716  * @obj: a pointer to the #AtspiAccessible instance to query.
717  *
718  * Get the #AtspiApplication interface for an #AtspiAccessible.
719  *
720  * Returns: a pointer to an #AtspiApplication interface instance, or
721  *          NULL if @obj does not implement #AtspiApplication.
722  **/
723 AtspiApplication *
724 atspi_accessible_get_application (AtspiAccessible *accessible)
725 {
726   return (_atspi_accessible_is_a (accessible, atspi_interface_application) ?
727           accessible : NULL);  
728 }
729
730 /**
731  * atspi_accessible_get_action:
732  * @obj: a pointer to the #AtspiAccessible instance to query.
733  *
734  * Get the #AtspiAction interface for an #AtspiAccessible.
735  *
736  * Returns: a pointer to an #AtspiAction interface instance, or
737  *          NULL if @obj does not implement #AtspiAction.
738  **/
739 AtspiAction *
740 atspi_accessible_get_action (AtspiAccessible *accessible)
741 {
742   return (_atspi_accessible_is_a (accessible, atspi_interface_action) ?
743           accessible : NULL);  
744 }
745
746 /**
747  * atspi_accessible_get_collection:
748  * @obj: a pointer to the #AtspiAccessible instance to query.
749  *
750  * Get the #AtspiCollection interface for an #AtspiAccessible.
751  *
752  * Returns: a pointer to an #AtspiCollection interface instance, or
753  *          NULL if @obj does not implement #AtspiCollection.
754  **/
755 AtspiCollection *
756 atspi_accessible_get_collection (AtspiAccessible *accessible)
757 {
758   return (_atspi_accessible_is_a (accessible, atspi_interface_collection) ?
759           accessible : NULL);  
760 }
761 #endif
762
763 /**
764  * atspi_accessible_get_component:
765  * @obj: a pointer to the #AtspiAccessible instance to query.
766  *
767  * Get the #AtspiComponent interface for an #AtspiAccessible.
768  *
769  * Returns: a pointer to an #AtspiComponent interface instance, or
770  *          NULL if @obj does not implement #AtspiComponent.
771  **/
772 AtspiComponent *
773 atspi_accessible_get_component (AtspiAccessible *accessible)
774 {
775   return (_atspi_accessible_is_a (accessible, atspi_interface_component) ?
776           ATSPI_COMPONENT (accessible) : NULL);  
777 }
778
779 #if 0
780 /**
781  * atspi_accessible_get_document:
782  * @obj: a pointer to the #AtspiAccessible instance to query.
783  *
784  * Get the #AtspiDocument interface for an #AtspiAccessible.
785  *
786  * Returns: a pointer to an #AtspiDocument interface instance, or
787  *          NULL if @obj does not implement #AtspiDocument.
788  **/
789 AtspiDocument *
790 atspi_accessible_get_document (AtspiAccessible *accessible)
791 {
792   return (_atspi_accessible_is_a (accessible, atspi_interface_document) ?
793           accessible : NULL);  
794 }
795
796 /**
797  * atspi_accessible_get_editable_text:
798  * @obj: a pointer to the #AtspiAccessible instance to query.
799  *
800  * Get the #AtspiEditableText interface for an #AtspiAccessible.
801  *
802  * Returns: a pointer to an #AtspiEditableText interface instance, or
803  *          NULL if @obj does not implement #AtspiEditableText.
804  **/
805 AtspiEditableText *
806 atspi_accessible_get_editable_text (AtspiAccessible *accessible)
807 {
808   return (_atspi_accessible_is_a (accessible, atspi_interface_editable_text) ?
809           accessible : NULL);  
810 }
811
812 /**
813  * atspi_accessible_get_hypertext:
814  * @obj: a pointer to the #AtspiAccessible instance to query.
815  *
816  * Get the #AtspiHypertext interface for an #AtspiAccessible.
817  *
818  * Returns: a pointer to an #AtspiHypertext interface instance, or
819  *          NULL if @obj does not implement #AtspiHypertext.
820  **/
821 AtspiHypertext *
822 atspi_accessible_get_hypertext (AtspiAccessible *accessible)
823 {
824   return (_atspi_accessible_is_a (accessible, atspi_interface_hypertext) ?
825           accessible : NULL);  
826 }
827
828 /**
829  * atspi_accessible_get_image:
830  * @obj: a pointer to the #AtspiAccessible instance to query.
831  *
832  * Get the #AtspiImage interface for an #AtspiAccessible.
833  *
834  * Returns: a pointer to an #AtspiImage interface instance, or
835  *          NULL if @obj does not implement #AtspiImage.
836  **/
837 AtspiImage *
838 atspi_accessible_get_image (AtspiAccessible *accessible)
839 {
840   return (_atspi_accessible_is_a (accessible, atspi_interface_image) ?
841           accessible : NULL);  
842 }
843
844 /**
845  * atspi_accessible_get_selection:
846  * @obj: a pointer to the #AtspiAccessible instance to query.
847  *
848  * Get the #AtspiSelection interface for an #AtspiAccessible.
849  *
850  * Returns: a pointer to an #AtspiSelection interface instance, or
851  *          NULL if @obj does not implement #AtspiSelection.
852  **/
853 AtspiSelection *
854 atspi_accessible_get_selection (AtspiAccessible *accessible)
855 {
856   return (_atspi_accessible_is_a (accessible, atspi_interface_selection) ?
857           accessible : NULL);  
858 }
859
860 /**
861  * atspi_accessible_get_streamable_content:
862  * @obj: a pointer to the #AtspiAccessible instance to query.
863  *
864  * Get the #AtspiStreamableContent interface for an #AtspiAccessible.
865  *
866  * Returns: a pointer to an #AtspiStreamableContent interface instance, or
867  *          NULL if @obj does not implement #AtspiStreamableContent.
868  **/
869 AtspiStreamableContent *
870 atspi_accessible_get_streamable_content (AtspiAccessible *accessible)
871 {
872   return (_atspi_accessible_is_a (accessible, atspi_interface_streamable_content) ?
873           accessible : NULL);  
874 }
875
876 /**
877  * atspi_accessible_get_table:
878  * @obj: a pointer to the #AtspiAccessible instance to query.
879  *
880  * Get the #AtspiTable interface for an #AtspiAccessible.
881  *
882  * Returns: a pointer to an #AtspiTable interface instance, or
883  *          NULL if @obj does not implement #AtspiTable.
884  **/
885 AtspiTable *
886 atspi_accessible_get_table (AtspiAccessible *accessible)
887 {
888   return (_atspi_accessible_is_a (accessible, atspi_interface_table) ?
889           accessible : NULL);  
890 }
891
892 /**
893  * atspi_accessible_get_text:
894  * @obj: a pointer to the #AtspiAccessible instance to query.
895  *
896  * Get the #AtspiTable interface for an #AtspiAccessible.
897  *
898  * Returns: a pointer to an #AtspiTable interface instance, or
899  *          NULL if @obj does not implement #AtspiTable.
900  **/
901 AtspiTable *
902 atspi_accessible_get_text (AtspiAccessible *accessible)
903 {
904   return (_atspi_accessible_is_a (accessible, atspi_interface_text) ?
905           accessible : NULL);  
906 }
907
908 /**
909  * atspi_accessible_get_value:
910  * @obj: a pointer to the #AtspiAccessible instance to query.
911  *
912  * Get the #AtspiTable interface for an #AtspiAccessible.
913  *
914  * Returns: a pointer to an #AtspiTable interface instance, or
915  *          NULL if @obj does not implement #AtspiTable.
916  **/
917 AtspiTable *
918 atspi_accessible_get_value (AtspiAccessible *accessible)
919 {
920   return (_atspi_accessible_is_a (accessible, atspi_interface_value) ?
921           accessible : NULL);  
922 }
923
924 static gboolean
925 cspi_init_relation_type_table (AccessibleRelationType *relation_type_table)
926 {
927   int i;
928   for (i = 0; i < Accessibility_RELATION_LAST_DEFINED; ++i)
929     {
930       relation_type_table [i] = SPI_RELATION_NULL;
931     }
932   relation_type_table [Accessibility_RELATION_NULL] = SPI_RELATION_NULL;
933   relation_type_table [Accessibility_RELATION_LABEL_FOR] = SPI_RELATION_LABEL_FOR;
934   relation_type_table [Accessibility_RELATION_LABELLED_BY] = SPI_RELATION_LABELED_BY;
935   relation_type_table [Accessibility_RELATION_CONTROLLER_FOR] = SPI_RELATION_CONTROLLER_FOR;
936   relation_type_table [Accessibility_RELATION_CONTROLLED_BY] = SPI_RELATION_CONTROLLED_BY;
937   relation_type_table [Accessibility_RELATION_MEMBER_OF] = SPI_RELATION_MEMBER_OF;
938   relation_type_table [Accessibility_RELATION_TOOLTIP_FOR] = SPI_RELATION_NULL;
939   relation_type_table [Accessibility_RELATION_NODE_CHILD_OF] = SPI_RELATION_NODE_CHILD_OF;
940   relation_type_table [Accessibility_RELATION_EXTENDED] = SPI_RELATION_EXTENDED;
941   relation_type_table [Accessibility_RELATION_FLOWS_TO] = SPI_RELATION_FLOWS_TO;
942   relation_type_table [Accessibility_RELATION_FLOWS_FROM] = SPI_RELATION_FLOWS_FROM;
943   relation_type_table [Accessibility_RELATION_SUBWINDOW_OF] = SPI_RELATION_SUBWINDOW_OF;
944   relation_type_table [Accessibility_RELATION_EMBEDS] = SPI_RELATION_EMBEDS;
945   relation_type_table [Accessibility_RELATION_EMBEDDED_BY] = SPI_RELATION_EMBEDDED_BY;
946   relation_type_table [Accessibility_RELATION_POPUP_FOR] = SPI_RELATION_POPUP_FOR;
947   relation_type_table [Accessibility_RELATION_PARENT_WINDOW_OF] = SPI_RELATION_PARENT_WINDOW_OF;
948   relation_type_table [Accessibility_RELATION_DESCRIBED_BY] = SPI_RELATION_DESCRIBED_BY;
949   relation_type_table [Accessibility_RELATION_DESCRIPTION_FOR] = SPI_RELATION_DESCRIPTION_FOR;
950   return TRUE;
951 }
952
953 static AccessibleRelationType
954 cspi_relation_type_from_spi_relation_type (Accessibility_RelationType type)
955 {
956   /* array is sized according to IDL RelationType because IDL RelationTypes are the index */    
957   static AccessibleRelationType cspi_relation_type_table [Accessibility_RELATION_LAST_DEFINED];
958   static gboolean is_initialized = FALSE;
959   AccessibleRelationType cspi_type;
960   if (!is_initialized)
961     {
962       is_initialized = cspi_init_relation_type_table (cspi_relation_type_table);            
963     }
964   if (type >= 0 && type < Accessibility_RELATION_LAST_DEFINED)
965     {
966       cspi_type = cspi_relation_type_table [type];          
967     }
968   else
969     {
970       cspi_type = SPI_RELATION_NULL;
971     }
972   return cspi_type; 
973 }
974 /**
975  * AccessibleRelation_getRelationType:
976  * @obj: a pointer to the #AtspiAccessibleRelation object to query.
977  *
978  * Get the type of relationship represented by an #AtspiAccessibleRelation.
979  *
980  * Returns: an #AtspiAccessibleRelationType indicating the type of relation
981  *         encapsulated in this #AtspiAccessibleRelation object.
982  *
983  **/
984 AccessibleRelationType
985 AccessibleRelation_getRelationType (AccessibleRelation *obj)
986 {
987   cspi_return_val_if_fail (obj, SPI_RELATION_NULL);
988   return cspi_relation_type_from_spi_relation_type (obj->type);
989 }
990
991 /**
992  * AccessibleRelation_getNTargets:
993  * @obj: a pointer to the #AtspiAccessibleRelation object to query.
994  *
995  * Get the number of objects which this relationship has as its
996  *       target objects (the subject is the #AtspiAccessible from which this
997  *       #AtspiAccessibleRelation originated).
998  *
999  * Returns: a short integer indicating how many target objects which the
1000  *       originating #AtspiAccessible object has the #AtspiAccessibleRelation
1001  *       relationship with.
1002  **/
1003 int
1004 AccessibleRelation_getNTargets (AccessibleRelation *obj)
1005 {
1006   cspi_return_val_if_fail (obj, -1);
1007   return obj->targets->len;
1008 }
1009
1010 /**
1011  * AccessibleRelation_getTarget:
1012  * @obj: a pointer to the #AtspiAccessibleRelation object to query.
1013  * @i: a (zero-index) integer indicating which (of possibly several) target is requested.
1014  *
1015  * Get the @i-th target of a specified #AtspiAccessibleRelation relationship.
1016  *
1017  * Returns: an #AtspiAccessible which is the @i-th object with which the
1018  *      originating #AtspiAccessible has relationship specified in the
1019  *      #AtspiAccessibleRelation object.
1020  *
1021  **/
1022 Accessible *
1023 AccessibleRelation_getTarget (AccessibleRelation *obj, int i)
1024 {
1025   cspi_return_val_if_fail (obj, NULL);
1026
1027   if (i < 0 || i >= obj->targets->len) return NULL;
1028   return cspi_object_add (
1029                          g_array_index (obj->targets, Accessible *, i));
1030 }
1031
1032 /**
1033  * AccessibleStateSet_ref:
1034  * @obj: a pointer to the #AtspiAccessibleStateSet object on which to operate.
1035  *
1036  * Increment the reference count for an #AtspiAccessibleStateSet object.
1037  *
1038  **/
1039 void
1040 AccessibleStateSet_ref (AccessibleStateSet *obj)
1041 {
1042   spi_state_set_cache_ref (obj);
1043 }
1044
1045 /**
1046  * AccessibleStateSet_unref:
1047  * @obj: a pointer to the #AtspiAccessibleStateSet object on which to operate.
1048  *
1049  * Decrement the reference count for an #AtspiAccessibleStateSet object.
1050  *
1051  **/
1052 void
1053 AccessibleStateSet_unref (AccessibleStateSet *obj)
1054 {
1055   spi_state_set_cache_unref (obj);
1056 }
1057
1058 static Accessibility_StateType
1059 spi_state_to_dbus (AccessibleState state)
1060 {
1061 #define MAP_STATE(a) \
1062   case SPI_STATE_##a: \
1063     return Accessibility_STATE_##a
1064
1065   switch (state)
1066     {
1067       MAP_STATE (INVALID);
1068       MAP_STATE (ACTIVE);
1069       MAP_STATE (ARMED);
1070       MAP_STATE (BUSY);
1071       MAP_STATE (CHECKED);
1072       MAP_STATE (DEFUNCT);
1073       MAP_STATE (EDITABLE);
1074       MAP_STATE (ENABLED);
1075       MAP_STATE (EXPANDABLE);
1076       MAP_STATE (EXPANDED);
1077       MAP_STATE (FOCUSABLE);
1078       MAP_STATE (FOCUSED);
1079       MAP_STATE (HORIZONTAL);
1080       MAP_STATE (ICONIFIED);
1081       MAP_STATE (MODAL);
1082       MAP_STATE (MULTI_LINE);
1083       MAP_STATE (MULTISELECTABLE);
1084       MAP_STATE (OPAQUE);
1085       MAP_STATE (PRESSED);
1086       MAP_STATE (RESIZABLE);
1087       MAP_STATE (SELECTABLE);
1088       MAP_STATE (SELECTED);
1089       MAP_STATE (SENSITIVE);
1090       MAP_STATE (SHOWING);
1091       MAP_STATE (SINGLE_LINE);
1092       MAP_STATE (STALE);
1093       MAP_STATE (TRANSIENT);
1094       MAP_STATE (VERTICAL);
1095       MAP_STATE (VISIBLE);
1096       MAP_STATE (MANAGES_DESCENDANTS);
1097       MAP_STATE (INDETERMINATE);
1098       MAP_STATE (TRUNCATED);
1099       MAP_STATE (REQUIRED);
1100       MAP_STATE (INVALID_ENTRY);
1101       MAP_STATE (SUPPORTS_AUTOCOMPLETION);
1102       MAP_STATE (SELECTABLE_TEXT);
1103       MAP_STATE (IS_DEFAULT);
1104       MAP_STATE (VISITED);
1105     default:
1106       return Accessibility_STATE_INVALID;
1107   }
1108 #undef MAP_STATE
1109 }             
1110
1111 /**
1112  * AccessibleStateSet_contains:
1113  * @obj: a pointer to the #AtspiAccessibleStateSet object on which to operate.
1114  * @state: an #AtspiAccessibleState for which the specified #AtspiAccessibleStateSet
1115  *       will be queried.
1116  *
1117  * Determine whether a given #AtspiAccessibleStateSet includes a given state; that is,
1118  *       whether @state is true for the stateset in question.
1119  *
1120  * Returns: #TRUE if @state is true/included in the given #AtspiAccessibleStateSet,
1121  *          otherwise #FALSE.
1122  *
1123  **/
1124 gboolean
1125 AccessibleStateSet_contains (AccessibleStateSet *obj,
1126                              AccessibleState state)
1127 {
1128   return spi_state_set_cache_contains (obj, spi_state_to_dbus (state));
1129 }
1130
1131 /**
1132  * AccessibleStateSet_add:
1133  * @obj: a pointer to the #AtspiAccessibleStateSet object on which to operate.
1134  * @state: an #AtspiAccessibleState to be added to the specified #AtspiAccessibleStateSet
1135  *
1136  * Add a particular #AtspiAccessibleState to an #AtspiAccessibleStateSet (i.e. set the
1137  *       given state to #TRUE in the stateset.
1138  *
1139  **/
1140 void
1141 AccessibleStateSet_add (AccessibleStateSet *obj,
1142                         AccessibleState state)
1143 {
1144   spi_state_set_cache_add (obj, spi_state_to_dbus (state));
1145 }
1146
1147 /**
1148  * AccessibleStateSet_remove:
1149  * @obj: a pointer to the #AtspiAccessibleStateSet object on which to operate.
1150  * @state: an #AtspiAccessibleState to be removed from the specified #AtspiAccessibleStateSet
1151  *
1152  * Remove a particular #AtspiAccessibleState to an #AtspiAccessibleStateSet (i.e. set the
1153  *       given state to #FALSE in the stateset.)
1154  *
1155  **/
1156 void
1157 AccessibleStateSet_remove (AccessibleStateSet *obj,
1158                            AccessibleState state)
1159 {
1160   spi_state_set_cache_remove (obj, spi_state_to_dbus (state));
1161 }
1162
1163 /**
1164  * AccessibleStateSet_equals:
1165  * @obj: a pointer to the first #AtspiAccessibleStateSet object on which to operate.
1166  * @obj2: a pointer to the second #AtspiAccessibleStateSet object on which to operate.
1167  *
1168  * Determine whether two instances of #AtspiAccessibleStateSet are equivalent (i.e.
1169  *         consist of the same #AtspiAccessibleStates).  Useful for checking multiple
1170  *         state variables at once; construct the target state then compare against it.
1171  *
1172  * @see AccessibleStateSet_compare().
1173  *
1174  * Returns: #TRUE if the two #AtspiAccessibleStateSets are equivalent,
1175  *          otherwise #FALSE.
1176  *
1177  **/
1178 gboolean
1179 AccessibleStateSet_equals (AccessibleStateSet *obj,
1180                            AccessibleStateSet *obj2)
1181 {
1182   gboolean   eq;
1183   AtkStateSet *cmp;
1184
1185   if (obj == obj2)
1186     {
1187       return TRUE;
1188     }
1189
1190   cmp = spi_state_set_cache_xor (obj, obj2);
1191   eq = spi_state_set_cache_is_empty (cmp);
1192   spi_state_set_cache_unref (cmp);
1193
1194   return eq;
1195 }
1196
1197 /**
1198  * AccessibleStateSet_compare:
1199  * @obj: a pointer to the first #AtspiAccessibleStateSet object on which to operate.
1200  * @obj2: a pointer to the second #AtspiAccessibleStateSet object on which to operate.
1201  *
1202  * Determine the differences between two instances of #AtspiAccessibleStateSet.
1203  * Not Yet Implemented.
1204  *.
1205  * @see AccessibleStateSet_equals().
1206  *
1207  * Returns: an #AtspiAccessibleStateSet object containing all states contained on one of
1208  *          the two sets but not the other.
1209  *
1210  **/
1211 AccessibleStateSet *
1212 AccessibleStateSet_compare (AccessibleStateSet *obj,
1213                             AccessibleStateSet *obj2)
1214 {
1215   return spi_state_set_cache_xor (obj, obj2);
1216 }
1217
1218 /**
1219  * AccessibleStateSet_isEmpty:
1220  * @obj: a pointer to the #AtspiAccessibleStateSet object on which to operate.
1221  *
1222  * Determine whether a given #AtspiAccessibleStateSet is the empty set.
1223  *
1224  * Returns: #TRUE if the given #AtspiAccessibleStateSet contains no (true) states,
1225  *          otherwise #FALSE.
1226  *
1227  **/
1228 gboolean
1229 AccessibleStateSet_isEmpty (AccessibleStateSet *obj)
1230 {
1231   return spi_state_set_cache_is_empty (obj);
1232 }
1233 #endif
1234
1235 gboolean
1236 _atspi_accessible_is_a (AtspiAccessible *accessible,
1237                       const char *interface_name)
1238 {
1239   int n;
1240
1241   if (accessible == NULL)
1242     {
1243       return FALSE;
1244     }
1245
1246   n = _atspi_get_iface_num (interface_name);
1247   if (n == -1) return FALSE;
1248   return (gboolean) ((accessible->interfaces & (1 << n))? TRUE: FALSE);
1249 }
1250
1251 /* TODO: Move to a finalizer */
1252 static void
1253 cspi_object_destroyed (AtspiAccessible *accessible)
1254 {
1255   gboolean cached;
1256   AtspiEvent e;
1257
1258   /* TODO: Only fire if object not already marked defunct */
1259   e.type = "object:state-change:defunct";
1260   e.source = accessible;
1261   e.detail1 = 1;
1262   e.detail2 = 0;
1263   g_value_unset (&e.any);
1264   _atspi_send_event (&e);
1265
1266     g_free (accessible->path);
1267
1268     if (accessible->states)
1269       g_object_unref (accessible->states);
1270     g_free (accessible->description);
1271     g_free (accessible->name);
1272 }
1273
1274 AtspiAccessible *
1275 atspi_accessible_new (AtspiApplication *app, const gchar *path)
1276 {
1277   AtspiAccessible *accessible;
1278   
1279   accessible = g_object_new (ATSPI_TYPE_ACCESSIBLE, NULL);
1280   g_return_val_if_fail (accessible != NULL, NULL);
1281
1282   accessible->app = g_object_ref (app);
1283   accessible->path = g_strdup (path);
1284
1285   return accessible;
1286 }