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"
34 impl_get_CharacterCount (DBusMessageIter * iter, void *user_data)
36 AtkText *text = (AtkText *) user_data;
37 g_return_val_if_fail (ATK_IS_TEXT (user_data), FALSE);
38 return droute_return_v_int32 (iter, atk_text_get_character_count (text));
42 impl_get_CaretOffset (DBusMessageIter * iter, void *user_data)
44 AtkText *text = (AtkText *) user_data;
45 g_return_val_if_fail (ATK_IS_TEXT (user_data), FALSE);
46 return droute_return_v_int32 (iter, atk_text_get_caret_offset (text));
50 impl_GetText (DBusConnection * bus, DBusMessage * message, void *user_data)
52 AtkText *text = (AtkText *) user_data;
53 dbus_int32_t startOffset, endOffset;
58 g_return_val_if_fail (ATK_IS_TEXT (user_data),
59 droute_not_yet_handled_error (message));
60 dbus_error_init (&error);
61 if (!dbus_message_get_args
62 (message, &error, DBUS_TYPE_INT32, &startOffset, DBUS_TYPE_INT32,
63 &endOffset, DBUS_TYPE_INVALID))
65 return droute_invalid_arguments_error (message);
67 txt = atk_text_get_text (text, startOffset, endOffset);
70 reply = dbus_message_new_method_return (message);
73 dbus_message_append_args (reply, DBUS_TYPE_STRING, &txt,
81 impl_SetCaretOffset (DBusConnection * bus, DBusMessage * message,
84 AtkText *text = (AtkText *) user_data;
90 g_return_val_if_fail (ATK_IS_TEXT (user_data),
91 droute_not_yet_handled_error (message));
92 dbus_error_init (&error);
93 if (!dbus_message_get_args
94 (message, &error, DBUS_TYPE_INT32, &offset, DBUS_TYPE_INVALID))
96 return droute_invalid_arguments_error (message);
98 rv = atk_text_set_caret_offset (text, offset);
99 reply = dbus_message_new_method_return (message);
102 dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &rv,
109 impl_GetTextBeforeOffset (DBusConnection * bus, DBusMessage * message,
112 AtkText *text = (AtkText *) user_data;
116 dbus_int32_t startOffset, endOffset;
117 gint intstart_offset = 0, intend_offset = 0;
121 g_return_val_if_fail (ATK_IS_TEXT (user_data),
122 droute_not_yet_handled_error (message));
123 dbus_error_init (&error);
124 if (!dbus_message_get_args
125 (message, &error, DBUS_TYPE_INT32, &offset, DBUS_TYPE_UINT32, &type,
128 return droute_invalid_arguments_error (message);
131 atk_text_get_text_before_offset (text, offset, (AtkTextBoundary) type,
132 &intstart_offset, &intend_offset);
133 startOffset = intstart_offset;
134 endOffset = intend_offset;
137 reply = dbus_message_new_method_return (message);
140 dbus_message_append_args (reply, DBUS_TYPE_STRING, &txt,
141 DBUS_TYPE_INT32, &startOffset,
142 DBUS_TYPE_INT32, &endOffset,
150 impl_GetTextAtOffset (DBusConnection * bus, DBusMessage * message,
153 AtkText *text = (AtkText *) user_data;
154 dbus_int32_t offset, type;
156 dbus_int32_t startOffset, endOffset;
157 gint intstart_offset = 0, intend_offset = 0;
161 g_return_val_if_fail (ATK_IS_TEXT (user_data),
162 droute_not_yet_handled_error (message));
163 dbus_error_init (&error);
164 if (!dbus_message_get_args
165 (message, &error, DBUS_TYPE_INT32, &offset, DBUS_TYPE_UINT32, &type,
168 return droute_invalid_arguments_error (message);
171 atk_text_get_text_at_offset (text, offset, (AtkTextBoundary) type,
172 &intstart_offset, &intend_offset);
173 startOffset = intstart_offset;
174 endOffset = intend_offset;
177 reply = dbus_message_new_method_return (message);
180 dbus_message_append_args (reply, DBUS_TYPE_STRING, &txt,
181 DBUS_TYPE_INT32, &startOffset,
182 DBUS_TYPE_INT32, &endOffset,
190 impl_GetTextAfterOffset (DBusConnection * bus, DBusMessage * message,
193 AtkText *text = (AtkText *) user_data;
197 dbus_int32_t startOffset, endOffset;
198 gint intstart_offset = 0, intend_offset = 0;
202 g_return_val_if_fail (ATK_IS_TEXT (user_data),
203 droute_not_yet_handled_error (message));
204 dbus_error_init (&error);
205 if (!dbus_message_get_args
206 (message, &error, DBUS_TYPE_INT32, &offset, DBUS_TYPE_UINT32, &type,
209 return droute_invalid_arguments_error (message);
212 atk_text_get_text_after_offset (text, offset, (AtkTextBoundary) type,
213 &intstart_offset, &intend_offset);
214 startOffset = intstart_offset;
215 endOffset = intend_offset;
218 reply = dbus_message_new_method_return (message);
221 dbus_message_append_args (reply, DBUS_TYPE_STRING, &txt,
222 DBUS_TYPE_INT32, &startOffset,
223 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,
259 impl_GetAttributeValue (DBusConnection * bus, DBusMessage * message,
262 AtkText *text = (AtkText *) user_data;
265 dbus_int32_t startOffset, endOffset;
267 gint intstart_offset = 0, intend_offset = 0;
271 AtkAttributeSet *set;
275 g_return_val_if_fail (ATK_IS_TEXT (user_data),
276 droute_not_yet_handled_error (message));
277 dbus_error_init (&error);
278 if (!dbus_message_get_args
279 (message, &error, DBUS_TYPE_INT32, &offset, DBUS_TYPE_STRING,
280 &attributeName, DBUS_TYPE_INVALID))
282 return droute_invalid_arguments_error (message);
285 set = atk_text_get_run_attributes (text, offset,
286 &intstart_offset, &intend_offset);
287 startOffset = intstart_offset;
288 endOffset = intend_offset;
290 cur_attr = (GSList *) set;
293 at = (AtkAttribute *) cur_attr->data;
294 if (!strcmp (at->name, attributeName))
300 cur_attr = cur_attr->next;
304 reply = dbus_message_new_method_return (message);
307 dbus_message_append_args (reply, DBUS_TYPE_STRING, &rv, DBUS_TYPE_INT32,
308 &startOffset, DBUS_TYPE_INT32, &endOffset,
309 DBUS_TYPE_BOOLEAN, &defined,
312 atk_attribute_set_free (set);
317 _string_from_attribute_set (AtkAttributeSet * set)
319 gchar *attributes, *tmp, *tmp2;
323 attributes = g_strdup ("");
324 cur_attr = (GSList *) set;
327 at = (AtkAttribute *) cur_attr->data;
328 tmp = g_strdup_printf ("%s%s:%s%s",
329 ((GSList *) (set) == cur_attr) ? "" : " ",
331 (cur_attr->next) ? ";" : "");
332 tmp2 = g_strconcat (attributes, tmp, NULL);
336 cur_attr = cur_attr->next;
342 impl_GetAttributes (DBusConnection * bus, DBusMessage * message,
345 AtkText *text = (AtkText *) user_data;
347 dbus_int32_t startOffset, endOffset;
348 gint intstart_offset, intend_offset;
351 AtkAttributeSet *set;
352 DBusMessageIter iter;
354 g_return_val_if_fail (ATK_IS_TEXT (user_data),
355 droute_not_yet_handled_error (message));
356 dbus_error_init (&error);
357 if (!dbus_message_get_args
358 (message, &error, DBUS_TYPE_INT32, &offset, DBUS_TYPE_INVALID))
360 return droute_invalid_arguments_error (message);
363 set = atk_text_get_run_attributes (text, offset,
364 &intstart_offset, &intend_offset);
366 startOffset = intstart_offset;
367 endOffset = intend_offset;
368 reply = dbus_message_new_method_return (message);
371 dbus_message_iter_init_append (reply, &iter);
372 spi_object_append_attribute_set (&iter, set);
373 dbus_message_append_args (reply, DBUS_TYPE_INT32, &startOffset,
374 DBUS_TYPE_INT32, &endOffset,
377 atk_attribute_set_free (set);
382 impl_GetDefaultAttributes (DBusConnection * bus, DBusMessage * message,
385 AtkText *text = (AtkText *) user_data;
388 AtkAttributeSet *set;
389 DBusMessageIter iter;
391 g_return_val_if_fail (ATK_IS_TEXT (user_data),
392 droute_not_yet_handled_error (message));
393 dbus_error_init (&error);
395 set = atk_text_get_default_attributes (text);
396 reply = dbus_message_new_method_return (message);
399 dbus_message_iter_init_append (reply, &iter);
400 spi_object_append_attribute_set (&iter, set);
402 atk_attribute_set_free (set);
407 impl_GetCharacterExtents (DBusConnection * bus, DBusMessage * message,
410 AtkText *text = (AtkText *) user_data;
412 dbus_uint32_t coordType;
413 dbus_int32_t x, y, width, height;
414 gint ix = 0, iy = 0, iw = 0, ih = 0;
418 g_return_val_if_fail (ATK_IS_TEXT (user_data),
419 droute_not_yet_handled_error (message));
420 dbus_error_init (&error);
421 if (!dbus_message_get_args
422 (message, &error, DBUS_TYPE_INT32, &offset, DBUS_TYPE_UINT32,
423 &coordType, DBUS_TYPE_INVALID))
425 return droute_invalid_arguments_error (message);
427 atk_text_get_character_extents (text, offset, &ix, &iy, &iw, &ih,
428 (AtkCoordType) coordType);
433 reply = dbus_message_new_method_return (message);
436 dbus_message_append_args (reply, DBUS_TYPE_INT32, &x, DBUS_TYPE_INT32,
437 &y, DBUS_TYPE_INT32, &width, DBUS_TYPE_INT32,
438 &height, DBUS_TYPE_INVALID);
444 impl_GetOffsetAtPoint (DBusConnection * bus, DBusMessage * message,
447 AtkText *text = (AtkText *) user_data;
449 dbus_uint32_t coordType;
454 g_return_val_if_fail (ATK_IS_TEXT (user_data),
455 droute_not_yet_handled_error (message));
456 dbus_error_init (&error);
457 if (!dbus_message_get_args
458 (message, &error, DBUS_TYPE_INT32, &x, DBUS_TYPE_INT32, &y,
459 DBUS_TYPE_UINT32, &coordType, DBUS_TYPE_INVALID))
461 return droute_invalid_arguments_error (message);
463 rv = atk_text_get_offset_at_point (text, x, y, coordType);
464 reply = dbus_message_new_method_return (message);
467 dbus_message_append_args (reply, DBUS_TYPE_INT32, &rv,
474 impl_GetNSelections (DBusConnection * bus, DBusMessage * message,
477 AtkText *text = (AtkText *) user_data;
481 g_return_val_if_fail (ATK_IS_TEXT (user_data),
482 droute_not_yet_handled_error (message));
483 rv = atk_text_get_n_selections (text);
484 reply = dbus_message_new_method_return (message);
487 dbus_message_append_args (reply, DBUS_TYPE_INT32, &rv,
494 impl_GetSelection (DBusConnection * bus, DBusMessage * message,
497 AtkText *text = (AtkText *) user_data;
498 dbus_int32_t selectionNum;
499 dbus_int32_t startOffset, endOffset;
500 gint intstart_offset = 0, intend_offset = 0;
504 g_return_val_if_fail (ATK_IS_TEXT (user_data),
505 droute_not_yet_handled_error (message));
506 dbus_error_init (&error);
507 if (!dbus_message_get_args
508 (message, &error, DBUS_TYPE_INT32, &selectionNum, DBUS_TYPE_INVALID))
510 return droute_invalid_arguments_error (message);
512 /* atk_text_get_selection returns gchar * which we discard */
513 g_free (atk_text_get_selection
514 (text, selectionNum, &intstart_offset, &intend_offset));
515 startOffset = intstart_offset;
516 endOffset = intend_offset;
517 reply = dbus_message_new_method_return (message);
520 dbus_message_append_args (reply, DBUS_TYPE_INT32, &startOffset,
521 DBUS_TYPE_INT32, &endOffset,
528 impl_AddSelection (DBusConnection * bus, DBusMessage * message,
531 AtkText *text = (AtkText *) user_data;
532 dbus_int32_t startOffset, endOffset;
537 g_return_val_if_fail (ATK_IS_TEXT (user_data),
538 droute_not_yet_handled_error (message));
539 dbus_error_init (&error);
540 if (!dbus_message_get_args
541 (message, &error, DBUS_TYPE_INT32, &startOffset, DBUS_TYPE_INT32,
542 &endOffset, DBUS_TYPE_INVALID))
544 return droute_invalid_arguments_error (message);
546 rv = atk_text_add_selection (text, startOffset, endOffset);
547 reply = dbus_message_new_method_return (message);
550 dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &rv,
557 impl_RemoveSelection (DBusConnection * bus, DBusMessage * message,
560 AtkText *text = (AtkText *) user_data;
561 dbus_int32_t selectionNum;
566 g_return_val_if_fail (ATK_IS_TEXT (user_data),
567 droute_not_yet_handled_error (message));
568 dbus_error_init (&error);
569 if (!dbus_message_get_args
570 (message, &error, DBUS_TYPE_INT32, &selectionNum, DBUS_TYPE_INVALID))
572 return droute_invalid_arguments_error (message);
574 rv = atk_text_remove_selection (text, selectionNum);
575 reply = dbus_message_new_method_return (message);
578 dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &rv,
585 impl_SetSelection (DBusConnection * bus, DBusMessage * message,
588 AtkText *text = (AtkText *) user_data;
589 dbus_int32_t selectionNum, startOffset, endOffset;
594 g_return_val_if_fail (ATK_IS_TEXT (user_data),
595 droute_not_yet_handled_error (message));
596 dbus_error_init (&error);
597 if (!dbus_message_get_args
598 (message, &error, DBUS_TYPE_INT32, &selectionNum, DBUS_TYPE_INT32,
599 &startOffset, DBUS_TYPE_INT32, &endOffset, DBUS_TYPE_INVALID))
601 return droute_invalid_arguments_error (message);
603 rv = atk_text_set_selection (text, selectionNum, startOffset, endOffset);
604 reply = dbus_message_new_method_return (message);
607 dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &rv,
614 impl_GetRangeExtents (DBusConnection * bus, DBusMessage * message,
617 AtkText *text = (AtkText *) user_data;
618 dbus_int32_t startOffset, endOffset;
619 dbus_uint32_t coordType;
620 AtkTextRectangle rect;
621 dbus_int32_t x, y, width, height;
625 g_return_val_if_fail (ATK_IS_TEXT (user_data),
626 droute_not_yet_handled_error (message));
627 dbus_error_init (&error);
628 if (!dbus_message_get_args
629 (message, &error, DBUS_TYPE_INT32, &startOffset, DBUS_TYPE_INT32,
630 &endOffset, DBUS_TYPE_UINT32, &coordType, DBUS_TYPE_INVALID))
632 return droute_invalid_arguments_error (message);
634 memset (&rect, 0, sizeof (rect));
635 atk_text_get_range_extents (text, startOffset, endOffset,
636 (AtkCoordType) coordType, &rect);
640 height = rect.height;
641 reply = dbus_message_new_method_return (message);
644 dbus_message_append_args (reply, DBUS_TYPE_INT32, &x, DBUS_TYPE_INT32,
645 &y, DBUS_TYPE_INT32, &width, DBUS_TYPE_INT32,
646 &height, DBUS_TYPE_INVALID);
651 #define MAXRANGELEN 512
654 impl_GetBoundedRanges (DBusConnection * bus, DBusMessage * message,
657 AtkText *text = (AtkText *) user_data;
658 dbus_int32_t x, y, width, height;
659 dbus_uint32_t coordType, xClipType, yClipType;
661 AtkTextRange **range_list = NULL;
662 AtkTextRectangle rect;
664 DBusMessageIter iter, array, struc, variant;
666 g_return_val_if_fail (ATK_IS_TEXT (user_data),
667 droute_not_yet_handled_error (message));
668 dbus_error_init (&error);
669 if (!dbus_message_get_args
670 (message, &error, DBUS_TYPE_INT32, &x, DBUS_TYPE_INT32, &y,
671 DBUS_TYPE_INT32, &height, DBUS_TYPE_INT32, &width, DBUS_TYPE_UINT32,
672 &coordType, DBUS_TYPE_UINT32, &xClipType, DBUS_TYPE_UINT32, &yClipType,
675 return droute_invalid_arguments_error (message);
680 rect.height = height;
683 atk_text_get_bounded_ranges (text, &rect, (AtkCoordType) coordType,
684 (AtkTextClipType) xClipType,
685 (AtkTextClipType) yClipType);
686 reply = dbus_message_new_method_return (message);
689 /* This isn't pleasant. */
690 dbus_message_iter_init_append (reply, &iter);
691 if (dbus_message_iter_open_container
692 (&iter, DBUS_TYPE_ARRAY, "(iisv)", &array))
695 for (len = 0; len < MAXRANGELEN && range_list[len]; ++len)
697 if (dbus_message_iter_open_container
698 (&array, DBUS_TYPE_STRUCT, NULL, &struc))
701 val = range_list[len]->start_offset;
702 dbus_message_iter_append_basic (&struc, DBUS_TYPE_INT32, &val);
703 val = range_list[len]->end_offset;
704 dbus_message_iter_append_basic (&struc, DBUS_TYPE_INT32, &val);
705 dbus_message_iter_append_basic (&struc, DBUS_TYPE_STRING,
706 &range_list[len]->content);
707 /* The variant is unimplemented in atk, but I don't want to
708 * unilaterally muck with the spec and remove it, so I'll just
709 * throw in a dummy value */
710 if (dbus_message_iter_open_container
711 (&struc, DBUS_TYPE_VARIANT, "i", &variant))
713 dbus_uint32_t dummy = 0;
714 dbus_message_iter_append_basic (&variant, DBUS_TYPE_INT32,
716 dbus_message_iter_close_container (&struc, &variant);
718 dbus_message_iter_close_container (&array, &struc);
721 dbus_message_iter_close_container (&iter, &array);
727 impl_GetAttributeRun (DBusConnection * bus, DBusMessage * message,
731 AtkText *text = (AtkText *) user_data;
733 dbus_bool_t includeDefaults;
734 dbus_int32_t startOffset, endOffset;
735 gint intstart_offset = 0, intend_offset = 0;
737 AtkAttributeSet *attributes = NULL;
738 AtkAttribute *attr = NULL;
739 DBusMessageIter iter, iterArray;
741 g_return_val_if_fail (ATK_IS_TEXT (user_data),
742 droute_not_yet_handled_error (message));
743 dbus_error_init (&error);
744 if (!dbus_message_get_args
745 (message, &error, DBUS_TYPE_INT32, &offset, DBUS_TYPE_BOOLEAN,
746 &includeDefaults, DBUS_TYPE_INVALID))
748 return droute_invalid_arguments_error (message);
752 atk_text_get_run_attributes (text, offset, &intstart_offset,
757 attributes = g_slist_concat (attributes,
758 atk_text_get_default_attributes (text));
761 reply = dbus_message_new_method_return (message);
765 dbus_message_iter_init_append (reply, &iter);
766 spi_object_append_attribute_set (&iter, attributes);
768 startOffset = intstart_offset;
769 endOffset = intend_offset;
770 dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &startOffset);
771 dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &endOffset);
773 atk_attribute_set_free (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_object_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, methods, properties);