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;
72 g_return_val_if_fail (ATK_IS_TEXT (user_data),
73 droute_not_yet_handled_error (message));
74 if (!dbus_message_get_args
75 (message, NULL, DBUS_TYPE_INT32, &startOffset, DBUS_TYPE_INT32,
76 &endOffset, DBUS_TYPE_INVALID))
78 return droute_invalid_arguments_error (message);
80 txt = atk_text_get_text (text, startOffset, endOffset);
81 txt = validate_allocated_string (txt);
82 reply = dbus_message_new_method_return (message);
85 dbus_message_append_args (reply, DBUS_TYPE_STRING, &txt,
93 impl_SetCaretOffset (DBusConnection * bus, DBusMessage * message,
96 AtkText *text = (AtkText *) user_data;
101 g_return_val_if_fail (ATK_IS_TEXT (user_data),
102 droute_not_yet_handled_error (message));
103 if (!dbus_message_get_args
104 (message, NULL, DBUS_TYPE_INT32, &offset, DBUS_TYPE_INVALID))
106 return droute_invalid_arguments_error (message);
108 rv = atk_text_set_caret_offset (text, offset);
109 reply = dbus_message_new_method_return (message);
112 dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &rv,
119 impl_GetTextBeforeOffset (DBusConnection * bus, DBusMessage * message,
122 AtkText *text = (AtkText *) user_data;
126 dbus_int32_t startOffset, endOffset;
127 gint intstart_offset = 0, intend_offset = 0;
130 g_return_val_if_fail (ATK_IS_TEXT (user_data),
131 droute_not_yet_handled_error (message));
132 if (!dbus_message_get_args
133 (message, NULL, DBUS_TYPE_INT32, &offset, DBUS_TYPE_UINT32, &type,
136 return droute_invalid_arguments_error (message);
139 atk_text_get_text_before_offset (text, offset, (AtkTextBoundary) type,
140 &intstart_offset, &intend_offset);
141 startOffset = intstart_offset;
142 endOffset = intend_offset;
143 txt = validate_allocated_string (txt);
144 reply = dbus_message_new_method_return (message);
147 dbus_message_append_args (reply, DBUS_TYPE_STRING, &txt,
148 DBUS_TYPE_INT32, &startOffset,
149 DBUS_TYPE_INT32, &endOffset,
157 impl_GetTextAtOffset (DBusConnection * bus, DBusMessage * message,
160 AtkText *text = (AtkText *) user_data;
161 dbus_int32_t offset, type;
163 dbus_int32_t startOffset, endOffset;
164 gint intstart_offset = 0, intend_offset = 0;
167 g_return_val_if_fail (ATK_IS_TEXT (user_data),
168 droute_not_yet_handled_error (message));
169 if (!dbus_message_get_args
170 (message, NULL, DBUS_TYPE_INT32, &offset, DBUS_TYPE_UINT32, &type,
173 return droute_invalid_arguments_error (message);
176 atk_text_get_text_at_offset (text, offset, (AtkTextBoundary) type,
177 &intstart_offset, &intend_offset);
178 startOffset = intstart_offset;
179 endOffset = intend_offset;
180 txt = validate_allocated_string (txt);
181 reply = dbus_message_new_method_return (message);
184 dbus_message_append_args (reply, DBUS_TYPE_STRING, &txt,
185 DBUS_TYPE_INT32, &startOffset,
186 DBUS_TYPE_INT32, &endOffset,
194 impl_GetTextAfterOffset (DBusConnection * bus, DBusMessage * message,
197 AtkText *text = (AtkText *) user_data;
201 dbus_int32_t startOffset, endOffset;
202 gint intstart_offset = 0, intend_offset = 0;
205 g_return_val_if_fail (ATK_IS_TEXT (user_data),
206 droute_not_yet_handled_error (message));
207 if (!dbus_message_get_args
208 (message, NULL, DBUS_TYPE_INT32, &offset, DBUS_TYPE_UINT32, &type,
211 return droute_invalid_arguments_error (message);
214 atk_text_get_text_after_offset (text, offset, (AtkTextBoundary) type,
215 &intstart_offset, &intend_offset);
216 startOffset = intstart_offset;
217 endOffset = intend_offset;
218 txt = validate_allocated_string (txt);
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;
240 g_return_val_if_fail (ATK_IS_TEXT (user_data),
241 droute_not_yet_handled_error (message));
242 if (!dbus_message_get_args
243 (message, NULL, DBUS_TYPE_INT32, &offset, DBUS_TYPE_INVALID))
245 return droute_invalid_arguments_error (message);
247 ch = atk_text_get_character_at_offset (text, offset);
248 reply = dbus_message_new_method_return (message);
251 dbus_message_append_args (reply, DBUS_TYPE_INT32, &ch,
258 impl_GetAttributeValue (DBusConnection * bus, DBusMessage * message,
261 AtkText *text = (AtkText *) user_data;
264 dbus_int32_t startOffset, endOffset;
266 gint intstart_offset = 0, intend_offset = 0;
269 AtkAttributeSet *set;
273 g_return_val_if_fail (ATK_IS_TEXT (user_data),
274 droute_not_yet_handled_error (message));
275 if (!dbus_message_get_args
276 (message, NULL, DBUS_TYPE_INT32, &offset, DBUS_TYPE_STRING,
277 &attributeName, DBUS_TYPE_INVALID))
279 return droute_invalid_arguments_error (message);
282 set = atk_text_get_run_attributes (text, offset,
283 &intstart_offset, &intend_offset);
284 startOffset = intstart_offset;
285 endOffset = intend_offset;
287 cur_attr = (GSList *) set;
290 at = (AtkAttribute *) cur_attr->data;
291 if (!strcmp (at->name, attributeName))
297 cur_attr = cur_attr->next;
301 reply = dbus_message_new_method_return (message);
304 dbus_message_append_args (reply, DBUS_TYPE_STRING, &rv, DBUS_TYPE_INT32,
305 &startOffset, DBUS_TYPE_INT32, &endOffset,
306 DBUS_TYPE_BOOLEAN, &defined,
309 atk_attribute_set_free (set);
314 impl_GetAttributes (DBusConnection * bus, DBusMessage * message,
317 AtkText *text = (AtkText *) user_data;
319 dbus_int32_t startOffset, endOffset;
320 gint intstart_offset, intend_offset;
322 AtkAttributeSet *set;
323 DBusMessageIter iter;
325 g_return_val_if_fail (ATK_IS_TEXT (user_data),
326 droute_not_yet_handled_error (message));
327 if (!dbus_message_get_args
328 (message, NULL, DBUS_TYPE_INT32, &offset, DBUS_TYPE_INVALID))
330 return droute_invalid_arguments_error (message);
333 set = atk_text_get_run_attributes (text, offset,
334 &intstart_offset, &intend_offset);
336 startOffset = intstart_offset;
337 endOffset = intend_offset;
338 reply = dbus_message_new_method_return (message);
341 dbus_message_iter_init_append (reply, &iter);
342 spi_object_append_attribute_set (&iter, set);
343 dbus_message_append_args (reply, DBUS_TYPE_INT32, &startOffset,
344 DBUS_TYPE_INT32, &endOffset,
347 atk_attribute_set_free (set);
352 impl_GetDefaultAttributes (DBusConnection * bus, DBusMessage * message,
355 AtkText *text = (AtkText *) user_data;
357 AtkAttributeSet *set;
358 DBusMessageIter iter;
360 g_return_val_if_fail (ATK_IS_TEXT (user_data),
361 droute_not_yet_handled_error (message));
363 set = atk_text_get_default_attributes (text);
364 reply = dbus_message_new_method_return (message);
367 dbus_message_iter_init_append (reply, &iter);
368 spi_object_append_attribute_set (&iter, set);
370 atk_attribute_set_free (set);
375 impl_GetCharacterExtents (DBusConnection * bus, DBusMessage * message,
378 AtkText *text = (AtkText *) user_data;
380 dbus_uint32_t coordType;
381 dbus_int32_t x, y, width, height;
382 gint ix = 0, iy = 0, iw = 0, ih = 0;
385 g_return_val_if_fail (ATK_IS_TEXT (user_data),
386 droute_not_yet_handled_error (message));
387 if (!dbus_message_get_args
388 (message, NULL, DBUS_TYPE_INT32, &offset, DBUS_TYPE_UINT32,
389 &coordType, DBUS_TYPE_INVALID))
391 return droute_invalid_arguments_error (message);
393 atk_text_get_character_extents (text, offset, &ix, &iy, &iw, &ih,
394 (AtkCoordType) coordType);
399 reply = dbus_message_new_method_return (message);
402 dbus_message_append_args (reply, DBUS_TYPE_INT32, &x, DBUS_TYPE_INT32,
403 &y, DBUS_TYPE_INT32, &width, DBUS_TYPE_INT32,
404 &height, DBUS_TYPE_INVALID);
410 impl_GetOffsetAtPoint (DBusConnection * bus, DBusMessage * message,
413 AtkText *text = (AtkText *) user_data;
415 dbus_uint32_t coordType;
419 g_return_val_if_fail (ATK_IS_TEXT (user_data),
420 droute_not_yet_handled_error (message));
421 if (!dbus_message_get_args
422 (message, NULL, DBUS_TYPE_INT32, &x, DBUS_TYPE_INT32, &y,
423 DBUS_TYPE_UINT32, &coordType, DBUS_TYPE_INVALID))
425 return droute_invalid_arguments_error (message);
427 rv = atk_text_get_offset_at_point (text, x, y, coordType);
428 reply = dbus_message_new_method_return (message);
431 dbus_message_append_args (reply, DBUS_TYPE_INT32, &rv,
438 impl_GetNSelections (DBusConnection * bus, DBusMessage * message,
441 AtkText *text = (AtkText *) user_data;
445 g_return_val_if_fail (ATK_IS_TEXT (user_data),
446 droute_not_yet_handled_error (message));
447 rv = atk_text_get_n_selections (text);
448 reply = dbus_message_new_method_return (message);
451 dbus_message_append_args (reply, DBUS_TYPE_INT32, &rv,
458 impl_GetSelection (DBusConnection * bus, DBusMessage * message,
461 AtkText *text = (AtkText *) user_data;
462 dbus_int32_t selectionNum;
463 dbus_int32_t startOffset, endOffset;
464 gint intstart_offset = 0, intend_offset = 0;
467 g_return_val_if_fail (ATK_IS_TEXT (user_data),
468 droute_not_yet_handled_error (message));
469 if (!dbus_message_get_args
470 (message, NULL, DBUS_TYPE_INT32, &selectionNum, DBUS_TYPE_INVALID))
472 return droute_invalid_arguments_error (message);
474 /* atk_text_get_selection returns gchar * which we discard */
475 g_free (atk_text_get_selection
476 (text, selectionNum, &intstart_offset, &intend_offset));
477 startOffset = intstart_offset;
478 endOffset = intend_offset;
479 reply = dbus_message_new_method_return (message);
482 dbus_message_append_args (reply, DBUS_TYPE_INT32, &startOffset,
483 DBUS_TYPE_INT32, &endOffset,
490 impl_AddSelection (DBusConnection * bus, DBusMessage * message,
493 AtkText *text = (AtkText *) user_data;
494 dbus_int32_t startOffset, endOffset;
498 g_return_val_if_fail (ATK_IS_TEXT (user_data),
499 droute_not_yet_handled_error (message));
500 if (!dbus_message_get_args
501 (message, NULL, DBUS_TYPE_INT32, &startOffset, DBUS_TYPE_INT32,
502 &endOffset, DBUS_TYPE_INVALID))
504 return droute_invalid_arguments_error (message);
506 rv = atk_text_add_selection (text, startOffset, endOffset);
507 reply = dbus_message_new_method_return (message);
510 dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &rv,
517 impl_RemoveSelection (DBusConnection * bus, DBusMessage * message,
520 AtkText *text = (AtkText *) user_data;
521 dbus_int32_t selectionNum;
525 g_return_val_if_fail (ATK_IS_TEXT (user_data),
526 droute_not_yet_handled_error (message));
527 if (!dbus_message_get_args
528 (message, NULL, DBUS_TYPE_INT32, &selectionNum, DBUS_TYPE_INVALID))
530 return droute_invalid_arguments_error (message);
532 rv = atk_text_remove_selection (text, selectionNum);
533 reply = dbus_message_new_method_return (message);
536 dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &rv,
543 impl_SetSelection (DBusConnection * bus, DBusMessage * message,
546 AtkText *text = (AtkText *) user_data;
547 dbus_int32_t selectionNum, startOffset, endOffset;
551 g_return_val_if_fail (ATK_IS_TEXT (user_data),
552 droute_not_yet_handled_error (message));
553 if (!dbus_message_get_args
554 (message, NULL, DBUS_TYPE_INT32, &selectionNum, DBUS_TYPE_INT32,
555 &startOffset, DBUS_TYPE_INT32, &endOffset, DBUS_TYPE_INVALID))
557 return droute_invalid_arguments_error (message);
559 rv = atk_text_set_selection (text, selectionNum, startOffset, endOffset);
560 reply = dbus_message_new_method_return (message);
563 dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &rv,
570 impl_GetRangeExtents (DBusConnection * bus, DBusMessage * message,
573 AtkText *text = (AtkText *) user_data;
574 dbus_int32_t startOffset, endOffset;
575 dbus_uint32_t coordType;
576 AtkTextRectangle rect;
577 dbus_int32_t x, y, width, height;
580 g_return_val_if_fail (ATK_IS_TEXT (user_data),
581 droute_not_yet_handled_error (message));
582 if (!dbus_message_get_args
583 (message, NULL, DBUS_TYPE_INT32, &startOffset, DBUS_TYPE_INT32,
584 &endOffset, DBUS_TYPE_UINT32, &coordType, DBUS_TYPE_INVALID))
586 return droute_invalid_arguments_error (message);
588 memset (&rect, 0, sizeof (rect));
589 atk_text_get_range_extents (text, startOffset, endOffset,
590 (AtkCoordType) coordType, &rect);
594 height = rect.height;
595 reply = dbus_message_new_method_return (message);
598 dbus_message_append_args (reply, DBUS_TYPE_INT32, &x, DBUS_TYPE_INT32,
599 &y, DBUS_TYPE_INT32, &width, DBUS_TYPE_INT32,
600 &height, DBUS_TYPE_INVALID);
605 #define MAXRANGELEN 512
608 impl_GetBoundedRanges (DBusConnection * bus, DBusMessage * message,
611 AtkText *text = (AtkText *) user_data;
612 dbus_int32_t x, y, width, height;
613 dbus_uint32_t coordType, xClipType, yClipType;
614 AtkTextRange **range_list = NULL;
615 AtkTextRectangle rect;
617 DBusMessageIter iter, array, struc, variant;
619 g_return_val_if_fail (ATK_IS_TEXT (user_data),
620 droute_not_yet_handled_error (message));
621 if (!dbus_message_get_args
622 (message, NULL, DBUS_TYPE_INT32, &x, DBUS_TYPE_INT32, &y,
623 DBUS_TYPE_INT32, &height, DBUS_TYPE_INT32, &width, DBUS_TYPE_UINT32,
624 &coordType, DBUS_TYPE_UINT32, &xClipType, DBUS_TYPE_UINT32, &yClipType,
627 return droute_invalid_arguments_error (message);
632 rect.height = height;
635 atk_text_get_bounded_ranges (text, &rect, (AtkCoordType) coordType,
636 (AtkTextClipType) xClipType,
637 (AtkTextClipType) yClipType);
638 reply = dbus_message_new_method_return (message);
641 /* This isn't pleasant. */
642 dbus_message_iter_init_append (reply, &iter);
643 if (dbus_message_iter_open_container
644 (&iter, DBUS_TYPE_ARRAY, "(iisv)", &array))
647 for (len = 0; len < MAXRANGELEN && range_list[len]; ++len)
649 if (dbus_message_iter_open_container
650 (&array, DBUS_TYPE_STRUCT, NULL, &struc))
653 val = range_list[len]->start_offset;
654 dbus_message_iter_append_basic (&struc, DBUS_TYPE_INT32, &val);
655 val = range_list[len]->end_offset;
656 dbus_message_iter_append_basic (&struc, DBUS_TYPE_INT32, &val);
657 dbus_message_iter_append_basic (&struc, DBUS_TYPE_STRING,
658 &range_list[len]->content);
659 /* The variant is unimplemented in atk, but I don't want to
660 * unilaterally muck with the spec and remove it, so I'll just
661 * throw in a dummy value */
662 if (dbus_message_iter_open_container
663 (&struc, DBUS_TYPE_VARIANT, "i", &variant))
665 dbus_uint32_t dummy = 0;
666 dbus_message_iter_append_basic (&variant, DBUS_TYPE_INT32,
668 dbus_message_iter_close_container (&struc, &variant);
670 dbus_message_iter_close_container (&array, &struc);
673 dbus_message_iter_close_container (&iter, &array);
679 impl_GetAttributeRun (DBusConnection * bus, DBusMessage * message,
682 AtkText *text = (AtkText *) user_data;
684 dbus_bool_t includeDefaults;
685 dbus_int32_t startOffset, endOffset;
686 gint intstart_offset = 0, intend_offset = 0;
688 AtkAttributeSet *attributes = NULL;
689 DBusMessageIter iter;
691 g_return_val_if_fail (ATK_IS_TEXT (user_data),
692 droute_not_yet_handled_error (message));
693 if (!dbus_message_get_args
694 (message, NULL, DBUS_TYPE_INT32, &offset, DBUS_TYPE_BOOLEAN,
695 &includeDefaults, DBUS_TYPE_INVALID))
697 return droute_invalid_arguments_error (message);
701 atk_text_get_run_attributes (text, offset, &intstart_offset,
706 attributes = g_slist_concat (attributes,
707 atk_text_get_default_attributes (text));
710 reply = dbus_message_new_method_return (message);
714 dbus_message_iter_init_append (reply, &iter);
715 spi_object_append_attribute_set (&iter, attributes);
717 startOffset = intstart_offset;
718 endOffset = intend_offset;
719 dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &startOffset);
720 dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &endOffset);
722 atk_attribute_set_free (attributes);
728 impl_GetDefaultAttributeSet (DBusConnection * bus, DBusMessage * message,
731 AtkText *text = (AtkText *) user_data;
733 DBusMessageIter iter;
734 AtkAttributeSet *attributes;
736 g_return_val_if_fail (ATK_IS_TEXT (user_data),
737 droute_not_yet_handled_error (message));
739 attributes = atk_text_get_default_attributes (text);
741 reply = dbus_message_new_method_return (message);
744 dbus_message_iter_init_append (reply, &iter);
745 spi_object_append_attribute_set (&iter, attributes);
749 atk_attribute_set_free (attributes);
754 static DRouteMethod methods[] = {
755 {impl_GetText, "GetText"},
756 {impl_SetCaretOffset, "SetCaretOffset"},
757 {impl_GetTextBeforeOffset, "GetTextBeforeOffset"},
758 {impl_GetTextAtOffset, "GetTextAtOffset"},
759 {impl_GetTextAfterOffset, "GetTextAfterOffset"},
760 {impl_GetCharacterAtOffset, "GetCharacterAtOffset"},
761 {impl_GetAttributeValue, "GetAttributeValue"},
762 {impl_GetAttributes, "GetAttributes"},
763 {impl_GetDefaultAttributes, "GetDefaultAttributes"},
764 {impl_GetCharacterExtents, "GetCharacterExtents"},
765 {impl_GetOffsetAtPoint, "GetOffsetAtPoint"},
766 {impl_GetNSelections, "GetNSelections"},
767 {impl_GetSelection, "GetSelection"},
768 {impl_AddSelection, "AddSelection"},
769 {impl_RemoveSelection, "RemoveSelection"},
770 {impl_SetSelection, "SetSelection"},
771 {impl_GetRangeExtents, "GetRangeExtents"},
772 {impl_GetBoundedRanges, "GetBoundedRanges"},
773 {impl_GetAttributeRun, "GetAttributeRun"},
774 {impl_GetDefaultAttributeSet, "GetDefaultAttributeSet"},
778 static DRouteProperty properties[] = {
779 {impl_get_CharacterCount, NULL, "CharacterCount"},
780 {impl_get_CaretOffset, NULL, "CaretOffset"},
785 spi_initialize_text (DRoutePath * path)
787 droute_path_add_interface (path,
788 ATSPI_DBUS_INTERFACE_TEXT, spi_org_a11y_atspi_Text, methods, properties);