LCOV - code coverage report
Current view: top level - vcl/unx/gtk/a11y - atktext.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 0 326 0.0 %
Date: 2014-11-03 Functions: 0 25 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       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/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      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 .
      18             :  */
      19             : 
      20             : #include "atkwrapper.hxx"
      21             : #include "atktextattributes.hxx"
      22             : #include <algorithm>
      23             : 
      24             : #include <com/sun/star/accessibility/AccessibleTextType.hpp>
      25             : #include <com/sun/star/accessibility/TextSegment.hpp>
      26             : #include <com/sun/star/accessibility/XAccessibleMultiLineText.hpp>
      27             : #include <com/sun/star/accessibility/XAccessibleText.hpp>
      28             : #include <com/sun/star/accessibility/XAccessibleTextAttributes.hpp>
      29             : #include <com/sun/star/accessibility/XAccessibleTextMarkup.hpp>
      30             : #include <com/sun/star/text/TextMarkupType.hpp>
      31             : 
      32             : // #define ENABLE_TRACING
      33             : 
      34             : #ifdef ENABLE_TRACING
      35             : #include <stdio.h>
      36             : #endif
      37             : 
      38             : using namespace ::com::sun::star;
      39             : 
      40             : static sal_Int16
      41           0 : text_type_from_boundary(AtkTextBoundary boundary_type)
      42             : {
      43           0 :     switch(boundary_type)
      44             :     {
      45             :         case ATK_TEXT_BOUNDARY_CHAR:
      46           0 :             return accessibility::AccessibleTextType::CHARACTER;
      47             :         case ATK_TEXT_BOUNDARY_WORD_START:
      48             :         case ATK_TEXT_BOUNDARY_WORD_END:
      49           0 :             return accessibility::AccessibleTextType::WORD;
      50             :         case ATK_TEXT_BOUNDARY_SENTENCE_START:
      51             :         case ATK_TEXT_BOUNDARY_SENTENCE_END:
      52           0 :             return accessibility::AccessibleTextType::SENTENCE;
      53             :         case ATK_TEXT_BOUNDARY_LINE_START:
      54             :         case ATK_TEXT_BOUNDARY_LINE_END:
      55           0 :             return accessibility::AccessibleTextType::LINE;
      56             :         default:
      57           0 :             return -1;
      58             :     }
      59             : }
      60             : 
      61             : /*****************************************************************************/
      62             : 
      63             : static gchar *
      64           0 : adjust_boundaries( accessibility::XAccessibleText* pText,
      65             :                    accessibility::TextSegment& rTextSegment,
      66             :                    AtkTextBoundary  boundary_type,
      67             :                    gint * start_offset, gint * end_offset )
      68             : {
      69           0 :     accessibility::TextSegment aTextSegment;
      70           0 :     OUString aString;
      71           0 :     gint start = 0, end = 0;
      72             : 
      73           0 :     if( !rTextSegment.SegmentText.isEmpty() )
      74             :     {
      75           0 :         switch(boundary_type)
      76             :         {
      77             :         case ATK_TEXT_BOUNDARY_CHAR:
      78             :         case ATK_TEXT_BOUNDARY_LINE_START:
      79             :         case ATK_TEXT_BOUNDARY_LINE_END:
      80             :         case ATK_TEXT_BOUNDARY_SENTENCE_START:
      81           0 :             start = rTextSegment.SegmentStart;
      82           0 :             end = rTextSegment.SegmentEnd;
      83           0 :             aString = rTextSegment.SegmentText;
      84           0 :             break;
      85             : 
      86             :         // the OOo break iterator behaves as SENTENCE_START
      87             :         case ATK_TEXT_BOUNDARY_SENTENCE_END:
      88           0 :             start = rTextSegment.SegmentStart;
      89           0 :             end = rTextSegment.SegmentEnd;
      90             : 
      91           0 :             if( start > 0 )
      92           0 :                 --start;
      93           0 :             if( end > 0 && end < pText->getCharacterCount() - 1 )
      94           0 :                 --end;
      95             : 
      96           0 :             aString = pText->getTextRange(start, end);
      97           0 :             break;
      98             : 
      99             :         case ATK_TEXT_BOUNDARY_WORD_START:
     100           0 :             start = rTextSegment.SegmentStart;
     101             : 
     102             :             // Determine the start index of the next segment
     103           0 :             aTextSegment = pText->getTextBehindIndex(rTextSegment.SegmentEnd,
     104           0 :                                                      text_type_from_boundary(boundary_type));
     105           0 :             if( !aTextSegment.SegmentText.isEmpty() )
     106           0 :                 end = aTextSegment.SegmentStart;
     107             :             else
     108           0 :                 end = pText->getCharacterCount();
     109             : 
     110           0 :             aString = pText->getTextRange(start, end);
     111           0 :             break;
     112             : 
     113             :         case ATK_TEXT_BOUNDARY_WORD_END:
     114           0 :             end = rTextSegment.SegmentEnd;
     115             : 
     116             :             // Determine the end index of the previous segment
     117           0 :             aTextSegment = pText->getTextBeforeIndex(rTextSegment.SegmentStart,
     118           0 :                                                      text_type_from_boundary(boundary_type));
     119           0 :             if( !aTextSegment.SegmentText.isEmpty() )
     120           0 :                 start = aTextSegment.SegmentEnd;
     121             :             else
     122           0 :                 start = 0;
     123             : 
     124           0 :             aString = pText->getTextRange(start, end);
     125           0 :             break;
     126             : 
     127             :         default:
     128           0 :             return NULL;
     129             :         }
     130             :     }
     131             : 
     132           0 :     *start_offset = start;
     133           0 :     *end_offset   = end;
     134             : 
     135             : #ifdef ENABLE_TRACING
     136             :     fprintf(stderr, "adjust_boundaries( %d, %d, %d ) returns %d, %d\n",
     137             :         rTextSegment.SegmentStart, rTextSegment.SegmentEnd, boundary_type,
     138             :         start, end);
     139             : #endif
     140             : 
     141           0 :     return OUStringToGChar(aString);
     142             : }
     143             : 
     144             : /*****************************************************************************/
     145             : 
     146             : static accessibility::XAccessibleText*
     147           0 :     getText( AtkText *pText ) throw (uno::RuntimeException)
     148             : {
     149           0 :     AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( pText );
     150           0 :     if( pWrap )
     151             :     {
     152           0 :         if( !pWrap->mpText && pWrap->mpContext )
     153             :         {
     154           0 :             uno::Any any = pWrap->mpContext->queryInterface( cppu::UnoType<accessibility::XAccessibleText>::get() );
     155           0 :             pWrap->mpText = reinterpret_cast< accessibility::XAccessibleText * > (any.pReserved);
     156           0 :             pWrap->mpText->acquire();
     157             :         }
     158             : 
     159           0 :         return pWrap->mpText;
     160             :     }
     161             : 
     162           0 :     return NULL;
     163             : }
     164             : 
     165             : /*****************************************************************************/
     166             : 
     167             : static accessibility::XAccessibleTextMarkup*
     168           0 :     getTextMarkup( AtkText *pText ) throw (uno::RuntimeException)
     169             : {
     170           0 :     AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( pText );
     171           0 :     if( pWrap )
     172             :     {
     173           0 :         if( !pWrap->mpTextMarkup && pWrap->mpContext )
     174             :         {
     175           0 :             uno::Any any = pWrap->mpContext->queryInterface( cppu::UnoType<accessibility::XAccessibleTextMarkup>::get() );
     176             :             /* Since this not a dedicated interface in Atk and thus has not
     177             :              * been queried during wrapper initialization, we need to check
     178             :              * the return value here.
     179             :              */
     180           0 :             if( typelib_TypeClass_INTERFACE == any.pType->eTypeClass )
     181             :             {
     182           0 :                 pWrap->mpTextMarkup = reinterpret_cast< accessibility::XAccessibleTextMarkup * > (any.pReserved);
     183           0 :                 if( pWrap->mpTextMarkup )
     184           0 :                     pWrap->mpTextMarkup->acquire();
     185           0 :             }
     186             :         }
     187             : 
     188           0 :         return pWrap->mpTextMarkup;
     189             :     }
     190             : 
     191           0 :     return NULL;
     192             : }
     193             : 
     194             : /*****************************************************************************/
     195             : 
     196             : static accessibility::XAccessibleTextAttributes*
     197           0 :     getTextAttributes( AtkText *pText ) throw (uno::RuntimeException)
     198             : {
     199           0 :     AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( pText );
     200           0 :     if( pWrap )
     201             :     {
     202           0 :         if( !pWrap->mpTextAttributes && pWrap->mpContext )
     203             :         {
     204           0 :             uno::Any any = pWrap->mpContext->queryInterface( cppu::UnoType<accessibility::XAccessibleTextAttributes>::get() );
     205             :             /* Since this not a dedicated interface in Atk and thus has not
     206             :              * been queried during wrapper initialization, we need to check
     207             :              * the return value here.
     208             :              */
     209           0 :             if( typelib_TypeClass_INTERFACE == any.pType->eTypeClass )
     210             :             {
     211           0 :                 pWrap->mpTextAttributes = reinterpret_cast< accessibility::XAccessibleTextAttributes * > (any.pReserved);
     212           0 :                 pWrap->mpTextAttributes->acquire();
     213           0 :             }
     214             :         }
     215             : 
     216           0 :         return pWrap->mpTextAttributes;
     217             :     }
     218             : 
     219           0 :     return NULL;
     220             : }
     221             : 
     222             : /*****************************************************************************/
     223             : 
     224             : static accessibility::XAccessibleMultiLineText*
     225           0 :     getMultiLineText( AtkText *pText ) throw (uno::RuntimeException)
     226             : {
     227           0 :     AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( pText );
     228           0 :     if( pWrap )
     229             :     {
     230           0 :         if( !pWrap->mpMultiLineText && pWrap->mpContext )
     231             :         {
     232           0 :             uno::Any any = pWrap->mpContext->queryInterface( cppu::UnoType<accessibility::XAccessibleMultiLineText>::get() );
     233             :             /* Since this not a dedicated interface in Atk and thus has not
     234             :              * been queried during wrapper initialization, we need to check
     235             :              * the return value here.
     236             :              */
     237           0 :             if( typelib_TypeClass_INTERFACE == any.pType->eTypeClass )
     238             :             {
     239           0 :                 pWrap->mpMultiLineText = reinterpret_cast< accessibility::XAccessibleMultiLineText * > (any.pReserved);
     240           0 :                 pWrap->mpMultiLineText->acquire();
     241           0 :             }
     242             :         }
     243             : 
     244           0 :         return pWrap->mpMultiLineText;
     245             :     }
     246             : 
     247           0 :     return NULL;
     248             : }
     249             : 
     250             : /*****************************************************************************/
     251             : 
     252             : extern "C" {
     253             : 
     254             : static gchar *
     255           0 : text_wrapper_get_text (AtkText *text,
     256             :                        gint     start_offset,
     257             :                        gint     end_offset)
     258             : {
     259           0 :     gchar * ret = NULL;
     260             : 
     261           0 :     g_return_val_if_fail( (end_offset == -1) || (end_offset >= start_offset), NULL );
     262             : 
     263             :     /* at-spi expects the delete event to be send before the deletion happened
     264             :      * so we save the deleted string object in the UNO event notification and
     265             :      * fool libatk-bridge.so here ..
     266             :      */
     267           0 :     void * pData = g_object_get_data( G_OBJECT(text), "ooo::text_changed::delete" );
     268           0 :     if( pData != NULL )
     269             :     {
     270             :         accessibility::TextSegment * pTextSegment =
     271           0 :             reinterpret_cast <accessibility::TextSegment *> (pData);
     272             : 
     273           0 :         if( pTextSegment->SegmentStart == start_offset &&
     274           0 :             pTextSegment->SegmentEnd == end_offset )
     275             :         {
     276           0 :             OString aUtf8 = OUStringToOString( pTextSegment->SegmentText, RTL_TEXTENCODING_UTF8 );
     277           0 :             return g_strdup( aUtf8.getStr() );
     278             :         }
     279             :     }
     280             : 
     281             :     try {
     282           0 :         accessibility::XAccessibleText* pText = getText( text );
     283           0 :         if( pText )
     284             :         {
     285           0 :             OUString aText;
     286           0 :             sal_Int32 n = pText->getCharacterCount();
     287             : 
     288           0 :             if( -1 == end_offset )
     289           0 :                 aText = pText->getText();
     290           0 :             else if( start_offset < n )
     291           0 :                 aText = pText->getTextRange(start_offset, end_offset);
     292             : 
     293           0 :             ret = g_strdup( OUStringToOString(aText, RTL_TEXTENCODING_UTF8 ).getStr() );
     294             :         }
     295             :     }
     296           0 :     catch(const uno::Exception&) {
     297           0 :         g_warning( "Exception in getText()" );
     298             :     }
     299             : 
     300             : #ifdef ENABLE_TRACING
     301             :     fprintf(stderr, "text_wrapper_get_text( %d,%d ) returns %s\n", start_offset, end_offset, ret ? ret : "null" );
     302             : #endif
     303           0 :     return ret;
     304             : }
     305             : 
     306             : static gchar *
     307           0 : text_wrapper_get_text_after_offset (AtkText          *text,
     308             :                                     gint             offset,
     309             :                                     AtkTextBoundary  boundary_type,
     310             :                                     gint             *start_offset,
     311             :                                     gint             *end_offset)
     312             : {
     313             :     try {
     314           0 :         accessibility::XAccessibleText* pText = getText( text );
     315           0 :         if( pText )
     316             :         {
     317           0 :             accessibility::TextSegment aTextSegment = pText->getTextBehindIndex(offset, text_type_from_boundary(boundary_type));
     318           0 :             return adjust_boundaries(pText, aTextSegment, boundary_type, start_offset, end_offset);
     319             :         }
     320             :     }
     321           0 :     catch(const uno::Exception&) {
     322           0 :         g_warning( "Exception in get_text_after_offset()" );
     323             :     }
     324             : 
     325           0 :     return NULL;
     326             : }
     327             : 
     328             : static gchar *
     329           0 : text_wrapper_get_text_at_offset (AtkText          *text,
     330             :                                  gint             offset,
     331             :                                  AtkTextBoundary  boundary_type,
     332             :                                  gint             *start_offset,
     333             :                                  gint             *end_offset)
     334             : {
     335             :     try {
     336           0 :         accessibility::XAccessibleText* pText = getText( text );
     337           0 :         if( pText )
     338             :         {
     339             :             /* If the user presses the 'End' key, the caret will be placed behind the last character,
     340             :              * which is the same index as the first character of the next line. In atk the magic offset
     341             :              * '-2' is used to cover this special case.
     342             :              */
     343           0 :             if (
     344           0 :                  -2 == offset &&
     345           0 :                      (ATK_TEXT_BOUNDARY_LINE_START == boundary_type ||
     346             :                       ATK_TEXT_BOUNDARY_LINE_END == boundary_type)
     347             :                )
     348             :             {
     349           0 :                 accessibility::XAccessibleMultiLineText* pMultiLineText = getMultiLineText( text );
     350           0 :                 if( pMultiLineText )
     351             :                 {
     352           0 :                     accessibility::TextSegment aTextSegment = pMultiLineText->getTextAtLineWithCaret();
     353           0 :                     return adjust_boundaries(pText, aTextSegment, boundary_type, start_offset, end_offset);
     354             :                 }
     355             :             }
     356             : 
     357           0 :             accessibility::TextSegment aTextSegment = pText->getTextAtIndex(offset, text_type_from_boundary(boundary_type));
     358           0 :             return adjust_boundaries(pText, aTextSegment, boundary_type, start_offset, end_offset);
     359             :         }
     360             :     }
     361           0 :     catch(const uno::Exception&) {
     362           0 :         g_warning( "Exception in get_text_at_offset()" );
     363             :     }
     364             : 
     365           0 :     return NULL;
     366             : }
     367             : 
     368             : static gunichar
     369           0 : text_wrapper_get_character_at_offset (AtkText          *text,
     370             :                                       gint             offset)
     371             : {
     372             :     gint start, end;
     373           0 :     gunichar uc = 0;
     374             : 
     375             :     gchar * char_as_string =
     376             :         text_wrapper_get_text_at_offset(text, offset, ATK_TEXT_BOUNDARY_CHAR,
     377           0 :                                         &start, &end);
     378           0 :     if( char_as_string )
     379             :     {
     380           0 :         uc = g_utf8_get_char( char_as_string );
     381           0 :         g_free( char_as_string );
     382             :     }
     383             : 
     384           0 :     return uc;
     385             : }
     386             : 
     387             : static gchar *
     388           0 : text_wrapper_get_text_before_offset (AtkText          *text,
     389             :                                      gint             offset,
     390             :                                      AtkTextBoundary  boundary_type,
     391             :                                      gint             *start_offset,
     392             :                                      gint             *end_offset)
     393             : {
     394             :     try {
     395           0 :         accessibility::XAccessibleText* pText = getText( text );
     396           0 :         if( pText )
     397             :         {
     398           0 :             accessibility::TextSegment aTextSegment = pText->getTextBeforeIndex(offset, text_type_from_boundary(boundary_type));
     399           0 :             return adjust_boundaries(pText, aTextSegment, boundary_type, start_offset, end_offset);
     400             :         }
     401             :     }
     402           0 :     catch(const uno::Exception&) {
     403           0 :         g_warning( "Exception in text_before_offset()" );
     404             :     }
     405             : 
     406           0 :     return NULL;
     407             : }
     408             : 
     409             : static gint
     410           0 : text_wrapper_get_caret_offset (AtkText          *text)
     411             : {
     412           0 :     gint offset = -1;
     413             : 
     414             :     try {
     415           0 :         accessibility::XAccessibleText* pText = getText( text );
     416           0 :         if( pText )
     417           0 :             offset = pText->getCaretPosition();
     418             :     }
     419           0 :     catch(const uno::Exception&) {
     420           0 :         g_warning( "Exception in getCaretPosition()" );
     421             :     }
     422             : 
     423             : #ifdef ENABLE_TRACING
     424             :     fprintf(stderr, "get_caret_offset(%p) returns %d\n", text, offset);
     425             : #endif
     426             : 
     427           0 :     return offset;
     428             : }
     429             : 
     430             : static gboolean
     431           0 : text_wrapper_set_caret_offset (AtkText *text,
     432             :                                gint     offset)
     433             : {
     434             :     try {
     435           0 :         accessibility::XAccessibleText* pText = getText( text );
     436           0 :         if( pText )
     437           0 :             return pText->setCaretPosition( offset );
     438             :     }
     439           0 :     catch(const uno::Exception&) {
     440           0 :         g_warning( "Exception in setCaretPosition()" );
     441             :     }
     442             : 
     443           0 :     return FALSE;
     444             : }
     445             : 
     446             : // #i92232#
     447             : AtkAttributeSet*
     448           0 : handle_text_markup_as_run_attribute( accessibility::XAccessibleTextMarkup* pTextMarkup,
     449             :                                      const gint nTextMarkupType,
     450             :                                      const gint offset,
     451             :                                      AtkAttributeSet* pSet,
     452             :                                      gint *start_offset,
     453             :                                      gint *end_offset )
     454             : {
     455           0 :     const gint nTextMarkupCount( pTextMarkup->getTextMarkupCount( nTextMarkupType ) );
     456           0 :     if ( nTextMarkupCount > 0 )
     457             :     {
     458           0 :         for ( gint nTextMarkupIndex = 0;
     459             :               nTextMarkupIndex < nTextMarkupCount;
     460             :               ++nTextMarkupIndex )
     461             :         {
     462             :             accessibility::TextSegment aTextSegment =
     463           0 :                 pTextMarkup->getTextMarkup( nTextMarkupIndex, nTextMarkupType );
     464           0 :             const gint nStartOffsetTextMarkup = aTextSegment.SegmentStart;
     465           0 :             const gint nEndOffsetTextMarkup = aTextSegment.SegmentEnd;
     466           0 :             if ( nStartOffsetTextMarkup <= offset )
     467             :             {
     468           0 :                 if ( offset < nEndOffsetTextMarkup )
     469             :                 {
     470             :                     // text markup at <offset>
     471             :                     *start_offset = ::std::max( *start_offset,
     472           0 :                                                 nStartOffsetTextMarkup );
     473             :                     *end_offset = ::std::min( *end_offset,
     474           0 :                                               nEndOffsetTextMarkup );
     475           0 :                     switch ( nTextMarkupType )
     476             :                     {
     477             :                         case com::sun::star::text::TextMarkupType::SPELLCHECK:
     478             :                         {
     479           0 :                             pSet = attribute_set_prepend_misspelled( pSet );
     480             :                         }
     481           0 :                         break;
     482             :                         case com::sun::star::text::TextMarkupType::TRACK_CHANGE_INSERTION:
     483             :                         {
     484           0 :                             pSet = attribute_set_prepend_tracked_change_insertion( pSet );
     485             :                         }
     486           0 :                         break;
     487             :                         case com::sun::star::text::TextMarkupType::TRACK_CHANGE_DELETION:
     488             :                         {
     489           0 :                             pSet = attribute_set_prepend_tracked_change_deletion( pSet );
     490             :                         }
     491           0 :                         break;
     492             :                         case com::sun::star::text::TextMarkupType::TRACK_CHANGE_FORMATCHANGE:
     493             :                         {
     494           0 :                             pSet = attribute_set_prepend_tracked_change_formatchange( pSet );
     495             :                         }
     496           0 :                         break;
     497             :                         default:
     498             :                         {
     499             :                             OSL_ASSERT( false );
     500             :                         }
     501             :                     }
     502           0 :                     break; // no further iteration needed.
     503             :                 }
     504             :                 else
     505             :                 {
     506             :                     *start_offset = ::std::max( *start_offset,
     507           0 :                                                 nEndOffsetTextMarkup );
     508             :                     // continue iteration.
     509             :                 }
     510             :             }
     511             :             else
     512             :             {
     513             :                 *end_offset = ::std::min( *end_offset,
     514           0 :                                           nStartOffsetTextMarkup );
     515           0 :                 break; // no further iteration.
     516             :             }
     517           0 :         } // eof iteration over text markups
     518             :     }
     519             : 
     520           0 :     return pSet;
     521             : }
     522             : 
     523             : static AtkAttributeSet *
     524           0 : text_wrapper_get_run_attributes( AtkText        *text,
     525             :                                  gint           offset,
     526             :                                  gint           *start_offset,
     527             :                                  gint           *end_offset)
     528             : {
     529           0 :     AtkAttributeSet *pSet = NULL;
     530             : 
     531             :     try {
     532           0 :         bool bOffsetsAreValid = false;
     533             : 
     534           0 :         accessibility::XAccessibleText* pText = getText( text );
     535           0 :         accessibility::XAccessibleTextAttributes* pTextAttributes = getTextAttributes( text );
     536           0 :         if( pText && pTextAttributes )
     537             :         {
     538             :             uno::Sequence< beans::PropertyValue > aAttributeList =
     539           0 :                 pTextAttributes->getRunAttributes( offset, uno::Sequence< OUString > () );
     540             : 
     541           0 :             pSet = attribute_set_new_from_property_values( aAttributeList, true, text );
     542             :             //  #i100938#
     543             :             // - always provide start_offset and end_offset
     544             :             {
     545             :                 accessibility::TextSegment aTextSegment =
     546           0 :                     pText->getTextAtIndex(offset, accessibility::AccessibleTextType::ATTRIBUTE_RUN);
     547             : 
     548           0 :                 *start_offset = aTextSegment.SegmentStart;
     549             :                 // #i100938#
     550             :                 // Do _not_ increment the end_offset provide by <accessibility::TextSegment> instance
     551           0 :                 *end_offset = aTextSegment.SegmentEnd;
     552           0 :                 bOffsetsAreValid = true;
     553           0 :             }
     554             :         }
     555             : 
     556             :         // Special handling for misspelled text
     557             :         // #i92232#
     558             :         // - add special handling for tracked changes and refactor the
     559             :         //   corresponding code for handling misspelled text.
     560           0 :         accessibility::XAccessibleTextMarkup* pTextMarkup = getTextMarkup( text );
     561           0 :         if( pTextMarkup )
     562             :         {
     563             :             // Get attribute run here if it hasn't been done before
     564           0 :             if (!bOffsetsAreValid && pText)
     565             :             {
     566             :                 accessibility::TextSegment aAttributeTextSegment =
     567           0 :                     pText->getTextAtIndex(offset, accessibility::AccessibleTextType::ATTRIBUTE_RUN);
     568           0 :                 *start_offset = aAttributeTextSegment.SegmentStart;
     569           0 :                 *end_offset = aAttributeTextSegment.SegmentEnd;
     570             :             }
     571             :             // handle misspelled text
     572             :             pSet = handle_text_markup_as_run_attribute(
     573             :                     pTextMarkup,
     574             :                     com::sun::star::text::TextMarkupType::SPELLCHECK,
     575           0 :                     offset, pSet, start_offset, end_offset );
     576             :             // handle tracked changes
     577             :             pSet = handle_text_markup_as_run_attribute(
     578             :                     pTextMarkup,
     579             :                     com::sun::star::text::TextMarkupType::TRACK_CHANGE_INSERTION,
     580           0 :                     offset, pSet, start_offset, end_offset );
     581             :             pSet = handle_text_markup_as_run_attribute(
     582             :                     pTextMarkup,
     583             :                     com::sun::star::text::TextMarkupType::TRACK_CHANGE_DELETION,
     584           0 :                     offset, pSet, start_offset, end_offset );
     585             :             pSet = handle_text_markup_as_run_attribute(
     586             :                     pTextMarkup,
     587             :                     com::sun::star::text::TextMarkupType::TRACK_CHANGE_FORMATCHANGE,
     588           0 :                     offset, pSet, start_offset, end_offset );
     589             :         }
     590             :     }
     591           0 :     catch(const uno::Exception&){
     592             : 
     593           0 :         g_warning( "Exception in get_run_attributes()" );
     594             : 
     595           0 :         if( pSet )
     596             :         {
     597           0 :             atk_attribute_set_free( pSet );
     598           0 :             pSet = NULL;
     599             :         }
     600             :     }
     601             : 
     602           0 :     return pSet;
     603             : }
     604             : 
     605             : /*****************************************************************************/
     606             : 
     607             : static AtkAttributeSet *
     608           0 : text_wrapper_get_default_attributes( AtkText *text )
     609             : {
     610           0 :     AtkAttributeSet *pSet = NULL;
     611             : 
     612             :     try {
     613           0 :         accessibility::XAccessibleTextAttributes* pTextAttributes = getTextAttributes( text );
     614           0 :         if( pTextAttributes )
     615             :         {
     616             :             uno::Sequence< beans::PropertyValue > aAttributeList =
     617           0 :                 pTextAttributes->getDefaultAttributes( uno::Sequence< OUString > () );
     618             : 
     619           0 :             pSet = attribute_set_new_from_property_values( aAttributeList, false, text );
     620             :         }
     621             :     }
     622           0 :     catch(const uno::Exception&) {
     623             : 
     624           0 :         g_warning( "Exception in get_default_attributes()" );
     625             : 
     626           0 :         if( pSet )
     627             :         {
     628           0 :             atk_attribute_set_free( pSet );
     629           0 :             pSet = NULL;
     630             :         }
     631             :     }
     632             : 
     633           0 :     return pSet;
     634             : }
     635             : 
     636             : /*****************************************************************************/
     637             : 
     638             : static void
     639           0 : text_wrapper_get_character_extents( AtkText          *text,
     640             :                                     gint             offset,
     641             :                                     gint             *x,
     642             :                                     gint             *y,
     643             :                                     gint             *width,
     644             :                                     gint             *height,
     645             :                                     AtkCoordType      coords )
     646             : {
     647             :     try {
     648           0 :         accessibility::XAccessibleText* pText = getText( text );
     649           0 :         if( pText )
     650             :         {
     651           0 :             *x = *y = *width = *height = 0;
     652           0 :             awt::Rectangle aRect = pText->getCharacterBounds( offset );
     653             : 
     654           0 :             gint origin_x = 0;
     655           0 :             gint origin_y = 0;
     656             : 
     657           0 :             if( coords == ATK_XY_SCREEN )
     658             :             {
     659           0 :                 g_return_if_fail( ATK_IS_COMPONENT( text ) );
     660             :                 SAL_WNODEPRECATED_DECLARATIONS_PUSH
     661           0 :                 atk_component_get_position( ATK_COMPONENT( text ), &origin_x, &origin_y, coords);
     662             :                 SAL_WNODEPRECATED_DECLARATIONS_POP
     663             :             }
     664             : 
     665           0 :             *x = aRect.X + origin_x;
     666           0 :             *y = aRect.Y + origin_y;
     667           0 :             *width = aRect.Width;
     668           0 :             *height = aRect.Height;
     669             : 
     670             : #ifdef ENABLE_TRACING
     671             :             fprintf(stderr, "get_character_extents(%d, %d) returns: %d,%d,%d,%d ",
     672             :                 offset, coords, *x, *y, *width, *height);
     673             : #endif
     674             :         }
     675             :     }
     676           0 :     catch(const uno::Exception&) {
     677           0 :         g_warning( "Exception in getCharacterBounds" );
     678             :     }
     679             : }
     680             : 
     681             : static gint
     682           0 : text_wrapper_get_character_count (AtkText *text)
     683             : {
     684           0 :     gint rv = 0;
     685             : 
     686             :     try {
     687           0 :         accessibility::XAccessibleText* pText = getText( text );
     688           0 :         if( pText )
     689           0 :             rv = pText->getCharacterCount();
     690             :     }
     691           0 :     catch(const uno::Exception&) {
     692           0 :         g_warning( "Exception in getCharacterCount" );
     693             :     }
     694             : 
     695             : #ifdef ENABLE_TRACING
     696             :     fprintf(stderr, "get_character_count(%p) returns: %d\n", text, rv);
     697             : #endif
     698             : 
     699           0 :     return rv;
     700             : }
     701             : 
     702             : static gint
     703           0 : text_wrapper_get_offset_at_point (AtkText     *text,
     704             :                                   gint         x,
     705             :                                   gint         y,
     706             :                                   AtkCoordType coords)
     707             : {
     708             :     try {
     709           0 :         accessibility::XAccessibleText* pText = getText( text );
     710           0 :         if( pText )
     711             :         {
     712           0 :             gint origin_x = 0;
     713           0 :             gint origin_y = 0;
     714             : 
     715           0 :             if( coords == ATK_XY_SCREEN )
     716             :             {
     717           0 :                 g_return_val_if_fail( ATK_IS_COMPONENT( text ), -1 );
     718             :                 SAL_WNODEPRECATED_DECLARATIONS_PUSH
     719           0 :                 atk_component_get_position( ATK_COMPONENT( text ), &origin_x, &origin_y, coords);
     720             :                 SAL_WNODEPRECATED_DECLARATIONS_POP
     721             :             }
     722             : 
     723           0 :             return pText->getIndexAtPoint( awt::Point(x - origin_x, y - origin_y) );
     724             :         }
     725             :     }
     726           0 :     catch(const uno::Exception&) {
     727           0 :         g_warning( "Exception in getIndexAtPoint" );
     728             :     }
     729             : 
     730           0 :     return -1;
     731             : }
     732             : 
     733             : // FIXME: the whole series of selections API is problematic ...
     734             : 
     735             : static gint
     736           0 : text_wrapper_get_n_selections (AtkText *text)
     737             : {
     738           0 :     gint rv = 0;
     739             : 
     740             :     try {
     741           0 :         accessibility::XAccessibleText* pText = getText( text );
     742           0 :         if( pText )
     743           0 :             rv = ( pText->getSelectionEnd() > pText->getSelectionStart() ) ? 1 : 0;
     744             :     }
     745           0 :     catch(const uno::Exception&) {
     746           0 :         g_warning( "Exception in getSelectionEnd() or getSelectionStart()" );
     747             :     }
     748             : 
     749             : #ifdef ENABLE_TRACING
     750             :     fprintf(stderr, "get_n_selections(%p) returns %d\n", text, rv);
     751             : #endif
     752             : 
     753           0 :     return rv;
     754             : }
     755             : 
     756             : static gchar *
     757           0 : text_wrapper_get_selection (AtkText *text,
     758             :                             gint     selection_num,
     759             :                             gint    *start_offset,
     760             :                             gint    *end_offset)
     761             : {
     762           0 :     g_return_val_if_fail( selection_num == 0, FALSE );
     763             : 
     764             :     try {
     765           0 :         accessibility::XAccessibleText* pText = getText( text );
     766           0 :         if( pText )
     767             :         {
     768           0 :             *start_offset = pText->getSelectionStart();
     769           0 :             *end_offset   = pText->getSelectionEnd();
     770             : 
     771           0 :             return OUStringToGChar( pText->getSelectedText() );
     772             :         }
     773             :     }
     774           0 :     catch(const uno::Exception&) {
     775           0 :         g_warning( "Exception in getSelectionEnd(), getSelectionStart() or getSelectedText()" );
     776             :     }
     777             : 
     778           0 :     return NULL;
     779             : }
     780             : 
     781             : static gboolean
     782           0 : text_wrapper_add_selection (AtkText *text,
     783             :                             gint     start_offset,
     784             :                             gint     end_offset)
     785             : {
     786             :     // FIXME: can we try to be more compatible by expanding an
     787             :     //        existing adjacent selection ?
     788             : 
     789             :     try {
     790           0 :         accessibility::XAccessibleText* pText = getText( text );
     791           0 :         if( pText )
     792           0 :             return pText->setSelection( start_offset, end_offset ); // ?
     793             :     }
     794           0 :     catch(const uno::Exception&) {
     795           0 :         g_warning( "Exception in setSelection()" );
     796             :     }
     797             : 
     798           0 :     return FALSE;
     799             : }
     800             : 
     801             : static gboolean
     802           0 : text_wrapper_remove_selection (AtkText *text,
     803             :                                gint     selection_num)
     804             : {
     805           0 :     g_return_val_if_fail( selection_num == 0, FALSE );
     806             : 
     807             :     try {
     808           0 :         accessibility::XAccessibleText* pText = getText( text );
     809           0 :         if( pText )
     810           0 :             return pText->setSelection( 0, 0 ); // ?
     811             :     }
     812           0 :     catch(const uno::Exception&) {
     813           0 :         g_warning( "Exception in setSelection()" );
     814             :     }
     815             : 
     816           0 :     return FALSE;
     817             : }
     818             : 
     819             : static gboolean
     820           0 : text_wrapper_set_selection (AtkText *text,
     821             :                             gint     selection_num,
     822             :                             gint     start_offset,
     823             :                             gint     end_offset)
     824             : {
     825           0 :     g_return_val_if_fail( selection_num == 0, FALSE );
     826             : 
     827             :     try {
     828           0 :         accessibility::XAccessibleText* pText = getText( text );
     829           0 :         if( pText )
     830           0 :             return pText->setSelection( start_offset, end_offset );
     831             :     }
     832           0 :     catch(const uno::Exception&) {
     833           0 :         g_warning( "Exception in setSelection()" );
     834             :     }
     835             : 
     836           0 :     return FALSE;
     837             : }
     838             : 
     839             : } // extern "C"
     840             : 
     841             : void
     842           0 : textIfaceInit (AtkTextIface *iface)
     843             : {
     844           0 :   g_return_if_fail (iface != NULL);
     845             : 
     846           0 :   iface->get_text = text_wrapper_get_text;
     847           0 :   iface->get_character_at_offset = text_wrapper_get_character_at_offset;
     848           0 :   iface->get_text_before_offset = text_wrapper_get_text_before_offset;
     849           0 :   iface->get_text_at_offset = text_wrapper_get_text_at_offset;
     850           0 :   iface->get_text_after_offset = text_wrapper_get_text_after_offset;
     851           0 :   iface->get_caret_offset = text_wrapper_get_caret_offset;
     852           0 :   iface->set_caret_offset = text_wrapper_set_caret_offset;
     853           0 :   iface->get_character_count = text_wrapper_get_character_count;
     854           0 :   iface->get_n_selections = text_wrapper_get_n_selections;
     855           0 :   iface->get_selection = text_wrapper_get_selection;
     856           0 :   iface->add_selection = text_wrapper_add_selection;
     857           0 :   iface->remove_selection = text_wrapper_remove_selection;
     858           0 :   iface->set_selection = text_wrapper_set_selection;
     859           0 :   iface->get_run_attributes = text_wrapper_get_run_attributes;
     860           0 :   iface->get_default_attributes = text_wrapper_get_default_attributes;
     861           0 :   iface->get_character_extents = text_wrapper_get_character_extents;
     862           0 :   iface->get_offset_at_point = text_wrapper_get_offset_at_point;
     863             : }
     864             : 
     865             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10