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