2008-05-16 Mark Doffman <mark.doffman@codethink.co.uk>
[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 #if 0
159 static DBusMessage *
160 impl_getRelationSet (DBusConnection * bus, DBusMessage * message,
161                      void *user_data)
162 {
163 }
164 #endif
165
166 static gboolean
167 spi_init_role_lookup_table (Accessibility_Role * role_table)
168 {
169   int i;
170   /* if it's not in the list below, dunno what it is */
171   for (i = 0; i < ATK_ROLE_LAST_DEFINED; ++i)
172     {
173       role_table[i] = Accessibility_ROLE_UNKNOWN;
174     }
175
176   role_table[ATK_ROLE_INVALID] = Accessibility_ROLE_INVALID;
177   role_table[ATK_ROLE_ACCEL_LABEL] = Accessibility_ROLE_ACCELERATOR_LABEL;
178   role_table[ATK_ROLE_ALERT] = Accessibility_ROLE_ALERT;
179   role_table[ATK_ROLE_ANIMATION] = Accessibility_ROLE_ANIMATION;
180   role_table[ATK_ROLE_ARROW] = Accessibility_ROLE_ARROW;
181   role_table[ATK_ROLE_CALENDAR] = Accessibility_ROLE_CALENDAR;
182   role_table[ATK_ROLE_CANVAS] = Accessibility_ROLE_CANVAS;
183   role_table[ATK_ROLE_CHECK_BOX] = Accessibility_ROLE_CHECK_BOX;
184   role_table[ATK_ROLE_CHECK_MENU_ITEM] = Accessibility_ROLE_CHECK_MENU_ITEM;
185   role_table[ATK_ROLE_COLOR_CHOOSER] = Accessibility_ROLE_COLOR_CHOOSER;
186   role_table[ATK_ROLE_COLUMN_HEADER] = Accessibility_ROLE_COLUMN_HEADER;
187   role_table[ATK_ROLE_COMBO_BOX] = Accessibility_ROLE_COMBO_BOX;
188   role_table[ATK_ROLE_DATE_EDITOR] = Accessibility_ROLE_DATE_EDITOR;
189   role_table[ATK_ROLE_DESKTOP_ICON] = Accessibility_ROLE_DESKTOP_ICON;
190   role_table[ATK_ROLE_DESKTOP_FRAME] = Accessibility_ROLE_DESKTOP_FRAME;
191   role_table[ATK_ROLE_DIAL] = Accessibility_ROLE_DIAL;
192   role_table[ATK_ROLE_DIALOG] = Accessibility_ROLE_DIALOG;
193   role_table[ATK_ROLE_DIRECTORY_PANE] = Accessibility_ROLE_DIRECTORY_PANE;
194   role_table[ATK_ROLE_DRAWING_AREA] = Accessibility_ROLE_DRAWING_AREA;
195   role_table[ATK_ROLE_FILE_CHOOSER] = Accessibility_ROLE_FILE_CHOOSER;
196   role_table[ATK_ROLE_FILLER] = Accessibility_ROLE_FILLER;
197   role_table[ATK_ROLE_FONT_CHOOSER] = Accessibility_ROLE_FONT_CHOOSER;
198   role_table[ATK_ROLE_FRAME] = Accessibility_ROLE_FRAME;
199   role_table[ATK_ROLE_GLASS_PANE] = Accessibility_ROLE_GLASS_PANE;
200   role_table[ATK_ROLE_HTML_CONTAINER] = Accessibility_ROLE_HTML_CONTAINER;
201   role_table[ATK_ROLE_ICON] = Accessibility_ROLE_ICON;
202   role_table[ATK_ROLE_IMAGE] = Accessibility_ROLE_IMAGE;
203   role_table[ATK_ROLE_INTERNAL_FRAME] = Accessibility_ROLE_INTERNAL_FRAME;
204   role_table[ATK_ROLE_LABEL] = Accessibility_ROLE_LABEL;
205   role_table[ATK_ROLE_LAYERED_PANE] = Accessibility_ROLE_LAYERED_PANE;
206   role_table[ATK_ROLE_LIST] = Accessibility_ROLE_LIST;
207   role_table[ATK_ROLE_LIST_ITEM] = Accessibility_ROLE_LIST_ITEM;
208   role_table[ATK_ROLE_MENU] = Accessibility_ROLE_MENU;
209   role_table[ATK_ROLE_MENU_BAR] = Accessibility_ROLE_MENU_BAR;
210   role_table[ATK_ROLE_MENU_ITEM] = Accessibility_ROLE_MENU_ITEM;
211   role_table[ATK_ROLE_OPTION_PANE] = Accessibility_ROLE_OPTION_PANE;
212   role_table[ATK_ROLE_PAGE_TAB] = Accessibility_ROLE_PAGE_TAB;
213   role_table[ATK_ROLE_PAGE_TAB_LIST] = Accessibility_ROLE_PAGE_TAB_LIST;
214   role_table[ATK_ROLE_PANEL] = Accessibility_ROLE_PANEL;
215   role_table[ATK_ROLE_PASSWORD_TEXT] = Accessibility_ROLE_PASSWORD_TEXT;
216   role_table[ATK_ROLE_POPUP_MENU] = Accessibility_ROLE_POPUP_MENU;
217   role_table[ATK_ROLE_PROGRESS_BAR] = Accessibility_ROLE_PROGRESS_BAR;
218   role_table[ATK_ROLE_PUSH_BUTTON] = Accessibility_ROLE_PUSH_BUTTON;
219   role_table[ATK_ROLE_RADIO_BUTTON] = Accessibility_ROLE_RADIO_BUTTON;
220   role_table[ATK_ROLE_RADIO_MENU_ITEM] = Accessibility_ROLE_RADIO_MENU_ITEM;
221   role_table[ATK_ROLE_ROOT_PANE] = Accessibility_ROLE_ROOT_PANE;
222   role_table[ATK_ROLE_ROW_HEADER] = Accessibility_ROLE_ROW_HEADER;
223   role_table[ATK_ROLE_SCROLL_BAR] = Accessibility_ROLE_SCROLL_BAR;
224   role_table[ATK_ROLE_SCROLL_PANE] = Accessibility_ROLE_SCROLL_PANE;
225   role_table[ATK_ROLE_SEPARATOR] = Accessibility_ROLE_SEPARATOR;
226   role_table[ATK_ROLE_SLIDER] = Accessibility_ROLE_SLIDER;
227   role_table[ATK_ROLE_SPIN_BUTTON] = Accessibility_ROLE_SPIN_BUTTON;
228   role_table[ATK_ROLE_SPLIT_PANE] = Accessibility_ROLE_SPLIT_PANE;
229   role_table[ATK_ROLE_STATUSBAR] = Accessibility_ROLE_STATUS_BAR;
230   role_table[ATK_ROLE_TABLE] = Accessibility_ROLE_TABLE;
231   role_table[ATK_ROLE_TABLE_CELL] = Accessibility_ROLE_TABLE_CELL;
232   role_table[ATK_ROLE_TABLE_COLUMN_HEADER] =
233     Accessibility_ROLE_TABLE_COLUMN_HEADER;
234   role_table[ATK_ROLE_TABLE_ROW_HEADER] = Accessibility_ROLE_TABLE_ROW_HEADER;
235   role_table[ATK_ROLE_TEAR_OFF_MENU_ITEM] =
236     Accessibility_ROLE_TEAROFF_MENU_ITEM;
237   role_table[ATK_ROLE_TERMINAL] = Accessibility_ROLE_TERMINAL;
238   role_table[ATK_ROLE_TEXT] = Accessibility_ROLE_TEXT;
239   role_table[ATK_ROLE_TOGGLE_BUTTON] = Accessibility_ROLE_TOGGLE_BUTTON;
240   role_table[ATK_ROLE_TOOL_BAR] = Accessibility_ROLE_TOOL_BAR;
241   role_table[ATK_ROLE_TOOL_TIP] = Accessibility_ROLE_TOOL_TIP;
242   role_table[ATK_ROLE_TREE] = Accessibility_ROLE_TREE;
243   role_table[ATK_ROLE_TREE_TABLE] = Accessibility_ROLE_TREE_TABLE;
244   role_table[ATK_ROLE_UNKNOWN] = Accessibility_ROLE_UNKNOWN;
245   role_table[ATK_ROLE_VIEWPORT] = Accessibility_ROLE_VIEWPORT;
246   role_table[ATK_ROLE_WINDOW] = Accessibility_ROLE_WINDOW;
247   role_table[ATK_ROLE_HEADER] = Accessibility_ROLE_HEADER;
248   role_table[ATK_ROLE_FOOTER] = Accessibility_ROLE_FOOTER;
249   role_table[ATK_ROLE_PARAGRAPH] = Accessibility_ROLE_PARAGRAPH;
250   role_table[ATK_ROLE_RULER] = Accessibility_ROLE_RULER;
251   role_table[ATK_ROLE_APPLICATION] = Accessibility_ROLE_APPLICATION;
252   role_table[ATK_ROLE_AUTOCOMPLETE] = Accessibility_ROLE_AUTOCOMPLETE;
253   role_table[ATK_ROLE_EDITBAR] = Accessibility_ROLE_EDITBAR;
254   role_table[ATK_ROLE_EMBEDDED] = Accessibility_ROLE_EMBEDDED;
255   role_table[ATK_ROLE_ENTRY] = Accessibility_ROLE_ENTRY;
256   role_table[ATK_ROLE_CHART] = Accessibility_ROLE_CHART;
257   role_table[ATK_ROLE_CAPTION] = Accessibility_ROLE_CAPTION;
258   role_table[ATK_ROLE_DOCUMENT_FRAME] = Accessibility_ROLE_DOCUMENT_FRAME;
259   role_table[ATK_ROLE_HEADING] = Accessibility_ROLE_HEADING;
260   role_table[ATK_ROLE_PAGE] = Accessibility_ROLE_PAGE;
261   role_table[ATK_ROLE_SECTION] = Accessibility_ROLE_SECTION;
262   role_table[ATK_ROLE_FORM] = Accessibility_ROLE_FORM;
263   role_table[ATK_ROLE_REDUNDANT_OBJECT] = Accessibility_ROLE_REDUNDANT_OBJECT;
264   role_table[ATK_ROLE_LINK] = Accessibility_ROLE_LINK;
265   role_table[ATK_ROLE_INPUT_METHOD_WINDOW] =
266     Accessibility_ROLE_INPUT_METHOD_WINDOW;
267   return TRUE;
268 }
269
270 Accessibility_Role
271 spi_accessible_role_from_atk_role (AtkRole role)
272 {
273   static gboolean is_initialized = FALSE;
274   static Accessibility_Role spi_role_table[ATK_ROLE_LAST_DEFINED];
275   Accessibility_Role spi_role;
276
277   if (!is_initialized)
278     {
279       is_initialized = spi_init_role_lookup_table (spi_role_table);
280     }
281
282   if (role >= 0 && role < ATK_ROLE_LAST_DEFINED)
283     {
284       spi_role = spi_role_table[role];
285     }
286   else
287     {
288       spi_role = Accessibility_ROLE_EXTENDED;
289     }
290   return spi_role;
291 }
292
293 static DBusMessage *
294 impl_getRole (DBusConnection * bus, DBusMessage * message, void *user_data)
295 {
296   AtkObject *object = get_object (message);
297   gint role;
298   dbus_uint32_t rv;
299   DBusMessage *reply;
300
301   if (!object)
302     return spi_dbus_general_error (message);
303   role = atk_object_get_role (object);
304   rv = spi_accessible_role_from_atk_role (role);
305   reply = dbus_message_new_method_return (message);
306   if (reply)
307     {
308       dbus_message_append_args (reply, DBUS_TYPE_UINT32, &rv,
309                                 DBUS_TYPE_INVALID);
310     }
311   return reply;
312 }
313
314 static char *
315 impl_get_role_str (void *datum)
316 {
317   g_assert (ATK_IS_OBJECT (datum));
318   return g_strdup_printf ("%d",
319                           spi_accessible_role_from_atk_role
320                           (atk_object_get_role ((AtkObject *) datum)));
321 }
322
323 static DBusMessage *
324 impl_getRoleName (DBusConnection * bus, DBusMessage * message,
325                   void *user_data)
326 {
327   AtkObject *object = get_object (message);
328   gint role;
329   const char *role_name;
330   DBusMessage *reply;
331
332   if (!object)
333     return spi_dbus_general_error (message);
334   role = atk_object_get_role (object);
335   role_name = atk_role_get_name (role);
336   if (!role_name)
337     role_name = "";
338   reply = dbus_message_new_method_return (message);
339   if (reply)
340     {
341       dbus_message_append_args (reply, DBUS_TYPE_STRING, &role_name,
342                                 DBUS_TYPE_INVALID);
343     }
344   return reply;
345 }
346
347 static DBusMessage *
348 impl_getLocalizedRoleName (DBusConnection * bus, DBusMessage * message,
349                            void *user_data)
350 {
351   AtkObject *object = get_object (message);
352   gint role;
353   const char *role_name;
354   DBusMessage *reply;
355
356   if (!object)
357     return spi_dbus_general_error (message);
358   role = atk_object_get_role (object);
359   role_name = atk_role_get_localized_name (role);
360   if (!role_name)
361     role_name = "";
362   reply = dbus_message_new_method_return (message);
363   if (reply)
364     {
365       dbus_message_append_args (reply, DBUS_TYPE_STRING, &role_name,
366                                 DBUS_TYPE_INVALID);
367     }
368   return reply;
369 }
370
371 static Accessibility_StateType *accessible_state_types = NULL;
372 static AtkStateType *atk_state_types = NULL;
373
374 static gboolean
375 spi_init_state_type_tables (void)
376 {
377   gint i;
378
379   if (accessible_state_types || atk_state_types)
380     return FALSE;
381   if (!accessible_state_types)
382     accessible_state_types =
383       g_new (Accessibility_StateType, ATK_STATE_LAST_DEFINED);
384   if (!atk_state_types)
385     atk_state_types = g_new (AtkStateType, Accessibility_STATE_LAST_DEFINED);
386   g_return_val_if_fail (accessible_state_types, FALSE);
387   g_return_val_if_fail (atk_state_types, FALSE);
388
389   for (i = 0; i < Accessibility_STATE_LAST_DEFINED; i++)
390     {
391       atk_state_types[i] = ATK_STATE_INVALID;
392     }
393
394   for (i = 0; i < ATK_STATE_LAST_DEFINED; i++)
395     {
396       accessible_state_types[i] = Accessibility_STATE_INVALID;
397     }
398
399   accessible_state_types[ATK_STATE_ACTIVE] = Accessibility_STATE_ACTIVE;
400   atk_state_types[Accessibility_STATE_ACTIVE] = ATK_STATE_ACTIVE;
401   accessible_state_types[ATK_STATE_ARMED] = Accessibility_STATE_ARMED;
402   atk_state_types[Accessibility_STATE_ARMED] = ATK_STATE_ARMED;
403   accessible_state_types[ATK_STATE_BUSY] = Accessibility_STATE_BUSY;
404   atk_state_types[Accessibility_STATE_BUSY] = ATK_STATE_BUSY;
405   accessible_state_types[ATK_STATE_CHECKED] = Accessibility_STATE_CHECKED;
406   atk_state_types[Accessibility_STATE_CHECKED] = ATK_STATE_CHECKED;
407   accessible_state_types[ATK_STATE_DEFUNCT] = Accessibility_STATE_DEFUNCT;
408   atk_state_types[Accessibility_STATE_DEFUNCT] = ATK_STATE_DEFUNCT;
409   accessible_state_types[ATK_STATE_EDITABLE] = Accessibility_STATE_EDITABLE;
410   atk_state_types[Accessibility_STATE_EDITABLE] = ATK_STATE_EDITABLE;
411   accessible_state_types[ATK_STATE_ENABLED] = Accessibility_STATE_ENABLED;
412   atk_state_types[Accessibility_STATE_ENABLED] = ATK_STATE_ENABLED;
413   accessible_state_types[ATK_STATE_EXPANDABLE] =
414     Accessibility_STATE_EXPANDABLE;
415   atk_state_types[Accessibility_STATE_EXPANDABLE] = ATK_STATE_EXPANDABLE;
416   accessible_state_types[ATK_STATE_EXPANDED] = Accessibility_STATE_EXPANDED;
417   atk_state_types[Accessibility_STATE_EXPANDED] = ATK_STATE_EXPANDED;
418   accessible_state_types[ATK_STATE_FOCUSABLE] = Accessibility_STATE_FOCUSABLE;
419   atk_state_types[Accessibility_STATE_FOCUSABLE] = ATK_STATE_FOCUSABLE;
420   accessible_state_types[ATK_STATE_FOCUSED] = Accessibility_STATE_FOCUSED;
421   atk_state_types[Accessibility_STATE_FOCUSED] = ATK_STATE_FOCUSED;
422   accessible_state_types[ATK_STATE_HORIZONTAL] =
423     Accessibility_STATE_HORIZONTAL;
424   atk_state_types[Accessibility_STATE_HORIZONTAL] = ATK_STATE_HORIZONTAL;
425   accessible_state_types[ATK_STATE_ICONIFIED] = Accessibility_STATE_ICONIFIED;
426   atk_state_types[Accessibility_STATE_ICONIFIED] = ATK_STATE_ICONIFIED;
427   accessible_state_types[ATK_STATE_MODAL] = Accessibility_STATE_MODAL;
428   atk_state_types[Accessibility_STATE_MODAL] = ATK_STATE_MODAL;
429   accessible_state_types[ATK_STATE_MULTI_LINE] =
430     Accessibility_STATE_MULTI_LINE;
431   atk_state_types[Accessibility_STATE_MULTI_LINE] = ATK_STATE_MULTI_LINE;
432   accessible_state_types[ATK_STATE_MULTISELECTABLE] =
433     Accessibility_STATE_MULTISELECTABLE;
434   atk_state_types[Accessibility_STATE_MULTISELECTABLE] =
435     ATK_STATE_MULTISELECTABLE;
436   accessible_state_types[ATK_STATE_OPAQUE] = Accessibility_STATE_OPAQUE;
437   atk_state_types[Accessibility_STATE_OPAQUE] = ATK_STATE_OPAQUE;
438   accessible_state_types[ATK_STATE_PRESSED] = Accessibility_STATE_PRESSED;
439   atk_state_types[Accessibility_STATE_PRESSED] = ATK_STATE_PRESSED;
440   accessible_state_types[ATK_STATE_RESIZABLE] = Accessibility_STATE_RESIZABLE;
441   atk_state_types[Accessibility_STATE_RESIZABLE] = ATK_STATE_RESIZABLE;
442   accessible_state_types[ATK_STATE_SELECTABLE] =
443     Accessibility_STATE_SELECTABLE;
444   atk_state_types[Accessibility_STATE_SELECTABLE] = ATK_STATE_SELECTABLE;
445   accessible_state_types[ATK_STATE_SELECTED] = Accessibility_STATE_SELECTED;
446   atk_state_types[Accessibility_STATE_SELECTED] = ATK_STATE_SELECTED;
447   accessible_state_types[ATK_STATE_SENSITIVE] = Accessibility_STATE_SENSITIVE;
448   atk_state_types[Accessibility_STATE_SENSITIVE] = ATK_STATE_SENSITIVE;
449   accessible_state_types[ATK_STATE_SHOWING] = Accessibility_STATE_SHOWING;
450   atk_state_types[Accessibility_STATE_SHOWING] = ATK_STATE_SHOWING;
451   accessible_state_types[ATK_STATE_SINGLE_LINE] =
452     Accessibility_STATE_SINGLE_LINE;
453   atk_state_types[Accessibility_STATE_SINGLE_LINE] = ATK_STATE_SINGLE_LINE;
454   accessible_state_types[ATK_STATE_STALE] = Accessibility_STATE_STALE;
455   atk_state_types[Accessibility_STATE_STALE] = ATK_STATE_STALE;
456   accessible_state_types[ATK_STATE_TRANSIENT] = Accessibility_STATE_TRANSIENT;
457   atk_state_types[Accessibility_STATE_TRANSIENT] = ATK_STATE_TRANSIENT;
458   accessible_state_types[ATK_STATE_VERTICAL] = Accessibility_STATE_VERTICAL;
459   atk_state_types[Accessibility_STATE_VERTICAL] = ATK_STATE_VERTICAL;
460   accessible_state_types[ATK_STATE_VISIBLE] = Accessibility_STATE_VISIBLE;
461   atk_state_types[Accessibility_STATE_VISIBLE] = ATK_STATE_VISIBLE;
462   accessible_state_types[ATK_STATE_MANAGES_DESCENDANTS] =
463     Accessibility_STATE_MANAGES_DESCENDANTS;
464   atk_state_types[Accessibility_STATE_MANAGES_DESCENDANTS] =
465     ATK_STATE_MANAGES_DESCENDANTS;
466   accessible_state_types[ATK_STATE_INDETERMINATE] =
467     Accessibility_STATE_INDETERMINATE;
468   atk_state_types[Accessibility_STATE_INDETERMINATE] =
469     ATK_STATE_INDETERMINATE;
470   accessible_state_types[ATK_STATE_TRUNCATED] = Accessibility_STATE_TRUNCATED;
471   atk_state_types[Accessibility_STATE_TRUNCATED] = ATK_STATE_TRUNCATED;
472   accessible_state_types[ATK_STATE_REQUIRED] = Accessibility_STATE_REQUIRED;
473   atk_state_types[Accessibility_STATE_REQUIRED] = ATK_STATE_REQUIRED;
474   accessible_state_types[ATK_STATE_INVALID_ENTRY] =
475     Accessibility_STATE_INVALID_ENTRY;
476   atk_state_types[Accessibility_STATE_INVALID_ENTRY] =
477     ATK_STATE_INVALID_ENTRY;
478   accessible_state_types[ATK_STATE_SUPPORTS_AUTOCOMPLETION] =
479     Accessibility_STATE_SUPPORTS_AUTOCOMPLETION;
480   atk_state_types[Accessibility_STATE_SUPPORTS_AUTOCOMPLETION] =
481     ATK_STATE_SUPPORTS_AUTOCOMPLETION;
482   accessible_state_types[ATK_STATE_SELECTABLE_TEXT] =
483     Accessibility_STATE_SELECTABLE_TEXT;
484   atk_state_types[Accessibility_STATE_SELECTABLE_TEXT] =
485     ATK_STATE_SELECTABLE_TEXT;
486   accessible_state_types[ATK_STATE_DEFAULT] = Accessibility_STATE_IS_DEFAULT;
487   atk_state_types[Accessibility_STATE_IS_DEFAULT] = ATK_STATE_DEFAULT;
488   accessible_state_types[ATK_STATE_VISITED] = Accessibility_STATE_VISITED;
489   atk_state_types[Accessibility_STATE_VISITED] = ATK_STATE_VISITED;
490
491
492   return TRUE;
493 }
494
495 static void
496 get_state (AtkObject * object, dbus_uint32_t * array)
497 {
498   AtkStateSet *set = atk_object_ref_state_set (object);
499   int i;
500
501   array[0] = 0;
502   array[1] = 0;
503   if (!set)
504     return;
505   spi_init_state_type_tables ();
506
507   g_assert (ATK_STATE_LAST_DEFINED <= 64);
508   for (i = 0; i < ATK_STATE_LAST_DEFINED; i++)
509     {
510       if (atk_state_set_contains_state (set, i))
511         {
512           int a = accessible_state_types[i];
513           g_assert (a < 64);
514           BITARRAY_SET (array, a);
515         }
516     }
517   g_object_unref (set);
518 }
519
520 static DBusMessage *
521 impl_getState (DBusConnection * bus, DBusMessage * message, void *user_data)
522 {
523   AtkObject *object = get_object (message);
524   dbus_uint32_t rv[2];
525   DBusMessage *reply;
526
527   if (!object)
528     return spi_dbus_general_error (message);
529   get_state (object, rv);
530   reply = dbus_message_new_method_return (message);
531   if (reply)
532     {
533       dbus_message_append_args (reply, DBUS_TYPE_ARRAY, DBUS_TYPE_INT32, &rv,
534                                 2, DBUS_TYPE_INVALID);
535     }
536   return reply;
537 }
538
539 static DBusMessage *
540 impl_getAttributes (DBusConnection * bus, DBusMessage * message,
541                     void *user_data)
542 {
543   AtkObject *object = get_object (message);
544   DBusMessage *reply;
545   AtkAttributeSet *attributes;
546   AtkAttribute *attr = NULL;
547   char **retval;
548   gint n_attributes = 0;
549   gint i;
550
551   if (!object)
552     return spi_dbus_general_error (message);
553
554   attributes = atk_object_get_attributes (object);
555   if (attributes)
556     n_attributes = g_slist_length (attributes);
557
558   retval = (char **) g_malloc (n_attributes * sizeof (char *));
559
560   for (i = 0; i < n_attributes; ++i)
561     {
562       attr = g_slist_nth_data (attributes, i);
563       retval[i] = g_strconcat (attr->name, ":", attr->value, NULL);
564     }
565   if (attributes)
566     atk_attribute_set_free (attributes);
567   reply = dbus_message_new_method_return (message);
568   if (reply)
569     {
570       dbus_message_append_args (reply, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,
571                                 &retval, n_attributes, DBUS_TYPE_INVALID);
572     }
573   for (i = 0; i < n_attributes; i++)
574     g_free (retval[i]);
575   g_free (retval);
576   return reply;
577 }
578
579 static DBusMessage *
580 impl_getApplication (DBusConnection * bus, DBusMessage * message,
581                      void *user_data)
582 {
583   AtkObject *root = atk_get_root ();
584   return spi_dbus_return_object (message, root, FALSE);
585 }
586
587 static DRouteMethod methods[] = {
588   //{impl_isEqual, "isEqual"},
589   {impl_getChildren, "getChildren"},
590   {impl_getIndexInParent, "getIndexInParent"},
591   //{impl_getRelationSet, "getRelationSet"},,o" },
592   {impl_getRole, "getRole"},
593   {impl_getRoleName, "getRoleName"},
594   {impl_getLocalizedRoleName, "getLocalizedRoleName"},
595   {impl_getState, "getState"},
596   {impl_getAttributes, "getAttributes"},
597   {impl_getApplication, "getApplication"},
598   {NULL, NULL}
599 };
600
601 static DRouteProperty properties[] = {
602   {impl_get_name, impl_set_name, "name"},
603   {impl_get_description, impl_set_description, "description"},
604   {impl_get_parent, NULL, "parent"},
605   //{impl_get_childCount, NULL, "childCount"},
606   //{NULL, NULL, NULL, "role"},
607   {NULL, NULL, NULL}
608 };
609
610 void
611 spi_initialize_accessible (DRouteData * data)
612 {
613   droute_add_interface (data, "org.freedesktop.atspi.Accessible",
614                         methods, properties,
615                         (DRouteGetDatumFunction) get_object_from_path, NULL);
616 };