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