bump product version to 7.6.3.2-android
[LibreOffice.git] / vcl / unx / gtk3 / a11y / atktext.cxx
blobe8ceab3bb657a7df787bc8ac3419bc8ff25690f3
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "atkwrapper.hxx"
21 #include "atktextattributes.hxx"
22 #include <algorithm>
24 #include <osl/diagnose.h>
25 #include <rtl/character.hxx>
27 #include <com/sun/star/accessibility/AccessibleScrollType.hpp>
28 #include <com/sun/star/accessibility/AccessibleTextType.hpp>
29 #include <com/sun/star/accessibility/TextSegment.hpp>
30 #include <com/sun/star/accessibility/XAccessibleMultiLineText.hpp>
31 #include <com/sun/star/accessibility/XAccessibleText.hpp>
32 #include <com/sun/star/accessibility/XAccessibleTextAttributes.hpp>
33 #include <com/sun/star/accessibility/XAccessibleTextMarkup.hpp>
34 #include <com/sun/star/lang/NoSupportException.hpp>
35 #include <com/sun/star/text/TextMarkupType.hpp>
37 using namespace ::com::sun::star;
39 static sal_Int16
40 text_type_from_boundary(AtkTextBoundary boundary_type)
42 switch(boundary_type)
44 case ATK_TEXT_BOUNDARY_CHAR:
45 return accessibility::AccessibleTextType::CHARACTER;
46 case ATK_TEXT_BOUNDARY_WORD_START:
47 case ATK_TEXT_BOUNDARY_WORD_END:
48 return accessibility::AccessibleTextType::WORD;
49 case ATK_TEXT_BOUNDARY_SENTENCE_START:
50 case ATK_TEXT_BOUNDARY_SENTENCE_END:
51 return accessibility::AccessibleTextType::SENTENCE;
52 case ATK_TEXT_BOUNDARY_LINE_START:
53 case ATK_TEXT_BOUNDARY_LINE_END:
54 return accessibility::AccessibleTextType::LINE;
55 default:
56 return -1;
60 /*****************************************************************************/
62 #if ATK_CHECK_VERSION(2,32,0)
63 static accessibility::AccessibleScrollType
64 scroll_type_from_scroll_type(AtkScrollType type)
66 switch(type)
68 case ATK_SCROLL_TOP_LEFT:
69 return accessibility::AccessibleScrollType_SCROLL_TOP_LEFT;
70 case ATK_SCROLL_BOTTOM_RIGHT:
71 return accessibility::AccessibleScrollType_SCROLL_BOTTOM_RIGHT;
72 case ATK_SCROLL_TOP_EDGE:
73 return accessibility::AccessibleScrollType_SCROLL_TOP_EDGE;
74 case ATK_SCROLL_BOTTOM_EDGE:
75 return accessibility::AccessibleScrollType_SCROLL_BOTTOM_EDGE;
76 case ATK_SCROLL_LEFT_EDGE:
77 return accessibility::AccessibleScrollType_SCROLL_LEFT_EDGE;
78 case ATK_SCROLL_RIGHT_EDGE:
79 return accessibility::AccessibleScrollType_SCROLL_RIGHT_EDGE;
80 case ATK_SCROLL_ANYWHERE:
81 return accessibility::AccessibleScrollType_SCROLL_ANYWHERE;
82 default:
83 throw lang::NoSupportException();
86 #endif
88 /*****************************************************************************/
90 static gchar *
91 adjust_boundaries( css::uno::Reference<css::accessibility::XAccessibleText> const & pText,
92 accessibility::TextSegment const & rTextSegment,
93 AtkTextBoundary boundary_type,
94 gint * start_offset, gint * end_offset )
96 accessibility::TextSegment aTextSegment;
97 OUString aString;
98 gint start = 0, end = 0;
100 if( !rTextSegment.SegmentText.isEmpty() )
102 switch(boundary_type)
104 case ATK_TEXT_BOUNDARY_CHAR:
105 if ((rTextSegment.SegmentEnd - rTextSegment.SegmentStart) == 1
106 && rtl::isSurrogate(rTextSegment.SegmentText[0]))
107 return nullptr;
108 [[fallthrough]];
109 case ATK_TEXT_BOUNDARY_LINE_START:
110 case ATK_TEXT_BOUNDARY_LINE_END:
111 case ATK_TEXT_BOUNDARY_SENTENCE_START:
112 start = rTextSegment.SegmentStart;
113 end = rTextSegment.SegmentEnd;
114 aString = rTextSegment.SegmentText;
115 break;
117 // the OOo break iterator behaves as SENTENCE_START
118 case ATK_TEXT_BOUNDARY_SENTENCE_END:
119 start = rTextSegment.SegmentStart;
120 end = rTextSegment.SegmentEnd;
122 if( start > 0 )
123 --start;
124 if( end > 0 && end < pText->getCharacterCount() - 1 )
125 --end;
127 aString = pText->getTextRange(start, end);
128 break;
130 case ATK_TEXT_BOUNDARY_WORD_START:
131 start = rTextSegment.SegmentStart;
133 // Determine the start index of the next segment
134 aTextSegment = pText->getTextBehindIndex(rTextSegment.SegmentEnd,
135 text_type_from_boundary(boundary_type));
136 if( !aTextSegment.SegmentText.isEmpty() )
137 end = aTextSegment.SegmentStart;
138 else
139 end = pText->getCharacterCount();
141 aString = pText->getTextRange(start, end);
142 break;
144 case ATK_TEXT_BOUNDARY_WORD_END:
145 end = rTextSegment.SegmentEnd;
147 // Determine the end index of the previous segment
148 aTextSegment = pText->getTextBeforeIndex(rTextSegment.SegmentStart,
149 text_type_from_boundary(boundary_type));
150 if( !aTextSegment.SegmentText.isEmpty() )
151 start = aTextSegment.SegmentEnd;
152 else
153 start = 0;
155 aString = pText->getTextRange(start, end);
156 break;
158 default:
159 return nullptr;
163 *start_offset = start;
164 *end_offset = end;
166 return OUStringToGChar(aString);
169 /*****************************************************************************/
171 /// @throws uno::RuntimeException
172 static css::uno::Reference<css::accessibility::XAccessibleText>
173 getText( AtkText *pText )
175 AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( pText );
176 if( pWrap )
178 if( !pWrap->mpText.is() )
180 pWrap->mpText.set(pWrap->mpContext, css::uno::UNO_QUERY);
183 return pWrap->mpText;
186 return css::uno::Reference<css::accessibility::XAccessibleText>();
189 /*****************************************************************************/
191 /// @throws uno::RuntimeException
192 static css::uno::Reference<css::accessibility::XAccessibleTextMarkup>
193 getTextMarkup( AtkText *pText )
195 AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( pText );
196 if( pWrap )
198 if( !pWrap->mpTextMarkup.is() )
200 pWrap->mpTextMarkup.set(pWrap->mpContext, css::uno::UNO_QUERY);
203 return pWrap->mpTextMarkup;
206 return css::uno::Reference<css::accessibility::XAccessibleTextMarkup>();
209 /*****************************************************************************/
211 /// @throws uno::RuntimeException
212 static css::uno::Reference<css::accessibility::XAccessibleTextAttributes>
213 getTextAttributes( AtkText *pText )
215 AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( pText );
216 if( pWrap )
218 if( !pWrap->mpTextAttributes.is() )
220 pWrap->mpTextAttributes.set(pWrap->mpContext, css::uno::UNO_QUERY);
223 return pWrap->mpTextAttributes;
226 return css::uno::Reference<css::accessibility::XAccessibleTextAttributes>();
229 /*****************************************************************************/
231 /// @throws uno::RuntimeException
232 static css::uno::Reference<css::accessibility::XAccessibleMultiLineText>
233 getMultiLineText( AtkText *pText )
235 AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( pText );
236 if( pWrap )
238 if( !pWrap->mpMultiLineText.is() )
240 pWrap->mpMultiLineText.set(pWrap->mpContext, css::uno::UNO_QUERY);
243 return pWrap->mpMultiLineText;
246 return css::uno::Reference<css::accessibility::XAccessibleMultiLineText>();
249 /*****************************************************************************/
251 extern "C" {
253 static gchar *
254 text_wrapper_get_text (AtkText *text,
255 gint start_offset,
256 gint end_offset)
258 gchar * ret = nullptr;
260 g_return_val_if_fail( (end_offset == -1) || (end_offset >= start_offset), nullptr );
262 try {
263 css::uno::Reference<css::accessibility::XAccessibleText> pText
264 = getText( text );
265 if( pText.is() )
267 OUString aText;
268 sal_Int32 n = pText->getCharacterCount();
270 if( start_offset < n )
272 if( -1 == end_offset )
273 aText = pText->getTextRange(start_offset, n - start_offset);
274 else
275 aText = pText->getTextRange(start_offset, end_offset);
278 ret = g_strdup( OUStringToOString(aText, RTL_TEXTENCODING_UTF8 ).getStr() );
281 catch(const uno::Exception&) {
282 g_warning( "Exception in getText()" );
285 return ret;
288 static gchar *
289 text_wrapper_get_text_after_offset (AtkText *text,
290 gint offset,
291 AtkTextBoundary boundary_type,
292 gint *start_offset,
293 gint *end_offset)
295 try {
296 css::uno::Reference<css::accessibility::XAccessibleText> pText
297 = getText( text );
298 if( pText.is() )
300 accessibility::TextSegment aTextSegment = pText->getTextBehindIndex(offset, text_type_from_boundary(boundary_type));
301 return adjust_boundaries(pText, aTextSegment, boundary_type, start_offset, end_offset);
304 catch(const uno::Exception&) {
305 g_warning( "Exception in get_text_after_offset()" );
308 return nullptr;
311 static gchar *
312 text_wrapper_get_text_at_offset (AtkText *text,
313 gint offset,
314 AtkTextBoundary boundary_type,
315 gint *start_offset,
316 gint *end_offset)
318 try {
319 css::uno::Reference<css::accessibility::XAccessibleText> pText
320 = getText( text );
321 if( pText.is() )
323 /* If the user presses the 'End' key, the caret will be placed behind the last character,
324 * which is the same index as the first character of the next line. In atk the magic offset
325 * '-2' is used to cover this special case.
327 if (
328 -2 == offset &&
329 (ATK_TEXT_BOUNDARY_LINE_START == boundary_type ||
330 ATK_TEXT_BOUNDARY_LINE_END == boundary_type)
333 css::uno::Reference<
334 css::accessibility::XAccessibleMultiLineText> pMultiLineText
335 = getMultiLineText( text );
336 if( pMultiLineText.is() )
338 accessibility::TextSegment aTextSegment = pMultiLineText->getTextAtLineWithCaret();
339 return adjust_boundaries(pText, aTextSegment, boundary_type, start_offset, end_offset);
343 accessibility::TextSegment aTextSegment = pText->getTextAtIndex(offset, text_type_from_boundary(boundary_type));
344 return adjust_boundaries(pText, aTextSegment, boundary_type, start_offset, end_offset);
347 catch(const uno::Exception&) {
348 g_warning( "Exception in get_text_at_offset()" );
351 return nullptr;
354 static gunichar
355 text_wrapper_get_character_at_offset (AtkText *text,
356 gint offset)
358 gint start, end;
359 gunichar uc = 0xFFFFFFFF;
361 gchar * char_as_string =
362 text_wrapper_get_text_at_offset(text, offset, ATK_TEXT_BOUNDARY_CHAR,
363 &start, &end);
364 if( char_as_string )
366 uc = g_utf8_get_char( char_as_string );
367 g_free( char_as_string );
370 return uc;
373 static gchar *
374 text_wrapper_get_text_before_offset (AtkText *text,
375 gint offset,
376 AtkTextBoundary boundary_type,
377 gint *start_offset,
378 gint *end_offset)
380 try {
381 css::uno::Reference<css::accessibility::XAccessibleText> pText
382 = getText( text );
383 if( pText.is() )
385 accessibility::TextSegment aTextSegment = pText->getTextBeforeIndex(offset, text_type_from_boundary(boundary_type));
386 return adjust_boundaries(pText, aTextSegment, boundary_type, start_offset, end_offset);
389 catch(const uno::Exception&) {
390 g_warning( "Exception in text_before_offset()" );
393 return nullptr;
396 static gint
397 text_wrapper_get_caret_offset (AtkText *text)
399 gint offset = -1;
401 try {
402 css::uno::Reference<css::accessibility::XAccessibleText> pText
403 = getText( text );
404 if( pText.is() )
405 offset = pText->getCaretPosition();
407 catch(const uno::Exception&) {
408 g_warning( "Exception in getCaretPosition()" );
411 return offset;
414 static gboolean
415 text_wrapper_set_caret_offset (AtkText *text,
416 gint offset)
418 try {
419 css::uno::Reference<css::accessibility::XAccessibleText> pText
420 = getText( text );
421 if( pText.is() )
422 return pText->setCaretPosition( offset );
424 catch(const uno::Exception&) {
425 g_warning( "Exception in setCaretPosition()" );
428 return FALSE;
431 // #i92232#
432 static AtkAttributeSet*
433 handle_text_markup_as_run_attribute( css::uno::Reference<css::accessibility::XAccessibleTextMarkup> const & pTextMarkup,
434 const gint nTextMarkupType,
435 const gint offset,
436 AtkAttributeSet* pSet,
437 gint *start_offset,
438 gint *end_offset )
440 const gint nTextMarkupCount( pTextMarkup->getTextMarkupCount( nTextMarkupType ) );
441 if ( nTextMarkupCount > 0 )
443 for ( gint nTextMarkupIndex = 0;
444 nTextMarkupIndex < nTextMarkupCount;
445 ++nTextMarkupIndex )
447 accessibility::TextSegment aTextSegment =
448 pTextMarkup->getTextMarkup( nTextMarkupIndex, nTextMarkupType );
449 const gint nStartOffsetTextMarkup = aTextSegment.SegmentStart;
450 const gint nEndOffsetTextMarkup = aTextSegment.SegmentEnd;
451 if ( nStartOffsetTextMarkup <= offset )
453 if ( offset < nEndOffsetTextMarkup )
455 // text markup at <offset>
456 *start_offset = ::std::max( *start_offset,
457 nStartOffsetTextMarkup );
458 *end_offset = ::std::min( *end_offset,
459 nEndOffsetTextMarkup );
460 switch ( nTextMarkupType )
462 case css::text::TextMarkupType::SPELLCHECK:
464 pSet = attribute_set_prepend_misspelled( pSet );
466 break;
467 case css::text::TextMarkupType::TRACK_CHANGE_INSERTION:
469 pSet = attribute_set_prepend_tracked_change_insertion( pSet );
471 break;
472 case css::text::TextMarkupType::TRACK_CHANGE_DELETION:
474 pSet = attribute_set_prepend_tracked_change_deletion( pSet );
476 break;
477 case css::text::TextMarkupType::TRACK_CHANGE_FORMATCHANGE:
479 pSet = attribute_set_prepend_tracked_change_formatchange( pSet );
481 break;
482 default:
484 OSL_ASSERT( false );
487 break; // no further iteration needed.
489 else
491 *start_offset = ::std::max( *start_offset,
492 nEndOffsetTextMarkup );
493 // continue iteration.
496 else
498 *end_offset = ::std::min( *end_offset,
499 nStartOffsetTextMarkup );
500 break; // no further iteration.
502 } // eof iteration over text markups
505 return pSet;
508 static AtkAttributeSet *
509 text_wrapper_get_run_attributes( AtkText *text,
510 gint offset,
511 gint *start_offset,
512 gint *end_offset)
514 AtkAttributeSet *pSet = nullptr;
516 try {
517 bool bOffsetsAreValid = false;
519 css::uno::Reference<css::accessibility::XAccessibleText> pText
520 = getText( text );
521 if( pText.is())
523 uno::Sequence< beans::PropertyValue > aAttributeList;
525 css::uno::Reference<css::accessibility::XAccessibleTextAttributes>
526 pTextAttributes = getTextAttributes( text );
527 if(pTextAttributes.is()) // Text attributes are available for paragraphs only
529 aAttributeList = pTextAttributes->getRunAttributes( offset, uno::Sequence< OUString > () );
531 else // For other text objects use character attributes
533 aAttributeList = pText->getCharacterAttributes( offset, uno::Sequence< OUString > () );
536 pSet = attribute_set_new_from_property_values( aAttributeList, true, text );
537 // #i100938#
538 // - always provide start_offset and end_offset
540 accessibility::TextSegment aTextSegment =
541 pText->getTextAtIndex(offset, accessibility::AccessibleTextType::ATTRIBUTE_RUN);
543 *start_offset = aTextSegment.SegmentStart;
544 // #i100938#
545 // Do _not_ increment the end_offset provide by <accessibility::TextSegment> instance
546 *end_offset = aTextSegment.SegmentEnd;
547 bOffsetsAreValid = true;
551 // Special handling for misspelled text
552 // #i92232#
553 // - add special handling for tracked changes and refactor the
554 // corresponding code for handling misspelled text.
555 css::uno::Reference<css::accessibility::XAccessibleTextMarkup>
556 pTextMarkup = getTextMarkup( text );
557 if( pTextMarkup.is() )
559 // Get attribute run here if it hasn't been done before
560 if (!bOffsetsAreValid && pText.is())
562 accessibility::TextSegment aAttributeTextSegment =
563 pText->getTextAtIndex(offset, accessibility::AccessibleTextType::ATTRIBUTE_RUN);
564 *start_offset = aAttributeTextSegment.SegmentStart;
565 *end_offset = aAttributeTextSegment.SegmentEnd;
567 // handle misspelled text
568 pSet = handle_text_markup_as_run_attribute(
569 pTextMarkup,
570 css::text::TextMarkupType::SPELLCHECK,
571 offset, pSet, start_offset, end_offset );
572 // handle tracked changes
573 pSet = handle_text_markup_as_run_attribute(
574 pTextMarkup,
575 css::text::TextMarkupType::TRACK_CHANGE_INSERTION,
576 offset, pSet, start_offset, end_offset );
577 pSet = handle_text_markup_as_run_attribute(
578 pTextMarkup,
579 css::text::TextMarkupType::TRACK_CHANGE_DELETION,
580 offset, pSet, start_offset, end_offset );
581 pSet = handle_text_markup_as_run_attribute(
582 pTextMarkup,
583 css::text::TextMarkupType::TRACK_CHANGE_FORMATCHANGE,
584 offset, pSet, start_offset, end_offset );
587 catch(const uno::Exception&){
589 g_warning( "Exception in get_run_attributes()" );
591 if( pSet )
593 atk_attribute_set_free( pSet );
594 pSet = nullptr;
598 return pSet;
601 /*****************************************************************************/
603 static AtkAttributeSet *
604 text_wrapper_get_default_attributes( AtkText *text )
606 AtkAttributeSet *pSet = nullptr;
608 try {
609 css::uno::Reference<css::accessibility::XAccessibleTextAttributes>
610 pTextAttributes = getTextAttributes( text );
611 if( pTextAttributes.is() )
613 uno::Sequence< beans::PropertyValue > aAttributeList =
614 pTextAttributes->getDefaultAttributes( uno::Sequence< OUString > () );
616 pSet = attribute_set_new_from_property_values( aAttributeList, false, text );
619 catch(const uno::Exception&) {
621 g_warning( "Exception in get_default_attributes()" );
623 if( pSet )
625 atk_attribute_set_free( pSet );
626 pSet = nullptr;
630 return pSet;
633 /*****************************************************************************/
635 static void
636 text_wrapper_get_character_extents( AtkText *text,
637 gint offset,
638 gint *x,
639 gint *y,
640 gint *width,
641 gint *height,
642 AtkCoordType coords )
644 *x = *y = *width = *height = -1;
646 try {
647 css::uno::Reference<css::accessibility::XAccessibleText> pText
648 = getText( text );
649 if( pText.is() )
651 awt::Rectangle aRect = pText->getCharacterBounds( offset );
653 gint origin_x = 0;
654 gint origin_y = 0;
656 if (coords == ATK_XY_SCREEN || coords == ATK_XY_WINDOW)
658 g_return_if_fail( ATK_IS_COMPONENT( text ) );
659 gint nWidth = -1;
660 gint nHeight = -1;
661 atk_component_get_extents(ATK_COMPONENT(text), &origin_x, &origin_y, &nWidth, &nHeight, coords);
664 *x = aRect.X + origin_x;
665 *y = aRect.Y + origin_y;
666 *width = aRect.Width;
667 *height = aRect.Height;
670 catch(const uno::Exception&) {
671 g_warning( "Exception in getCharacterBounds" );
675 static gint
676 text_wrapper_get_character_count (AtkText *text)
678 gint rv = 0;
680 try {
681 css::uno::Reference<css::accessibility::XAccessibleText> pText
682 = getText( text );
683 if( pText.is() )
684 rv = pText->getCharacterCount();
686 catch(const uno::Exception&) {
687 g_warning( "Exception in getCharacterCount" );
690 return rv;
693 static gint
694 text_wrapper_get_offset_at_point (AtkText *text,
695 gint x,
696 gint y,
697 AtkCoordType coords)
699 try {
700 css::uno::Reference<css::accessibility::XAccessibleText> pText
701 = getText( text );
702 if( pText.is() )
704 gint origin_x = 0;
705 gint origin_y = 0;
707 if (coords == ATK_XY_SCREEN || coords == ATK_XY_WINDOW)
709 g_return_val_if_fail( ATK_IS_COMPONENT( text ), -1 );
710 gint nWidth = -1;
711 gint nHeight = -1;
712 atk_component_get_extents(ATK_COMPONENT(text), &origin_x, &origin_y, &nWidth, &nHeight, coords);
715 return pText->getIndexAtPoint( awt::Point(x - origin_x, y - origin_y) );
718 catch(const uno::Exception&) {
719 g_warning( "Exception in getIndexAtPoint" );
722 return -1;
725 // FIXME: the whole series of selections API is problematic ...
727 static gint
728 text_wrapper_get_n_selections (AtkText *text)
730 gint rv = 0;
732 try {
733 css::uno::Reference<css::accessibility::XAccessibleText> pText
734 = getText( text );
735 if( pText.is() )
736 rv = ( pText->getSelectionEnd() > pText->getSelectionStart() ) ? 1 : 0;
738 catch(const uno::Exception&) {
739 g_warning( "Exception in getSelectionEnd() or getSelectionStart()" );
742 return rv;
745 static gchar *
746 text_wrapper_get_selection (AtkText *text,
747 gint selection_num,
748 gint *start_offset,
749 gint *end_offset)
751 g_return_val_if_fail( selection_num == 0, FALSE );
753 try {
754 css::uno::Reference<css::accessibility::XAccessibleText> pText
755 = getText( text );
756 if( pText.is() )
758 *start_offset = pText->getSelectionStart();
759 *end_offset = pText->getSelectionEnd();
761 return OUStringToGChar( pText->getSelectedText() );
764 catch(const uno::Exception&) {
765 g_warning( "Exception in getSelectionEnd(), getSelectionStart() or getSelectedText()" );
768 return nullptr;
771 static gboolean
772 text_wrapper_add_selection (AtkText *text,
773 gint start_offset,
774 gint end_offset)
776 // FIXME: can we try to be more compatible by expanding an
777 // existing adjacent selection ?
779 try {
780 css::uno::Reference<css::accessibility::XAccessibleText> pText
781 = getText( text );
782 if( pText.is() )
783 return pText->setSelection( start_offset, end_offset ); // ?
785 catch(const uno::Exception&) {
786 g_warning( "Exception in setSelection()" );
789 return FALSE;
792 static gboolean
793 text_wrapper_remove_selection (AtkText *text,
794 gint selection_num)
796 g_return_val_if_fail( selection_num == 0, FALSE );
798 try {
799 css::uno::Reference<css::accessibility::XAccessibleText> pText
800 = getText( text );
801 if( pText.is() )
802 return pText->setSelection( 0, 0 ); // ?
804 catch(const uno::Exception&) {
805 g_warning( "Exception in setSelection()" );
808 return FALSE;
811 static gboolean
812 text_wrapper_set_selection (AtkText *text,
813 gint selection_num,
814 gint start_offset,
815 gint end_offset)
817 g_return_val_if_fail( selection_num == 0, FALSE );
819 try {
820 css::uno::Reference<css::accessibility::XAccessibleText> pText
821 = getText( text );
822 if( pText.is() )
823 return pText->setSelection( start_offset, end_offset );
825 catch(const uno::Exception&) {
826 g_warning( "Exception in setSelection()" );
829 return FALSE;
832 #if ATK_CHECK_VERSION(2,32,0)
833 static gboolean
834 text_wrapper_scroll_substring_to(AtkText *text,
835 gint start_offset,
836 gint end_offset,
837 AtkScrollType scroll_type)
839 try {
840 css::uno::Reference<css::accessibility::XAccessibleText> pText
841 = getText( text );
843 if( pText.is() )
844 return pText->scrollSubstringTo( start_offset, end_offset,
845 scroll_type_from_scroll_type( scroll_type ) );
847 catch(const uno::Exception&) {
848 g_warning( "Exception in scrollSubstringTo()" );
851 return FALSE;
853 #endif
855 } // extern "C"
857 void
858 textIfaceInit (AtkTextIface *iface)
860 g_return_if_fail (iface != nullptr);
862 iface->get_text = text_wrapper_get_text;
863 iface->get_character_at_offset = text_wrapper_get_character_at_offset;
864 iface->get_text_before_offset = text_wrapper_get_text_before_offset;
865 iface->get_text_at_offset = text_wrapper_get_text_at_offset;
866 iface->get_text_after_offset = text_wrapper_get_text_after_offset;
867 iface->get_caret_offset = text_wrapper_get_caret_offset;
868 iface->set_caret_offset = text_wrapper_set_caret_offset;
869 iface->get_character_count = text_wrapper_get_character_count;
870 iface->get_n_selections = text_wrapper_get_n_selections;
871 iface->get_selection = text_wrapper_get_selection;
872 iface->add_selection = text_wrapper_add_selection;
873 iface->remove_selection = text_wrapper_remove_selection;
874 iface->set_selection = text_wrapper_set_selection;
875 iface->get_run_attributes = text_wrapper_get_run_attributes;
876 iface->get_default_attributes = text_wrapper_get_default_attributes;
877 iface->get_character_extents = text_wrapper_get_character_extents;
878 iface->get_offset_at_point = text_wrapper_get_offset_at_point;
879 #if ATK_CHECK_VERSION(2,32,0)
880 iface->scroll_substring_to = text_wrapper_scroll_substring_to;
881 #endif
884 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */