2 * AT-SPI - Assistive Technology Service Provider Interface
3 * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
5 * Copyright 2001, 2002 Sun Microsystems Inc.,
6 * Copyright 2001, 2002 Ximian, Inc.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the
20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
24 /* text.c : implements the Text interface */
30 #include <atk/atktext.h>
31 #include <libspi/text.h>
32 #include <libspi/spi-private.h>
34 /* Our parent Gtk object type */
35 #define PARENT_TYPE SPI_TYPE_BASE
45 get_text_from_servant (PortableServer_Servant servant)
47 SpiBase *object = SPI_BASE (bonobo_object_from_servant (servant));
49 g_return_val_if_fail (object, NULL);
50 g_return_val_if_fail (ATK_IS_OBJECT(object->gobj), NULL);
51 return ATK_TEXT (object->gobj);
55 impl_getText (PortableServer_Servant servant,
56 const CORBA_long startOffset,
57 const CORBA_long endOffset,
58 CORBA_Environment *ev)
62 AtkText *text = get_text_from_servant (servant);
64 g_return_val_if_fail (text != NULL, CORBA_string_dup (""));
66 txt = atk_text_get_text (text, startOffset, endOffset);
69 rv = CORBA_string_dup (txt);
73 rv = CORBA_string_dup ("");
80 impl_getTextAfterOffset (PortableServer_Servant servant,
81 const CORBA_long offset,
83 Accessibility_TEXT_BOUNDARY_TYPE
84 type, CORBA_long * startOffset,
85 CORBA_long * endOffset,
86 CORBA_Environment *ev)
90 gint intStartOffset, intEndOffset;
91 AtkText *text = get_text_from_servant (servant);
93 g_return_val_if_fail (text != NULL, CORBA_string_dup (""));
95 txt = atk_text_get_text_after_offset (text,
96 offset, (AtkTextBoundary) type,
97 &intStartOffset, &intEndOffset);
98 *startOffset = intStartOffset;
99 *endOffset = intEndOffset;
103 rv = CORBA_string_dup (txt);
107 rv = CORBA_string_dup ("");
114 impl_getTextAtOffset (PortableServer_Servant servant,
115 const CORBA_long offset,
116 const Accessibility_TEXT_BOUNDARY_TYPE type,
117 CORBA_long * startOffset,
118 CORBA_long * endOffset,
119 CORBA_Environment *ev)
123 gint intStartOffset, intEndOffset;
124 AtkText *text = get_text_from_servant (servant);
126 g_return_val_if_fail (text != NULL, CORBA_string_dup (""));
128 txt = atk_text_get_text_at_offset (
130 offset, (AtkTextBoundary) type,
131 &intStartOffset, &intEndOffset);
133 *startOffset = intStartOffset;
134 *endOffset = intEndOffset;
138 rv = CORBA_string_dup (txt);
142 rv = CORBA_string_dup ("");
148 static CORBA_unsigned_long
149 impl_getCharacterAtOffset (PortableServer_Servant servant,
150 const CORBA_long offset,
151 CORBA_Environment *ev)
153 AtkText *text = get_text_from_servant (servant);
155 g_return_val_if_fail (text != NULL, 0);
157 return atk_text_get_character_at_offset (text, offset);
162 impl_getTextBeforeOffset (PortableServer_Servant servant,
163 const CORBA_long offset,
165 Accessibility_TEXT_BOUNDARY_TYPE
166 type, CORBA_long * startOffset,
167 CORBA_long * endOffset,
168 CORBA_Environment *ev)
172 gint intStartOffset, intEndOffset;
173 AtkText *text = get_text_from_servant (servant);
175 g_return_val_if_fail (text != NULL, CORBA_string_dup (""));
177 txt = atk_text_get_text_before_offset (text,
178 offset, (AtkTextBoundary) type,
179 &intStartOffset, &intEndOffset);
181 *startOffset = intStartOffset;
182 *endOffset = intEndOffset;
186 rv = CORBA_string_dup (txt);
190 rv = CORBA_string_dup ("");
197 impl__get_caretOffset (PortableServer_Servant servant,
198 CORBA_Environment *ev)
200 AtkText *text = get_text_from_servant (servant);
202 g_return_val_if_fail (text != NULL, -1);
204 return atk_text_get_caret_offset (text);
209 _string_from_attribute_set (AtkAttributeSet *set)
211 gchar *attributes, *tmp, *tmp2;
216 attributes = g_strdup ("");
217 cur_attr = (GSList *) set;
220 at = (AtkAttribute *) cur_attr->data;
221 tmp = g_strdup_printf ("%s%s:%s%s",
222 ((GSList *)(set) == cur_attr) ? "" : " ",
224 (cur_attr->next) ? ";" : "");
225 tmp2 = g_strconcat (attributes, tmp, NULL);
229 cur_attr = cur_attr->next;
231 rv = CORBA_string_dup (attributes);
239 impl_getAttributes (PortableServer_Servant servant,
240 const CORBA_long offset,
241 CORBA_long * startOffset,
242 CORBA_long * endOffset,
243 CORBA_Environment *ev)
245 AtkAttributeSet *set;
246 gint intstart_offset, intend_offset;
248 AtkText *text = get_text_from_servant (servant);
250 g_return_val_if_fail (text != NULL, CORBA_string_dup (""));
252 set = atk_text_get_run_attributes (text, offset,
253 &intstart_offset, &intend_offset);
254 *startOffset = intstart_offset;
255 *endOffset = intend_offset;
256 rv = _string_from_attribute_set (set);
257 atk_attribute_set_free (set);
262 impl_getAttributeValue (PortableServer_Servant servant,
263 const CORBA_long offset,
264 const CORBA_char *attributename,
265 CORBA_long * startOffset,
266 CORBA_long * endOffset,
267 CORBA_boolean * defined,
268 CORBA_Environment *ev)
270 AtkAttributeSet *set;
271 gint intstart_offset, intend_offset;
273 CORBA_string rv = NULL;
274 AtkText *text = get_text_from_servant (servant);
277 g_return_val_if_fail (text != NULL, CORBA_string_dup (""));
279 set = atk_text_get_run_attributes (text, offset,
280 &intstart_offset, &intend_offset);
281 *startOffset = intstart_offset;
282 *endOffset = intend_offset;
284 cur_attr = (GSList *) set;
287 at = (AtkAttribute *) cur_attr->data;
288 if (!strcmp (at->name, attributename))
290 rv = CORBA_string_dup (at->value);
294 cur_attr = cur_attr->next;
296 atk_attribute_set_free (set);
297 return (rv ? rv : CORBA_string_dup (""));
301 impl_getDefaultAttributes (PortableServer_Servant servant,
302 CORBA_Environment *ev)
304 AtkAttributeSet *set;
306 AtkText *text = get_text_from_servant (servant);
308 g_return_val_if_fail (text != NULL, CORBA_string_dup (""));
310 set = atk_text_get_default_attributes (text);
312 rv = _string_from_attribute_set (set);
313 atk_attribute_set_free (set);
318 impl_getCharacterExtents (PortableServer_Servant servant,
319 const CORBA_long offset, CORBA_long * x,
320 CORBA_long * y, CORBA_long * width,
322 const CORBA_short coordType,
323 CORBA_Environment *ev)
325 AtkText *text = get_text_from_servant (servant);
328 g_return_if_fail (text != NULL);
330 atk_text_get_character_extents (
333 (AtkCoordType) coordType);
342 impl__get_characterCount (PortableServer_Servant servant,
343 CORBA_Environment *ev)
345 AtkText *text = get_text_from_servant (servant);
347 g_return_val_if_fail (text != NULL, 0);
349 return atk_text_get_character_count (text);
354 impl_getOffsetAtPoint (PortableServer_Servant servant,
355 const CORBA_long x, const CORBA_long y,
356 const CORBA_short coordType,
357 CORBA_Environment *ev)
359 AtkText *text = get_text_from_servant (servant);
361 g_return_val_if_fail (text != NULL, -1);
363 return atk_text_get_offset_at_point (text,
365 (AtkCoordType) coordType);
370 impl_getNSelections (PortableServer_Servant servant,
371 CORBA_Environment *ev)
373 AtkText *text = get_text_from_servant (servant);
375 g_return_val_if_fail (text != NULL, 0);
377 return atk_text_get_n_selections (text);
382 impl_getSelection (PortableServer_Servant servant,
383 const CORBA_long selectionNum,
384 CORBA_long * startOffset, CORBA_long * endOffset,
385 CORBA_Environment *ev)
387 AtkText *text = get_text_from_servant (servant);
388 gint intStartOffset, intEndOffset;
390 g_return_if_fail (text != NULL);
392 /* atk_text_get_selection returns gchar* which we discard */
393 g_free (atk_text_get_selection (text, selectionNum,
394 &intStartOffset, &intEndOffset));
396 *startOffset = intStartOffset;
397 *endOffset = intEndOffset;
402 impl_addSelection (PortableServer_Servant servant,
403 const CORBA_long startOffset,
404 const CORBA_long endOffset,
405 CORBA_Environment *ev)
407 AtkText *text = get_text_from_servant (servant);
409 g_return_val_if_fail (text != NULL, FALSE);
411 return atk_text_add_selection (text,
412 startOffset, endOffset);
417 impl_removeSelection (PortableServer_Servant servant,
418 const CORBA_long selectionNum,
419 CORBA_Environment *ev)
421 AtkText *text = get_text_from_servant (servant);
423 g_return_val_if_fail (text != NULL, FALSE);
425 return atk_text_remove_selection (text, selectionNum);
430 impl_setSelection (PortableServer_Servant servant,
431 const CORBA_long selectionNum,
432 const CORBA_long startOffset,
433 const CORBA_long endOffset,
434 CORBA_Environment *ev)
436 AtkText *text = get_text_from_servant (servant);
438 g_return_val_if_fail (text != NULL, FALSE);
440 return atk_text_set_selection (text,
441 selectionNum, startOffset, endOffset);
446 impl_setCaretOffset (PortableServer_Servant servant,
447 const CORBA_long value,
448 CORBA_Environment *ev)
450 AtkText *text = get_text_from_servant (servant);
452 g_return_val_if_fail (text != NULL, FALSE);
454 return atk_text_set_caret_offset (text, value);
458 impl_getRangeExtents(PortableServer_Servant servant,
459 const CORBA_long startOffset,
460 const CORBA_long endOffset,
461 CORBA_long * x, CORBA_long * y,
464 const CORBA_short coordType,
465 CORBA_Environment * ev)
467 AtkText *text = get_text_from_servant (servant);
468 AtkTextRectangle rect;
470 g_return_if_fail (text != NULL);
472 atk_text_get_range_extents (text, (gint) startOffset, (gint) endOffset,
473 (AtkCoordType) coordType, &rect);
477 *height = rect.height;
480 #define MAXRANGELEN 512
482 static Accessibility_Text_RangeList *
483 _spi_text_range_seq_from_atkrangelist (AtkTextRange **range_list)
485 Accessibility_Text_RangeList *rangeList =
486 Accessibility_Text_RangeList__alloc ();
489 for (len = 0; len < MAXRANGELEN && range_list[len]; ++len);
491 rangeList->_length = len;
492 rangeList->_buffer = Accessibility_Text_RangeList_allocbuf (len);
493 for (i = 0; i < len; ++i)
495 rangeList->_buffer[i].startOffset = range_list[i]->start_offset;
496 rangeList->_buffer[i].endOffset = range_list[i]->end_offset;
497 rangeList->_buffer[i].content = CORBA_string_dup (range_list[i]->content);
503 static Accessibility_Text_RangeList *
504 impl_getBoundedRanges(PortableServer_Servant servant,
507 const CORBA_long width,
508 const CORBA_long height,
509 const CORBA_short coordType,
510 const Accessibility_TEXT_CLIP_TYPE xClipType,
511 const Accessibility_TEXT_CLIP_TYPE yClipType,
512 CORBA_Environment * ev)
514 AtkText *text = get_text_from_servant (servant);
515 AtkTextRange **range_list = NULL;
516 AtkTextRectangle rect;
521 rect.height = height;
523 range_list = atk_text_get_bounded_ranges (text, &rect,
524 (AtkCoordType) coordType,
525 (AtkTextClipType) xClipType,
526 (AtkTextClipType) yClipType);
528 return _spi_text_range_seq_from_atkrangelist (range_list);
533 static Accessibility_AttributeSet *
534 impl_getAttributeRun (PortableServer_Servant servant,
535 const CORBA_long offset,
536 CORBA_long *startOffset, CORBA_long *endOffset,
537 const CORBA_boolean includeDefaults,
538 CORBA_Environment *ev){
540 AtkAttributeSet *attributes, *default_attributes = NULL;
541 AtkAttribute *attr = NULL;
542 gint intstart_offset, intend_offset;
543 Accessibility_AttributeSet *retval = NULL;
544 AtkText *text = get_text_from_servant (servant);
545 gint n_attributes = 0, total_attributes = 0, n_default_attributes = 0;
548 g_return_val_if_fail (text != NULL, NULL);
550 attributes = atk_text_get_run_attributes (text, offset,
551 &intstart_offset, &intend_offset);
553 if (attributes) total_attributes = n_attributes = g_slist_length (attributes);
557 default_attributes = atk_text_get_default_attributes (text);
558 if (default_attributes)
559 n_default_attributes = g_slist_length (default_attributes);
560 total_attributes += n_default_attributes;
563 *startOffset = intstart_offset;
564 *endOffset = intend_offset;
566 retval = CORBA_sequence_CORBA_string__alloc ();
567 retval->_length = retval->_maximum = total_attributes;
568 retval->_buffer = CORBA_sequence_CORBA_string_allocbuf (total_attributes);
569 CORBA_sequence_set_release (retval, CORBA_TRUE);
571 if (total_attributes)
573 for (i = 0; i < n_attributes; ++i)
575 attr = g_slist_nth_data (attributes, i);
576 retval->_buffer[i] = CORBA_string_dup (g_strconcat (attr->name, ":", attr->value, NULL));
579 for (j = 0; j < n_default_attributes; ++i, ++j)
581 attr = g_slist_nth_data (default_attributes, i);
582 retval->_buffer[i] = CORBA_string_dup (g_strconcat (attr->name, ":", attr->value, NULL));
585 atk_attribute_set_free (attributes);
586 if (default_attributes)
587 atk_attribute_set_free (default_attributes);
592 static Accessibility_AttributeSet *
593 impl_getDefaultAttributeSet (PortableServer_Servant servant,
594 CORBA_Environment *ev){
595 AtkAttributeSet *attributes;
596 AtkAttribute *attr = NULL;
597 Accessibility_AttributeSet *retval = NULL;
598 AtkText *text = get_text_from_servant (servant);
599 gint n_attributes = 0;
602 g_return_val_if_fail (text != NULL, NULL);
604 attributes = atk_text_get_default_attributes (text);
608 n_attributes = g_slist_length (attributes);
610 retval = CORBA_sequence_CORBA_string__alloc ();
611 retval->_length = retval->_maximum = n_attributes;
612 retval->_buffer = CORBA_sequence_CORBA_string_allocbuf (n_attributes);
613 CORBA_sequence_set_release (retval, CORBA_TRUE);
615 for (i = 0; i < n_attributes; ++i)
617 attr = g_slist_nth_data (attributes, i);
618 retval->_buffer [i] = CORBA_string_dup (g_strconcat (attr->name, ":", attr->value, NULL));
620 atk_attribute_set_free (attributes);
627 spi_text_class_init (SpiTextClass *klass)
629 POA_Accessibility_Text__epv *epv = &klass->epv;
631 /* Initialize epv table */
633 epv->getText = impl_getText;
634 epv->getTextAfterOffset = impl_getTextAfterOffset;
635 epv->getCharacterAtOffset = impl_getCharacterAtOffset;
636 epv->getTextAtOffset = impl_getTextAtOffset;
637 epv->getTextBeforeOffset = impl_getTextBeforeOffset;
638 epv->_get_caretOffset = impl__get_caretOffset;
639 epv->getAttributes = impl_getAttributes;
640 epv->getDefaultAttributes = impl_getDefaultAttributes;
641 epv->getCharacterExtents = impl_getCharacterExtents;
642 epv->_get_characterCount = impl__get_characterCount;
643 epv->getOffsetAtPoint = impl_getOffsetAtPoint;
644 epv->getNSelections = impl_getNSelections;
645 epv->getSelection = impl_getSelection;
646 epv->addSelection = impl_addSelection;
647 epv->removeSelection = impl_removeSelection;
648 epv->setSelection = impl_setSelection;
649 epv->setCaretOffset = impl_setCaretOffset;
650 epv->getRangeExtents = impl_getRangeExtents;
651 epv->getBoundedRanges = impl_getBoundedRanges;
652 epv->getAttributeValue = impl_getAttributeValue;
653 epv->getAttributeRun = impl_getAttributeRun;
654 epv->getDefaultAttributeSet = impl_getDefaultAttributeSet;
658 spi_text_init (SpiText *text)
662 BONOBO_TYPE_FUNC_FULL (SpiText,
668 spi_text_construct (SpiText *text, AtkObject *obj)
670 spi_base_construct (SPI_BASE (text), G_OBJECT(obj));
675 spi_text_interface_new (AtkObject *obj)
679 g_return_val_if_fail (ATK_IS_TEXT (obj), NULL);
681 retval = g_object_new (SPI_TEXT_TYPE, NULL);
683 spi_text_construct (retval, obj);