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

Generated by: LCOV version 1.11