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