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>
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 validate_allocated_string (gchar *str)
55 if (!g_utf8_validate (str, -1, NULL))
57 g_warning ("atk-bridge: received bad UTF-8 string from a get_text function");
65 impl_GetText (DBusConnection * bus, DBusMessage * message, void *user_data)
67 AtkText *text = (AtkText *) user_data;
68 dbus_int32_t startOffset, endOffset;
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))
80 return droute_invalid_arguments_error (message);
82 txt = atk_text_get_text (text, startOffset, endOffset);
83 txt = validate_allocated_string (txt);
84 reply = dbus_message_new_method_return (message);
87 dbus_message_append_args (reply, DBUS_TYPE_STRING, &txt,
95 impl_SetCaretOffset (DBusConnection * bus, DBusMessage * message,
98 AtkText *text = (AtkText *) user_data;
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))
110 return droute_invalid_arguments_error (message);
112 rv = atk_text_set_caret_offset (text, offset);
113 reply = dbus_message_new_method_return (message);
116 dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &rv,
123 impl_GetTextBeforeOffset (DBusConnection * bus, DBusMessage * message,
126 AtkText *text = (AtkText *) user_data;
130 dbus_int32_t startOffset, endOffset;
131 gint intstart_offset = 0, intend_offset = 0;
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,
142 return droute_invalid_arguments_error (message);
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);
153 dbus_message_append_args (reply, DBUS_TYPE_STRING, &txt,
154 DBUS_TYPE_INT32, &startOffset,
155 DBUS_TYPE_INT32, &endOffset,
163 impl_GetTextAtOffset (DBusConnection * bus, DBusMessage * message,
166 AtkText *text = (AtkText *) user_data;
167 dbus_int32_t offset, type;
169 dbus_int32_t startOffset, endOffset;
170 gint intstart_offset = 0, intend_offset = 0;
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,
181 return droute_invalid_arguments_error (message);
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);
192 dbus_message_append_args (reply, DBUS_TYPE_STRING, &txt,
193 DBUS_TYPE_INT32, &startOffset,
194 DBUS_TYPE_INT32, &endOffset,
202 impl_GetTextAfterOffset (DBusConnection * bus, DBusMessage * message,
205 AtkText *text = (AtkText *) user_data;
209 dbus_int32_t startOffset, endOffset;
210 gint intstart_offset = 0, intend_offset = 0;
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,
221 return droute_invalid_arguments_error (message);
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);
232 dbus_message_append_args (reply, DBUS_TYPE_STRING, &txt,
233 DBUS_TYPE_INT32, &startOffset,
234 DBUS_TYPE_INT32, &endOffset,
242 impl_GetCharacterAtOffset (DBusConnection * bus, DBusMessage * message,
245 AtkText *text = (AtkText *) user_data;
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))
257 return droute_invalid_arguments_error (message);
259 ch = atk_text_get_character_at_offset (text, offset);
260 reply = dbus_message_new_method_return (message);
263 dbus_message_append_args (reply, DBUS_TYPE_INT32, &ch,
270 impl_GetAttributeValue (DBusConnection * bus, DBusMessage * message,
273 AtkText *text = (AtkText *) user_data;
276 dbus_int32_t startOffset, endOffset;
278 gint intstart_offset = 0, intend_offset = 0;
282 AtkAttributeSet *set;
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))
293 return droute_invalid_arguments_error (message);
296 set = atk_text_get_run_attributes (text, offset,
297 &intstart_offset, &intend_offset);
298 startOffset = intstart_offset;
299 endOffset = intend_offset;
301 cur_attr = (GSList *) set;
304 at = (AtkAttribute *) cur_attr->data;
305 if (!strcmp (at->name, attributeName))
311 cur_attr = cur_attr->next;
315 reply = dbus_message_new_method_return (message);
318 dbus_message_append_args (reply, DBUS_TYPE_STRING, &rv, DBUS_TYPE_INT32,
319 &startOffset, DBUS_TYPE_INT32, &endOffset,
320 DBUS_TYPE_BOOLEAN, &defined,
323 atk_attribute_set_free (set);
328 impl_GetAttributes (DBusConnection * bus, DBusMessage * message,
331 AtkText *text = (AtkText *) user_data;
333 dbus_int32_t startOffset, endOffset;
334 gint intstart_offset, intend_offset;
337 AtkAttributeSet *set;
338 DBusMessageIter iter;
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))
346 return droute_invalid_arguments_error (message);
349 set = atk_text_get_run_attributes (text, offset,
350 &intstart_offset, &intend_offset);
352 startOffset = intstart_offset;
353 endOffset = intend_offset;
354 reply = dbus_message_new_method_return (message);
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,
363 atk_attribute_set_free (set);
368 impl_GetDefaultAttributes (DBusConnection * bus, DBusMessage * message,
371 AtkText *text = (AtkText *) user_data;
374 AtkAttributeSet *set;
375 DBusMessageIter iter;
377 g_return_val_if_fail (ATK_IS_TEXT (user_data),
378 droute_not_yet_handled_error (message));
379 dbus_error_init (&error);
381 set = atk_text_get_default_attributes (text);
382 reply = dbus_message_new_method_return (message);
385 dbus_message_iter_init_append (reply, &iter);
386 spi_object_append_attribute_set (&iter, set);
388 atk_attribute_set_free (set);
393 impl_GetCharacterExtents (DBusConnection * bus, DBusMessage * message,
396 AtkText *text = (AtkText *) user_data;
398 dbus_uint32_t coordType;
399 dbus_int32_t x, y, width, height;
400 gint ix = 0, iy = 0, iw = 0, ih = 0;
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))
411 return droute_invalid_arguments_error (message);
413 atk_text_get_character_extents (text, offset, &ix, &iy, &iw, &ih,
414 (AtkCoordType) coordType);
419 reply = dbus_message_new_method_return (message);
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);
430 impl_GetOffsetAtPoint (DBusConnection * bus, DBusMessage * message,
433 AtkText *text = (AtkText *) user_data;
435 dbus_uint32_t coordType;
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))
447 return droute_invalid_arguments_error (message);
449 rv = atk_text_get_offset_at_point (text, x, y, coordType);
450 reply = dbus_message_new_method_return (message);
453 dbus_message_append_args (reply, DBUS_TYPE_INT32, &rv,
460 impl_GetNSelections (DBusConnection * bus, DBusMessage * message,
463 AtkText *text = (AtkText *) user_data;
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);
473 dbus_message_append_args (reply, DBUS_TYPE_INT32, &rv,
480 impl_GetSelection (DBusConnection * bus, DBusMessage * message,
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;
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))
496 return droute_invalid_arguments_error (message);
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);
506 dbus_message_append_args (reply, DBUS_TYPE_INT32, &startOffset,
507 DBUS_TYPE_INT32, &endOffset,
514 impl_AddSelection (DBusConnection * bus, DBusMessage * message,
517 AtkText *text = (AtkText *) user_data;
518 dbus_int32_t startOffset, endOffset;
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))
530 return droute_invalid_arguments_error (message);
532 rv = atk_text_add_selection (text, startOffset, endOffset);
533 reply = dbus_message_new_method_return (message);
536 dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &rv,
543 impl_RemoveSelection (DBusConnection * bus, DBusMessage * message,
546 AtkText *text = (AtkText *) user_data;
547 dbus_int32_t selectionNum;
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))
558 return droute_invalid_arguments_error (message);
560 rv = atk_text_remove_selection (text, selectionNum);
561 reply = dbus_message_new_method_return (message);
564 dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &rv,
571 impl_SetSelection (DBusConnection * bus, DBusMessage * message,
574 AtkText *text = (AtkText *) user_data;
575 dbus_int32_t selectionNum, startOffset, endOffset;
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))
587 return droute_invalid_arguments_error (message);
589 rv = atk_text_set_selection (text, selectionNum, startOffset, endOffset);
590 reply = dbus_message_new_method_return (message);
593 dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &rv,
600 impl_GetRangeExtents (DBusConnection * bus, DBusMessage * message,
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;
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))
618 return droute_invalid_arguments_error (message);
620 memset (&rect, 0, sizeof (rect));
621 atk_text_get_range_extents (text, startOffset, endOffset,
622 (AtkCoordType) coordType, &rect);
626 height = rect.height;
627 reply = dbus_message_new_method_return (message);
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);
637 #define MAXRANGELEN 512
640 impl_GetBoundedRanges (DBusConnection * bus, DBusMessage * message,
643 AtkText *text = (AtkText *) user_data;
644 dbus_int32_t x, y, width, height;
645 dbus_uint32_t coordType, xClipType, yClipType;
647 AtkTextRange **range_list = NULL;
648 AtkTextRectangle rect;
650 DBusMessageIter iter, array, struc, variant;
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,
661 return droute_invalid_arguments_error (message);
666 rect.height = height;
669 atk_text_get_bounded_ranges (text, &rect, (AtkCoordType) coordType,
670 (AtkTextClipType) xClipType,
671 (AtkTextClipType) yClipType);
672 reply = dbus_message_new_method_return (message);
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))
681 for (len = 0; len < MAXRANGELEN && range_list[len]; ++len)
683 if (dbus_message_iter_open_container
684 (&array, DBUS_TYPE_STRUCT, NULL, &struc))
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))
699 dbus_uint32_t dummy = 0;
700 dbus_message_iter_append_basic (&variant, DBUS_TYPE_INT32,
702 dbus_message_iter_close_container (&struc, &variant);
704 dbus_message_iter_close_container (&array, &struc);
707 dbus_message_iter_close_container (&iter, &array);
713 impl_GetAttributeRun (DBusConnection * bus, DBusMessage * message,
717 AtkText *text = (AtkText *) user_data;
719 dbus_bool_t includeDefaults;
720 dbus_int32_t startOffset, endOffset;
721 gint intstart_offset = 0, intend_offset = 0;
723 AtkAttributeSet *attributes = NULL;
724 DBusMessageIter iter;
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))
733 return droute_invalid_arguments_error (message);
737 atk_text_get_run_attributes (text, offset, &intstart_offset,
742 attributes = g_slist_concat (attributes,
743 atk_text_get_default_attributes (text));
746 reply = dbus_message_new_method_return (message);
750 dbus_message_iter_init_append (reply, &iter);
751 spi_object_append_attribute_set (&iter, attributes);
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);
758 atk_attribute_set_free (attributes);
764 impl_GetDefaultAttributeSet (DBusConnection * bus, DBusMessage * message,
767 AtkText *text = (AtkText *) user_data;
769 DBusMessageIter iter;
770 AtkAttributeSet *attributes;
772 g_return_val_if_fail (ATK_IS_TEXT (user_data),
773 droute_not_yet_handled_error (message));
775 attributes = atk_text_get_default_attributes (text);
777 reply = dbus_message_new_method_return (message);
780 dbus_message_iter_init_append (reply, &iter);
781 spi_object_append_attribute_set (&iter, attributes);
785 atk_attribute_set_free (attributes);
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"},
814 static DRouteProperty properties[] = {
815 {impl_get_CharacterCount, NULL, "CharacterCount"},
816 {impl_get_CaretOffset, NULL, "CaretOffset"},
821 spi_initialize_text (DRoutePath * path)
823 droute_path_add_interface (path,
824 ATSPI_DBUS_INTERFACE_TEXT, spi_org_a11y_atspi_Text, methods, properties);