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 "accessible-marshaller.h"
35 impl_get_CharacterCount (DBusMessageIter * iter,
38 AtkText *text = (AtkText *) user_data;
39 g_return_val_if_fail (ATK_IS_TEXT (user_data), FALSE);
40 return droute_return_v_int32 (iter, atk_text_get_character_count (text));
44 impl_get_CaretOffset (DBusMessageIter * iter,
47 AtkText *text = (AtkText *) user_data;
48 g_return_val_if_fail (ATK_IS_TEXT (user_data), FALSE);
49 return droute_return_v_int32 (iter, atk_text_get_caret_offset (text));
53 impl_GetText (DBusConnection * bus, DBusMessage * message, void *user_data)
55 AtkText *text = (AtkText *) user_data;
56 dbus_int32_t startOffset, endOffset;
61 g_return_val_if_fail (ATK_IS_TEXT (user_data),
62 droute_not_yet_handled_error (message));
63 dbus_error_init (&error);
64 if (!dbus_message_get_args
65 (message, &error, DBUS_TYPE_INT32, &startOffset, DBUS_TYPE_INT32,
66 &endOffset, DBUS_TYPE_INVALID))
68 return droute_invalid_arguments_error (message);
70 txt = atk_text_get_text (text, startOffset, endOffset);
73 reply = dbus_message_new_method_return (message);
76 dbus_message_append_args (reply, DBUS_TYPE_STRING, &txt,
84 impl_SetCaretOffset (DBusConnection * bus, DBusMessage * message,
87 AtkText *text = (AtkText *) user_data;
93 g_return_val_if_fail (ATK_IS_TEXT (user_data),
94 droute_not_yet_handled_error (message));
95 dbus_error_init (&error);
96 if (!dbus_message_get_args
97 (message, &error, DBUS_TYPE_INT32, &offset, DBUS_TYPE_INVALID))
99 return droute_invalid_arguments_error (message);
101 rv = atk_text_set_caret_offset (text, offset);
102 reply = dbus_message_new_method_return (message);
105 dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &rv,
112 impl_GetTextBeforeOffset (DBusConnection * bus, DBusMessage * message,
115 AtkText *text = (AtkText *) user_data;
119 dbus_int32_t startOffset, endOffset;
120 gint intstart_offset = 0, intend_offset = 0;
124 g_return_val_if_fail (ATK_IS_TEXT (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, &offset, DBUS_TYPE_UINT32, &type,
131 return droute_invalid_arguments_error (message);
134 atk_text_get_text_before_offset (text, offset, (AtkTextBoundary) type,
135 &intstart_offset, &intend_offset);
136 startOffset = intstart_offset;
137 endOffset = intend_offset;
140 reply = dbus_message_new_method_return (message);
143 dbus_message_append_args (reply, DBUS_TYPE_STRING, &txt, DBUS_TYPE_INT32,
144 &startOffset, DBUS_TYPE_INT32, &endOffset,
152 impl_GetTextAtOffset (DBusConnection * bus, DBusMessage * message,
155 AtkText *text = (AtkText *) user_data;
156 dbus_int32_t offset, type;
158 dbus_int32_t startOffset, endOffset;
159 gint intstart_offset = 0, intend_offset = 0;
163 g_return_val_if_fail (ATK_IS_TEXT (user_data),
164 droute_not_yet_handled_error (message));
165 dbus_error_init (&error);
166 if (!dbus_message_get_args
167 (message, &error, DBUS_TYPE_INT32, &offset, DBUS_TYPE_UINT32, &type,
170 return droute_invalid_arguments_error (message);
173 atk_text_get_text_at_offset (text, offset, (AtkTextBoundary) type,
174 &intstart_offset, &intend_offset);
175 startOffset = intstart_offset;
176 endOffset = intend_offset;
179 reply = dbus_message_new_method_return (message);
182 dbus_message_append_args (reply, DBUS_TYPE_STRING, &txt, DBUS_TYPE_INT32,
183 &startOffset, 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, DBUS_TYPE_INT32,
223 &startOffset, DBUS_TYPE_INT32, &endOffset,
231 impl_GetCharacterAtOffset (DBusConnection * bus, DBusMessage * message,
234 AtkText *text = (AtkText *) user_data;
240 g_return_val_if_fail (ATK_IS_TEXT (user_data),
241 droute_not_yet_handled_error (message));
242 dbus_error_init (&error);
243 if (!dbus_message_get_args
244 (message, &error, DBUS_TYPE_INT32, &offset, DBUS_TYPE_INVALID))
246 return droute_invalid_arguments_error (message);
248 ch = atk_text_get_character_at_offset (text, offset);
249 reply = dbus_message_new_method_return (message);
252 dbus_message_append_args (reply, DBUS_TYPE_INT32, &ch, DBUS_TYPE_INVALID);
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;
270 AtkAttributeSet *set;
274 g_return_val_if_fail (ATK_IS_TEXT (user_data),
275 droute_not_yet_handled_error (message));
276 dbus_error_init (&error);
277 if (!dbus_message_get_args
278 (message, &error, DBUS_TYPE_INT32, &offset, DBUS_TYPE_STRING,
279 &attributeName, DBUS_TYPE_INVALID))
281 return droute_invalid_arguments_error (message);
284 set = atk_text_get_run_attributes (text, offset,
285 &intstart_offset, &intend_offset);
286 startOffset = intstart_offset;
287 endOffset = intend_offset;
289 cur_attr = (GSList *) set;
292 at = (AtkAttribute *) cur_attr->data;
293 if (!strcmp (at->name, attributeName))
299 cur_attr = cur_attr->next;
303 reply = dbus_message_new_method_return (message);
306 dbus_message_append_args (reply, DBUS_TYPE_STRING, &rv, DBUS_TYPE_INT32,
307 &startOffset, DBUS_TYPE_INT32, &endOffset,
308 DBUS_TYPE_BOOLEAN, &defined, DBUS_TYPE_INVALID);
310 atk_attribute_set_free (set);
315 _string_from_attribute_set (AtkAttributeSet * set)
317 gchar *attributes, *tmp, *tmp2;
321 attributes = g_strdup ("");
322 cur_attr = (GSList *) set;
325 at = (AtkAttribute *) cur_attr->data;
326 tmp = g_strdup_printf ("%s%s:%s%s",
327 ((GSList *) (set) == cur_attr) ? "" : " ",
329 (cur_attr->next) ? ";" : "");
330 tmp2 = g_strconcat (attributes, tmp, NULL);
334 cur_attr = cur_attr->next;
340 impl_GetAttributes (DBusConnection * bus, DBusMessage * message,
343 AtkText *text = (AtkText *) user_data;
345 dbus_int32_t startOffset, endOffset;
346 gint intstart_offset, intend_offset;
349 AtkAttributeSet *set;
350 DBusMessageIter iter;
352 g_return_val_if_fail (ATK_IS_TEXT (user_data),
353 droute_not_yet_handled_error (message));
354 dbus_error_init (&error);
355 if (!dbus_message_get_args
356 (message, &error, DBUS_TYPE_INT32, &offset, DBUS_TYPE_INVALID))
358 return droute_invalid_arguments_error (message);
361 set = atk_text_get_run_attributes (text, offset,
362 &intstart_offset, &intend_offset);
364 startOffset = intstart_offset;
365 endOffset = intend_offset;
366 reply = dbus_message_new_method_return (message);
369 dbus_message_iter_init_append (reply, &iter);
370 spi_atk_append_attribute_set (&iter, set);
371 dbus_message_append_args (reply, DBUS_TYPE_INT32, &startOffset,
372 DBUS_TYPE_INT32, &endOffset, DBUS_TYPE_INVALID);
374 atk_attribute_set_free (set);
379 impl_GetDefaultAttributes (DBusConnection * bus, DBusMessage * message,
382 AtkText *text = (AtkText *) user_data;
385 AtkAttributeSet *set;
386 DBusMessageIter iter;
388 g_return_val_if_fail (ATK_IS_TEXT (user_data),
389 droute_not_yet_handled_error (message));
390 dbus_error_init (&error);
392 set = atk_text_get_default_attributes (text);
393 reply = dbus_message_new_method_return (message);
396 dbus_message_iter_init_append (reply, &iter);
397 spi_atk_append_attribute_set (&iter, set);
399 atk_attribute_set_free (set);
404 impl_GetCharacterExtents (DBusConnection * bus, DBusMessage * message,
407 AtkText *text = (AtkText *) user_data;
409 dbus_uint32_t coordType;
410 dbus_int32_t x, y, width, height;
411 gint ix = 0, iy = 0, iw = 0, ih = 0;
415 g_return_val_if_fail (ATK_IS_TEXT (user_data),
416 droute_not_yet_handled_error (message));
417 dbus_error_init (&error);
418 if (!dbus_message_get_args
419 (message, &error, DBUS_TYPE_INT32, &offset, DBUS_TYPE_UINT32, &coordType,
422 return droute_invalid_arguments_error (message);
424 atk_text_get_character_extents (text, offset, &ix, &iy, &iw, &ih,
425 (AtkCoordType) coordType);
430 reply = dbus_message_new_method_return (message);
433 dbus_message_append_args (reply, DBUS_TYPE_INT32, &x, DBUS_TYPE_INT32,
434 &y, DBUS_TYPE_INT32, &width, DBUS_TYPE_INT32,
435 &height, DBUS_TYPE_INVALID);
441 impl_GetOffsetAtPoint (DBusConnection * bus, DBusMessage * message,
444 AtkText *text = (AtkText *) user_data;
446 dbus_uint32_t coordType;
451 g_return_val_if_fail (ATK_IS_TEXT (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, &x, DBUS_TYPE_INT32, &y,
456 DBUS_TYPE_UINT32, &coordType, DBUS_TYPE_INVALID))
458 return droute_invalid_arguments_error (message);
460 rv = atk_text_get_offset_at_point (text, x, y, coordType);
461 reply = dbus_message_new_method_return (message);
464 dbus_message_append_args (reply, DBUS_TYPE_INT32, &rv,
471 impl_GetNSelections (DBusConnection * bus, DBusMessage * message,
474 AtkText *text = (AtkText *) user_data;
478 g_return_val_if_fail (ATK_IS_TEXT (user_data),
479 droute_not_yet_handled_error (message));
480 rv = atk_text_get_n_selections (text);
481 reply = dbus_message_new_method_return (message);
484 dbus_message_append_args (reply, DBUS_TYPE_INT32, &rv,
491 impl_GetSelection (DBusConnection * bus, DBusMessage * message,
494 AtkText *text = (AtkText *) user_data;
495 dbus_int32_t selectionNum;
496 dbus_int32_t startOffset, endOffset;
497 gint intstart_offset = 0, intend_offset = 0;
501 g_return_val_if_fail (ATK_IS_TEXT (user_data),
502 droute_not_yet_handled_error (message));
503 dbus_error_init (&error);
504 if (!dbus_message_get_args
505 (message, &error, DBUS_TYPE_INT32, &selectionNum, DBUS_TYPE_INVALID))
507 return droute_invalid_arguments_error (message);
509 /* atk_text_get_selection returns gchar * which we discard */
510 g_free (atk_text_get_selection
511 (text, selectionNum, &intstart_offset, &intend_offset));
512 startOffset = intstart_offset;
513 endOffset = intend_offset;
514 reply = dbus_message_new_method_return (message);
517 dbus_message_append_args (reply, DBUS_TYPE_INT32, &startOffset,
518 DBUS_TYPE_INT32, &endOffset,
525 impl_AddSelection (DBusConnection * bus, DBusMessage * message,
528 AtkText *text = (AtkText *) user_data;
529 dbus_int32_t startOffset, endOffset;
534 g_return_val_if_fail (ATK_IS_TEXT (user_data),
535 droute_not_yet_handled_error (message));
536 dbus_error_init (&error);
537 if (!dbus_message_get_args
538 (message, &error, DBUS_TYPE_INT32, &startOffset, DBUS_TYPE_INT32,
539 &endOffset, DBUS_TYPE_INVALID))
541 return droute_invalid_arguments_error (message);
543 rv = atk_text_add_selection (text, startOffset, endOffset);
544 reply = dbus_message_new_method_return (message);
547 dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &rv,
554 impl_RemoveSelection (DBusConnection * bus, DBusMessage * message,
557 AtkText *text = (AtkText *) user_data;
558 dbus_int32_t selectionNum;
563 g_return_val_if_fail (ATK_IS_TEXT (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, &selectionNum, DBUS_TYPE_INVALID))
569 return droute_invalid_arguments_error (message);
571 rv = atk_text_remove_selection (text, selectionNum);
572 reply = dbus_message_new_method_return (message);
575 dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &rv,
582 impl_SetSelection (DBusConnection * bus, DBusMessage * message,
585 AtkText *text = (AtkText *) user_data;
586 dbus_int32_t selectionNum, startOffset, endOffset;
591 g_return_val_if_fail (ATK_IS_TEXT (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, &selectionNum, DBUS_TYPE_INT32,
596 &startOffset, DBUS_TYPE_INT32, &endOffset, DBUS_TYPE_INVALID))
598 return droute_invalid_arguments_error (message);
600 rv = atk_text_set_selection (text, selectionNum, startOffset, endOffset);
601 reply = dbus_message_new_method_return (message);
604 dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &rv,
611 impl_GetRangeExtents (DBusConnection * bus, DBusMessage * message,
614 AtkText *text = (AtkText *) user_data;
615 dbus_int32_t startOffset, endOffset;
616 dbus_uint32_t coordType;
617 AtkTextRectangle rect;
618 dbus_int32_t x, y, width, height;
622 g_return_val_if_fail (ATK_IS_TEXT (user_data),
623 droute_not_yet_handled_error (message));
624 dbus_error_init (&error);
625 if (!dbus_message_get_args
626 (message, &error, DBUS_TYPE_INT32, &startOffset, DBUS_TYPE_INT32,
627 &endOffset, DBUS_TYPE_UINT32, &coordType, DBUS_TYPE_INVALID))
629 return droute_invalid_arguments_error (message);
631 memset (&rect, 0, sizeof (rect));
632 atk_text_get_range_extents (text, startOffset, endOffset,
633 (AtkCoordType) coordType, &rect);
637 height = rect.height;
638 reply = dbus_message_new_method_return (message);
641 dbus_message_append_args (reply, DBUS_TYPE_INT32, &x, DBUS_TYPE_INT32,
642 &y, DBUS_TYPE_INT32, &width, DBUS_TYPE_INT32,
643 &height, DBUS_TYPE_INVALID);
648 #define MAXRANGELEN 512
651 impl_GetBoundedRanges (DBusConnection * bus, DBusMessage * message,
654 AtkText *text = (AtkText *) user_data;
655 dbus_int32_t x, y, width, height;
656 dbus_uint32_t coordType, xClipType, yClipType;
658 AtkTextRange **range_list = NULL;
659 AtkTextRectangle rect;
661 DBusMessageIter iter, array, struc, variant;
663 g_return_val_if_fail (ATK_IS_TEXT (user_data),
664 droute_not_yet_handled_error (message));
665 dbus_error_init (&error);
666 if (!dbus_message_get_args
667 (message, &error, DBUS_TYPE_INT32, &x, DBUS_TYPE_INT32, &y,
668 DBUS_TYPE_INT32, &height, DBUS_TYPE_INT32, &width, DBUS_TYPE_UINT32,
669 &coordType, DBUS_TYPE_UINT32, &xClipType, DBUS_TYPE_UINT32, &yClipType,
672 return droute_invalid_arguments_error (message);
677 rect.height = height;
680 atk_text_get_bounded_ranges (text, &rect, (AtkCoordType) coordType,
681 (AtkTextClipType) xClipType,
682 (AtkTextClipType) yClipType);
683 reply = dbus_message_new_method_return (message);
686 /* This isn't pleasant. */
687 dbus_message_iter_init_append (reply, &iter);
688 if (dbus_message_iter_open_container
689 (&iter, DBUS_TYPE_ARRAY, "(iisv)", &array))
692 for (len = 0; len < MAXRANGELEN && range_list[len]; ++len)
694 if (dbus_message_iter_open_container
695 (&array, DBUS_TYPE_STRUCT, NULL, &struc))
698 val = range_list[len]->start_offset;
699 dbus_message_iter_append_basic (&struc, DBUS_TYPE_INT32, &val);
700 val = range_list[len]->end_offset;
701 dbus_message_iter_append_basic (&struc, DBUS_TYPE_INT32, &val);
702 dbus_message_iter_append_basic (&struc, DBUS_TYPE_STRING,
703 &range_list[len]->content);
704 /* The variant is unimplemented in atk, but I don't want to
705 * unilaterally muck with the spec and remove it, so I'll just
706 * throw in a dummy value */
707 if (dbus_message_iter_open_container
708 (&struc, DBUS_TYPE_VARIANT, "i", &variant))
710 dbus_uint32_t dummy = 0;
711 dbus_message_iter_append_basic (&variant, DBUS_TYPE_INT32,
713 dbus_message_iter_close_container (&struc, &variant);
715 dbus_message_iter_close_container (&array, &struc);
718 dbus_message_iter_close_container (&iter, &array);
724 impl_GetAttributeRun (DBusConnection * bus, DBusMessage * message,
728 AtkText *text = (AtkText *) user_data;
730 dbus_bool_t includeDefaults;
731 dbus_int32_t startOffset, endOffset;
732 gint intstart_offset = 0, intend_offset = 0;
734 AtkAttributeSet *attributes, *default_attributes = NULL;
735 AtkAttribute *attr = NULL;
736 DBusMessageIter iter, iterArray;
738 g_return_val_if_fail (ATK_IS_TEXT (user_data),
739 droute_not_yet_handled_error (message));
740 dbus_error_init (&error);
741 if (!dbus_message_get_args
742 (message, &error, DBUS_TYPE_INT32, &offset, DBUS_TYPE_BOOLEAN,
743 &includeDefaults, DBUS_TYPE_INVALID))
745 return droute_invalid_arguments_error (message);
749 atk_text_get_run_attributes (text, offset, &intstart_offset,
752 reply = dbus_message_new_method_return (message);
756 dbus_message_iter_init_append (reply, &iter);
757 dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "{ss}", &iterArray);
758 spi_atk_append_attribute_set_inner (&iterArray, attributes);
761 default_attributes = atk_text_get_default_attributes (text);
762 spi_atk_append_attribute_set_inner (&iterArray, default_attributes);
764 dbus_message_iter_close_container (&iter, &iterArray);
766 startOffset = intstart_offset;
767 endOffset = intend_offset;
768 dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &startOffset);
769 dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &endOffset);
771 atk_attribute_set_free (attributes);
772 if (default_attributes)
773 atk_attribute_set_free (default_attributes);
779 impl_GetDefaultAttributeSet (DBusConnection * bus, DBusMessage * message,
782 AtkText *text = (AtkText *) user_data;
784 DBusMessageIter iter;
785 AtkAttributeSet *attributes;
787 g_return_val_if_fail (ATK_IS_TEXT (user_data),
788 droute_not_yet_handled_error (message));
790 attributes = atk_text_get_default_attributes (text);
792 reply = dbus_message_new_method_return (message);
795 dbus_message_iter_init_append (reply, &iter);
796 spi_atk_append_attribute_set (&iter, attributes);
800 atk_attribute_set_free (attributes);
805 static DRouteMethod methods[] = {
806 {impl_GetText, "GetText"},
807 {impl_SetCaretOffset, "SetCaretOffset"},
808 {impl_GetTextBeforeOffset, "GetTextBeforeOffset"},
809 {impl_GetTextAtOffset, "GetTextAtOffset"},
810 {impl_GetTextAfterOffset, "GetTextAfterOffset"},
811 {impl_GetCharacterAtOffset, "GetCharacterAtOffset"},
812 {impl_GetAttributeValue, "GetAttributeValue"},
813 {impl_GetAttributes, "GetAttributes"},
814 {impl_GetDefaultAttributes, "GetDefaultAttributes"},
815 {impl_GetCharacterExtents, "GetCharacterExtents"},
816 {impl_GetOffsetAtPoint, "GetOffsetAtPoint"},
817 {impl_GetNSelections, "GetNSelections"},
818 {impl_GetSelection, "GetSelection"},
819 {impl_AddSelection, "AddSelection"},
820 {impl_RemoveSelection, "RemoveSelection"},
821 {impl_SetSelection, "SetSelection"},
822 {impl_GetRangeExtents, "GetRangeExtents"},
823 {impl_GetBoundedRanges, "GetBoundedRanges"},
824 {impl_GetAttributeRun, "GetAttributeRun"},
825 {impl_GetDefaultAttributeSet, "GetDefaultAttributeSet"},
829 static DRouteProperty properties[] = {
830 {impl_get_CharacterCount, NULL, "CharacterCount"},
831 {impl_get_CaretOffset, NULL, "CaretOffset"},
836 spi_initialize_text (DRoutePath *path)
838 droute_path_add_interface (path,
839 SPI_DBUS_INTERFACE_TEXT,