Use macros for interface names
[platform/core/uifw/at-spi2-atk.git] / atk-adaptor / accessible.c
1 /*
2  * AT-SPI - Assistive Technology Service Provider Interface
3  * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
4  *
5  * Copyright 2008 Novell, Inc.
6  * Copyright 2001, 2002 Sun Microsystems Inc.,
7  * Copyright 2001, 2002 Ximian, Inc.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Library General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Library General Public License for more details.
18  *
19  * You should have received a copy of the GNU Library General Public
20  * License along with this library; if not, write to the
21  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22  * Boston, MA 02111-1307, USA.
23  */
24
25 #include "accessible.h"
26 #include "bitarray.h"
27
28 #define get_object(message) spi_dbus_get_object(dbus_message_get_path(message))
29
30 static AtkObject *
31 get_object_from_path (const char *path, void *user_data)
32 {
33   return spi_dbus_get_object (path);
34 }
35
36 static dbus_bool_t
37 impl_get_name (const char *path, DBusMessageIter * iter, void *user_data)
38 {
39   AtkObject *object = spi_dbus_get_object (path);
40   if (!object)
41     return FALSE;
42   return droute_return_v_string (iter, atk_object_get_name (object));
43 }
44
45 static dbus_bool_t
46 impl_set_name (const char *path, DBusMessageIter * iter, void *user_data)
47 {
48   AtkObject *object = spi_dbus_get_object (path);
49   const char *name = droute_get_v_string (iter);
50   atk_object_set_name (object, name);
51   return TRUE;
52 }
53
54 static dbus_bool_t
55 impl_get_description (const char *path, DBusMessageIter * iter,
56                       void *user_data)
57 {
58   AtkObject *object = spi_dbus_get_object (path);
59   if (!object)
60     return FALSE;
61   return droute_return_v_string (iter, atk_object_get_description (object));
62 }
63
64 static dbus_bool_t
65 impl_set_description (const char *path, DBusMessageIter * iter,
66                       void *user_data)
67 {
68   AtkObject *object = spi_dbus_get_object (path);
69   const char *description = droute_get_v_string (iter);
70   atk_object_set_description (object, description);
71   return TRUE;
72 }
73
74 static dbus_bool_t
75 impl_get_parent (const char *path, DBusMessageIter * iter, void *user_data)
76 {
77   AtkObject *object = spi_dbus_get_object (path);
78
79   if (!object)
80     return FALSE;
81   return spi_dbus_return_v_object (iter, atk_object_get_parent (object),
82                                    FALSE);
83 }
84
85 static dbus_bool_t
86 impl_get_childCount (const char *path, DBusMessageIter * iter,
87                      void *user_data)
88 {
89   AtkObject *object = spi_dbus_get_object (path);
90
91   if (!object)
92     return FALSE;
93   return droute_return_v_int32 (iter,
94                                 atk_object_get_n_accessible_children
95                                 (object));
96 }
97
98 static DBusMessage *
99 impl_getChildren (DBusConnection * bus, DBusMessage * message,
100                   void *user_data)
101 {
102   AtkObject *object = get_object (message);
103   gint i;
104   gint count;
105   DBusMessage *reply;
106   DBusMessageIter iter, iter_array;
107
108   if (!object)
109     return spi_dbus_general_error (message);
110   count = atk_object_get_n_accessible_children (object);
111   reply = dbus_message_new_method_return (message);
112   if (!reply) goto oom;
113   dbus_message_iter_init_append (reply, &iter);
114   if (!dbus_message_iter_open_container
115       (&iter, DBUS_TYPE_ARRAY, "o", &iter_array))
116     goto oom;
117   for (i = 0; i < count; i++)
118     {
119       AtkObject *child = atk_object_ref_accessible_child (object, i);
120       char *path = spi_dbus_get_path (child);
121       if (path)
122         {
123           dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_OBJECT_PATH,
124                                           &path);
125           g_free (path);
126         }
127       if (child)
128         g_object_unref (child);
129     }
130   if (!dbus_message_iter_close_container (&iter, &iter_array))
131     goto oom;
132   return reply;
133 oom:
134   // TODO: handle out-of-memory
135   return reply;
136 }
137
138 static DBusMessage *
139 impl_getIndexInParent (DBusConnection * bus, DBusMessage * message,
140                        void *user_data)
141 {
142   AtkObject *object = get_object (message);
143   dbus_uint32_t rv;
144   DBusMessage *reply;
145
146   if (!object)
147     return spi_dbus_general_error (message);
148   rv = atk_object_get_index_in_parent (object);
149   reply = dbus_message_new_method_return (message);
150   if (reply)
151     {
152       dbus_message_append_args (reply, DBUS_TYPE_UINT32, &rv,
153                                 DBUS_TYPE_INVALID);
154     }
155   return reply;
156 }
157
158 static gboolean
159 spi_init_relation_type_table (Accessibility_RelationType *types)
160 {
161   gint i;
162
163   for (i = 0; i < ATK_RELATION_LAST_DEFINED; i++)
164     types[i] = Accessibility_RELATION_NULL;
165
166   types[ATK_RELATION_CONTROLLED_BY] = Accessibility_RELATION_CONTROLLED_BY;
167   types[ATK_RELATION_CONTROLLER_FOR] = Accessibility_RELATION_CONTROLLER_FOR;
168   types[ATK_RELATION_LABEL_FOR] = Accessibility_RELATION_LABEL_FOR;
169   types[ATK_RELATION_LABELLED_BY] = Accessibility_RELATION_LABELLED_BY;
170   types[ATK_RELATION_MEMBER_OF] = Accessibility_RELATION_MEMBER_OF;
171   types[ATK_RELATION_NODE_CHILD_OF] = Accessibility_RELATION_NODE_CHILD_OF;
172   types[ATK_RELATION_FLOWS_TO] = Accessibility_RELATION_FLOWS_TO;
173   types[ATK_RELATION_FLOWS_FROM] = Accessibility_RELATION_FLOWS_FROM;
174   types[ATK_RELATION_SUBWINDOW_OF] = Accessibility_RELATION_SUBWINDOW_OF;
175   types[ATK_RELATION_EMBEDS] = Accessibility_RELATION_EMBEDS;
176   types[ATK_RELATION_EMBEDDED_BY] = Accessibility_RELATION_EMBEDDED_BY;
177   types[ATK_RELATION_POPUP_FOR] = Accessibility_RELATION_POPUP_FOR;
178   types[ATK_RELATION_PARENT_WINDOW_OF] = Accessibility_RELATION_PARENT_WINDOW_OF;
179   types[ATK_RELATION_DESCRIPTION_FOR] = Accessibility_RELATION_DESCRIPTION_FOR;
180   types[ATK_RELATION_DESCRIBED_BY] = Accessibility_RELATION_DESCRIBED_BY;
181
182   return TRUE;
183 }
184
185 static Accessibility_RelationType
186 spi_relation_type_from_atk_relation_type (AtkRelationType type)
187 {
188   static gboolean is_initialized = FALSE;
189   static Accessibility_RelationType spi_relation_type_table [ATK_RELATION_LAST_DEFINED];
190   Accessibility_RelationType spi_type;
191
192   if (!is_initialized)
193     is_initialized = spi_init_relation_type_table (spi_relation_type_table);       
194
195   if (type > ATK_RELATION_NULL && type < ATK_RELATION_LAST_DEFINED)
196     spi_type = spi_relation_type_table[type];
197   else
198     spi_type = Accessibility_RELATION_EXTENDED;
199   return spi_type;
200 }
201
202 static DBusMessage *
203 impl_getRelationSet (DBusConnection * bus, DBusMessage * message,
204                      void *user_data)
205 {
206   AtkObject *object = get_object (message);
207   DBusMessage *reply;
208   AtkRelationSet *set;
209   DBusMessageIter iter, iter_array, iter_struct, iter_targets;
210   gint count;
211   gint i, j;
212
213   if (!object)
214     return spi_dbus_general_error (message);
215   reply = dbus_message_new_method_return (message);
216   if (!reply) return NULL;
217   set = atk_object_ref_relation_set (object);
218   dbus_message_iter_init_append (reply, &iter);
219   if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "(uao)", &iter_array))
220   {
221     goto oom;
222   }
223   count = atk_relation_set_get_n_relations (set);
224   for (i = 0; i < count; i++)
225   {
226     AtkRelation *r = atk_relation_set_get_relation (set, i);
227     AtkRelationType rt;
228     GPtrArray *target;
229     dbus_uint32_t type;
230     if (!r) continue;
231     rt= atk_relation_get_relation_type (r);
232     type = spi_relation_type_from_atk_relation_type (rt);
233     target = atk_relation_get_target (r);
234     if (!dbus_message_iter_open_container (&iter_array, DBUS_TYPE_STRUCT, NULL, &iter_struct))
235     {
236       goto oom;
237     }
238     dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_UINT32, &type);
239     if (!dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "o", &iter_targets))
240     {
241       goto oom;
242     }
243     for (j = 0; j < target->len; j++)
244     {
245       AtkObject *obj = target->pdata[j];
246       char *path;
247       if (!obj) continue;
248       path = spi_dbus_get_path (obj);
249       dbus_message_iter_append (&iter_targets, DBUS_TYPE_OBJECT_PATH, &path);
250     }
251     dbus_message_iter_close_container (&iter_struct, &iter_targets);
252     dbus_message_iter_close_container (&iter_array, &iter_struct);
253   }
254   dbus_message_iter_close_container (&iter, &iter_array);
255 oom:
256   // TODO: handle out of memory */
257   return reply;
258 }
259
260 static gboolean
261 spi_init_role_lookup_table (Accessibility_Role * role_table)
262 {
263   int i;
264   /* if it's not in the list below, dunno what it is */
265   for (i = 0; i < ATK_ROLE_LAST_DEFINED; ++i)
266     {
267       role_table[i] = Accessibility_ROLE_UNKNOWN;
268     }
269
270   role_table[ATK_ROLE_INVALID] = Accessibility_ROLE_INVALID;
271   role_table[ATK_ROLE_ACCEL_LABEL] = Accessibility_ROLE_ACCELERATOR_LABEL;
272   role_table[ATK_ROLE_ALERT] = Accessibility_ROLE_ALERT;
273   role_table[ATK_ROLE_ANIMATION] = Accessibility_ROLE_ANIMATION;
274   role_table[ATK_ROLE_ARROW] = Accessibility_ROLE_ARROW;
275   role_table[ATK_ROLE_CALENDAR] = Accessibility_ROLE_CALENDAR;
276   role_table[ATK_ROLE_CANVAS] = Accessibility_ROLE_CANVAS;
277   role_table[ATK_ROLE_CHECK_BOX] = Accessibility_ROLE_CHECK_BOX;
278   role_table[ATK_ROLE_CHECK_MENU_ITEM] = Accessibility_ROLE_CHECK_MENU_ITEM;
279   role_table[ATK_ROLE_COLOR_CHOOSER] = Accessibility_ROLE_COLOR_CHOOSER;
280   role_table[ATK_ROLE_COLUMN_HEADER] = Accessibility_ROLE_COLUMN_HEADER;
281   role_table[ATK_ROLE_COMBO_BOX] = Accessibility_ROLE_COMBO_BOX;
282   role_table[ATK_ROLE_DATE_EDITOR] = Accessibility_ROLE_DATE_EDITOR;
283   role_table[ATK_ROLE_DESKTOP_ICON] = Accessibility_ROLE_DESKTOP_ICON;
284   role_table[ATK_ROLE_DESKTOP_FRAME] = Accessibility_ROLE_DESKTOP_FRAME;
285   role_table[ATK_ROLE_DIAL] = Accessibility_ROLE_DIAL;
286   role_table[ATK_ROLE_DIALOG] = Accessibility_ROLE_DIALOG;
287   role_table[ATK_ROLE_DIRECTORY_PANE] = Accessibility_ROLE_DIRECTORY_PANE;
288   role_table[ATK_ROLE_DRAWING_AREA] = Accessibility_ROLE_DRAWING_AREA;
289   role_table[ATK_ROLE_FILE_CHOOSER] = Accessibility_ROLE_FILE_CHOOSER;
290   role_table[ATK_ROLE_FILLER] = Accessibility_ROLE_FILLER;
291   role_table[ATK_ROLE_FONT_CHOOSER] = Accessibility_ROLE_FONT_CHOOSER;
292   role_table[ATK_ROLE_FRAME] = Accessibility_ROLE_FRAME;
293   role_table[ATK_ROLE_GLASS_PANE] = Accessibility_ROLE_GLASS_PANE;
294   role_table[ATK_ROLE_HTML_CONTAINER] = Accessibility_ROLE_HTML_CONTAINER;
295   role_table[ATK_ROLE_ICON] = Accessibility_ROLE_ICON;
296   role_table[ATK_ROLE_IMAGE] = Accessibility_ROLE_IMAGE;
297   role_table[ATK_ROLE_INTERNAL_FRAME] = Accessibility_ROLE_INTERNAL_FRAME;
298   role_table[ATK_ROLE_LABEL] = Accessibility_ROLE_LABEL;
299   role_table[ATK_ROLE_LAYERED_PANE] = Accessibility_ROLE_LAYERED_PANE;
300   role_table[ATK_ROLE_LIST] = Accessibility_ROLE_LIST;
301   role_table[ATK_ROLE_LIST_ITEM] = Accessibility_ROLE_LIST_ITEM;
302   role_table[ATK_ROLE_MENU] = Accessibility_ROLE_MENU;
303   role_table[ATK_ROLE_MENU_BAR] = Accessibility_ROLE_MENU_BAR;
304   role_table[ATK_ROLE_MENU_ITEM] = Accessibility_ROLE_MENU_ITEM;
305   role_table[ATK_ROLE_OPTION_PANE] = Accessibility_ROLE_OPTION_PANE;
306   role_table[ATK_ROLE_PAGE_TAB] = Accessibility_ROLE_PAGE_TAB;
307   role_table[ATK_ROLE_PAGE_TAB_LIST] = Accessibility_ROLE_PAGE_TAB_LIST;
308   role_table[ATK_ROLE_PANEL] = Accessibility_ROLE_PANEL;
309   role_table[ATK_ROLE_PASSWORD_TEXT] = Accessibility_ROLE_PASSWORD_TEXT;
310   role_table[ATK_ROLE_POPUP_MENU] = Accessibility_ROLE_POPUP_MENU;
311   role_table[ATK_ROLE_PROGRESS_BAR] = Accessibility_ROLE_PROGRESS_BAR;
312   role_table[ATK_ROLE_PUSH_BUTTON] = Accessibility_ROLE_PUSH_BUTTON;
313   role_table[ATK_ROLE_RADIO_BUTTON] = Accessibility_ROLE_RADIO_BUTTON;
314   role_table[ATK_ROLE_RADIO_MENU_ITEM] = Accessibility_ROLE_RADIO_MENU_ITEM;
315   role_table[ATK_ROLE_ROOT_PANE] = Accessibility_ROLE_ROOT_PANE;
316   role_table[ATK_ROLE_ROW_HEADER] = Accessibility_ROLE_ROW_HEADER;
317   role_table[ATK_ROLE_SCROLL_BAR] = Accessibility_ROLE_SCROLL_BAR;
318   role_table[ATK_ROLE_SCROLL_PANE] = Accessibility_ROLE_SCROLL_PANE;
319   role_table[ATK_ROLE_SEPARATOR] = Accessibility_ROLE_SEPARATOR;
320   role_table[ATK_ROLE_SLIDER] = Accessibility_ROLE_SLIDER;
321   role_table[ATK_ROLE_SPIN_BUTTON] = Accessibility_ROLE_SPIN_BUTTON;
322   role_table[ATK_ROLE_SPLIT_PANE] = Accessibility_ROLE_SPLIT_PANE;
323   role_table[ATK_ROLE_STATUSBAR] = Accessibility_ROLE_STATUS_BAR;
324   role_table[ATK_ROLE_TABLE] = Accessibility_ROLE_TABLE;
325   role_table[ATK_ROLE_TABLE_CELL] = Accessibility_ROLE_TABLE_CELL;
326   role_table[ATK_ROLE_TABLE_COLUMN_HEADER] =
327     Accessibility_ROLE_TABLE_COLUMN_HEADER;
328   role_table[ATK_ROLE_TABLE_ROW_HEADER] = Accessibility_ROLE_TABLE_ROW_HEADER;
329   role_table[ATK_ROLE_TEAR_OFF_MENU_ITEM] =
330     Accessibility_ROLE_TEAROFF_MENU_ITEM;
331   role_table[ATK_ROLE_TERMINAL] = Accessibility_ROLE_TERMINAL;
332   role_table[ATK_ROLE_TEXT] = Accessibility_ROLE_TEXT;
333   role_table[ATK_ROLE_TOGGLE_BUTTON] = Accessibility_ROLE_TOGGLE_BUTTON;
334   role_table[ATK_ROLE_TOOL_BAR] = Accessibility_ROLE_TOOL_BAR;
335   role_table[ATK_ROLE_TOOL_TIP] = Accessibility_ROLE_TOOL_TIP;
336   role_table[ATK_ROLE_TREE] = Accessibility_ROLE_TREE;
337   role_table[ATK_ROLE_TREE_TABLE] = Accessibility_ROLE_TREE_TABLE;
338   role_table[ATK_ROLE_UNKNOWN] = Accessibility_ROLE_UNKNOWN;
339   role_table[ATK_ROLE_VIEWPORT] = Accessibility_ROLE_VIEWPORT;
340   role_table[ATK_ROLE_WINDOW] = Accessibility_ROLE_WINDOW;
341   role_table[ATK_ROLE_HEADER] = Accessibility_ROLE_HEADER;
342   role_table[ATK_ROLE_FOOTER] = Accessibility_ROLE_FOOTER;
343   role_table[ATK_ROLE_PARAGRAPH] = Accessibility_ROLE_PARAGRAPH;
344   role_table[ATK_ROLE_RULER] = Accessibility_ROLE_RULER;
345   role_table[ATK_ROLE_APPLICATION] = Accessibility_ROLE_APPLICATION;
346   role_table[ATK_ROLE_AUTOCOMPLETE] = Accessibility_ROLE_AUTOCOMPLETE;
347   role_table[ATK_ROLE_EDITBAR] = Accessibility_ROLE_EDITBAR;
348   role_table[ATK_ROLE_EMBEDDED] = Accessibility_ROLE_EMBEDDED;
349   role_table[ATK_ROLE_ENTRY] = Accessibility_ROLE_ENTRY;
350   role_table[ATK_ROLE_CHART] = Accessibility_ROLE_CHART;
351   role_table[ATK_ROLE_CAPTION] = Accessibility_ROLE_CAPTION;
352   role_table[ATK_ROLE_DOCUMENT_FRAME] = Accessibility_ROLE_DOCUMENT_FRAME;
353   role_table[ATK_ROLE_HEADING] = Accessibility_ROLE_HEADING;
354   role_table[ATK_ROLE_PAGE] = Accessibility_ROLE_PAGE;
355   role_table[ATK_ROLE_SECTION] = Accessibility_ROLE_SECTION;
356   role_table[ATK_ROLE_FORM] = Accessibility_ROLE_FORM;
357   role_table[ATK_ROLE_REDUNDANT_OBJECT] = Accessibility_ROLE_REDUNDANT_OBJECT;
358   role_table[ATK_ROLE_LINK] = Accessibility_ROLE_LINK;
359   role_table[ATK_ROLE_INPUT_METHOD_WINDOW] =
360     Accessibility_ROLE_INPUT_METHOD_WINDOW;
361   return TRUE;
362 }
363
364 Accessibility_Role
365 spi_accessible_role_from_atk_role (AtkRole role)
366 {
367   static gboolean is_initialized = FALSE;
368   static Accessibility_Role spi_role_table[ATK_ROLE_LAST_DEFINED];
369   Accessibility_Role spi_role;
370
371   if (!is_initialized)
372     {
373       is_initialized = spi_init_role_lookup_table (spi_role_table);
374     }
375
376   if (role >= 0 && role < ATK_ROLE_LAST_DEFINED)
377     {
378       spi_role = spi_role_table[role];
379     }
380   else
381     {
382       spi_role = Accessibility_ROLE_EXTENDED;
383     }
384   return spi_role;
385 }
386
387 static DBusMessage *
388 impl_getRole (DBusConnection * bus, DBusMessage * message, void *user_data)
389 {
390   AtkObject *object = get_object (message);
391   gint role;
392   dbus_uint32_t rv;
393   DBusMessage *reply;
394
395   if (!object)
396     return spi_dbus_general_error (message);
397   role = atk_object_get_role (object);
398   rv = spi_accessible_role_from_atk_role (role);
399   reply = dbus_message_new_method_return (message);
400   if (reply)
401     {
402       dbus_message_append_args (reply, DBUS_TYPE_UINT32, &rv,
403                                 DBUS_TYPE_INVALID);
404     }
405   return reply;
406 }
407
408 static char *
409 impl_get_role_str (void *datum)
410 {
411   g_assert (ATK_IS_OBJECT (datum));
412   return g_strdup_printf ("%d",
413                           spi_accessible_role_from_atk_role
414                           (atk_object_get_role ((AtkObject *) datum)));
415 }
416
417 static DBusMessage *
418 impl_getRoleName (DBusConnection * bus, DBusMessage * message,
419                   void *user_data)
420 {
421   AtkObject *object = get_object (message);
422   gint role;
423   const char *role_name;
424   DBusMessage *reply;
425
426   if (!object)
427     return spi_dbus_general_error (message);
428   role = atk_object_get_role (object);
429   role_name = atk_role_get_name (role);
430   if (!role_name)
431     role_name = "";
432   reply = dbus_message_new_method_return (message);
433   if (reply)
434     {
435       dbus_message_append_args (reply, DBUS_TYPE_STRING, &role_name,
436                                 DBUS_TYPE_INVALID);
437     }
438   return reply;
439 }
440
441 static DBusMessage *
442 impl_getLocalizedRoleName (DBusConnection * bus, DBusMessage * message,
443                            void *user_data)
444 {
445   AtkObject *object = get_object (message);
446   gint role;
447   const char *role_name;
448   DBusMessage *reply;
449
450   if (!object)
451     return spi_dbus_general_error (message);
452   role = atk_object_get_role (object);
453   role_name = atk_role_get_localized_name (role);
454   if (!role_name)
455     role_name = "";
456   reply = dbus_message_new_method_return (message);
457   if (reply)
458     {
459       dbus_message_append_args (reply, DBUS_TYPE_STRING, &role_name,
460                                 DBUS_TYPE_INVALID);
461     }
462   return reply;
463 }
464
465 static Accessibility_StateType *accessible_state_types = NULL;
466 static AtkStateType *atk_state_types = NULL;
467
468 static gboolean
469 spi_init_state_type_tables (void)
470 {
471   gint i;
472
473   if (accessible_state_types || atk_state_types)
474     return FALSE;
475   if (!accessible_state_types)
476     accessible_state_types =
477       g_new (Accessibility_StateType, ATK_STATE_LAST_DEFINED);
478   if (!atk_state_types)
479     atk_state_types = g_new (AtkStateType, Accessibility_STATE_LAST_DEFINED);
480   g_return_val_if_fail (accessible_state_types, FALSE);
481   g_return_val_if_fail (atk_state_types, FALSE);
482
483   for (i = 0; i < Accessibility_STATE_LAST_DEFINED; i++)
484     {
485       atk_state_types[i] = ATK_STATE_INVALID;
486     }
487
488   for (i = 0; i < ATK_STATE_LAST_DEFINED; i++)
489     {
490       accessible_state_types[i] = Accessibility_STATE_INVALID;
491     }
492
493   accessible_state_types[ATK_STATE_ACTIVE] = Accessibility_STATE_ACTIVE;
494   atk_state_types[Accessibility_STATE_ACTIVE] = ATK_STATE_ACTIVE;
495   accessible_state_types[ATK_STATE_ARMED] = Accessibility_STATE_ARMED;
496   atk_state_types[Accessibility_STATE_ARMED] = ATK_STATE_ARMED;
497   accessible_state_types[ATK_STATE_BUSY] = Accessibility_STATE_BUSY;
498   atk_state_types[Accessibility_STATE_BUSY] = ATK_STATE_BUSY;
499   accessible_state_types[ATK_STATE_CHECKED] = Accessibility_STATE_CHECKED;
500   atk_state_types[Accessibility_STATE_CHECKED] = ATK_STATE_CHECKED;
501   accessible_state_types[ATK_STATE_DEFUNCT] = Accessibility_STATE_DEFUNCT;
502   atk_state_types[Accessibility_STATE_DEFUNCT] = ATK_STATE_DEFUNCT;
503   accessible_state_types[ATK_STATE_EDITABLE] = Accessibility_STATE_EDITABLE;
504   atk_state_types[Accessibility_STATE_EDITABLE] = ATK_STATE_EDITABLE;
505   accessible_state_types[ATK_STATE_ENABLED] = Accessibility_STATE_ENABLED;
506   atk_state_types[Accessibility_STATE_ENABLED] = ATK_STATE_ENABLED;
507   accessible_state_types[ATK_STATE_EXPANDABLE] =
508     Accessibility_STATE_EXPANDABLE;
509   atk_state_types[Accessibility_STATE_EXPANDABLE] = ATK_STATE_EXPANDABLE;
510   accessible_state_types[ATK_STATE_EXPANDED] = Accessibility_STATE_EXPANDED;
511   atk_state_types[Accessibility_STATE_EXPANDED] = ATK_STATE_EXPANDED;
512   accessible_state_types[ATK_STATE_FOCUSABLE] = Accessibility_STATE_FOCUSABLE;
513   atk_state_types[Accessibility_STATE_FOCUSABLE] = ATK_STATE_FOCUSABLE;
514   accessible_state_types[ATK_STATE_FOCUSED] = Accessibility_STATE_FOCUSED;
515   atk_state_types[Accessibility_STATE_FOCUSED] = ATK_STATE_FOCUSED;
516   accessible_state_types[ATK_STATE_HORIZONTAL] =
517     Accessibility_STATE_HORIZONTAL;
518   atk_state_types[Accessibility_STATE_HORIZONTAL] = ATK_STATE_HORIZONTAL;
519   accessible_state_types[ATK_STATE_ICONIFIED] = Accessibility_STATE_ICONIFIED;
520   atk_state_types[Accessibility_STATE_ICONIFIED] = ATK_STATE_ICONIFIED;
521   accessible_state_types[ATK_STATE_MODAL] = Accessibility_STATE_MODAL;
522   atk_state_types[Accessibility_STATE_MODAL] = ATK_STATE_MODAL;
523   accessible_state_types[ATK_STATE_MULTI_LINE] =
524     Accessibility_STATE_MULTI_LINE;
525   atk_state_types[Accessibility_STATE_MULTI_LINE] = ATK_STATE_MULTI_LINE;
526   accessible_state_types[ATK_STATE_MULTISELECTABLE] =
527     Accessibility_STATE_MULTISELECTABLE;
528   atk_state_types[Accessibility_STATE_MULTISELECTABLE] =
529     ATK_STATE_MULTISELECTABLE;
530   accessible_state_types[ATK_STATE_OPAQUE] = Accessibility_STATE_OPAQUE;
531   atk_state_types[Accessibility_STATE_OPAQUE] = ATK_STATE_OPAQUE;
532   accessible_state_types[ATK_STATE_PRESSED] = Accessibility_STATE_PRESSED;
533   atk_state_types[Accessibility_STATE_PRESSED] = ATK_STATE_PRESSED;
534   accessible_state_types[ATK_STATE_RESIZABLE] = Accessibility_STATE_RESIZABLE;
535   atk_state_types[Accessibility_STATE_RESIZABLE] = ATK_STATE_RESIZABLE;
536   accessible_state_types[ATK_STATE_SELECTABLE] =
537     Accessibility_STATE_SELECTABLE;
538   atk_state_types[Accessibility_STATE_SELECTABLE] = ATK_STATE_SELECTABLE;
539   accessible_state_types[ATK_STATE_SELECTED] = Accessibility_STATE_SELECTED;
540   atk_state_types[Accessibility_STATE_SELECTED] = ATK_STATE_SELECTED;
541   accessible_state_types[ATK_STATE_SENSITIVE] = Accessibility_STATE_SENSITIVE;
542   atk_state_types[Accessibility_STATE_SENSITIVE] = ATK_STATE_SENSITIVE;
543   accessible_state_types[ATK_STATE_SHOWING] = Accessibility_STATE_SHOWING;
544   atk_state_types[Accessibility_STATE_SHOWING] = ATK_STATE_SHOWING;
545   accessible_state_types[ATK_STATE_SINGLE_LINE] =
546     Accessibility_STATE_SINGLE_LINE;
547   atk_state_types[Accessibility_STATE_SINGLE_LINE] = ATK_STATE_SINGLE_LINE;
548   accessible_state_types[ATK_STATE_STALE] = Accessibility_STATE_STALE;
549   atk_state_types[Accessibility_STATE_STALE] = ATK_STATE_STALE;
550   accessible_state_types[ATK_STATE_TRANSIENT] = Accessibility_STATE_TRANSIENT;
551   atk_state_types[Accessibility_STATE_TRANSIENT] = ATK_STATE_TRANSIENT;
552   accessible_state_types[ATK_STATE_VERTICAL] = Accessibility_STATE_VERTICAL;
553   atk_state_types[Accessibility_STATE_VERTICAL] = ATK_STATE_VERTICAL;
554   accessible_state_types[ATK_STATE_VISIBLE] = Accessibility_STATE_VISIBLE;
555   atk_state_types[Accessibility_STATE_VISIBLE] = ATK_STATE_VISIBLE;
556   accessible_state_types[ATK_STATE_MANAGES_DESCENDANTS] =
557     Accessibility_STATE_MANAGES_DESCENDANTS;
558   atk_state_types[Accessibility_STATE_MANAGES_DESCENDANTS] =
559     ATK_STATE_MANAGES_DESCENDANTS;
560   accessible_state_types[ATK_STATE_INDETERMINATE] =
561     Accessibility_STATE_INDETERMINATE;
562   atk_state_types[Accessibility_STATE_INDETERMINATE] =
563     ATK_STATE_INDETERMINATE;
564   accessible_state_types[ATK_STATE_TRUNCATED] = Accessibility_STATE_TRUNCATED;
565   atk_state_types[Accessibility_STATE_TRUNCATED] = ATK_STATE_TRUNCATED;
566   accessible_state_types[ATK_STATE_REQUIRED] = Accessibility_STATE_REQUIRED;
567   atk_state_types[Accessibility_STATE_REQUIRED] = ATK_STATE_REQUIRED;
568   accessible_state_types[ATK_STATE_INVALID_ENTRY] =
569     Accessibility_STATE_INVALID_ENTRY;
570   atk_state_types[Accessibility_STATE_INVALID_ENTRY] =
571     ATK_STATE_INVALID_ENTRY;
572   accessible_state_types[ATK_STATE_SUPPORTS_AUTOCOMPLETION] =
573     Accessibility_STATE_SUPPORTS_AUTOCOMPLETION;
574   atk_state_types[Accessibility_STATE_SUPPORTS_AUTOCOMPLETION] =
575     ATK_STATE_SUPPORTS_AUTOCOMPLETION;
576   accessible_state_types[ATK_STATE_SELECTABLE_TEXT] =
577     Accessibility_STATE_SELECTABLE_TEXT;
578   atk_state_types[Accessibility_STATE_SELECTABLE_TEXT] =
579     ATK_STATE_SELECTABLE_TEXT;
580   accessible_state_types[ATK_STATE_DEFAULT] = Accessibility_STATE_IS_DEFAULT;
581   atk_state_types[Accessibility_STATE_IS_DEFAULT] = ATK_STATE_DEFAULT;
582   accessible_state_types[ATK_STATE_VISITED] = Accessibility_STATE_VISITED;
583   atk_state_types[Accessibility_STATE_VISITED] = ATK_STATE_VISITED;
584
585
586   return TRUE;
587 }
588
589 static void
590 get_state (AtkObject * object, dbus_uint32_t * array)
591 {
592   AtkStateSet *set = atk_object_ref_state_set (object);
593   int i;
594
595   array[0] = 0;
596   array[1] = 0;
597   if (!set)
598     return;
599   spi_init_state_type_tables ();
600
601   g_assert (ATK_STATE_LAST_DEFINED <= 64);
602   for (i = 0; i < ATK_STATE_LAST_DEFINED; i++)
603     {
604       if (atk_state_set_contains_state (set, i))
605         {
606           int a = accessible_state_types[i];
607           g_assert (a < 64);
608           BITARRAY_SET (array, a);
609         }
610     }
611   g_object_unref (set);
612 }
613
614 static DBusMessage *
615 impl_getState (DBusConnection * bus, DBusMessage * message, void *user_data)
616 {
617   AtkObject *object = get_object (message);
618   dbus_uint32_t rv[2];
619   DBusMessage *reply;
620
621   if (!object)
622     return spi_dbus_general_error (message);
623   get_state (object, rv);
624   reply = dbus_message_new_method_return (message);
625   if (reply)
626     {
627       dbus_message_append_args (reply, DBUS_TYPE_ARRAY, DBUS_TYPE_INT32, &rv,
628                                 2, DBUS_TYPE_INVALID);
629     }
630   return reply;
631 }
632
633 static DBusMessage *
634 impl_getAttributes (DBusConnection * bus, DBusMessage * message,
635                     void *user_data)
636 {
637   AtkObject *object = get_object (message);
638   DBusMessage *reply;
639   AtkAttributeSet *attributes;
640   AtkAttribute *attr = NULL;
641   char **retval;
642   gint n_attributes = 0;
643   gint i;
644
645   if (!object)
646     return spi_dbus_general_error (message);
647
648   attributes = atk_object_get_attributes (object);
649   if (attributes)
650     n_attributes = g_slist_length (attributes);
651
652   retval = (char **) g_malloc (n_attributes * sizeof (char *));
653
654   for (i = 0; i < n_attributes; ++i)
655     {
656       attr = g_slist_nth_data (attributes, i);
657       retval[i] = g_strconcat (attr->name, ":", attr->value, NULL);
658     }
659   if (attributes)
660     atk_attribute_set_free (attributes);
661   reply = dbus_message_new_method_return (message);
662   if (reply)
663     {
664       dbus_message_append_args (reply, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,
665                                 &retval, n_attributes, DBUS_TYPE_INVALID);
666     }
667   for (i = 0; i < n_attributes; i++)
668     g_free (retval[i]);
669   g_free (retval);
670   return reply;
671 }
672
673 static DBusMessage *
674 impl_getApplication (DBusConnection * bus, DBusMessage * message,
675                      void *user_data)
676 {
677   AtkObject *root = atk_get_root ();
678   return spi_dbus_return_object (message, root, FALSE);
679 }
680
681 static DRouteMethod methods[] = {
682   //{impl_isEqual, "isEqual"},
683   {impl_getChildren, "getChildren"},
684   {impl_getIndexInParent, "getIndexInParent"},
685   {impl_getRelationSet, "getRelationSet"},
686   {impl_getRole, "getRole"},
687   {impl_getRoleName, "getRoleName"},
688   {impl_getLocalizedRoleName, "getLocalizedRoleName"},
689   {impl_getState, "getState"},
690   {impl_getAttributes, "getAttributes"},
691   {impl_getApplication, "getApplication"},
692   {NULL, NULL}
693 };
694
695 static DRouteProperty properties[] = {
696   {impl_get_name, impl_set_name, "name"},
697   {impl_get_description, impl_set_description, "description"},
698   {impl_get_parent, NULL, "parent"},
699   //{impl_get_childCount, NULL, "childCount"},
700   //{NULL, NULL, NULL, "role"},
701   {NULL, NULL, NULL}
702 };
703
704 void
705 spi_initialize_accessible (DRouteData * data)
706 {
707   droute_add_interface (data, SPI_DBUS_INTERFACE_ACCESSIBLE,
708                         methods, properties,
709                         (DRouteGetDatumFunction) get_object_from_path, NULL);
710 };