Move setting of LD_LIBRARY_PATH closer to invocation of cppunittester
[LibreOffice.git] / vcl / unx / gtk3 / a11y / atktext.cxx
blobb140232055d35a7c795c764acbd47fb7d473119a
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 for ( gint nTextMarkupIndex = 0;
442 nTextMarkupIndex < nTextMarkupCount;
443 ++nTextMarkupIndex )
445 accessibility::TextSegment aTextSegment =
446 pTextMarkup->getTextMarkup( nTextMarkupIndex, nTextMarkupType );
447 const gint nStartOffsetTextMarkup = aTextSegment.SegmentStart;
448 const gint nEndOffsetTextMarkup = aTextSegment.SegmentEnd;
449 if ( nStartOffsetTextMarkup <= offset )
451 if ( offset < nEndOffsetTextMarkup )
453 // text markup at <offset>
454 *start_offset = ::std::max( *start_offset,
455 nStartOffsetTextMarkup );
456 *end_offset = ::std::min( *end_offset,
457 nEndOffsetTextMarkup );
458 switch ( nTextMarkupType )
460 case css::text::TextMarkupType::SPELLCHECK:
462 pSet = attribute_set_prepend_misspelled( pSet );
464 break;
465 case css::text::TextMarkupType::TRACK_CHANGE_INSERTION:
467 pSet = attribute_set_prepend_tracked_change_insertion( pSet );
469 break;
470 case css::text::TextMarkupType::TRACK_CHANGE_DELETION:
472 pSet = attribute_set_prepend_tracked_change_deletion( pSet );
474 break;
475 case css::text::TextMarkupType::TRACK_CHANGE_FORMATCHANGE:
477 pSet = attribute_set_prepend_tracked_change_formatchange( pSet );
479 break;
480 default:
482 OSL_ASSERT( false );
485 break; // no further iteration needed.
487 else
489 *start_offset = ::std::max( *start_offset,
490 nEndOffsetTextMarkup );
491 // continue iteration.
494 else
496 *end_offset = ::std::min( *end_offset,
497 nStartOffsetTextMarkup );
498 break; // no further iteration.
502 return pSet;
505 static AtkAttributeSet *
506 text_wrapper_get_run_attributes( AtkText *text,
507 gint offset,
508 gint *start_offset,
509 gint *end_offset)
511 AtkAttributeSet *pSet = nullptr;
513 try {
514 bool bOffsetsAreValid = false;
516 css::uno::Reference<css::accessibility::XAccessibleText> pText
517 = getText( text );
518 if( pText.is())
520 uno::Sequence< beans::PropertyValue > aAttributeList;
522 css::uno::Reference<css::accessibility::XAccessibleTextAttributes>
523 pTextAttributes = getTextAttributes( text );
524 if(pTextAttributes.is()) // Text attributes are available for paragraphs only
526 aAttributeList = pTextAttributes->getRunAttributes( offset, uno::Sequence< OUString > () );
528 else // For other text objects use character attributes
530 aAttributeList = pText->getCharacterAttributes( offset, uno::Sequence< OUString > () );
533 pSet = attribute_set_new_from_property_values( aAttributeList, true, text );
534 // #i100938#
535 // - always provide start_offset and end_offset
537 accessibility::TextSegment aTextSegment =
538 pText->getTextAtIndex(offset, accessibility::AccessibleTextType::ATTRIBUTE_RUN);
540 *start_offset = aTextSegment.SegmentStart;
541 // #i100938#
542 // Do _not_ increment the end_offset provide by <accessibility::TextSegment> instance
543 *end_offset = aTextSegment.SegmentEnd;
544 bOffsetsAreValid = true;
548 // Special handling for misspelled text
549 // #i92232#
550 // - add special handling for tracked changes and refactor the
551 // corresponding code for handling misspelled text.
552 css::uno::Reference<css::accessibility::XAccessibleTextMarkup>
553 pTextMarkup = getTextMarkup( text );
554 if( pTextMarkup.is() )
556 // Get attribute run here if it hasn't been done before
557 if (!bOffsetsAreValid && pText.is())
559 accessibility::TextSegment aAttributeTextSegment =
560 pText->getTextAtIndex(offset, accessibility::AccessibleTextType::ATTRIBUTE_RUN);
561 *start_offset = aAttributeTextSegment.SegmentStart;
562 *end_offset = aAttributeTextSegment.SegmentEnd;
564 // handle misspelled text
565 pSet = handle_text_markup_as_run_attribute(
566 pTextMarkup,
567 css::text::TextMarkupType::SPELLCHECK,
568 offset, pSet, start_offset, end_offset );
569 // handle tracked changes
570 pSet = handle_text_markup_as_run_attribute(
571 pTextMarkup,
572 css::text::TextMarkupType::TRACK_CHANGE_INSERTION,
573 offset, pSet, start_offset, end_offset );
574 pSet = handle_text_markup_as_run_attribute(
575 pTextMarkup,
576 css::text::TextMarkupType::TRACK_CHANGE_DELETION,
577 offset, pSet, start_offset, end_offset );
578 pSet = handle_text_markup_as_run_attribute(
579 pTextMarkup,
580 css::text::TextMarkupType::TRACK_CHANGE_FORMATCHANGE,
581 offset, pSet, start_offset, end_offset );
584 catch(const uno::Exception&){
586 g_warning( "Exception in get_run_attributes()" );
588 if( pSet )
590 atk_attribute_set_free( pSet );
591 pSet = nullptr;
595 return pSet;
598 /*****************************************************************************/
600 static AtkAttributeSet *
601 text_wrapper_get_default_attributes( AtkText *text )
603 AtkAttributeSet *pSet = nullptr;
605 try {
606 css::uno::Reference<css::accessibility::XAccessibleTextAttributes>
607 pTextAttributes = getTextAttributes( text );
608 if( pTextAttributes.is() )
610 uno::Sequence< beans::PropertyValue > aAttributeList =
611 pTextAttributes->getDefaultAttributes( uno::Sequence< OUString > () );
613 pSet = attribute_set_new_from_property_values( aAttributeList, false, text );
616 catch(const uno::Exception&) {
618 g_warning( "Exception in get_default_attributes()" );
620 if( pSet )
622 atk_attribute_set_free( pSet );
623 pSet = nullptr;
627 return pSet;
630 /*****************************************************************************/
632 static void
633 text_wrapper_get_character_extents( AtkText *text,
634 gint offset,
635 gint *x,
636 gint *y,
637 gint *width,
638 gint *height,
639 AtkCoordType coords )
641 *x = *y = *width = *height = -1;
643 try {
644 css::uno::Reference<css::accessibility::XAccessibleText> pText
645 = getText( text );
646 if( pText.is() )
648 awt::Rectangle aRect = pText->getCharacterBounds( offset );
650 gint origin_x = 0;
651 gint origin_y = 0;
653 if (coords == ATK_XY_SCREEN || coords == ATK_XY_WINDOW)
655 g_return_if_fail( ATK_IS_COMPONENT( text ) );
656 gint nWidth = -1;
657 gint nHeight = -1;
658 atk_component_get_extents(ATK_COMPONENT(text), &origin_x, &origin_y, &nWidth, &nHeight, coords);
661 *x = aRect.X + origin_x;
662 *y = aRect.Y + origin_y;
663 *width = aRect.Width;
664 *height = aRect.Height;
667 catch(const uno::Exception&) {
668 g_warning( "Exception in getCharacterBounds" );
672 static gint
673 text_wrapper_get_character_count (AtkText *text)
675 gint rv = 0;
677 try {
678 css::uno::Reference<css::accessibility::XAccessibleText> pText
679 = getText( text );
680 if( pText.is() )
681 rv = pText->getCharacterCount();
683 catch(const uno::Exception&) {
684 g_warning( "Exception in getCharacterCount" );
687 return rv;
690 static gint
691 text_wrapper_get_offset_at_point (AtkText *text,
692 gint x,
693 gint y,
694 AtkCoordType coords)
696 try {
697 css::uno::Reference<css::accessibility::XAccessibleText> pText
698 = getText( text );
699 if( pText.is() )
701 gint origin_x = 0;
702 gint origin_y = 0;
704 if (coords == ATK_XY_SCREEN || coords == ATK_XY_WINDOW)
706 g_return_val_if_fail( ATK_IS_COMPONENT( text ), -1 );
707 gint nWidth = -1;
708 gint nHeight = -1;
709 atk_component_get_extents(ATK_COMPONENT(text), &origin_x, &origin_y, &nWidth, &nHeight, coords);
712 return pText->getIndexAtPoint( awt::Point(x - origin_x, y - origin_y) );
715 catch(const uno::Exception&) {
716 g_warning( "Exception in getIndexAtPoint" );
719 return -1;
722 // FIXME: the whole series of selections API is problematic ...
724 static gint
725 text_wrapper_get_n_selections (AtkText *text)
727 gint rv = 0;
729 try {
730 css::uno::Reference<css::accessibility::XAccessibleText> pText
731 = getText( text );
732 if( pText.is() )
733 rv = ( pText->getSelectionEnd() > pText->getSelectionStart() ) ? 1 : 0;
735 catch(const uno::Exception&) {
736 g_warning( "Exception in getSelectionEnd() or getSelectionStart()" );
739 return rv;
742 static gchar *
743 text_wrapper_get_selection (AtkText *text,
744 gint selection_num,
745 gint *start_offset,
746 gint *end_offset)
748 g_return_val_if_fail( selection_num == 0, FALSE );
750 try {
751 css::uno::Reference<css::accessibility::XAccessibleText> pText
752 = getText( text );
753 if( pText.is() )
755 *start_offset = pText->getSelectionStart();
756 *end_offset = pText->getSelectionEnd();
758 return OUStringToGChar( pText->getSelectedText() );
761 catch(const uno::Exception&) {
762 g_warning( "Exception in getSelectionEnd(), getSelectionStart() or getSelectedText()" );
765 return nullptr;
768 static gboolean
769 text_wrapper_add_selection (AtkText *text,
770 gint start_offset,
771 gint end_offset)
773 // FIXME: can we try to be more compatible by expanding an
774 // existing adjacent selection ?
776 try {
777 css::uno::Reference<css::accessibility::XAccessibleText> pText
778 = getText( text );
779 if( pText.is() )
780 return pText->setSelection( start_offset, end_offset ); // ?
782 catch(const uno::Exception&) {
783 g_warning( "Exception in setSelection()" );
786 return FALSE;
789 static gboolean
790 text_wrapper_remove_selection (AtkText *text,
791 gint selection_num)
793 g_return_val_if_fail( selection_num == 0, FALSE );
795 try {
796 css::uno::Reference<css::accessibility::XAccessibleText> pText
797 = getText( text );
798 if( pText.is() )
799 return pText->setSelection( 0, 0 ); // ?
801 catch(const uno::Exception&) {
802 g_warning( "Exception in setSelection()" );
805 return FALSE;
808 static gboolean
809 text_wrapper_set_selection (AtkText *text,
810 gint selection_num,
811 gint start_offset,
812 gint end_offset)
814 g_return_val_if_fail( selection_num == 0, FALSE );
816 try {
817 css::uno::Reference<css::accessibility::XAccessibleText> pText
818 = getText( text );
819 if( pText.is() )
820 return pText->setSelection( start_offset, end_offset );
822 catch(const uno::Exception&) {
823 g_warning( "Exception in setSelection()" );
826 return FALSE;
829 #if ATK_CHECK_VERSION(2,32,0)
830 static gboolean
831 text_wrapper_scroll_substring_to(AtkText *text,
832 gint start_offset,
833 gint end_offset,
834 AtkScrollType scroll_type)
836 try {
837 css::uno::Reference<css::accessibility::XAccessibleText> pText
838 = getText( text );
840 if( pText.is() )
841 return pText->scrollSubstringTo( start_offset, end_offset,
842 scroll_type_from_scroll_type( scroll_type ) );
844 catch(const uno::Exception&) {
845 g_warning( "Exception in scrollSubstringTo()" );
848 return FALSE;
850 #endif
852 } // extern "C"
854 void
855 textIfaceInit (gpointer iface_, gpointer)
857 auto const iface = static_cast<AtkTextIface *>(iface_);
858 g_return_if_fail (iface != nullptr);
860 iface->get_text = text_wrapper_get_text;
861 iface->get_character_at_offset = text_wrapper_get_character_at_offset;
862 iface->get_text_before_offset = text_wrapper_get_text_before_offset;
863 iface->get_text_at_offset = text_wrapper_get_text_at_offset;
864 iface->get_text_after_offset = text_wrapper_get_text_after_offset;
865 iface->get_caret_offset = text_wrapper_get_caret_offset;
866 iface->set_caret_offset = text_wrapper_set_caret_offset;
867 iface->get_character_count = text_wrapper_get_character_count;
868 iface->get_n_selections = text_wrapper_get_n_selections;
869 iface->get_selection = text_wrapper_get_selection;
870 iface->add_selection = text_wrapper_add_selection;
871 iface->remove_selection = text_wrapper_remove_selection;
872 iface->set_selection = text_wrapper_set_selection;
873 iface->get_run_attributes = text_wrapper_get_run_attributes;
874 iface->get_default_attributes = text_wrapper_get_default_attributes;
875 iface->get_character_extents = text_wrapper_get_character_extents;
876 iface->get_offset_at_point = text_wrapper_get_offset_at_point;
877 #if ATK_CHECK_VERSION(2,32,0)
878 iface->scroll_substring_to = text_wrapper_scroll_substring_to;
879 #endif
882 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */