Fix compile-time warnings
[platform/core/uifw/at-spi2-atk.git] / atk-adaptor / adaptors / text-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 <string.h>
26
27 #include <atk/atk.h>
28 #include <droute/droute.h>
29
30 #include "spi-dbus.h"
31 #include "object.h"
32 #include "introspection.h"
33
34 static dbus_bool_t
35 impl_get_CharacterCount (DBusMessageIter * iter, void *user_data)
36 {
37   AtkText *text = (AtkText *) user_data;
38   g_return_val_if_fail (ATK_IS_TEXT (user_data), FALSE);
39   return droute_return_v_int32 (iter, atk_text_get_character_count (text));
40 }
41
42 static dbus_bool_t
43 impl_get_CaretOffset (DBusMessageIter * iter, void *user_data)
44 {
45   AtkText *text = (AtkText *) user_data;
46   g_return_val_if_fail (ATK_IS_TEXT (user_data), FALSE);
47   return droute_return_v_int32 (iter, atk_text_get_caret_offset (text));
48 }
49
50 static gchar *
51 validate_allocated_string (gchar *str)
52 {
53   if (!str)
54     return g_strdup ("");
55   if (!g_utf8_validate (str, -1, NULL))
56     {
57       g_warning ("atk-bridge: received bad UTF-8 string from a get_text function");
58       g_free (str);
59       return g_strdup ("");
60     }
61   return str;
62 }
63
64 static DBusMessage *
65 impl_GetText (DBusConnection * bus, DBusMessage * message, void *user_data)
66 {
67   AtkText *text = (AtkText *) user_data;
68   dbus_int32_t startOffset, endOffset;
69   gchar *txt;
70   DBusError error;
71   DBusMessage *reply;
72
73   g_return_val_if_fail (ATK_IS_TEXT (user_data),
74                         droute_not_yet_handled_error (message));
75   dbus_error_init (&error);
76   if (!dbus_message_get_args
77       (message, &error, DBUS_TYPE_INT32, &startOffset, DBUS_TYPE_INT32,
78        &endOffset, DBUS_TYPE_INVALID))
79     {
80       return droute_invalid_arguments_error (message);
81     }
82   txt = atk_text_get_text (text, startOffset, endOffset);
83   txt = validate_allocated_string (txt);
84   reply = dbus_message_new_method_return (message);
85   if (reply)
86     {
87       dbus_message_append_args (reply, DBUS_TYPE_STRING, &txt,
88                                 DBUS_TYPE_INVALID);
89     }
90   g_free (txt);
91   return reply;
92 }
93
94 static DBusMessage *
95 impl_SetCaretOffset (DBusConnection * bus, DBusMessage * message,
96                      void *user_data)
97 {
98   AtkText *text = (AtkText *) user_data;
99   dbus_int32_t offset;
100   dbus_bool_t rv;
101   DBusError error;
102   DBusMessage *reply;
103
104   g_return_val_if_fail (ATK_IS_TEXT (user_data),
105                         droute_not_yet_handled_error (message));
106   dbus_error_init (&error);
107   if (!dbus_message_get_args
108       (message, &error, DBUS_TYPE_INT32, &offset, DBUS_TYPE_INVALID))
109     {
110       return droute_invalid_arguments_error (message);
111     }
112   rv = atk_text_set_caret_offset (text, offset);
113   reply = dbus_message_new_method_return (message);
114   if (reply)
115     {
116       dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &rv,
117                                 DBUS_TYPE_INVALID);
118     }
119   return reply;
120 }
121
122 static DBusMessage *
123 impl_GetTextBeforeOffset (DBusConnection * bus, DBusMessage * message,
124                           void *user_data)
125 {
126   AtkText *text = (AtkText *) user_data;
127   dbus_int32_t offset;
128   dbus_uint32_t type;
129   gchar *txt;
130   dbus_int32_t startOffset, endOffset;
131   gint intstart_offset = 0, intend_offset = 0;
132   DBusError error;
133   DBusMessage *reply;
134
135   g_return_val_if_fail (ATK_IS_TEXT (user_data),
136                         droute_not_yet_handled_error (message));
137   dbus_error_init (&error);
138   if (!dbus_message_get_args
139       (message, &error, DBUS_TYPE_INT32, &offset, DBUS_TYPE_UINT32, &type,
140        DBUS_TYPE_INVALID))
141     {
142       return droute_invalid_arguments_error (message);
143     }
144   txt =
145     atk_text_get_text_before_offset (text, offset, (AtkTextBoundary) type,
146                                      &intstart_offset, &intend_offset);
147   startOffset = intstart_offset;
148   endOffset = intend_offset;
149   txt = validate_allocated_string (txt);
150   reply = dbus_message_new_method_return (message);
151   if (reply)
152     {
153       dbus_message_append_args (reply, DBUS_TYPE_STRING, &txt,
154                                 DBUS_TYPE_INT32, &startOffset,
155                                 DBUS_TYPE_INT32, &endOffset,
156                                 DBUS_TYPE_INVALID);
157     }
158   g_free (txt);
159   return reply;
160 }
161
162 static DBusMessage *
163 impl_GetTextAtOffset (DBusConnection * bus, DBusMessage * message,
164                       void *user_data)
165 {
166   AtkText *text = (AtkText *) user_data;
167   dbus_int32_t offset, type;
168   gchar *txt;
169   dbus_int32_t startOffset, endOffset;
170   gint intstart_offset = 0, intend_offset = 0;
171   DBusError error;
172   DBusMessage *reply;
173
174   g_return_val_if_fail (ATK_IS_TEXT (user_data),
175                         droute_not_yet_handled_error (message));
176   dbus_error_init (&error);
177   if (!dbus_message_get_args
178       (message, &error, DBUS_TYPE_INT32, &offset, DBUS_TYPE_UINT32, &type,
179        DBUS_TYPE_INVALID))
180     {
181       return droute_invalid_arguments_error (message);
182     }
183   txt =
184     atk_text_get_text_at_offset (text, offset, (AtkTextBoundary) type,
185                                  &intstart_offset, &intend_offset);
186   startOffset = intstart_offset;
187   endOffset = intend_offset;
188   txt = validate_allocated_string (txt);
189   reply = dbus_message_new_method_return (message);
190   if (reply)
191     {
192       dbus_message_append_args (reply, DBUS_TYPE_STRING, &txt,
193                                 DBUS_TYPE_INT32, &startOffset,
194                                 DBUS_TYPE_INT32, &endOffset,
195                                 DBUS_TYPE_INVALID);
196     }
197   g_free (txt);
198   return reply;
199 }
200
201 static DBusMessage *
202 impl_GetTextAfterOffset (DBusConnection * bus, DBusMessage * message,
203                          void *user_data)
204 {
205   AtkText *text = (AtkText *) user_data;
206   dbus_int32_t offset;
207   dbus_uint32_t type;
208   gchar *txt;
209   dbus_int32_t startOffset, endOffset;
210   gint intstart_offset = 0, intend_offset = 0;
211   DBusError error;
212   DBusMessage *reply;
213
214   g_return_val_if_fail (ATK_IS_TEXT (user_data),
215                         droute_not_yet_handled_error (message));
216   dbus_error_init (&error);
217   if (!dbus_message_get_args
218       (message, &error, DBUS_TYPE_INT32, &offset, DBUS_TYPE_UINT32, &type,
219        DBUS_TYPE_INVALID))
220     {
221       return droute_invalid_arguments_error (message);
222     }
223   txt =
224     atk_text_get_text_after_offset (text, offset, (AtkTextBoundary) type,
225                                     &intstart_offset, &intend_offset);
226   startOffset = intstart_offset;
227   endOffset = intend_offset;
228   txt = validate_allocated_string (txt);
229   reply = dbus_message_new_method_return (message);
230   if (reply)
231     {
232       dbus_message_append_args (reply, DBUS_TYPE_STRING, &txt,
233                                 DBUS_TYPE_INT32, &startOffset,
234                                 DBUS_TYPE_INT32, &endOffset,
235                                 DBUS_TYPE_INVALID);
236     }
237   g_free (txt);
238   return reply;
239 }
240
241 static DBusMessage *
242 impl_GetCharacterAtOffset (DBusConnection * bus, DBusMessage * message,
243                            void *user_data)
244 {
245   AtkText *text = (AtkText *) user_data;
246   dbus_int32_t offset;
247   dbus_int32_t ch;
248   DBusError error;
249   DBusMessage *reply;
250
251   g_return_val_if_fail (ATK_IS_TEXT (user_data),
252                         droute_not_yet_handled_error (message));
253   dbus_error_init (&error);
254   if (!dbus_message_get_args
255       (message, &error, DBUS_TYPE_INT32, &offset, DBUS_TYPE_INVALID))
256     {
257       return droute_invalid_arguments_error (message);
258     }
259   ch = atk_text_get_character_at_offset (text, offset);
260   reply = dbus_message_new_method_return (message);
261   if (reply)
262     {
263       dbus_message_append_args (reply, DBUS_TYPE_INT32, &ch,
264                                 DBUS_TYPE_INVALID);
265     }
266   return reply;
267 }
268
269 static DBusMessage *
270 impl_GetAttributeValue (DBusConnection * bus, DBusMessage * message,
271                         void *user_data)
272 {
273   AtkText *text = (AtkText *) user_data;
274   dbus_int32_t offset;
275   char *attributeName;
276   dbus_int32_t startOffset, endOffset;
277   dbus_bool_t defined;
278   gint intstart_offset = 0, intend_offset = 0;
279   char *rv = NULL;
280   DBusError error;
281   DBusMessage *reply;
282   AtkAttributeSet *set;
283   GSList *cur_attr;
284   AtkAttribute *at;
285
286   g_return_val_if_fail (ATK_IS_TEXT (user_data),
287                         droute_not_yet_handled_error (message));
288   dbus_error_init (&error);
289   if (!dbus_message_get_args
290       (message, &error, DBUS_TYPE_INT32, &offset, DBUS_TYPE_STRING,
291        &attributeName, DBUS_TYPE_INVALID))
292     {
293       return droute_invalid_arguments_error (message);
294     }
295
296   set = atk_text_get_run_attributes (text, offset,
297                                      &intstart_offset, &intend_offset);
298   startOffset = intstart_offset;
299   endOffset = intend_offset;
300   defined = FALSE;
301   cur_attr = (GSList *) set;
302   while (cur_attr)
303     {
304       at = (AtkAttribute *) cur_attr->data;
305       if (!strcmp (at->name, attributeName))
306         {
307           rv = at->value;
308           defined = TRUE;
309           break;
310         }
311       cur_attr = cur_attr->next;
312     }
313   if (!rv)
314     rv = "";
315   reply = dbus_message_new_method_return (message);
316   if (reply)
317     {
318       dbus_message_append_args (reply, DBUS_TYPE_STRING, &rv, DBUS_TYPE_INT32,
319                                 &startOffset, DBUS_TYPE_INT32, &endOffset,
320                                 DBUS_TYPE_BOOLEAN, &defined,
321                                 DBUS_TYPE_INVALID);
322     }
323   atk_attribute_set_free (set);
324   return reply;
325 }
326
327 static DBusMessage *
328 impl_GetAttributes (DBusConnection * bus, DBusMessage * message,
329                     void *user_data)
330 {
331   AtkText *text = (AtkText *) user_data;
332   dbus_int32_t offset;
333   dbus_int32_t startOffset, endOffset;
334   gint intstart_offset, intend_offset;
335   DBusError error;
336   DBusMessage *reply;
337   AtkAttributeSet *set;
338   DBusMessageIter iter;
339
340   g_return_val_if_fail (ATK_IS_TEXT (user_data),
341                         droute_not_yet_handled_error (message));
342   dbus_error_init (&error);
343   if (!dbus_message_get_args
344       (message, &error, DBUS_TYPE_INT32, &offset, DBUS_TYPE_INVALID))
345     {
346       return droute_invalid_arguments_error (message);
347     }
348
349   set = atk_text_get_run_attributes (text, offset,
350                                      &intstart_offset, &intend_offset);
351
352   startOffset = intstart_offset;
353   endOffset = intend_offset;
354   reply = dbus_message_new_method_return (message);
355   if (reply)
356     {
357       dbus_message_iter_init_append (reply, &iter);
358       spi_object_append_attribute_set (&iter, set);
359       dbus_message_append_args (reply, DBUS_TYPE_INT32, &startOffset,
360                                 DBUS_TYPE_INT32, &endOffset,
361                                 DBUS_TYPE_INVALID);
362     }
363   atk_attribute_set_free (set);
364   return reply;
365 }
366
367 static DBusMessage *
368 impl_GetDefaultAttributes (DBusConnection * bus, DBusMessage * message,
369                            void *user_data)
370 {
371   AtkText *text = (AtkText *) user_data;
372   DBusError error;
373   DBusMessage *reply;
374   AtkAttributeSet *set;
375   DBusMessageIter iter;
376
377   g_return_val_if_fail (ATK_IS_TEXT (user_data),
378                         droute_not_yet_handled_error (message));
379   dbus_error_init (&error);
380
381   set = atk_text_get_default_attributes (text);
382   reply = dbus_message_new_method_return (message);
383   if (reply)
384     {
385       dbus_message_iter_init_append (reply, &iter);
386       spi_object_append_attribute_set (&iter, set);
387     }
388   atk_attribute_set_free (set);
389   return reply;
390 }
391
392 static DBusMessage *
393 impl_GetCharacterExtents (DBusConnection * bus, DBusMessage * message,
394                           void *user_data)
395 {
396   AtkText *text = (AtkText *) user_data;
397   dbus_int32_t offset;
398   dbus_uint32_t coordType;
399   dbus_int32_t x, y, width, height;
400   gint ix = 0, iy = 0, iw = 0, ih = 0;
401   DBusError error;
402   DBusMessage *reply;
403
404   g_return_val_if_fail (ATK_IS_TEXT (user_data),
405                         droute_not_yet_handled_error (message));
406   dbus_error_init (&error);
407   if (!dbus_message_get_args
408       (message, &error, DBUS_TYPE_INT32, &offset, DBUS_TYPE_UINT32,
409        &coordType, DBUS_TYPE_INVALID))
410     {
411       return droute_invalid_arguments_error (message);
412     }
413   atk_text_get_character_extents (text, offset, &ix, &iy, &iw, &ih,
414                                   (AtkCoordType) coordType);
415   x = ix;
416   y = iy;
417   width = iw;
418   height = ih;
419   reply = dbus_message_new_method_return (message);
420   if (reply)
421     {
422       dbus_message_append_args (reply, DBUS_TYPE_INT32, &x, DBUS_TYPE_INT32,
423                                 &y, DBUS_TYPE_INT32, &width, DBUS_TYPE_INT32,
424                                 &height, DBUS_TYPE_INVALID);
425     }
426   return reply;
427 }
428
429 static DBusMessage *
430 impl_GetOffsetAtPoint (DBusConnection * bus, DBusMessage * message,
431                        void *user_data)
432 {
433   AtkText *text = (AtkText *) user_data;
434   dbus_int32_t x, y;
435   dbus_uint32_t coordType;
436   dbus_int32_t rv;
437   DBusError error;
438   DBusMessage *reply;
439
440   g_return_val_if_fail (ATK_IS_TEXT (user_data),
441                         droute_not_yet_handled_error (message));
442   dbus_error_init (&error);
443   if (!dbus_message_get_args
444       (message, &error, DBUS_TYPE_INT32, &x, DBUS_TYPE_INT32, &y,
445        DBUS_TYPE_UINT32, &coordType, DBUS_TYPE_INVALID))
446     {
447       return droute_invalid_arguments_error (message);
448     }
449   rv = atk_text_get_offset_at_point (text, x, y, coordType);
450   reply = dbus_message_new_method_return (message);
451   if (reply)
452     {
453       dbus_message_append_args (reply, DBUS_TYPE_INT32, &rv,
454                                 DBUS_TYPE_INVALID);
455     }
456   return reply;
457 }
458
459 static DBusMessage *
460 impl_GetNSelections (DBusConnection * bus, DBusMessage * message,
461                      void *user_data)
462 {
463   AtkText *text = (AtkText *) user_data;
464   dbus_int32_t rv;
465   DBusMessage *reply;
466
467   g_return_val_if_fail (ATK_IS_TEXT (user_data),
468                         droute_not_yet_handled_error (message));
469   rv = atk_text_get_n_selections (text);
470   reply = dbus_message_new_method_return (message);
471   if (reply)
472     {
473       dbus_message_append_args (reply, DBUS_TYPE_INT32, &rv,
474                                 DBUS_TYPE_INVALID);
475     }
476   return reply;
477 }
478
479 static DBusMessage *
480 impl_GetSelection (DBusConnection * bus, DBusMessage * message,
481                    void *user_data)
482 {
483   AtkText *text = (AtkText *) user_data;
484   dbus_int32_t selectionNum;
485   dbus_int32_t startOffset, endOffset;
486   gint intstart_offset = 0, intend_offset = 0;
487   DBusError error;
488   DBusMessage *reply;
489
490   g_return_val_if_fail (ATK_IS_TEXT (user_data),
491                         droute_not_yet_handled_error (message));
492   dbus_error_init (&error);
493   if (!dbus_message_get_args
494       (message, &error, DBUS_TYPE_INT32, &selectionNum, DBUS_TYPE_INVALID))
495     {
496       return droute_invalid_arguments_error (message);
497     }
498   /* atk_text_get_selection returns gchar * which we discard */
499   g_free (atk_text_get_selection
500           (text, selectionNum, &intstart_offset, &intend_offset));
501   startOffset = intstart_offset;
502   endOffset = intend_offset;
503   reply = dbus_message_new_method_return (message);
504   if (reply)
505     {
506       dbus_message_append_args (reply, DBUS_TYPE_INT32, &startOffset,
507                                 DBUS_TYPE_INT32, &endOffset,
508                                 DBUS_TYPE_INVALID);
509     }
510   return reply;
511 }
512
513 static DBusMessage *
514 impl_AddSelection (DBusConnection * bus, DBusMessage * message,
515                    void *user_data)
516 {
517   AtkText *text = (AtkText *) user_data;
518   dbus_int32_t startOffset, endOffset;
519   dbus_bool_t rv;
520   DBusError error;
521   DBusMessage *reply;
522
523   g_return_val_if_fail (ATK_IS_TEXT (user_data),
524                         droute_not_yet_handled_error (message));
525   dbus_error_init (&error);
526   if (!dbus_message_get_args
527       (message, &error, DBUS_TYPE_INT32, &startOffset, DBUS_TYPE_INT32,
528        &endOffset, DBUS_TYPE_INVALID))
529     {
530       return droute_invalid_arguments_error (message);
531     }
532   rv = atk_text_add_selection (text, startOffset, endOffset);
533   reply = dbus_message_new_method_return (message);
534   if (reply)
535     {
536       dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &rv,
537                                 DBUS_TYPE_INVALID);
538     }
539   return reply;
540 }
541
542 static DBusMessage *
543 impl_RemoveSelection (DBusConnection * bus, DBusMessage * message,
544                       void *user_data)
545 {
546   AtkText *text = (AtkText *) user_data;
547   dbus_int32_t selectionNum;
548   dbus_bool_t rv;
549   DBusError error;
550   DBusMessage *reply;
551
552   g_return_val_if_fail (ATK_IS_TEXT (user_data),
553                         droute_not_yet_handled_error (message));
554   dbus_error_init (&error);
555   if (!dbus_message_get_args
556       (message, &error, DBUS_TYPE_INT32, &selectionNum, DBUS_TYPE_INVALID))
557     {
558       return droute_invalid_arguments_error (message);
559     }
560   rv = atk_text_remove_selection (text, selectionNum);
561   reply = dbus_message_new_method_return (message);
562   if (reply)
563     {
564       dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &rv,
565                                 DBUS_TYPE_INVALID);
566     }
567   return reply;
568 }
569
570 static DBusMessage *
571 impl_SetSelection (DBusConnection * bus, DBusMessage * message,
572                    void *user_data)
573 {
574   AtkText *text = (AtkText *) user_data;
575   dbus_int32_t selectionNum, startOffset, endOffset;
576   dbus_bool_t rv;
577   DBusError error;
578   DBusMessage *reply;
579
580   g_return_val_if_fail (ATK_IS_TEXT (user_data),
581                         droute_not_yet_handled_error (message));
582   dbus_error_init (&error);
583   if (!dbus_message_get_args
584       (message, &error, DBUS_TYPE_INT32, &selectionNum, DBUS_TYPE_INT32,
585        &startOffset, DBUS_TYPE_INT32, &endOffset, DBUS_TYPE_INVALID))
586     {
587       return droute_invalid_arguments_error (message);
588     }
589   rv = atk_text_set_selection (text, selectionNum, startOffset, endOffset);
590   reply = dbus_message_new_method_return (message);
591   if (reply)
592     {
593       dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &rv,
594                                 DBUS_TYPE_INVALID);
595     }
596   return reply;
597 }
598
599 static DBusMessage *
600 impl_GetRangeExtents (DBusConnection * bus, DBusMessage * message,
601                       void *user_data)
602 {
603   AtkText *text = (AtkText *) user_data;
604   dbus_int32_t startOffset, endOffset;
605   dbus_uint32_t coordType;
606   AtkTextRectangle rect;
607   dbus_int32_t x, y, width, height;
608   DBusError error;
609   DBusMessage *reply;
610
611   g_return_val_if_fail (ATK_IS_TEXT (user_data),
612                         droute_not_yet_handled_error (message));
613   dbus_error_init (&error);
614   if (!dbus_message_get_args
615       (message, &error, DBUS_TYPE_INT32, &startOffset, DBUS_TYPE_INT32,
616        &endOffset, DBUS_TYPE_UINT32, &coordType, DBUS_TYPE_INVALID))
617     {
618       return droute_invalid_arguments_error (message);
619     }
620   memset (&rect, 0, sizeof (rect));
621   atk_text_get_range_extents (text, startOffset, endOffset,
622                               (AtkCoordType) coordType, &rect);
623   x = rect.x;
624   y = rect.y;
625   width = rect.width;
626   height = rect.height;
627   reply = dbus_message_new_method_return (message);
628   if (reply)
629     {
630       dbus_message_append_args (reply, DBUS_TYPE_INT32, &x, DBUS_TYPE_INT32,
631                                 &y, DBUS_TYPE_INT32, &width, DBUS_TYPE_INT32,
632                                 &height, DBUS_TYPE_INVALID);
633     }
634   return reply;
635 }
636
637 #define MAXRANGELEN 512
638
639 static DBusMessage *
640 impl_GetBoundedRanges (DBusConnection * bus, DBusMessage * message,
641                        void *user_data)
642 {
643   AtkText *text = (AtkText *) user_data;
644   dbus_int32_t x, y, width, height;
645   dbus_uint32_t coordType, xClipType, yClipType;
646   DBusError error;
647   AtkTextRange **range_list = NULL;
648   AtkTextRectangle rect;
649   DBusMessage *reply;
650   DBusMessageIter iter, array, struc, variant;
651
652   g_return_val_if_fail (ATK_IS_TEXT (user_data),
653                         droute_not_yet_handled_error (message));
654   dbus_error_init (&error);
655   if (!dbus_message_get_args
656       (message, &error, DBUS_TYPE_INT32, &x, DBUS_TYPE_INT32, &y,
657        DBUS_TYPE_INT32, &height, DBUS_TYPE_INT32, &width, DBUS_TYPE_UINT32,
658        &coordType, DBUS_TYPE_UINT32, &xClipType, DBUS_TYPE_UINT32, &yClipType,
659        DBUS_TYPE_INVALID))
660     {
661       return droute_invalid_arguments_error (message);
662     }
663   rect.x = x;
664   rect.y = y;
665   rect.width = width;
666   rect.height = height;
667
668   range_list =
669     atk_text_get_bounded_ranges (text, &rect, (AtkCoordType) coordType,
670                                  (AtkTextClipType) xClipType,
671                                  (AtkTextClipType) yClipType);
672   reply = dbus_message_new_method_return (message);
673   if (!reply)
674     return NULL;
675   /* This isn't pleasant. */
676   dbus_message_iter_init_append (reply, &iter);
677   if (dbus_message_iter_open_container
678       (&iter, DBUS_TYPE_ARRAY, "(iisv)", &array))
679     {
680       int len;
681       for (len = 0; len < MAXRANGELEN && range_list[len]; ++len)
682         {
683           if (dbus_message_iter_open_container
684               (&array, DBUS_TYPE_STRUCT, NULL, &struc))
685             {
686               dbus_int32_t val;
687               val = range_list[len]->start_offset;
688               dbus_message_iter_append_basic (&struc, DBUS_TYPE_INT32, &val);
689               val = range_list[len]->end_offset;
690               dbus_message_iter_append_basic (&struc, DBUS_TYPE_INT32, &val);
691               dbus_message_iter_append_basic (&struc, DBUS_TYPE_STRING,
692                                               &range_list[len]->content);
693               /* The variant is unimplemented in atk, but I don't want to
694                * unilaterally muck with the spec and remove it, so I'll just
695                * throw in a dummy value */
696               if (dbus_message_iter_open_container
697                   (&struc, DBUS_TYPE_VARIANT, "i", &variant))
698                 {
699                   dbus_uint32_t dummy = 0;
700                   dbus_message_iter_append_basic (&variant, DBUS_TYPE_INT32,
701                                                   &dummy);
702                   dbus_message_iter_close_container (&struc, &variant);
703                 }
704               dbus_message_iter_close_container (&array, &struc);
705             }
706         }
707       dbus_message_iter_close_container (&iter, &array);
708     }
709   return reply;
710 }
711
712 static DBusMessage *
713 impl_GetAttributeRun (DBusConnection * bus, DBusMessage * message,
714                       void *user_data)
715 {
716   DBusError error;
717   AtkText *text = (AtkText *) user_data;
718   dbus_int32_t offset;
719   dbus_bool_t includeDefaults;
720   dbus_int32_t startOffset, endOffset;
721   gint intstart_offset = 0, intend_offset = 0;
722   DBusMessage *reply;
723   AtkAttributeSet *attributes = NULL;
724   DBusMessageIter iter;
725
726   g_return_val_if_fail (ATK_IS_TEXT (user_data),
727                         droute_not_yet_handled_error (message));
728   dbus_error_init (&error);
729   if (!dbus_message_get_args
730       (message, &error, DBUS_TYPE_INT32, &offset, DBUS_TYPE_BOOLEAN,
731        &includeDefaults, DBUS_TYPE_INVALID))
732     {
733       return droute_invalid_arguments_error (message);
734     }
735
736   attributes =
737     atk_text_get_run_attributes (text, offset, &intstart_offset,
738                                  &intend_offset);
739
740   if (includeDefaults)
741     {
742       attributes = g_slist_concat (attributes,
743                                    atk_text_get_default_attributes (text));
744     }
745
746   reply = dbus_message_new_method_return (message);
747   if (!reply)
748     return NULL;
749
750   dbus_message_iter_init_append (reply, &iter);
751   spi_object_append_attribute_set (&iter, attributes);
752
753   startOffset = intstart_offset;
754   endOffset = intend_offset;
755   dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &startOffset);
756   dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &endOffset);
757
758   atk_attribute_set_free (attributes);
759
760   return reply;
761 }
762
763 static DBusMessage *
764 impl_GetDefaultAttributeSet (DBusConnection * bus, DBusMessage * message,
765                              void *user_data)
766 {
767   AtkText *text = (AtkText *) user_data;
768   DBusMessage *reply;
769   DBusMessageIter iter;
770   AtkAttributeSet *attributes;
771
772   g_return_val_if_fail (ATK_IS_TEXT (user_data),
773                         droute_not_yet_handled_error (message));
774
775   attributes = atk_text_get_default_attributes (text);
776
777   reply = dbus_message_new_method_return (message);
778   if (reply)
779     {
780       dbus_message_iter_init_append (reply, &iter);
781       spi_object_append_attribute_set (&iter, attributes);
782     }
783
784   if (attributes)
785     atk_attribute_set_free (attributes);
786
787   return reply;
788 }
789
790 static DRouteMethod methods[] = {
791   {impl_GetText, "GetText"},
792   {impl_SetCaretOffset, "SetCaretOffset"},
793   {impl_GetTextBeforeOffset, "GetTextBeforeOffset"},
794   {impl_GetTextAtOffset, "GetTextAtOffset"},
795   {impl_GetTextAfterOffset, "GetTextAfterOffset"},
796   {impl_GetCharacterAtOffset, "GetCharacterAtOffset"},
797   {impl_GetAttributeValue, "GetAttributeValue"},
798   {impl_GetAttributes, "GetAttributes"},
799   {impl_GetDefaultAttributes, "GetDefaultAttributes"},
800   {impl_GetCharacterExtents, "GetCharacterExtents"},
801   {impl_GetOffsetAtPoint, "GetOffsetAtPoint"},
802   {impl_GetNSelections, "GetNSelections"},
803   {impl_GetSelection, "GetSelection"},
804   {impl_AddSelection, "AddSelection"},
805   {impl_RemoveSelection, "RemoveSelection"},
806   {impl_SetSelection, "SetSelection"},
807   {impl_GetRangeExtents, "GetRangeExtents"},
808   {impl_GetBoundedRanges, "GetBoundedRanges"},
809   {impl_GetAttributeRun, "GetAttributeRun"},
810   {impl_GetDefaultAttributeSet, "GetDefaultAttributeSet"},
811   {NULL, NULL}
812 };
813
814 static DRouteProperty properties[] = {
815   {impl_get_CharacterCount, NULL, "CharacterCount"},
816   {impl_get_CaretOffset, NULL, "CaretOffset"},
817   {NULL, NULL, NULL}
818 };
819
820 void
821 spi_initialize_text (DRoutePath * path)
822 {
823   droute_path_add_interface (path,
824                              ATSPI_DBUS_INTERFACE_TEXT, spi_org_a11y_atspi_Text, methods, properties);
825 };