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