LCOV - code coverage report
Current view: top level - libreoffice/comphelper/source/misc - accessibletexthelper.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 372 0.0 %
Date: 2012-12-27 Functions: 0 40 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 <comphelper/accessibletexthelper.hxx>
      21             : #include <com/sun/star/accessibility/AccessibleTextType.hpp>
      22             : #include <com/sun/star/i18n/BreakIterator.hpp>
      23             : #include <com/sun/star/i18n/CharacterIteratorMode.hpp>
      24             : #include <com/sun/star/i18n/CharacterClassification.hpp>
      25             : #include <com/sun/star/i18n/WordType.hpp>
      26             : #include <com/sun/star/i18n/KCharacterType.hpp>
      27             : #include <comphelper/processfactory.hxx>
      28             : #include <com/sun/star/accessibility/TextSegment.hpp>
      29             : 
      30             : #include <algorithm>
      31             : 
      32             : //..............................................................................
      33             : namespace comphelper
      34             : {
      35             : //..............................................................................
      36             : 
      37             :     using namespace ::com::sun::star;
      38             :     using namespace ::com::sun::star::uno;
      39             :     using namespace ::com::sun::star::lang;
      40             :     using namespace ::com::sun::star::beans;
      41             :     using namespace ::com::sun::star::accessibility;
      42             : 
      43             :     //==============================================================================
      44             :     // OCommonAccessibleText
      45             :     //==============================================================================
      46             : 
      47           0 :     OCommonAccessibleText::OCommonAccessibleText()
      48             :     {
      49           0 :     }
      50             : 
      51             :     // -----------------------------------------------------------------------------
      52             : 
      53           0 :     OCommonAccessibleText::~OCommonAccessibleText()
      54             :     {
      55           0 :     }
      56             : 
      57             :     // -----------------------------------------------------------------------------
      58             : 
      59           0 :     Reference < i18n::XBreakIterator > OCommonAccessibleText::implGetBreakIterator()
      60             :     {
      61           0 :         if ( !m_xBreakIter.is() )
      62             :         {
      63           0 :             Reference< uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
      64           0 :             m_xBreakIter = i18n::BreakIterator::create(xContext);
      65             :         }
      66             : 
      67           0 :         return m_xBreakIter;
      68             :     }
      69             : 
      70             :     // -----------------------------------------------------------------------------
      71             : 
      72           0 :     Reference < i18n::XCharacterClassification > OCommonAccessibleText::implGetCharacterClassification()
      73             :     {
      74           0 :         if ( !m_xCharClass.is() )
      75             :         {
      76           0 :             m_xCharClass = i18n::CharacterClassification::create( ::comphelper::getProcessComponentContext() );
      77             :         }
      78             : 
      79           0 :         return m_xCharClass;
      80             :     }
      81             : 
      82             :     // -----------------------------------------------------------------------------
      83             : 
      84           0 :     sal_Bool OCommonAccessibleText::implIsValidBoundary( i18n::Boundary& rBoundary, sal_Int32 nLength )
      85             :     {
      86           0 :         return ( rBoundary.startPos >= 0 ) && ( rBoundary.startPos < nLength ) && ( rBoundary.endPos >= 0 ) && ( rBoundary.endPos <= nLength );
      87             :     }
      88             : 
      89             :     // -----------------------------------------------------------------------------
      90             : 
      91           0 :     sal_Bool OCommonAccessibleText::implIsValidIndex( sal_Int32 nIndex, sal_Int32 nLength )
      92             :     {
      93           0 :         return ( nIndex >= 0 ) && ( nIndex < nLength );
      94             :     }
      95             : 
      96             :     // -----------------------------------------------------------------------------
      97             : 
      98           0 :     sal_Bool OCommonAccessibleText::implIsValidRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex, sal_Int32 nLength )
      99             :     {
     100           0 :         return ( nStartIndex >= 0 ) && ( nStartIndex <= nLength ) && ( nEndIndex >= 0 ) && ( nEndIndex <= nLength );
     101             :     }
     102             : 
     103             :     // -----------------------------------------------------------------------------
     104             : 
     105           0 :     void OCommonAccessibleText::implGetGlyphBoundary( i18n::Boundary& rBoundary, sal_Int32 nIndex )
     106             :     {
     107           0 :         ::rtl::OUString sText( implGetText() );
     108             : 
     109           0 :         if ( implIsValidIndex( nIndex, sText.getLength() ) )
     110             :         {
     111           0 :             Reference < i18n::XBreakIterator > xBreakIter = implGetBreakIterator();
     112           0 :             if ( xBreakIter.is() )
     113             :             {
     114           0 :                 sal_Int32 nCount = 1;
     115             :                 sal_Int32 nDone;
     116           0 :                 sal_Int32 nStartIndex = xBreakIter->previousCharacters( sText, nIndex, implGetLocale(), i18n::CharacterIteratorMode::SKIPCELL, nCount, nDone );
     117           0 :                 if ( nDone != 0 )
     118           0 :                     nStartIndex = xBreakIter->nextCharacters( sText, nStartIndex, implGetLocale(), i18n::CharacterIteratorMode::SKIPCELL, nCount, nDone );
     119           0 :                 sal_Int32 nEndIndex = xBreakIter->nextCharacters( sText, nStartIndex, implGetLocale(), i18n::CharacterIteratorMode::SKIPCELL, nCount, nDone );
     120           0 :                 if ( nDone != 0 )
     121             :                 {
     122           0 :                     rBoundary.startPos = nStartIndex;
     123           0 :                     rBoundary.endPos = nEndIndex;
     124             :                 }
     125           0 :             }
     126             :         }
     127             :         else
     128             :         {
     129           0 :             rBoundary.startPos = nIndex;
     130           0 :             rBoundary.endPos = nIndex;
     131           0 :         }
     132           0 :     }
     133             : 
     134             :     // -----------------------------------------------------------------------------
     135             : 
     136           0 :     sal_Bool OCommonAccessibleText::implGetWordBoundary( i18n::Boundary& rBoundary, sal_Int32 nIndex )
     137             :     {
     138           0 :         sal_Bool bWord = sal_False;
     139           0 :         ::rtl::OUString sText( implGetText() );
     140             : 
     141           0 :         if ( implIsValidIndex( nIndex, sText.getLength() ) )
     142             :         {
     143           0 :             Reference < i18n::XBreakIterator > xBreakIter = implGetBreakIterator();
     144           0 :             if ( xBreakIter.is() )
     145             :             {
     146           0 :                 rBoundary = xBreakIter->getWordBoundary( sText, nIndex, implGetLocale(), i18n::WordType::ANY_WORD, sal_True );
     147             : 
     148             :                 // it's a word, if the first character is an alpha-numeric character
     149           0 :                 Reference< i18n::XCharacterClassification > xCharClass = implGetCharacterClassification();
     150           0 :                 if ( xCharClass.is() )
     151             :                 {
     152           0 :                     sal_Int32 nType = xCharClass->getCharacterType( sText, rBoundary.startPos, implGetLocale() );
     153           0 :                     if ( ( nType & ( i18n::KCharacterType::LETTER | i18n::KCharacterType::DIGIT ) ) != 0 )
     154           0 :                         bWord = sal_True;
     155           0 :                 }
     156           0 :             }
     157             :         }
     158             :         else
     159             :         {
     160           0 :             rBoundary.startPos = nIndex;
     161           0 :             rBoundary.endPos = nIndex;
     162             :         }
     163             : 
     164           0 :         return bWord;
     165             :     }
     166             : 
     167             :     // -----------------------------------------------------------------------------
     168             : 
     169           0 :     void OCommonAccessibleText::implGetSentenceBoundary( i18n::Boundary& rBoundary, sal_Int32 nIndex )
     170             :     {
     171           0 :         ::rtl::OUString sText( implGetText() );
     172             : 
     173           0 :         if ( implIsValidIndex( nIndex, sText.getLength() ) )
     174             :         {
     175           0 :             Locale aLocale = implGetLocale();
     176           0 :             Reference < i18n::XBreakIterator > xBreakIter = implGetBreakIterator();
     177           0 :             if ( xBreakIter.is() )
     178             :             {
     179           0 :                 rBoundary.endPos = xBreakIter->endOfSentence( sText, nIndex, aLocale );
     180           0 :                 rBoundary.startPos = xBreakIter->beginOfSentence( sText, rBoundary.endPos, aLocale );
     181           0 :             }
     182             :         }
     183             :         else
     184             :         {
     185           0 :             rBoundary.startPos = nIndex;
     186           0 :             rBoundary.endPos = nIndex;
     187           0 :         }
     188           0 :     }
     189             : 
     190             :     // -----------------------------------------------------------------------------
     191             : 
     192           0 :     void OCommonAccessibleText::implGetParagraphBoundary( i18n::Boundary& rBoundary, sal_Int32 nIndex )
     193             :     {
     194           0 :         ::rtl::OUString sText( implGetText() );
     195             : 
     196           0 :         if ( implIsValidIndex( nIndex, sText.getLength() ) )
     197             :         {
     198           0 :             rBoundary.startPos = 0;
     199           0 :             rBoundary.endPos = sText.getLength();
     200             : 
     201           0 :             sal_Int32 nFound = sText.lastIndexOf( (sal_Unicode)'\n', nIndex );
     202           0 :             if ( nFound != -1 )
     203           0 :                 rBoundary.startPos = nFound + 1;
     204             : 
     205           0 :             nFound = sText.indexOf( (sal_Unicode)'\n', nIndex );
     206           0 :             if ( nFound != -1 )
     207           0 :                 rBoundary.endPos = nFound + 1;
     208             :         }
     209             :         else
     210             :         {
     211           0 :             rBoundary.startPos = nIndex;
     212           0 :             rBoundary.endPos = nIndex;
     213           0 :         }
     214           0 :     }
     215             : 
     216             :     // -----------------------------------------------------------------------------
     217             : 
     218           0 :     void OCommonAccessibleText::implGetLineBoundary( i18n::Boundary& rBoundary, sal_Int32 nIndex )
     219             :     {
     220           0 :         ::rtl::OUString sText( implGetText() );
     221           0 :         sal_Int32 nLength = sText.getLength();
     222             : 
     223           0 :         if ( implIsValidIndex( nIndex, nLength ) || nIndex == nLength )
     224             :         {
     225           0 :             rBoundary.startPos = 0;
     226           0 :             rBoundary.endPos = nLength;
     227             :         }
     228             :         else
     229             :         {
     230           0 :             rBoundary.startPos = nIndex;
     231           0 :             rBoundary.endPos = nIndex;
     232           0 :         }
     233           0 :     }
     234             : 
     235             :     // -----------------------------------------------------------------------------
     236             : 
     237           0 :     sal_Unicode OCommonAccessibleText::getCharacter( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException)
     238             :     {
     239           0 :         ::rtl::OUString sText( implGetText() );
     240             : 
     241           0 :         if ( !implIsValidIndex( nIndex, sText.getLength() ) )
     242           0 :             throw IndexOutOfBoundsException();
     243             : 
     244           0 :         return sText.getStr()[nIndex];
     245             :     }
     246             : 
     247             :     // -----------------------------------------------------------------------------
     248             : 
     249           0 :     sal_Int32 OCommonAccessibleText::getCharacterCount() throw (RuntimeException)
     250             :     {
     251           0 :         return implGetText().getLength();
     252             :     }
     253             : 
     254             :     // -----------------------------------------------------------------------------
     255             : 
     256           0 :     ::rtl::OUString OCommonAccessibleText::getSelectedText() throw (RuntimeException)
     257             :     {
     258           0 :         ::rtl::OUString sText;
     259             :         sal_Int32 nStartIndex;
     260             :         sal_Int32 nEndIndex;
     261             : 
     262           0 :         implGetSelection( nStartIndex, nEndIndex );
     263             : 
     264             :         try
     265             :         {
     266           0 :             sText = getTextRange( nStartIndex, nEndIndex );
     267             :         }
     268           0 :         catch ( IndexOutOfBoundsException& )
     269             :         {
     270             :         }
     271             : 
     272           0 :         return sText;
     273             :     }
     274             : 
     275             :     // -----------------------------------------------------------------------------
     276             : 
     277           0 :     sal_Int32 OCommonAccessibleText::getSelectionStart() throw (RuntimeException)
     278             :     {
     279             :         sal_Int32 nStartIndex;
     280             :         sal_Int32 nEndIndex;
     281             : 
     282           0 :         implGetSelection( nStartIndex, nEndIndex );
     283             : 
     284           0 :         return nStartIndex;
     285             :     }
     286             : 
     287             :     // -----------------------------------------------------------------------------
     288             : 
     289           0 :     sal_Int32 OCommonAccessibleText::getSelectionEnd() throw (RuntimeException)
     290             :     {
     291             :         sal_Int32 nStartIndex;
     292             :         sal_Int32 nEndIndex;
     293             : 
     294           0 :         implGetSelection( nStartIndex, nEndIndex );
     295             : 
     296           0 :         return nEndIndex;
     297             :     }
     298             : 
     299             :     // -----------------------------------------------------------------------------
     300             : 
     301           0 :     ::rtl::OUString OCommonAccessibleText::getText() throw (RuntimeException)
     302             :     {
     303           0 :         return implGetText();
     304             :     }
     305             : 
     306             :     // -----------------------------------------------------------------------------
     307             : 
     308           0 :     ::rtl::OUString OCommonAccessibleText::getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (IndexOutOfBoundsException, RuntimeException)
     309             :     {
     310           0 :         ::rtl::OUString sText( implGetText() );
     311             : 
     312           0 :         if ( !implIsValidRange( nStartIndex, nEndIndex, sText.getLength() ) )
     313           0 :             throw IndexOutOfBoundsException();
     314             : 
     315           0 :         sal_Int32 nMinIndex = ::std::min( nStartIndex, nEndIndex );
     316           0 :         sal_Int32 nMaxIndex = ::std::max( nStartIndex, nEndIndex );
     317             : 
     318           0 :         return sText.copy( nMinIndex, nMaxIndex - nMinIndex );
     319             :     }
     320             : 
     321             :     // -----------------------------------------------------------------------------
     322             : 
     323           0 :     TextSegment OCommonAccessibleText::getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (IndexOutOfBoundsException, IllegalArgumentException, RuntimeException)
     324             :     {
     325           0 :         ::rtl::OUString sText( implGetText() );
     326           0 :         sal_Int32 nLength = sText.getLength();
     327             : 
     328           0 :         if ( !implIsValidIndex( nIndex, nLength ) && nIndex != nLength )
     329           0 :             throw IndexOutOfBoundsException();
     330             : 
     331           0 :         i18n::Boundary aBoundary;
     332           0 :         TextSegment aResult;
     333           0 :         aResult.SegmentStart = -1;
     334           0 :         aResult.SegmentEnd = -1;
     335             : 
     336           0 :         switch ( aTextType )
     337             :         {
     338             :             case AccessibleTextType::CHARACTER:
     339             :             {
     340           0 :                 if ( implIsValidIndex( nIndex, nLength ) )
     341             :                 {
     342           0 :                     aResult.SegmentText = sText.copy( nIndex, 1 );
     343           0 :                     aResult.SegmentStart = nIndex;
     344           0 :                     aResult.SegmentEnd = nIndex+1;
     345             :                 }
     346             :             }
     347           0 :             break;
     348             :             case AccessibleTextType::GLYPH:
     349             :             {
     350             :                 // get glyph at index
     351           0 :                 implGetGlyphBoundary( aBoundary, nIndex );
     352           0 :                 if ( implIsValidBoundary( aBoundary, nLength ) )
     353             :                 {
     354           0 :                     aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
     355           0 :                     aResult.SegmentStart = aBoundary.startPos;
     356           0 :                     aResult.SegmentEnd = aBoundary.endPos;
     357             :                 }
     358             :             }
     359           0 :             break;
     360             :             case AccessibleTextType::WORD:
     361             :             {
     362             :                 // get word at index
     363           0 :                 sal_Bool bWord = implGetWordBoundary( aBoundary, nIndex );
     364           0 :                 if ( bWord && implIsValidBoundary( aBoundary, nLength ) )
     365             :                 {
     366           0 :                     aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
     367           0 :                     aResult.SegmentStart = aBoundary.startPos;
     368           0 :                     aResult.SegmentEnd = aBoundary.endPos;
     369             :                 }
     370             :             }
     371           0 :             break;
     372             :             case AccessibleTextType::SENTENCE:
     373             :             {
     374             :                 // get sentence at index
     375           0 :                 implGetSentenceBoundary( aBoundary, nIndex );
     376           0 :                 if ( implIsValidBoundary( aBoundary, nLength ) )
     377             :                 {
     378           0 :                     aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
     379           0 :                     aResult.SegmentStart = aBoundary.startPos;
     380           0 :                     aResult.SegmentEnd = aBoundary.endPos;
     381             :                 }
     382             :             }
     383           0 :             break;
     384             :             case AccessibleTextType::PARAGRAPH:
     385             :             {
     386             :                 // get paragraph at index
     387           0 :                 implGetParagraphBoundary( aBoundary, nIndex );
     388           0 :                 if ( implIsValidBoundary( aBoundary, nLength ) )
     389             :                 {
     390           0 :                     aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
     391           0 :                     aResult.SegmentStart = aBoundary.startPos;
     392           0 :                     aResult.SegmentEnd = aBoundary.endPos;
     393             :                 }
     394             :             }
     395           0 :             break;
     396             :             case AccessibleTextType::LINE:
     397             :             {
     398             :                 // get line at index
     399           0 :                 implGetLineBoundary( aBoundary, nIndex );
     400           0 :                 if ( implIsValidBoundary( aBoundary, nLength ) )
     401             :                 {
     402           0 :                     aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
     403           0 :                     aResult.SegmentStart = aBoundary.startPos;
     404           0 :                     aResult.SegmentEnd = aBoundary.endPos;
     405             :                 }
     406             :             }
     407           0 :             break;
     408             :             case AccessibleTextType::ATTRIBUTE_RUN:
     409             :             {
     410             :                 // TODO: implGetAttributeRunBoundary() (incompatible!)
     411             : 
     412           0 :                 aResult.SegmentText = sText;
     413           0 :                 aResult.SegmentStart = 0;
     414           0 :                 aResult.SegmentEnd = nLength;
     415             :             }
     416           0 :             break;
     417             :             default:
     418             :             {
     419             :                 // unknown text type
     420             :             }
     421             :         }
     422             : 
     423           0 :         return aResult;
     424             :     }
     425             : 
     426             :     // -----------------------------------------------------------------------------
     427             : 
     428           0 :     TextSegment OCommonAccessibleText::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (IndexOutOfBoundsException, IllegalArgumentException, RuntimeException)
     429             :     {
     430           0 :         ::rtl::OUString sText( implGetText() );
     431           0 :         sal_Int32 nLength = sText.getLength();
     432             : 
     433           0 :         if ( !implIsValidIndex( nIndex, nLength ) && nIndex != nLength )
     434           0 :             throw IndexOutOfBoundsException();
     435             : 
     436           0 :         i18n::Boundary aBoundary;
     437           0 :         TextSegment aResult;
     438           0 :         aResult.SegmentStart = -1;
     439           0 :         aResult.SegmentEnd = -1;
     440             : 
     441           0 :         switch ( aTextType )
     442             :         {
     443             :             case AccessibleTextType::CHARACTER:
     444             :             {
     445           0 :                 if ( implIsValidIndex( nIndex - 1, nLength ) )
     446             :                 {
     447           0 :                     aResult.SegmentText = sText.copy( nIndex - 1, 1 );
     448           0 :                     aResult.SegmentStart = nIndex-1;
     449           0 :                     aResult.SegmentEnd = nIndex;
     450             :                 }
     451             :             }
     452           0 :             break;
     453             :             case AccessibleTextType::GLYPH:
     454             :             {
     455             :                 // get glyph at index
     456           0 :                 implGetGlyphBoundary( aBoundary, nIndex );
     457             :                 // get previous glyph
     458           0 :                 if ( aBoundary.startPos > 0 )
     459             :                 {
     460           0 :                     implGetGlyphBoundary( aBoundary, aBoundary.startPos - 1 );
     461           0 :                     if ( implIsValidBoundary( aBoundary, nLength ) )
     462             :                     {
     463           0 :                         aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
     464           0 :                         aResult.SegmentStart = aBoundary.startPos;
     465           0 :                         aResult.SegmentEnd = aBoundary.endPos;
     466             :                     }
     467             :                 }
     468             :             }
     469           0 :             break;
     470             :             case AccessibleTextType::WORD:
     471             :             {
     472             :                 // get word at index
     473           0 :                 implGetWordBoundary( aBoundary, nIndex );
     474             :                 // get previous word
     475           0 :                 sal_Bool bWord = sal_False;
     476           0 :                 while ( !bWord && aBoundary.startPos > 0 )
     477           0 :                     bWord = implGetWordBoundary( aBoundary, aBoundary.startPos - 1 );
     478           0 :                 if ( bWord && implIsValidBoundary( aBoundary, nLength ) )
     479             :                 {
     480           0 :                     aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
     481           0 :                     aResult.SegmentStart = aBoundary.startPos;
     482           0 :                     aResult.SegmentEnd = aBoundary.endPos;
     483             :                 }
     484             :             }
     485           0 :             break;
     486             :             case AccessibleTextType::SENTENCE:
     487             :             {
     488             :                 // get sentence at index
     489           0 :                 implGetSentenceBoundary( aBoundary, nIndex );
     490             :                 // get previous sentence
     491           0 :                 if ( aBoundary.startPos > 0 )
     492             :                 {
     493           0 :                     implGetSentenceBoundary( aBoundary, aBoundary.startPos - 1 );
     494           0 :                     if ( implIsValidBoundary( aBoundary, nLength ) )
     495             :                     {
     496           0 :                         aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
     497           0 :                         aResult.SegmentStart = aBoundary.startPos;
     498           0 :                         aResult.SegmentEnd = aBoundary.endPos;
     499             :                     }
     500             :                 }
     501             :             }
     502           0 :             break;
     503             :             case AccessibleTextType::PARAGRAPH:
     504             :             {
     505             :                 // get paragraph at index
     506           0 :                 implGetParagraphBoundary( aBoundary, nIndex );
     507             :                 // get previous paragraph
     508           0 :                 if ( aBoundary.startPos > 0 )
     509             :                 {
     510           0 :                     implGetParagraphBoundary( aBoundary, aBoundary.startPos - 1 );
     511           0 :                     if ( implIsValidBoundary( aBoundary, nLength ) )
     512             :                     {
     513           0 :                         aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
     514           0 :                         aResult.SegmentStart = aBoundary.startPos;
     515           0 :                         aResult.SegmentEnd = aBoundary.endPos;
     516             :                     }
     517             :                 }
     518             :             }
     519           0 :             break;
     520             :             case AccessibleTextType::LINE:
     521             :             {
     522             :                 // get line at index
     523           0 :                 implGetLineBoundary( aBoundary, nIndex );
     524             :                 // get previous line
     525           0 :                 if ( aBoundary.startPos > 0 )
     526             :                 {
     527           0 :                     implGetLineBoundary( aBoundary, aBoundary.startPos - 1 );
     528           0 :                     if ( implIsValidBoundary( aBoundary, nLength ) )
     529             :                     {
     530           0 :                         aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
     531           0 :                         aResult.SegmentStart = aBoundary.startPos;
     532           0 :                         aResult.SegmentEnd = aBoundary.endPos;
     533             :                     }
     534             :                 }
     535             :             }
     536           0 :             break;
     537             :             case AccessibleTextType::ATTRIBUTE_RUN:
     538             :             {
     539             :                 // TODO: implGetAttributeRunBoundary() (incompatible!)
     540             :             }
     541           0 :             break;
     542             :             default:
     543             :             {
     544             :                 // unknown text type
     545             :             }
     546             :         }
     547             : 
     548           0 :         return aResult;
     549             :     }
     550             : 
     551             :     // -----------------------------------------------------------------------------
     552             : 
     553           0 :     TextSegment OCommonAccessibleText::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (IndexOutOfBoundsException, IllegalArgumentException, RuntimeException)
     554             :     {
     555           0 :         ::rtl::OUString sText( implGetText() );
     556           0 :         sal_Int32 nLength = sText.getLength();
     557             : 
     558           0 :         if ( !implIsValidIndex( nIndex, nLength ) && nIndex != nLength )
     559           0 :             throw IndexOutOfBoundsException();
     560             : 
     561           0 :         i18n::Boundary aBoundary;
     562           0 :         TextSegment aResult;
     563           0 :         aResult.SegmentStart = -1;
     564           0 :         aResult.SegmentEnd = -1;
     565             : 
     566           0 :         switch ( aTextType )
     567             :         {
     568             :             case AccessibleTextType::CHARACTER:
     569             :             {
     570           0 :                 if ( implIsValidIndex( nIndex + 1, nLength ) )
     571             :                 {
     572           0 :                     aResult.SegmentText = sText.copy( nIndex + 1, 1 );
     573           0 :                     aResult.SegmentStart = nIndex+1;
     574           0 :                     aResult.SegmentEnd = nIndex+2;
     575             :                 }
     576             :             }
     577           0 :             break;
     578             :             case AccessibleTextType::GLYPH:
     579             :             {
     580             :                 // get glyph at index
     581           0 :                 implGetGlyphBoundary( aBoundary, nIndex );
     582             :                 // get next glyph
     583           0 :                 if ( aBoundary.endPos < nLength )
     584             :                 {
     585           0 :                     implGetGlyphBoundary( aBoundary, aBoundary.endPos );
     586           0 :                     if ( implIsValidBoundary( aBoundary, nLength ) )
     587             :                     {
     588           0 :                         aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
     589           0 :                         aResult.SegmentStart = aBoundary.startPos;
     590           0 :                         aResult.SegmentEnd = aBoundary.endPos;
     591             :                     }
     592             :                 }
     593             :             }
     594           0 :             break;
     595             :             case AccessibleTextType::WORD:
     596             :             {
     597             :                 // get word at index
     598           0 :                 implGetWordBoundary( aBoundary, nIndex );
     599             :                 // get next word
     600           0 :                 sal_Bool bWord = sal_False;
     601           0 :                 while ( !bWord && aBoundary.endPos < nLength )
     602           0 :                     bWord = implGetWordBoundary( aBoundary, aBoundary.endPos );
     603           0 :                 if ( bWord && implIsValidBoundary( aBoundary, nLength ) )
     604             :                 {
     605           0 :                     aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
     606           0 :                     aResult.SegmentStart = aBoundary.startPos;
     607           0 :                     aResult.SegmentEnd = aBoundary.endPos;
     608             :                 }
     609             :             }
     610           0 :             break;
     611             :             case AccessibleTextType::SENTENCE:
     612             :             {
     613             :                 // get sentence at index
     614           0 :                 implGetSentenceBoundary( aBoundary, nIndex );
     615             :                 // get next sentence
     616           0 :                 sal_Int32 nEnd = aBoundary.endPos;
     617           0 :                 sal_Int32 nI = aBoundary.endPos;
     618           0 :                 sal_Bool bFound = sal_False;
     619           0 :                 while ( !bFound && ++nI < nLength )
     620             :                 {
     621           0 :                     implGetSentenceBoundary( aBoundary, nI );
     622           0 :                     bFound = ( aBoundary.endPos > nEnd );
     623             :                 }
     624           0 :                 if ( bFound && implIsValidBoundary( aBoundary, nLength ) )
     625             :                 {
     626           0 :                     aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
     627           0 :                     aResult.SegmentStart = aBoundary.startPos;
     628           0 :                     aResult.SegmentEnd = aBoundary.endPos;
     629             :                 }
     630             :             }
     631           0 :             break;
     632             :             case AccessibleTextType::PARAGRAPH:
     633             :             {
     634             :                 // get paragraph at index
     635           0 :                 implGetParagraphBoundary( aBoundary, nIndex );
     636             :                 // get next paragraph
     637           0 :                 if ( aBoundary.endPos < nLength )
     638             :                 {
     639           0 :                     implGetParagraphBoundary( aBoundary, aBoundary.endPos );
     640           0 :                     if ( implIsValidBoundary( aBoundary, nLength ) )
     641             :                     {
     642           0 :                         aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
     643           0 :                         aResult.SegmentStart = aBoundary.startPos;
     644           0 :                         aResult.SegmentEnd = aBoundary.endPos;
     645             :                     }
     646             :                 }
     647             :             }
     648           0 :             break;
     649             :             case AccessibleTextType::LINE:
     650             :             {
     651             :                 // get line at index
     652           0 :                 implGetLineBoundary( aBoundary, nIndex );
     653             :                 // get next line
     654           0 :                 if ( aBoundary.endPos < nLength )
     655             :                 {
     656           0 :                     implGetLineBoundary( aBoundary, aBoundary.endPos );
     657           0 :                     if ( implIsValidBoundary( aBoundary, nLength ) )
     658             :                     {
     659           0 :                         aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
     660           0 :                         aResult.SegmentStart = aBoundary.startPos;
     661           0 :                         aResult.SegmentEnd = aBoundary.endPos;
     662             :                     }
     663             :                 }
     664             :             }
     665           0 :             break;
     666             :             case AccessibleTextType::ATTRIBUTE_RUN:
     667             :             {
     668             :                 // TODO: implGetAttributeRunBoundary() (incompatible!)
     669             :             }
     670           0 :             break;
     671             :             default:
     672             :             {
     673             :                 // unknown text type
     674             :             }
     675             :         }
     676             : 
     677           0 :         return aResult;
     678             :     }
     679             : 
     680             :     // -----------------------------------------------------------------------------
     681           0 :     bool OCommonAccessibleText::implInitTextChangedEvent(
     682             :         const rtl::OUString& rOldString,
     683             :         const rtl::OUString& rNewString,
     684             :         ::com::sun::star::uno::Any& rDeleted,
     685             :         ::com::sun::star::uno::Any& rInserted) // throw()
     686             :     {
     687           0 :         sal_uInt32 nLenOld = rOldString.getLength();
     688           0 :         sal_uInt32 nLenNew = rNewString.getLength();
     689             : 
     690             :         // equal
     691           0 :         if ((0 == nLenOld) && (0 == nLenNew))
     692           0 :             return false;
     693             : 
     694           0 :         TextSegment aDeletedText;
     695           0 :         TextSegment aInsertedText;
     696             : 
     697           0 :         aDeletedText.SegmentStart = -1;
     698           0 :         aDeletedText.SegmentEnd = -1;
     699           0 :         aInsertedText.SegmentStart = -1;
     700           0 :         aInsertedText.SegmentEnd = -1;
     701             : 
     702             :         // insert only
     703           0 :         if ((0 == nLenOld) && (nLenNew > 0))
     704             :         {
     705           0 :             aInsertedText.SegmentStart = 0;
     706           0 :             aInsertedText.SegmentEnd = nLenNew;
     707           0 :             aInsertedText.SegmentText = rNewString.copy( aInsertedText.SegmentStart, aInsertedText.SegmentEnd - aInsertedText.SegmentStart );
     708             : 
     709           0 :             rInserted <<= aInsertedText;
     710           0 :             return true;
     711             :         }
     712             : 
     713             :         // delete only
     714           0 :         if ((nLenOld > 0) && (0 == nLenNew))
     715             :         {
     716           0 :             aDeletedText.SegmentStart = 0;
     717           0 :             aDeletedText.SegmentEnd = nLenOld;
     718           0 :             aDeletedText.SegmentText = rOldString.copy( aDeletedText.SegmentStart, aDeletedText.SegmentEnd - aDeletedText.SegmentStart );
     719             : 
     720           0 :             rDeleted <<= aDeletedText;
     721           0 :             return true;
     722             :         }
     723             : 
     724           0 :         const sal_Unicode* pFirstDiffOld = rOldString.getStr();
     725           0 :         const sal_Unicode* pLastDiffOld  = rOldString.getStr() + nLenOld;
     726           0 :         const sal_Unicode* pFirstDiffNew = rNewString.getStr();
     727           0 :         const sal_Unicode* pLastDiffNew  = rNewString.getStr() + nLenNew;
     728             : 
     729             :         // find first difference
     730           0 :         while ((*pFirstDiffOld == *pFirstDiffNew) &&
     731             :                (pFirstDiffOld  <  pLastDiffOld) &&
     732             :                (pFirstDiffNew  <  pLastDiffNew))
     733             :         {
     734           0 :             pFirstDiffOld++;
     735           0 :             pFirstDiffNew++;
     736             :         }
     737             : 
     738             :         // equality test
     739           0 :         if ((0 == *pFirstDiffOld) && (0 == *pFirstDiffNew))
     740           0 :             return false;
     741             : 
     742             :         // find last difference
     743           0 :         while ( ( pLastDiffOld > pFirstDiffOld) &&
     744             :                 ( pLastDiffNew > pFirstDiffNew) &&
     745           0 :                 (pLastDiffOld[-1]  == pLastDiffNew[-1]))
     746             :         {
     747           0 :             pLastDiffOld--;
     748           0 :             pLastDiffNew--;
     749             :         }
     750             : 
     751           0 :         if (pFirstDiffOld < pLastDiffOld)
     752             :         {
     753           0 :             aDeletedText.SegmentStart = pFirstDiffOld - rOldString.getStr();
     754           0 :             aDeletedText.SegmentEnd = pLastDiffOld  - rOldString.getStr();
     755           0 :             aDeletedText.SegmentText = rOldString.copy( aDeletedText.SegmentStart, aDeletedText.SegmentEnd - aDeletedText.SegmentStart );
     756             : 
     757           0 :             rDeleted <<= aDeletedText;
     758             :         }
     759             : 
     760           0 :         if (pFirstDiffNew < pLastDiffNew)
     761             :         {
     762           0 :             aInsertedText.SegmentStart = pFirstDiffNew - rNewString.getStr();
     763           0 :             aInsertedText.SegmentEnd = pLastDiffNew  - rNewString.getStr();
     764           0 :             aInsertedText.SegmentText = rNewString.copy( aInsertedText.SegmentStart, aInsertedText.SegmentEnd - aInsertedText.SegmentStart );
     765             : 
     766           0 :             rInserted <<= aInsertedText;
     767             :         }
     768           0 :         return true;
     769             :     }
     770             : 
     771             :     //==============================================================================
     772             :     // OAccessibleTextHelper
     773             :     //==============================================================================
     774             : 
     775           0 :     OAccessibleTextHelper::OAccessibleTextHelper( IMutex* _pExternalLock )
     776           0 :         :OAccessibleExtendedComponentHelper( _pExternalLock )
     777             :     {
     778           0 :     }
     779             : 
     780             :     // -----------------------------------------------------------------------------
     781             :     // XInterface
     782             :     // -----------------------------------------------------------------------------
     783             : 
     784           0 :     IMPLEMENT_FORWARD_XINTERFACE2( OAccessibleTextHelper, OAccessibleExtendedComponentHelper, OAccessibleTextHelper_Base )
     785             : 
     786             :     // -----------------------------------------------------------------------------
     787             :     // XTypeProvider
     788             :     // -----------------------------------------------------------------------------
     789             : 
     790           0 :     IMPLEMENT_FORWARD_XTYPEPROVIDER2( OAccessibleTextHelper, OAccessibleExtendedComponentHelper, OAccessibleTextHelper_Base )
     791             : 
     792             :     // -----------------------------------------------------------------------------
     793             :     // XAccessibleText
     794             :     // -----------------------------------------------------------------------------
     795             : 
     796           0 :     sal_Unicode OAccessibleTextHelper::getCharacter( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException)
     797             :     {
     798           0 :         OExternalLockGuard aGuard( this );
     799             : 
     800           0 :         return OCommonAccessibleText::getCharacter( nIndex );
     801             :     }
     802             : 
     803             :     // -----------------------------------------------------------------------------
     804             : 
     805           0 :     sal_Int32 OAccessibleTextHelper::getCharacterCount() throw (RuntimeException)
     806             :     {
     807           0 :         OExternalLockGuard aGuard( this );
     808             : 
     809           0 :         return OCommonAccessibleText::getCharacterCount();
     810             :     }
     811             : 
     812             :     // -----------------------------------------------------------------------------
     813             : 
     814           0 :     ::rtl::OUString OAccessibleTextHelper::getSelectedText() throw (RuntimeException)
     815             :     {
     816           0 :         OExternalLockGuard aGuard( this );
     817             : 
     818           0 :         return OCommonAccessibleText::getSelectedText();
     819             :     }
     820             : 
     821             :     // -----------------------------------------------------------------------------
     822             : 
     823           0 :     sal_Int32 OAccessibleTextHelper::getSelectionStart() throw (RuntimeException)
     824             :     {
     825           0 :         OExternalLockGuard aGuard( this );
     826             : 
     827           0 :         return OCommonAccessibleText::getSelectionStart();
     828             :     }
     829             : 
     830             :     // -----------------------------------------------------------------------------
     831             : 
     832           0 :     sal_Int32 OAccessibleTextHelper::getSelectionEnd() throw (RuntimeException)
     833             :     {
     834           0 :         OExternalLockGuard aGuard( this );
     835             : 
     836           0 :         return OCommonAccessibleText::getSelectionEnd();
     837             :     }
     838             : 
     839             :     // -----------------------------------------------------------------------------
     840             : 
     841           0 :     ::rtl::OUString OAccessibleTextHelper::getText() throw (RuntimeException)
     842             :     {
     843           0 :         OExternalLockGuard aGuard( this );
     844             : 
     845           0 :         return OCommonAccessibleText::getText();
     846             :     }
     847             : 
     848             :     // -----------------------------------------------------------------------------
     849             : 
     850           0 :     ::rtl::OUString OAccessibleTextHelper::getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (IndexOutOfBoundsException, RuntimeException)
     851             :     {
     852           0 :         OExternalLockGuard aGuard( this );
     853             : 
     854           0 :         return OCommonAccessibleText::getTextRange( nStartIndex, nEndIndex );
     855             :     }
     856             : 
     857             :     // -----------------------------------------------------------------------------
     858             : 
     859           0 :     TextSegment OAccessibleTextHelper::getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (IndexOutOfBoundsException, IllegalArgumentException, RuntimeException)
     860             :     {
     861           0 :         OExternalLockGuard aGuard( this );
     862             : 
     863           0 :         return OCommonAccessibleText::getTextAtIndex( nIndex, aTextType );
     864             :     }
     865             : 
     866             :     // -----------------------------------------------------------------------------
     867             : 
     868           0 :     TextSegment OAccessibleTextHelper::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (IndexOutOfBoundsException, IllegalArgumentException, RuntimeException)
     869             :     {
     870           0 :         OExternalLockGuard aGuard( this );
     871             : 
     872           0 :         return OCommonAccessibleText::getTextBeforeIndex( nIndex, aTextType );
     873             :     }
     874             : 
     875             :     // -----------------------------------------------------------------------------
     876             : 
     877           0 :     TextSegment OAccessibleTextHelper::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (IndexOutOfBoundsException, IllegalArgumentException, RuntimeException)
     878             :     {
     879           0 :         OExternalLockGuard aGuard( this );
     880             : 
     881           0 :         return OCommonAccessibleText::getTextBehindIndex( nIndex, aTextType );
     882             :     }
     883             : 
     884             :     // -----------------------------------------------------------------------------
     885             : 
     886             : //..............................................................................
     887             : }   // namespace comphelper
     888             : //..............................................................................
     889             : 
     890             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10