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