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