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

Generated by: LCOV version 1.10