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