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"
33 impl_get_characterCount (DBusMessageIter * iter,
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,
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, DBUS_TYPE_INT32,
142 &startOffset, 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, DBUS_TYPE_INT32,
181 &startOffset, DBUS_TYPE_INT32, &endOffset,
189 impl_getTextAfterOffset (DBusConnection * bus, DBusMessage * message,
192 AtkText *text = (AtkText *) user_data;
196 dbus_int32_t startOffset, endOffset;
197 gint intstart_offset = 0, intend_offset = 0;
201 g_return_val_if_fail (ATK_IS_TEXT (user_data),
202 droute_not_yet_handled_error (message));
203 dbus_error_init (&error);
204 if (!dbus_message_get_args
205 (message, &error, DBUS_TYPE_INT32, &offset, DBUS_TYPE_UINT32, &type,
208 return droute_invalid_arguments_error (message);
211 atk_text_get_text_after_offset (text, offset, (AtkTextBoundary) type,
212 &intstart_offset, &intend_offset);
213 startOffset = intstart_offset;
214 endOffset = intend_offset;
217 reply = dbus_message_new_method_return (message);
220 dbus_message_append_args (reply, DBUS_TYPE_STRING, &txt, DBUS_TYPE_INT32,
221 &startOffset, DBUS_TYPE_INT32, &endOffset,
229 impl_getCharacterAtOffset (DBusConnection * bus, DBusMessage * message,
232 AtkText *text = (AtkText *) user_data;
238 g_return_val_if_fail (ATK_IS_TEXT (user_data),
239 droute_not_yet_handled_error (message));
240 dbus_error_init (&error);
241 if (!dbus_message_get_args
242 (message, &error, DBUS_TYPE_INT32, &offset, DBUS_TYPE_INVALID))
244 return droute_invalid_arguments_error (message);
246 ch = atk_text_get_character_at_offset (text, offset);
247 reply = dbus_message_new_method_return (message);
250 dbus_message_append_args (reply, DBUS_TYPE_INT32, &ch, DBUS_TYPE_INVALID);
256 impl_getAttributeValue (DBusConnection * bus, DBusMessage * message,
259 AtkText *text = (AtkText *) user_data;
262 dbus_int32_t startOffset, endOffset;
264 gint intstart_offset = 0, intend_offset = 0;
268 AtkAttributeSet *set;
272 g_return_val_if_fail (ATK_IS_TEXT (user_data),
273 droute_not_yet_handled_error (message));
274 dbus_error_init (&error);
275 if (!dbus_message_get_args
276 (message, &error, 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, DBUS_TYPE_INVALID);
308 atk_attribute_set_free (set);
313 _string_from_attribute_set (AtkAttributeSet * set)
315 gchar *attributes, *tmp, *tmp2;
319 attributes = g_strdup ("");
320 cur_attr = (GSList *) set;
323 at = (AtkAttribute *) cur_attr->data;
324 tmp = g_strdup_printf ("%s%s:%s%s",
325 ((GSList *) (set) == cur_attr) ? "" : " ",
327 (cur_attr->next) ? ";" : "");
328 tmp2 = g_strconcat (attributes, tmp, NULL);
332 cur_attr = cur_attr->next;
338 impl_getAttributes (DBusConnection * bus, DBusMessage * message,
341 AtkText *text = (AtkText *) user_data;
343 dbus_int32_t startOffset, endOffset;
344 gint intstart_offset, intend_offset;
347 AtkAttributeSet *set;
348 DBusMessageIter iter;
350 g_return_val_if_fail (ATK_IS_TEXT (user_data),
351 droute_not_yet_handled_error (message));
352 dbus_error_init (&error);
353 if (!dbus_message_get_args
354 (message, &error, DBUS_TYPE_INT32, &offset, DBUS_TYPE_INVALID))
356 return droute_invalid_arguments_error (message);
359 set = atk_text_get_run_attributes (text, offset,
360 &intstart_offset, &intend_offset);
362 startOffset = intstart_offset;
363 endOffset = intend_offset;
364 reply = dbus_message_new_method_return (message);
367 dbus_message_iter_init_append (reply, &iter);
368 spi_atk_append_attribute_set (&iter, set);
369 dbus_message_append_args (reply, DBUS_TYPE_INT32, &startOffset,
370 DBUS_TYPE_INT32, &endOffset, DBUS_TYPE_INVALID);
372 atk_attribute_set_free (set);
377 impl_getDefaultAttributes (DBusConnection * bus, DBusMessage * message,
380 AtkText *text = (AtkText *) user_data;
383 AtkAttributeSet *set;
384 DBusMessageIter iter;
386 g_return_val_if_fail (ATK_IS_TEXT (user_data),
387 droute_not_yet_handled_error (message));
388 dbus_error_init (&error);
390 set = atk_text_get_default_attributes (text);
391 reply = dbus_message_new_method_return (message);
394 dbus_message_iter_init_append (reply, &iter);
395 spi_atk_append_attribute_set (&iter, set);
397 atk_attribute_set_free (set);
402 impl_getCharacterExtents (DBusConnection * bus, DBusMessage * message,
405 AtkText *text = (AtkText *) user_data;
407 dbus_uint32_t coordType;
408 dbus_int32_t x, y, width, height;
409 gint ix = 0, iy = 0, iw = 0, ih = 0;
413 g_return_val_if_fail (ATK_IS_TEXT (user_data),
414 droute_not_yet_handled_error (message));
415 dbus_error_init (&error);
416 if (!dbus_message_get_args
417 (message, &error, DBUS_TYPE_INT32, &offset, DBUS_TYPE_UINT32, &coordType,
420 return droute_invalid_arguments_error (message);
422 atk_text_get_character_extents (text, offset, &ix, &iy, &iw, &ih,
423 (AtkCoordType) coordType);
428 reply = dbus_message_new_method_return (message);
431 dbus_message_append_args (reply, DBUS_TYPE_INT32, &x, DBUS_TYPE_INT32,
432 &y, DBUS_TYPE_INT32, &width, DBUS_TYPE_INT32,
433 &height, DBUS_TYPE_INVALID);
439 impl_getOffsetAtPoint (DBusConnection * bus, DBusMessage * message,
442 AtkText *text = (AtkText *) user_data;
444 dbus_uint32_t coordType;
449 g_return_val_if_fail (ATK_IS_TEXT (user_data),
450 droute_not_yet_handled_error (message));
451 dbus_error_init (&error);
452 if (!dbus_message_get_args
453 (message, &error, DBUS_TYPE_INT32, &x, DBUS_TYPE_INT32, &y,
454 DBUS_TYPE_UINT32, &coordType, DBUS_TYPE_INVALID))
456 return droute_invalid_arguments_error (message);
458 rv = atk_text_get_offset_at_point (text, x, y, coordType);
459 reply = dbus_message_new_method_return (message);
462 dbus_message_append_args (reply, DBUS_TYPE_INT32, &rv,
469 impl_getNSelections (DBusConnection * bus, DBusMessage * message,
472 AtkText *text = (AtkText *) user_data;
476 g_return_val_if_fail (ATK_IS_TEXT (user_data),
477 droute_not_yet_handled_error (message));
478 rv = atk_text_get_n_selections (text);
479 reply = dbus_message_new_method_return (message);
482 dbus_message_append_args (reply, DBUS_TYPE_INT32, &rv,
489 impl_getSelection (DBusConnection * bus, DBusMessage * message,
492 AtkText *text = (AtkText *) user_data;
493 dbus_int32_t selectionNum;
494 dbus_int32_t startOffset, endOffset;
495 gint intstart_offset = 0, intend_offset = 0;
499 g_return_val_if_fail (ATK_IS_TEXT (user_data),
500 droute_not_yet_handled_error (message));
501 dbus_error_init (&error);
502 if (!dbus_message_get_args
503 (message, &error, DBUS_TYPE_INT32, &selectionNum, DBUS_TYPE_INVALID))
505 return droute_invalid_arguments_error (message);
507 /* atk_text_get_selection returns gchar * which we discard */
508 g_free (atk_text_get_selection
509 (text, selectionNum, &intstart_offset, &intend_offset));
510 startOffset = intstart_offset;
511 endOffset = intend_offset;
512 reply = dbus_message_new_method_return (message);
515 dbus_message_append_args (reply, DBUS_TYPE_INT32, &startOffset,
516 DBUS_TYPE_INT32, &endOffset,
523 impl_addSelection (DBusConnection * bus, DBusMessage * message,
526 AtkText *text = (AtkText *) user_data;
527 dbus_int32_t startOffset, endOffset;
532 g_return_val_if_fail (ATK_IS_TEXT (user_data),
533 droute_not_yet_handled_error (message));
534 dbus_error_init (&error);
535 if (!dbus_message_get_args
536 (message, &error, DBUS_TYPE_INT32, &startOffset, DBUS_TYPE_INT32,
537 &endOffset, DBUS_TYPE_INVALID))
539 return droute_invalid_arguments_error (message);
541 rv = atk_text_add_selection (text, startOffset, endOffset);
542 reply = dbus_message_new_method_return (message);
545 dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &rv,
552 impl_removeSelection (DBusConnection * bus, DBusMessage * message,
555 AtkText *text = (AtkText *) user_data;
556 dbus_int32_t selectionNum;
561 g_return_val_if_fail (ATK_IS_TEXT (user_data),
562 droute_not_yet_handled_error (message));
563 dbus_error_init (&error);
564 if (!dbus_message_get_args
565 (message, &error, DBUS_TYPE_INT32, &selectionNum, DBUS_TYPE_INVALID))
567 return droute_invalid_arguments_error (message);
569 rv = atk_text_remove_selection (text, selectionNum);
570 reply = dbus_message_new_method_return (message);
573 dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &rv,
580 impl_setSelection (DBusConnection * bus, DBusMessage * message,
583 AtkText *text = (AtkText *) user_data;
584 dbus_int32_t selectionNum, startOffset, endOffset;
589 g_return_val_if_fail (ATK_IS_TEXT (user_data),
590 droute_not_yet_handled_error (message));
591 dbus_error_init (&error);
592 if (!dbus_message_get_args
593 (message, &error, DBUS_TYPE_INT32, &selectionNum, DBUS_TYPE_INT32,
594 &startOffset, DBUS_TYPE_INT32, &endOffset, DBUS_TYPE_INVALID))
596 return droute_invalid_arguments_error (message);
598 rv = atk_text_set_selection (text, selectionNum, startOffset, endOffset);
599 reply = dbus_message_new_method_return (message);
602 dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &rv,
609 impl_getRangeExtents (DBusConnection * bus, DBusMessage * message,
612 AtkText *text = (AtkText *) user_data;
613 dbus_int32_t startOffset, endOffset;
614 dbus_uint32_t coordType;
615 AtkTextRectangle rect;
616 dbus_int32_t x, y, width, height;
620 g_return_val_if_fail (ATK_IS_TEXT (user_data),
621 droute_not_yet_handled_error (message));
622 dbus_error_init (&error);
623 if (!dbus_message_get_args
624 (message, &error, DBUS_TYPE_INT32, &startOffset, DBUS_TYPE_INT32,
625 &endOffset, DBUS_TYPE_UINT32, &coordType, DBUS_TYPE_INVALID))
627 return droute_invalid_arguments_error (message);
629 memset (&rect, 0, sizeof (rect));
630 atk_text_get_range_extents (text, startOffset, endOffset,
631 (AtkCoordType) coordType, &rect);
635 height = rect.height;
636 reply = dbus_message_new_method_return (message);
639 dbus_message_append_args (reply, DBUS_TYPE_INT32, &x, DBUS_TYPE_INT32,
640 &y, DBUS_TYPE_INT32, &width, DBUS_TYPE_INT32,
641 &height, DBUS_TYPE_INVALID);
646 #define MAXRANGELEN 512
649 impl_getBoundedRanges (DBusConnection * bus, DBusMessage * message,
652 AtkText *text = (AtkText *) user_data;
653 dbus_int32_t x, y, width, height;
654 dbus_uint32_t coordType, xClipType, yClipType;
656 AtkTextRange **range_list = NULL;
657 AtkTextRectangle rect;
659 DBusMessageIter iter, array, struc, variant;
661 g_return_val_if_fail (ATK_IS_TEXT (user_data),
662 droute_not_yet_handled_error (message));
663 dbus_error_init (&error);
664 if (!dbus_message_get_args
665 (message, &error, DBUS_TYPE_INT32, &x, DBUS_TYPE_INT32, &y,
666 DBUS_TYPE_INT32, &height, DBUS_TYPE_INT32, &width, DBUS_TYPE_UINT32,
667 &coordType, DBUS_TYPE_UINT32, &xClipType, DBUS_TYPE_UINT32, &yClipType,
670 return droute_invalid_arguments_error (message);
675 rect.height = height;
678 atk_text_get_bounded_ranges (text, &rect, (AtkCoordType) coordType,
679 (AtkTextClipType) xClipType,
680 (AtkTextClipType) yClipType);
681 reply = dbus_message_new_method_return (message);
684 /* This isn't pleasant. */
685 dbus_message_iter_init_append (reply, &iter);
686 if (dbus_message_iter_open_container
687 (&iter, DBUS_TYPE_ARRAY, "(iisv)", &array))
690 for (len = 0; len < MAXRANGELEN && range_list[len]; ++len)
692 if (dbus_message_iter_open_container
693 (&array, DBUS_TYPE_STRUCT, NULL, &struc))
696 val = range_list[len]->start_offset;
697 dbus_message_iter_append_basic (&struc, DBUS_TYPE_INT32, &val);
698 val = range_list[len]->end_offset;
699 dbus_message_iter_append_basic (&struc, DBUS_TYPE_INT32, &val);
700 dbus_message_iter_append_basic (&struc, DBUS_TYPE_STRING,
701 &range_list[len]->content);
702 /* The variant is unimplemented in atk, but I don't want to
703 * unilaterally muck with the spec and remove it, so I'll just
704 * throw in a dummy value */
705 if (dbus_message_iter_open_container
706 (&struc, DBUS_TYPE_VARIANT, "i", &variant))
708 dbus_uint32_t dummy = 0;
709 dbus_message_iter_append_basic (&variant, DBUS_TYPE_INT32,
711 dbus_message_iter_close_container (&struc, &variant);
713 dbus_message_iter_close_container (&array, &struc);
716 dbus_message_iter_close_container (&iter, &array);
722 impl_getAttributeRun (DBusConnection * bus, DBusMessage * message,
726 AtkText *text = (AtkText *) user_data;
728 dbus_bool_t includeDefaults;
729 dbus_int32_t startOffset, endOffset;
730 gint intstart_offset = 0, intend_offset = 0;
732 AtkAttributeSet *attributes, *default_attributes = NULL;
733 AtkAttribute *attr = NULL;
734 DBusMessageIter iter, iterArray;
736 g_return_val_if_fail (ATK_IS_TEXT (user_data),
737 droute_not_yet_handled_error (message));
738 dbus_error_init (&error);
739 if (!dbus_message_get_args
740 (message, &error, DBUS_TYPE_INT32, &offset, DBUS_TYPE_BOOLEAN,
741 &includeDefaults, DBUS_TYPE_INVALID))
743 return droute_invalid_arguments_error (message);
747 atk_text_get_run_attributes (text, offset, &intstart_offset,
750 reply = dbus_message_new_method_return (message);
754 dbus_message_iter_init_append (reply, &iter);
755 dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "{ss}", &iterArray);
756 spi_atk_append_attribute_set_inner (&iterArray, attributes);
759 default_attributes = atk_text_get_default_attributes (text);
760 spi_atk_append_attribute_set_inner (&iterArray, default_attributes);
762 dbus_message_iter_close_container (&iter, &iterArray);
764 startOffset = intstart_offset;
765 endOffset = intend_offset;
766 dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &startOffset);
767 dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &endOffset);
769 atk_attribute_set_free (attributes);
770 if (default_attributes)
771 atk_attribute_set_free (default_attributes);
777 impl_getDefaultAttributeSet (DBusConnection * bus, DBusMessage * message,
780 AtkText *text = (AtkText *) user_data;
782 DBusMessageIter iter;
783 AtkAttributeSet *attributes;
785 g_return_val_if_fail (ATK_IS_TEXT (user_data),
786 droute_not_yet_handled_error (message));
788 attributes = atk_text_get_default_attributes (text);
790 reply = dbus_message_new_method_return (message);
793 dbus_message_iter_init_append (reply, &iter);
794 spi_atk_append_attribute_set (&iter, attributes);
798 atk_attribute_set_free (attributes);
803 static DRouteMethod methods[] = {
804 {impl_getText, "getText"},
805 {impl_setCaretOffset, "setCaretOffset"},
806 {impl_getTextBeforeOffset, "getTextBeforeOffset"},
807 {impl_getTextAtOffset, "getTextAtOffset"},
808 {impl_getTextAfterOffset, "getTextAfterOffset"},
809 {impl_getCharacterAtOffset, "getCharacterAtOffset"},
810 {impl_getAttributeValue, "getAttributeValue"},
811 {impl_getAttributes, "getAttributes"},
812 {impl_getDefaultAttributes, "getDefaultAttributes"},
813 {impl_getCharacterExtents, "getCharacterExtents"},
814 {impl_getOffsetAtPoint, "getOffsetAtPoint"},
815 {impl_getNSelections, "getNSelections"},
816 {impl_getSelection, "getSelection"},
817 {impl_addSelection, "addSelection"},
818 {impl_removeSelection, "removeSelection"},
819 {impl_setSelection, "setSelection"},
820 {impl_getRangeExtents, "getRangeExtents"},
821 {impl_getBoundedRanges, "getBoundedRanges"},
822 {impl_getAttributeRun, "getAttributeRun"},
823 {impl_getDefaultAttributeSet, "getDefaultAttributeSet"},
827 static DRouteProperty properties[] = {
828 {impl_get_characterCount, NULL, "characterCount"},
829 {impl_get_caretOffset, NULL, "caretOffset"},
834 spi_initialize_text (DRoutePath *path)
836 droute_path_add_interface (path,
837 SPI_DBUS_INTERFACE_TEXT,