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