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