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