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