26fec2b9b3300dec9afb4c9b2f2c6b5debd8601d
[platform/core/uifw/at-spi2-atk.git] / atk-adaptor / adaptors / table-adaptor.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 <atk/atk.h>
26 #include <droute/droute.h>
27
28 #include "spi-dbus.h"
29 #include "object.h"
30 #include "introspection.h"
31
32 static dbus_bool_t
33 impl_get_NRows (DBusMessageIter * iter, void *user_data)
34 {
35   AtkTable *table = (AtkTable *) user_data;
36   g_return_val_if_fail (ATK_IS_TABLE (user_data), FALSE);
37   return droute_return_v_int32 (iter, atk_table_get_n_rows (table));
38 }
39
40 static dbus_bool_t
41 impl_get_NColumns (DBusMessageIter * iter, void *user_data)
42 {
43   AtkTable *table = (AtkTable *) user_data;
44   g_return_val_if_fail (ATK_IS_TABLE (user_data), FALSE);
45   return droute_return_v_int32 (iter, atk_table_get_n_columns (table));
46 }
47
48 static dbus_bool_t
49 impl_get_Caption (DBusMessageIter * iter, void *user_data)
50 {
51   AtkTable *table = (AtkTable *) user_data;
52   g_return_val_if_fail (ATK_IS_TABLE (user_data), FALSE);
53   spi_object_append_v_reference (iter, atk_table_get_caption (table));
54   return TRUE;
55 }
56
57 static dbus_bool_t
58 impl_get_Summary (DBusMessageIter * iter, void *user_data)
59 {
60   AtkTable *table = (AtkTable *) user_data;
61   g_return_val_if_fail (ATK_IS_TABLE (user_data), FALSE);
62   spi_object_append_v_reference (iter, atk_table_get_summary (table));
63   return TRUE;
64 }
65
66 static dbus_bool_t
67 impl_get_NSelectedRows (DBusMessageIter * iter, void *user_data)
68 {
69   AtkTable *table = (AtkTable *) user_data;
70   gint *selected_rows = NULL;
71   int count;
72   g_return_val_if_fail (ATK_IS_TABLE (user_data), FALSE);
73   count = atk_table_get_selected_rows (table, &selected_rows);
74   if (selected_rows)
75     g_free (selected_rows);
76   return droute_return_v_int32 (iter, count);
77 }
78
79 static dbus_bool_t
80 impl_get_NSelectedColumns (DBusMessageIter * iter, void *user_data)
81 {
82   AtkTable *table = (AtkTable *) user_data;
83   gint *selected_columns = NULL;
84   int count;
85   g_return_val_if_fail (ATK_IS_TABLE (user_data), FALSE);
86   count = atk_table_get_selected_columns (table, &selected_columns);
87   if (selected_columns)
88     g_free (selected_columns);
89   return droute_return_v_int32 (iter, count);
90 }
91
92 static DBusMessage *
93 impl_GetAccessibleAt (DBusConnection * bus, DBusMessage * message,
94                       void *user_data)
95 {
96   AtkTable *table = (AtkTable *) user_data;
97   dbus_int32_t row, column;
98   DBusMessage *reply;
99   DBusError error;
100   AtkObject *obj;
101
102   g_return_val_if_fail (ATK_IS_TABLE (user_data),
103                         droute_not_yet_handled_error (message));
104   dbus_error_init (&error);
105   if (!dbus_message_get_args
106       (message, &error, DBUS_TYPE_INT32, &row, DBUS_TYPE_INT32, &column,
107        DBUS_TYPE_INVALID))
108     {
109       return droute_invalid_arguments_error (message);
110     }
111   obj = atk_table_ref_at (table, row, column);
112   reply = spi_object_return_reference (message, obj);
113   g_object_unref (obj);
114
115   return reply;
116 }
117
118 static DBusMessage *
119 impl_GetIndexAt (DBusConnection * bus, DBusMessage * message, void *user_data)
120 {
121   AtkTable *table = (AtkTable *) user_data;
122   dbus_int32_t row, column;
123   dbus_int32_t index;
124   DBusError error;
125   DBusMessage *reply;
126
127   g_return_val_if_fail (ATK_IS_TABLE (user_data),
128                         droute_not_yet_handled_error (message));
129   dbus_error_init (&error);
130   if (!dbus_message_get_args
131       (message, &error, DBUS_TYPE_INT32, &row, DBUS_TYPE_INT32, &column,
132        DBUS_TYPE_INVALID))
133     {
134       return droute_invalid_arguments_error (message);
135     }
136   index = atk_table_get_index_at (table, row, column);
137   reply = dbus_message_new_method_return (message);
138   if (reply)
139     {
140       dbus_message_append_args (reply, DBUS_TYPE_INT32, &index,
141                                 DBUS_TYPE_INVALID);
142     }
143   return reply;
144 }
145
146 static DBusMessage *
147 impl_GetRowAtIndex (DBusConnection * bus, DBusMessage * message,
148                     void *user_data)
149 {
150   AtkTable *table = (AtkTable *) user_data;
151   dbus_int32_t index;
152   dbus_int32_t row;
153   DBusError error;
154   DBusMessage *reply;
155
156   g_return_val_if_fail (ATK_IS_TABLE (user_data),
157                         droute_not_yet_handled_error (message));
158   dbus_error_init (&error);
159   if (!dbus_message_get_args
160       (message, &error, DBUS_TYPE_INT32, &index, DBUS_TYPE_INVALID))
161     {
162       return droute_invalid_arguments_error (message);
163     }
164   row = atk_table_get_row_at_index (table, index);
165   reply = dbus_message_new_method_return (message);
166   if (reply)
167     {
168       dbus_message_append_args (reply, DBUS_TYPE_INT32, &row,
169                                 DBUS_TYPE_INVALID);
170     }
171   return reply;
172 }
173
174 static DBusMessage *
175 impl_GetColumnAtIndex (DBusConnection * bus, DBusMessage * message,
176                        void *user_data)
177 {
178   AtkTable *table = (AtkTable *) user_data;
179   dbus_int32_t index;
180   dbus_int32_t column;
181   DBusError error;
182   DBusMessage *reply;
183
184   g_return_val_if_fail (ATK_IS_TABLE (user_data),
185                         droute_not_yet_handled_error (message));
186   dbus_error_init (&error);
187   if (!dbus_message_get_args
188       (message, &error, DBUS_TYPE_INT32, &index, DBUS_TYPE_INVALID))
189     {
190       return droute_invalid_arguments_error (message);
191     }
192   column = atk_table_get_column_at_index (table, index);
193   reply = dbus_message_new_method_return (message);
194   if (reply)
195     {
196       dbus_message_append_args (reply, DBUS_TYPE_INT32, &column,
197                                 DBUS_TYPE_INVALID);
198     }
199   return reply;
200 }
201
202 static const gchar *
203 validate_unallocated_string (const gchar *str)
204 {
205   if (!str)
206     return "";
207   if (!g_utf8_validate (str, -1, NULL))
208     {
209       g_warning ("atk-bridge: received bad UTF-8 string from a table function");
210       return "";
211     }
212   return str;
213 }
214
215 static DBusMessage *
216 impl_GetRowDescription (DBusConnection * bus, DBusMessage * message,
217                         void *user_data)
218 {
219   dbus_int32_t row;
220   AtkTable *table = (AtkTable *) user_data;
221   const gchar *description;
222   DBusError error;
223   DBusMessage *reply;
224
225   g_return_val_if_fail (ATK_IS_TABLE (user_data),
226                         droute_not_yet_handled_error (message));
227   dbus_error_init (&error);
228   if (!dbus_message_get_args
229       (message, &error, DBUS_TYPE_INT32, &row, DBUS_TYPE_INVALID))
230     {
231       return droute_invalid_arguments_error (message);
232     }
233   description = atk_table_get_row_description (table, row);
234   description = validate_unallocated_string (description);
235   reply = dbus_message_new_method_return (message);
236   if (reply)
237     {
238       dbus_message_append_args (reply, DBUS_TYPE_STRING, &description,
239                                 DBUS_TYPE_INVALID);
240     }
241   return reply;
242 }
243
244 static DBusMessage *
245 impl_GetColumnDescription (DBusConnection * bus, DBusMessage * message,
246                            void *user_data)
247 {
248   AtkTable *table = (AtkTable *) user_data;
249   dbus_int32_t column;
250   const char *description;
251   DBusError error;
252   DBusMessage *reply;
253
254   g_return_val_if_fail (ATK_IS_TABLE (user_data),
255                         droute_not_yet_handled_error (message));
256   dbus_error_init (&error);
257   if (!dbus_message_get_args
258       (message, &error, DBUS_TYPE_INT32, &column, DBUS_TYPE_INVALID))
259     {
260       return droute_invalid_arguments_error (message);
261     }
262   description = atk_table_get_column_description (table, column);
263   description = validate_unallocated_string (description);
264   reply = dbus_message_new_method_return (message);
265   if (reply)
266     {
267       dbus_message_append_args (reply, DBUS_TYPE_STRING, &description,
268                                 DBUS_TYPE_INVALID);
269     }
270   return reply;
271 }
272
273 static DBusMessage *
274 impl_GetRowExtentAt (DBusConnection * bus, DBusMessage * message,
275                      void *user_data)
276 {
277   AtkTable *table = (AtkTable *) user_data;
278   dbus_int32_t row, column;
279   dbus_int32_t extent;
280   DBusError error;
281   DBusMessage *reply;
282
283   g_return_val_if_fail (ATK_IS_TABLE (user_data),
284                         droute_not_yet_handled_error (message));
285   dbus_error_init (&error);
286   if (!dbus_message_get_args
287       (message, &error, DBUS_TYPE_INT32, &row, DBUS_TYPE_INT32, &column,
288        DBUS_TYPE_INVALID))
289     {
290       return droute_invalid_arguments_error (message);
291     }
292   extent = atk_table_get_row_extent_at (table, row, column);
293   reply = dbus_message_new_method_return (message);
294   if (reply)
295     {
296       dbus_message_append_args (reply, DBUS_TYPE_INT32, &extent,
297                                 DBUS_TYPE_INVALID);
298     }
299   return reply;
300 }
301
302 static DBusMessage *
303 impl_GetColumnExtentAt (DBusConnection * bus, DBusMessage * message,
304                         void *user_data)
305 {
306   AtkTable *table = (AtkTable *) user_data;
307   dbus_int32_t row, column;
308   dbus_int32_t extent;
309   DBusError error;
310   DBusMessage *reply;
311
312   g_return_val_if_fail (ATK_IS_TABLE (user_data),
313                         droute_not_yet_handled_error (message));
314   dbus_error_init (&error);
315   if (!dbus_message_get_args
316       (message, &error, DBUS_TYPE_INT32, &row, DBUS_TYPE_INT32, &column,
317        DBUS_TYPE_INVALID))
318     {
319       return droute_invalid_arguments_error (message);
320     }
321   extent = atk_table_get_column_extent_at (table, row, column);
322   reply = dbus_message_new_method_return (message);
323   if (reply)
324     {
325       dbus_message_append_args (reply, DBUS_TYPE_INT32, &extent,
326                                 DBUS_TYPE_INVALID);
327     }
328   return reply;
329 }
330
331 static DBusMessage *
332 impl_GetRowHeader (DBusConnection * bus, DBusMessage * message,
333                    void *user_data)
334 {
335   AtkTable *table = (AtkTable *) user_data;
336   dbus_int32_t row;
337   DBusError error;
338   AtkObject *obj = NULL;
339
340   g_return_val_if_fail (ATK_IS_TABLE (user_data),
341                         droute_not_yet_handled_error (message));
342   dbus_error_init (&error);
343   if (!dbus_message_get_args
344       (message, &error, DBUS_TYPE_INT32, &row, DBUS_TYPE_INVALID))
345     {
346       return droute_invalid_arguments_error (message);
347     }
348   obj = atk_table_get_row_header (table, row);
349   return spi_object_return_reference (message, obj);
350 }
351
352 static DBusMessage *
353 impl_GetColumnHeader (DBusConnection * bus, DBusMessage * message,
354                       void *user_data)
355 {
356   AtkTable *table = (AtkTable *) user_data;
357   dbus_int32_t column;
358   DBusError error;
359   AtkObject *obj;
360
361   g_return_val_if_fail (ATK_IS_TABLE (user_data),
362                         droute_not_yet_handled_error (message));
363   dbus_error_init (&error);
364   if (!dbus_message_get_args
365       (message, &error, DBUS_TYPE_INT32, &column, DBUS_TYPE_INVALID))
366     {
367       return droute_invalid_arguments_error (message);
368     }
369   obj = atk_table_get_column_header (table, column);
370   return spi_object_return_reference (message, obj);
371 }
372
373 static DBusMessage *
374 impl_GetSelectedRows (DBusConnection * bus, DBusMessage * message,
375                       void *user_data)
376 {
377   AtkTable *table = (AtkTable *) user_data;
378   gint *selected_rows = NULL;
379   gint count;
380   DBusMessage *reply;
381
382   g_return_val_if_fail (ATK_IS_TABLE (user_data),
383                         droute_not_yet_handled_error (message));
384   count = atk_table_get_selected_rows (table, &selected_rows);
385   if (!selected_rows)
386     count = 0;
387   reply = dbus_message_new_method_return (message);
388   if (reply)
389     {
390       /* tbd - figure out if this is safe for a 0-length array */
391       dbus_message_append_args (reply, DBUS_TYPE_ARRAY, DBUS_TYPE_INT32,
392                                 &selected_rows, count, DBUS_TYPE_INVALID);
393     }
394   if (selected_rows)
395     g_free (selected_rows);
396   return reply;
397 }
398
399 static DBusMessage *
400 impl_GetSelectedColumns (DBusConnection * bus, DBusMessage * message,
401                          void *user_data)
402 {
403   AtkTable *table = (AtkTable *) user_data;
404   gint *selected_columns = NULL;
405   gint count;
406   DBusMessage *reply;
407
408   g_return_val_if_fail (ATK_IS_TABLE (user_data),
409                         droute_not_yet_handled_error (message));
410   count = atk_table_get_selected_columns (table, &selected_columns);
411   if (!selected_columns)
412     count = 0;
413   reply = dbus_message_new_method_return (message);
414   if (reply)
415     {
416       /* tbd - figure out if this is safe for a 0-length array */
417       dbus_message_append_args (reply, DBUS_TYPE_ARRAY, DBUS_TYPE_INT32,
418                                 &selected_columns, count, DBUS_TYPE_INVALID);
419     }
420   if (selected_columns)
421     g_free (selected_columns);
422   return reply;
423 }
424
425 static DBusMessage *
426 impl_IsRowSelected (DBusConnection * bus, DBusMessage * message,
427                     void *user_data)
428 {
429   AtkTable *table = (AtkTable *) user_data;
430   dbus_int32_t row;
431   DBusError error;
432   DBusMessage *reply;
433   dbus_bool_t ret;
434
435   g_return_val_if_fail (ATK_IS_TABLE (user_data),
436                         droute_not_yet_handled_error (message));
437   dbus_error_init (&error);
438   if (!dbus_message_get_args
439       (message, &error, DBUS_TYPE_INT32, &row, DBUS_TYPE_INVALID))
440     {
441       return droute_invalid_arguments_error (message);
442     }
443   ret = atk_table_is_row_selected (table, row);
444   reply = dbus_message_new_method_return (message);
445   if (reply)
446     {
447       dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &ret,
448                                 DBUS_TYPE_INVALID);
449     }
450   return reply;
451 }
452
453 static DBusMessage *
454 impl_IsColumnSelected (DBusConnection * bus, DBusMessage * message,
455                        void *user_data)
456 {
457   AtkTable *table = (AtkTable *) user_data;
458   dbus_int32_t column;
459   DBusError error;
460   DBusMessage *reply;
461   dbus_bool_t ret;
462
463   g_return_val_if_fail (ATK_IS_TABLE (user_data),
464                         droute_not_yet_handled_error (message));
465   dbus_error_init (&error);
466   if (!dbus_message_get_args
467       (message, &error, DBUS_TYPE_INT32, &column, DBUS_TYPE_INVALID))
468     {
469       return droute_invalid_arguments_error (message);
470     }
471   ret = atk_table_is_column_selected (table, column);
472   reply = dbus_message_new_method_return (message);
473   if (reply)
474     {
475       dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &ret,
476                                 DBUS_TYPE_INVALID);
477     }
478   return reply;
479 }
480
481 static DBusMessage *
482 impl_IsSelected (DBusConnection * bus, DBusMessage * message, void *user_data)
483 {
484   AtkTable *table = (AtkTable *) user_data;
485   dbus_int32_t row, column;
486   DBusError error;
487   DBusMessage *reply;
488   dbus_bool_t ret;
489
490   g_return_val_if_fail (ATK_IS_TABLE (user_data),
491                         droute_not_yet_handled_error (message));
492   dbus_error_init (&error);
493   if (!dbus_message_get_args
494       (message, &error, DBUS_TYPE_INT32, &row, DBUS_TYPE_INT32, &column,
495        DBUS_TYPE_INVALID))
496     {
497       return droute_invalid_arguments_error (message);
498     }
499   ret = atk_table_is_selected (table, row, column);
500   reply = dbus_message_new_method_return (message);
501   if (reply)
502     {
503       dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &ret,
504                                 DBUS_TYPE_INVALID);
505     }
506   return reply;
507 }
508
509 static DBusMessage *
510 impl_AddRowSelection (DBusConnection * bus, DBusMessage * message,
511                       void *user_data)
512 {
513   AtkTable *table = (AtkTable *) user_data;
514   dbus_int32_t row;
515   DBusError error;
516   DBusMessage *reply;
517   dbus_bool_t ret;
518
519   g_return_val_if_fail (ATK_IS_TABLE (user_data),
520                         droute_not_yet_handled_error (message));
521   dbus_error_init (&error);
522   if (!dbus_message_get_args
523       (message, &error, DBUS_TYPE_INT32, &row, DBUS_TYPE_INVALID))
524     {
525       return droute_invalid_arguments_error (message);
526     }
527   ret = atk_table_add_row_selection (table, row);
528   reply = dbus_message_new_method_return (message);
529   if (reply)
530     {
531       dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &ret,
532                                 DBUS_TYPE_INVALID);
533     }
534   return reply;
535 }
536
537 static DBusMessage *
538 impl_AddColumnSelection (DBusConnection * bus, DBusMessage * message,
539                          void *user_data)
540 {
541   AtkTable *table = (AtkTable *) user_data;
542   dbus_int32_t column;
543   DBusError error;
544   DBusMessage *reply;
545   dbus_bool_t ret;
546
547   g_return_val_if_fail (ATK_IS_TABLE (user_data),
548                         droute_not_yet_handled_error (message));
549   dbus_error_init (&error);
550   if (!dbus_message_get_args
551       (message, &error, DBUS_TYPE_INT32, &column, DBUS_TYPE_INVALID))
552     {
553       return droute_invalid_arguments_error (message);
554     }
555   ret = atk_table_add_column_selection (table, column);
556   reply = dbus_message_new_method_return (message);
557   if (reply)
558     {
559       dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &ret,
560                                 DBUS_TYPE_INVALID);
561     }
562   return reply;
563 }
564
565 static DBusMessage *
566 impl_RemoveRowSelection (DBusConnection * bus, DBusMessage * message,
567                          void *user_data)
568 {
569   AtkTable *table = (AtkTable *) user_data;
570   dbus_int32_t row;
571   DBusError error;
572   DBusMessage *reply;
573   dbus_bool_t ret;
574
575   g_return_val_if_fail (ATK_IS_TABLE (user_data),
576                         droute_not_yet_handled_error (message));
577   dbus_error_init (&error);
578   if (!dbus_message_get_args
579       (message, &error, DBUS_TYPE_INT32, &row, DBUS_TYPE_INVALID))
580     {
581       return droute_invalid_arguments_error (message);
582     }
583   ret = atk_table_remove_row_selection (table, row);
584   reply = dbus_message_new_method_return (message);
585   if (reply)
586     {
587       dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &ret,
588                                 DBUS_TYPE_INVALID);
589     }
590   return reply;
591 }
592
593 static DBusMessage *
594 impl_RemoveColumnSelection (DBusConnection * bus, DBusMessage * message,
595                             void *user_data)
596 {
597   AtkTable *table = (AtkTable *) user_data;
598   dbus_int32_t column;
599   DBusError error;
600   DBusMessage *reply;
601   dbus_bool_t ret;
602
603   g_return_val_if_fail (ATK_IS_TABLE (user_data),
604                         droute_not_yet_handled_error (message));
605   dbus_error_init (&error);
606   if (!dbus_message_get_args
607       (message, &error, DBUS_TYPE_INT32, &column, DBUS_TYPE_INVALID))
608     {
609       return droute_invalid_arguments_error (message);
610     }
611   ret = atk_table_remove_column_selection (table, column);
612   reply = dbus_message_new_method_return (message);
613   if (reply)
614     {
615       dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &ret,
616                                 DBUS_TYPE_INVALID);
617     }
618   return reply;
619 }
620
621 static DBusMessage *
622 impl_GetRowColumnExtentsAtIndex (DBusConnection * bus, DBusMessage * message,
623                                  void *user_data)
624 {
625   AtkTable *table = (AtkTable *) user_data;
626   dbus_int32_t index;
627   DBusError error;
628   dbus_int32_t row, column, row_extents, col_extents;
629   dbus_bool_t is_selected;
630   dbus_bool_t ret;
631   DBusMessage *reply;
632
633   AtkObject *cell;
634   AtkRole role;
635
636   g_return_val_if_fail (ATK_IS_TABLE (user_data),
637                         droute_not_yet_handled_error (message));
638   dbus_error_init (&error);
639   if (!dbus_message_get_args
640       (message, &error, DBUS_TYPE_INT32, &index, DBUS_TYPE_INVALID))
641     {
642       return droute_invalid_arguments_error (message);
643     }
644   column = atk_table_get_column_at_index (table, index);
645   row = atk_table_get_row_at_index (table, index);
646   row_extents = atk_table_get_row_extent_at (table, row, column);
647   col_extents = atk_table_get_column_extent_at (table, row, column);
648   is_selected = atk_table_is_selected (table, row, column);
649   cell = atk_table_ref_at (table, row, column);
650   role = atk_object_get_role (cell);
651   g_object_unref (cell);
652   ret = (role == ATK_ROLE_TABLE_CELL ? TRUE : FALSE);
653   reply = dbus_message_new_method_return (message);
654   if (reply)
655     {
656       dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &ret,
657                                 DBUS_TYPE_INT32, &row, DBUS_TYPE_INT32,
658                                 &column, DBUS_TYPE_INT32, &row_extents,
659                                 DBUS_TYPE_INT32, &col_extents,
660                                 DBUS_TYPE_BOOLEAN, &is_selected,
661                                 DBUS_TYPE_INVALID);
662     }
663   return reply;
664 }
665
666 static DRouteMethod methods[] = {
667   {impl_GetAccessibleAt, "GetAccessibleAt"},
668   {impl_GetIndexAt, "GetIndexAt"},
669   {impl_GetRowAtIndex, "GetRowAtIndex"},
670   {impl_GetColumnAtIndex, "GetColumnAtIndex"},
671   {impl_GetRowDescription, "GetRowDescription"},
672   {impl_GetColumnDescription, "GetColumnDescription"},
673   {impl_GetRowExtentAt, "GetRowExtentAt"},
674   {impl_GetColumnExtentAt, "GetColumnExtentAt"},
675   {impl_GetRowHeader, "GetRowHeader"},
676   {impl_GetColumnHeader, "GetColumnHeader"},
677   {impl_GetSelectedRows, "GetSelectedRows"},
678   {impl_GetSelectedColumns, "GetSelectedColumns"},
679   {impl_IsRowSelected, "IsRowSelected"},
680   {impl_IsColumnSelected, "IsColumnSelected"},
681   {impl_IsSelected, "IsSelected"},
682   {impl_AddRowSelection, "AddRowSelection"},
683   {impl_AddColumnSelection, "AddColumnSelection"},
684   {impl_RemoveRowSelection, "RemoveRowSelection"},
685   {impl_RemoveColumnSelection, "RemoveColumnSelection"},
686   {impl_GetRowColumnExtentsAtIndex, "GetRowColumnExtentsAtIndex"},
687   {NULL, NULL}
688 };
689
690 static DRouteProperty properties[] = {
691   {impl_get_NRows, NULL, "NRows"},
692   {impl_get_NColumns, NULL, "NColumns"},
693   {impl_get_Caption, NULL, "Caption"},
694   {impl_get_Summary, NULL, "Summary"},
695   {impl_get_NSelectedRows, NULL, "NSelectedRows"},
696   {impl_get_NSelectedColumns, NULL, "NSelectedColumns"},
697   {NULL, NULL, NULL}
698 };
699
700 void
701 spi_initialize_table (DRoutePath * path)
702 {
703   droute_path_add_interface (path,
704                              ATSPI_DBUS_INTERFACE_TABLE, spi_org_a11y_atspi_Table, methods, properties);
705 };