2 * AT-SPI - Assistive Technology Service Provider Interface
3 * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
5 * Copyright 2008 Novell, Inc.
6 * Copyright 2001, 2002 Sun Microsystems Inc.,
7 * Copyright 2001, 2002 Ximian, Inc.
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.
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.
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.
28 #include <droute/droute.h>
30 #include "common/spi-dbus.h"
32 #include "introspection.h"
35 impl_get_CharacterCount (DBusMessageIter * iter, void *user_data)
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));
43 impl_get_CaretOffset (DBusMessageIter * iter, void *user_data)
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));
51 impl_GetText (DBusConnection * bus, DBusMessage * message, void *user_data)
53 AtkText *text = (AtkText *) user_data;
54 dbus_int32_t startOffset, endOffset;
59 g_return_val_if_fail (ATK_IS_TEXT (user_data),
60 droute_not_yet_handled_error (message));
61 dbus_error_init (&error);
62 if (!dbus_message_get_args
63 (message, &error, DBUS_TYPE_INT32, &startOffset, DBUS_TYPE_INT32,
64 &endOffset, DBUS_TYPE_INVALID))
66 return droute_invalid_arguments_error (message);
68 txt = atk_text_get_text (text, startOffset, endOffset);
71 reply = dbus_message_new_method_return (message);
74 dbus_message_append_args (reply, DBUS_TYPE_STRING, &txt,
82 impl_SetCaretOffset (DBusConnection * bus, DBusMessage * message,
85 AtkText *text = (AtkText *) user_data;
91 g_return_val_if_fail (ATK_IS_TEXT (user_data),
92 droute_not_yet_handled_error (message));
93 dbus_error_init (&error);
94 if (!dbus_message_get_args
95 (message, &error, DBUS_TYPE_INT32, &offset, DBUS_TYPE_INVALID))
97 return droute_invalid_arguments_error (message);
99 rv = atk_text_set_caret_offset (text, offset);
100 reply = dbus_message_new_method_return (message);
103 dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &rv,
110 impl_GetTextBeforeOffset (DBusConnection * bus, DBusMessage * message,
113 AtkText *text = (AtkText *) user_data;
117 dbus_int32_t startOffset, endOffset;
118 gint intstart_offset = 0, intend_offset = 0;
122 g_return_val_if_fail (ATK_IS_TEXT (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, &offset, DBUS_TYPE_UINT32, &type,
129 return droute_invalid_arguments_error (message);
132 atk_text_get_text_before_offset (text, offset, (AtkTextBoundary) type,
133 &intstart_offset, &intend_offset);
134 startOffset = intstart_offset;
135 endOffset = intend_offset;
138 reply = dbus_message_new_method_return (message);
141 dbus_message_append_args (reply, DBUS_TYPE_STRING, &txt,
142 DBUS_TYPE_INT32, &startOffset,
143 DBUS_TYPE_INT32, &endOffset,
151 impl_GetTextAtOffset (DBusConnection * bus, DBusMessage * message,
154 AtkText *text = (AtkText *) user_data;
155 dbus_int32_t offset, type;
157 dbus_int32_t startOffset, endOffset;
158 gint intstart_offset = 0, intend_offset = 0;
162 g_return_val_if_fail (ATK_IS_TEXT (user_data),
163 droute_not_yet_handled_error (message));
164 dbus_error_init (&error);
165 if (!dbus_message_get_args
166 (message, &error, DBUS_TYPE_INT32, &offset, DBUS_TYPE_UINT32, &type,
169 return droute_invalid_arguments_error (message);
172 atk_text_get_text_at_offset (text, offset, (AtkTextBoundary) type,
173 &intstart_offset, &intend_offset);
174 startOffset = intstart_offset;
175 endOffset = intend_offset;
178 reply = dbus_message_new_method_return (message);
181 dbus_message_append_args (reply, DBUS_TYPE_STRING, &txt,
182 DBUS_TYPE_INT32, &startOffset,
183 DBUS_TYPE_INT32, &endOffset,
191 impl_GetTextAfterOffset (DBusConnection * bus, DBusMessage * message,
194 AtkText *text = (AtkText *) user_data;
198 dbus_int32_t startOffset, endOffset;
199 gint intstart_offset = 0, intend_offset = 0;
203 g_return_val_if_fail (ATK_IS_TEXT (user_data),
204 droute_not_yet_handled_error (message));
205 dbus_error_init (&error);
206 if (!dbus_message_get_args
207 (message, &error, DBUS_TYPE_INT32, &offset, DBUS_TYPE_UINT32, &type,
210 return droute_invalid_arguments_error (message);
213 atk_text_get_text_after_offset (text, offset, (AtkTextBoundary) type,
214 &intstart_offset, &intend_offset);
215 startOffset = intstart_offset;
216 endOffset = intend_offset;
219 reply = dbus_message_new_method_return (message);
222 dbus_message_append_args (reply, DBUS_TYPE_STRING, &txt,
223 DBUS_TYPE_INT32, &startOffset,
224 DBUS_TYPE_INT32, &endOffset,
232 impl_GetCharacterAtOffset (DBusConnection * bus, DBusMessage * message,
235 AtkText *text = (AtkText *) user_data;
241 g_return_val_if_fail (ATK_IS_TEXT (user_data),
242 droute_not_yet_handled_error (message));
243 dbus_error_init (&error);
244 if (!dbus_message_get_args
245 (message, &error, DBUS_TYPE_INT32, &offset, DBUS_TYPE_INVALID))
247 return droute_invalid_arguments_error (message);
249 ch = atk_text_get_character_at_offset (text, offset);
250 reply = dbus_message_new_method_return (message);
253 dbus_message_append_args (reply, DBUS_TYPE_INT32, &ch,
260 impl_GetAttributeValue (DBusConnection * bus, DBusMessage * message,
263 AtkText *text = (AtkText *) user_data;
266 dbus_int32_t startOffset, endOffset;
268 gint intstart_offset = 0, intend_offset = 0;
272 AtkAttributeSet *set;
276 g_return_val_if_fail (ATK_IS_TEXT (user_data),
277 droute_not_yet_handled_error (message));
278 dbus_error_init (&error);
279 if (!dbus_message_get_args
280 (message, &error, DBUS_TYPE_INT32, &offset, DBUS_TYPE_STRING,
281 &attributeName, DBUS_TYPE_INVALID))
283 return droute_invalid_arguments_error (message);
286 set = atk_text_get_run_attributes (text, offset,
287 &intstart_offset, &intend_offset);
288 startOffset = intstart_offset;
289 endOffset = intend_offset;
291 cur_attr = (GSList *) set;
294 at = (AtkAttribute *) cur_attr->data;
295 if (!strcmp (at->name, attributeName))
301 cur_attr = cur_attr->next;
305 reply = dbus_message_new_method_return (message);
308 dbus_message_append_args (reply, DBUS_TYPE_STRING, &rv, DBUS_TYPE_INT32,
309 &startOffset, DBUS_TYPE_INT32, &endOffset,
310 DBUS_TYPE_BOOLEAN, &defined,
313 atk_attribute_set_free (set);
318 _string_from_attribute_set (AtkAttributeSet * set)
320 gchar *attributes, *tmp, *tmp2;
324 attributes = g_strdup ("");
325 cur_attr = (GSList *) set;
328 at = (AtkAttribute *) cur_attr->data;
329 tmp = g_strdup_printf ("%s%s:%s%s",
330 ((GSList *) (set) == cur_attr) ? "" : " ",
332 (cur_attr->next) ? ";" : "");
333 tmp2 = g_strconcat (attributes, tmp, NULL);
337 cur_attr = cur_attr->next;
343 impl_GetAttributes (DBusConnection * bus, DBusMessage * message,
346 AtkText *text = (AtkText *) user_data;
348 dbus_int32_t startOffset, endOffset;
349 gint intstart_offset, intend_offset;
352 AtkAttributeSet *set;
353 DBusMessageIter iter;
355 g_return_val_if_fail (ATK_IS_TEXT (user_data),
356 droute_not_yet_handled_error (message));
357 dbus_error_init (&error);
358 if (!dbus_message_get_args
359 (message, &error, DBUS_TYPE_INT32, &offset, DBUS_TYPE_INVALID))
361 return droute_invalid_arguments_error (message);
364 set = atk_text_get_run_attributes (text, offset,
365 &intstart_offset, &intend_offset);
367 startOffset = intstart_offset;
368 endOffset = intend_offset;
369 reply = dbus_message_new_method_return (message);
372 dbus_message_iter_init_append (reply, &iter);
373 spi_object_append_attribute_set (&iter, set);
374 dbus_message_append_args (reply, DBUS_TYPE_INT32, &startOffset,
375 DBUS_TYPE_INT32, &endOffset,
378 atk_attribute_set_free (set);
383 impl_GetDefaultAttributes (DBusConnection * bus, DBusMessage * message,
386 AtkText *text = (AtkText *) user_data;
389 AtkAttributeSet *set;
390 DBusMessageIter iter;
392 g_return_val_if_fail (ATK_IS_TEXT (user_data),
393 droute_not_yet_handled_error (message));
394 dbus_error_init (&error);
396 set = atk_text_get_default_attributes (text);
397 reply = dbus_message_new_method_return (message);
400 dbus_message_iter_init_append (reply, &iter);
401 spi_object_append_attribute_set (&iter, set);
403 atk_attribute_set_free (set);
408 impl_GetCharacterExtents (DBusConnection * bus, DBusMessage * message,
411 AtkText *text = (AtkText *) user_data;
413 dbus_uint32_t coordType;
414 dbus_int32_t x, y, width, height;
415 gint ix = 0, iy = 0, iw = 0, ih = 0;
419 g_return_val_if_fail (ATK_IS_TEXT (user_data),
420 droute_not_yet_handled_error (message));
421 dbus_error_init (&error);
422 if (!dbus_message_get_args
423 (message, &error, DBUS_TYPE_INT32, &offset, DBUS_TYPE_UINT32,
424 &coordType, DBUS_TYPE_INVALID))
426 return droute_invalid_arguments_error (message);
428 atk_text_get_character_extents (text, offset, &ix, &iy, &iw, &ih,
429 (AtkCoordType) coordType);
434 reply = dbus_message_new_method_return (message);
437 dbus_message_append_args (reply, DBUS_TYPE_INT32, &x, DBUS_TYPE_INT32,
438 &y, DBUS_TYPE_INT32, &width, DBUS_TYPE_INT32,
439 &height, DBUS_TYPE_INVALID);
445 impl_GetOffsetAtPoint (DBusConnection * bus, DBusMessage * message,
448 AtkText *text = (AtkText *) user_data;
450 dbus_uint32_t coordType;
455 g_return_val_if_fail (ATK_IS_TEXT (user_data),
456 droute_not_yet_handled_error (message));
457 dbus_error_init (&error);
458 if (!dbus_message_get_args
459 (message, &error, DBUS_TYPE_INT32, &x, DBUS_TYPE_INT32, &y,
460 DBUS_TYPE_UINT32, &coordType, DBUS_TYPE_INVALID))
462 return droute_invalid_arguments_error (message);
464 rv = atk_text_get_offset_at_point (text, x, y, coordType);
465 reply = dbus_message_new_method_return (message);
468 dbus_message_append_args (reply, DBUS_TYPE_INT32, &rv,
475 impl_GetNSelections (DBusConnection * bus, DBusMessage * message,
478 AtkText *text = (AtkText *) user_data;
482 g_return_val_if_fail (ATK_IS_TEXT (user_data),
483 droute_not_yet_handled_error (message));
484 rv = atk_text_get_n_selections (text);
485 reply = dbus_message_new_method_return (message);
488 dbus_message_append_args (reply, DBUS_TYPE_INT32, &rv,
495 impl_GetSelection (DBusConnection * bus, DBusMessage * message,
498 AtkText *text = (AtkText *) user_data;
499 dbus_int32_t selectionNum;
500 dbus_int32_t startOffset, endOffset;
501 gint intstart_offset = 0, intend_offset = 0;
505 g_return_val_if_fail (ATK_IS_TEXT (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, &selectionNum, DBUS_TYPE_INVALID))
511 return droute_invalid_arguments_error (message);
513 /* atk_text_get_selection returns gchar * which we discard */
514 g_free (atk_text_get_selection
515 (text, selectionNum, &intstart_offset, &intend_offset));
516 startOffset = intstart_offset;
517 endOffset = intend_offset;
518 reply = dbus_message_new_method_return (message);
521 dbus_message_append_args (reply, DBUS_TYPE_INT32, &startOffset,
522 DBUS_TYPE_INT32, &endOffset,
529 impl_AddSelection (DBusConnection * bus, DBusMessage * message,
532 AtkText *text = (AtkText *) user_data;
533 dbus_int32_t startOffset, endOffset;
538 g_return_val_if_fail (ATK_IS_TEXT (user_data),
539 droute_not_yet_handled_error (message));
540 dbus_error_init (&error);
541 if (!dbus_message_get_args
542 (message, &error, DBUS_TYPE_INT32, &startOffset, DBUS_TYPE_INT32,
543 &endOffset, DBUS_TYPE_INVALID))
545 return droute_invalid_arguments_error (message);
547 rv = atk_text_add_selection (text, startOffset, endOffset);
548 reply = dbus_message_new_method_return (message);
551 dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &rv,
558 impl_RemoveSelection (DBusConnection * bus, DBusMessage * message,
561 AtkText *text = (AtkText *) user_data;
562 dbus_int32_t selectionNum;
567 g_return_val_if_fail (ATK_IS_TEXT (user_data),
568 droute_not_yet_handled_error (message));
569 dbus_error_init (&error);
570 if (!dbus_message_get_args
571 (message, &error, DBUS_TYPE_INT32, &selectionNum, DBUS_TYPE_INVALID))
573 return droute_invalid_arguments_error (message);
575 rv = atk_text_remove_selection (text, selectionNum);
576 reply = dbus_message_new_method_return (message);
579 dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &rv,
586 impl_SetSelection (DBusConnection * bus, DBusMessage * message,
589 AtkText *text = (AtkText *) user_data;
590 dbus_int32_t selectionNum, startOffset, endOffset;
595 g_return_val_if_fail (ATK_IS_TEXT (user_data),
596 droute_not_yet_handled_error (message));
597 dbus_error_init (&error);
598 if (!dbus_message_get_args
599 (message, &error, DBUS_TYPE_INT32, &selectionNum, DBUS_TYPE_INT32,
600 &startOffset, DBUS_TYPE_INT32, &endOffset, DBUS_TYPE_INVALID))
602 return droute_invalid_arguments_error (message);
604 rv = atk_text_set_selection (text, selectionNum, startOffset, endOffset);
605 reply = dbus_message_new_method_return (message);
608 dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &rv,
615 impl_GetRangeExtents (DBusConnection * bus, DBusMessage * message,
618 AtkText *text = (AtkText *) user_data;
619 dbus_int32_t startOffset, endOffset;
620 dbus_uint32_t coordType;
621 AtkTextRectangle rect;
622 dbus_int32_t x, y, width, height;
626 g_return_val_if_fail (ATK_IS_TEXT (user_data),
627 droute_not_yet_handled_error (message));
628 dbus_error_init (&error);
629 if (!dbus_message_get_args
630 (message, &error, DBUS_TYPE_INT32, &startOffset, DBUS_TYPE_INT32,
631 &endOffset, DBUS_TYPE_UINT32, &coordType, DBUS_TYPE_INVALID))
633 return droute_invalid_arguments_error (message);
635 memset (&rect, 0, sizeof (rect));
636 atk_text_get_range_extents (text, startOffset, endOffset,
637 (AtkCoordType) coordType, &rect);
641 height = rect.height;
642 reply = dbus_message_new_method_return (message);
645 dbus_message_append_args (reply, DBUS_TYPE_INT32, &x, DBUS_TYPE_INT32,
646 &y, DBUS_TYPE_INT32, &width, DBUS_TYPE_INT32,
647 &height, DBUS_TYPE_INVALID);
652 #define MAXRANGELEN 512
655 impl_GetBoundedRanges (DBusConnection * bus, DBusMessage * message,
658 AtkText *text = (AtkText *) user_data;
659 dbus_int32_t x, y, width, height;
660 dbus_uint32_t coordType, xClipType, yClipType;
662 AtkTextRange **range_list = NULL;
663 AtkTextRectangle rect;
665 DBusMessageIter iter, array, struc, variant;
667 g_return_val_if_fail (ATK_IS_TEXT (user_data),
668 droute_not_yet_handled_error (message));
669 dbus_error_init (&error);
670 if (!dbus_message_get_args
671 (message, &error, DBUS_TYPE_INT32, &x, DBUS_TYPE_INT32, &y,
672 DBUS_TYPE_INT32, &height, DBUS_TYPE_INT32, &width, DBUS_TYPE_UINT32,
673 &coordType, DBUS_TYPE_UINT32, &xClipType, DBUS_TYPE_UINT32, &yClipType,
676 return droute_invalid_arguments_error (message);
681 rect.height = height;
684 atk_text_get_bounded_ranges (text, &rect, (AtkCoordType) coordType,
685 (AtkTextClipType) xClipType,
686 (AtkTextClipType) yClipType);
687 reply = dbus_message_new_method_return (message);
690 /* This isn't pleasant. */
691 dbus_message_iter_init_append (reply, &iter);
692 if (dbus_message_iter_open_container
693 (&iter, DBUS_TYPE_ARRAY, "(iisv)", &array))
696 for (len = 0; len < MAXRANGELEN && range_list[len]; ++len)
698 if (dbus_message_iter_open_container
699 (&array, DBUS_TYPE_STRUCT, NULL, &struc))
702 val = range_list[len]->start_offset;
703 dbus_message_iter_append_basic (&struc, DBUS_TYPE_INT32, &val);
704 val = range_list[len]->end_offset;
705 dbus_message_iter_append_basic (&struc, DBUS_TYPE_INT32, &val);
706 dbus_message_iter_append_basic (&struc, DBUS_TYPE_STRING,
707 &range_list[len]->content);
708 /* The variant is unimplemented in atk, but I don't want to
709 * unilaterally muck with the spec and remove it, so I'll just
710 * throw in a dummy value */
711 if (dbus_message_iter_open_container
712 (&struc, DBUS_TYPE_VARIANT, "i", &variant))
714 dbus_uint32_t dummy = 0;
715 dbus_message_iter_append_basic (&variant, DBUS_TYPE_INT32,
717 dbus_message_iter_close_container (&struc, &variant);
719 dbus_message_iter_close_container (&array, &struc);
722 dbus_message_iter_close_container (&iter, &array);
728 impl_GetAttributeRun (DBusConnection * bus, DBusMessage * message,
732 AtkText *text = (AtkText *) user_data;
734 dbus_bool_t includeDefaults;
735 dbus_int32_t startOffset, endOffset;
736 gint intstart_offset = 0, intend_offset = 0;
738 AtkAttributeSet *attributes = NULL;
739 AtkAttribute *attr = NULL;
740 DBusMessageIter iter, iterArray;
742 g_return_val_if_fail (ATK_IS_TEXT (user_data),
743 droute_not_yet_handled_error (message));
744 dbus_error_init (&error);
745 if (!dbus_message_get_args
746 (message, &error, DBUS_TYPE_INT32, &offset, DBUS_TYPE_BOOLEAN,
747 &includeDefaults, DBUS_TYPE_INVALID))
749 return droute_invalid_arguments_error (message);
753 atk_text_get_run_attributes (text, offset, &intstart_offset,
758 attributes = g_slist_concat (attributes,
759 atk_text_get_default_attributes (text));
762 reply = dbus_message_new_method_return (message);
766 dbus_message_iter_init_append (reply, &iter);
767 spi_object_append_attribute_set (&iter, attributes);
769 startOffset = intstart_offset;
770 endOffset = intend_offset;
771 dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &startOffset);
772 dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &endOffset);
774 atk_attribute_set_free (attributes);
780 impl_GetDefaultAttributeSet (DBusConnection * bus, DBusMessage * message,
783 AtkText *text = (AtkText *) user_data;
785 DBusMessageIter iter;
786 AtkAttributeSet *attributes;
788 g_return_val_if_fail (ATK_IS_TEXT (user_data),
789 droute_not_yet_handled_error (message));
791 attributes = atk_text_get_default_attributes (text);
793 reply = dbus_message_new_method_return (message);
796 dbus_message_iter_init_append (reply, &iter);
797 spi_object_append_attribute_set (&iter, attributes);
801 atk_attribute_set_free (attributes);
806 static DRouteMethod methods[] = {
807 {impl_GetText, "GetText"},
808 {impl_SetCaretOffset, "SetCaretOffset"},
809 {impl_GetTextBeforeOffset, "GetTextBeforeOffset"},
810 {impl_GetTextAtOffset, "GetTextAtOffset"},
811 {impl_GetTextAfterOffset, "GetTextAfterOffset"},
812 {impl_GetCharacterAtOffset, "GetCharacterAtOffset"},
813 {impl_GetAttributeValue, "GetAttributeValue"},
814 {impl_GetAttributes, "GetAttributes"},
815 {impl_GetDefaultAttributes, "GetDefaultAttributes"},
816 {impl_GetCharacterExtents, "GetCharacterExtents"},
817 {impl_GetOffsetAtPoint, "GetOffsetAtPoint"},
818 {impl_GetNSelections, "GetNSelections"},
819 {impl_GetSelection, "GetSelection"},
820 {impl_AddSelection, "AddSelection"},
821 {impl_RemoveSelection, "RemoveSelection"},
822 {impl_SetSelection, "SetSelection"},
823 {impl_GetRangeExtents, "GetRangeExtents"},
824 {impl_GetBoundedRanges, "GetBoundedRanges"},
825 {impl_GetAttributeRun, "GetAttributeRun"},
826 {impl_GetDefaultAttributeSet, "GetDefaultAttributeSet"},
830 static DRouteProperty properties[] = {
831 {impl_get_CharacterCount, NULL, "CharacterCount"},
832 {impl_get_CaretOffset, NULL, "CaretOffset"},
837 spi_initialize_text (DRoutePath * path)
839 droute_path_add_interface (path,
840 SPI_DBUS_INTERFACE_TEXT, spi_org_a11y_atspi_Text, methods, properties);