Version 4.0.0.1, tag libreoffice-4.0.0.1
[LibreOffice.git] / comphelper / source / misc / accessibletexthelper.cxx
blobab77650a77101f1d02e897d6a081d48da40ceec1
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <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>
30 #include <algorithm>
32 //..............................................................................
33 namespace comphelper
35 //..............................................................................
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;
43 //==============================================================================
44 // OCommonAccessibleText
45 //==============================================================================
47 OCommonAccessibleText::OCommonAccessibleText()
51 // -----------------------------------------------------------------------------
53 OCommonAccessibleText::~OCommonAccessibleText()
57 // -----------------------------------------------------------------------------
59 Reference < i18n::XBreakIterator > OCommonAccessibleText::implGetBreakIterator()
61 if ( !m_xBreakIter.is() )
63 Reference< uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
64 m_xBreakIter = i18n::BreakIterator::create(xContext);
67 return m_xBreakIter;
70 // -----------------------------------------------------------------------------
72 Reference < i18n::XCharacterClassification > OCommonAccessibleText::implGetCharacterClassification()
74 if ( !m_xCharClass.is() )
76 m_xCharClass = i18n::CharacterClassification::create( ::comphelper::getProcessComponentContext() );
79 return m_xCharClass;
82 // -----------------------------------------------------------------------------
84 sal_Bool OCommonAccessibleText::implIsValidBoundary( i18n::Boundary& rBoundary, sal_Int32 nLength )
86 return ( rBoundary.startPos >= 0 ) && ( rBoundary.startPos < nLength ) && ( rBoundary.endPos >= 0 ) && ( rBoundary.endPos <= nLength );
89 // -----------------------------------------------------------------------------
91 sal_Bool OCommonAccessibleText::implIsValidIndex( sal_Int32 nIndex, sal_Int32 nLength )
93 return ( nIndex >= 0 ) && ( nIndex < nLength );
96 // -----------------------------------------------------------------------------
98 sal_Bool OCommonAccessibleText::implIsValidRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex, sal_Int32 nLength )
100 return ( nStartIndex >= 0 ) && ( nStartIndex <= nLength ) && ( nEndIndex >= 0 ) && ( nEndIndex <= nLength );
103 // -----------------------------------------------------------------------------
105 void OCommonAccessibleText::implGetGlyphBoundary( i18n::Boundary& rBoundary, sal_Int32 nIndex )
107 ::rtl::OUString sText( implGetText() );
109 if ( implIsValidIndex( nIndex, sText.getLength() ) )
111 Reference < i18n::XBreakIterator > xBreakIter = implGetBreakIterator();
112 if ( xBreakIter.is() )
114 sal_Int32 nCount = 1;
115 sal_Int32 nDone;
116 sal_Int32 nStartIndex = xBreakIter->previousCharacters( sText, nIndex, implGetLocale(), i18n::CharacterIteratorMode::SKIPCELL, nCount, nDone );
117 if ( nDone != 0 )
118 nStartIndex = xBreakIter->nextCharacters( sText, nStartIndex, implGetLocale(), i18n::CharacterIteratorMode::SKIPCELL, nCount, nDone );
119 sal_Int32 nEndIndex = xBreakIter->nextCharacters( sText, nStartIndex, implGetLocale(), i18n::CharacterIteratorMode::SKIPCELL, nCount, nDone );
120 if ( nDone != 0 )
122 rBoundary.startPos = nStartIndex;
123 rBoundary.endPos = nEndIndex;
127 else
129 rBoundary.startPos = nIndex;
130 rBoundary.endPos = nIndex;
134 // -----------------------------------------------------------------------------
136 sal_Bool OCommonAccessibleText::implGetWordBoundary( i18n::Boundary& rBoundary, sal_Int32 nIndex )
138 sal_Bool bWord = sal_False;
139 ::rtl::OUString sText( implGetText() );
141 if ( implIsValidIndex( nIndex, sText.getLength() ) )
143 Reference < i18n::XBreakIterator > xBreakIter = implGetBreakIterator();
144 if ( xBreakIter.is() )
146 rBoundary = xBreakIter->getWordBoundary( sText, nIndex, implGetLocale(), i18n::WordType::ANY_WORD, sal_True );
148 // it's a word, if the first character is an alpha-numeric character
149 Reference< i18n::XCharacterClassification > xCharClass = implGetCharacterClassification();
150 if ( xCharClass.is() )
152 sal_Int32 nType = xCharClass->getCharacterType( sText, rBoundary.startPos, implGetLocale() );
153 if ( ( nType & ( i18n::KCharacterType::LETTER | i18n::KCharacterType::DIGIT ) ) != 0 )
154 bWord = sal_True;
158 else
160 rBoundary.startPos = nIndex;
161 rBoundary.endPos = nIndex;
164 return bWord;
167 // -----------------------------------------------------------------------------
169 void OCommonAccessibleText::implGetSentenceBoundary( i18n::Boundary& rBoundary, sal_Int32 nIndex )
171 ::rtl::OUString sText( implGetText() );
173 if ( implIsValidIndex( nIndex, sText.getLength() ) )
175 Locale aLocale = implGetLocale();
176 Reference < i18n::XBreakIterator > xBreakIter = implGetBreakIterator();
177 if ( xBreakIter.is() )
179 rBoundary.endPos = xBreakIter->endOfSentence( sText, nIndex, aLocale );
180 rBoundary.startPos = xBreakIter->beginOfSentence( sText, rBoundary.endPos, aLocale );
183 else
185 rBoundary.startPos = nIndex;
186 rBoundary.endPos = nIndex;
190 // -----------------------------------------------------------------------------
192 void OCommonAccessibleText::implGetParagraphBoundary( i18n::Boundary& rBoundary, sal_Int32 nIndex )
194 ::rtl::OUString sText( implGetText() );
196 if ( implIsValidIndex( nIndex, sText.getLength() ) )
198 rBoundary.startPos = 0;
199 rBoundary.endPos = sText.getLength();
201 sal_Int32 nFound = sText.lastIndexOf( (sal_Unicode)'\n', nIndex );
202 if ( nFound != -1 )
203 rBoundary.startPos = nFound + 1;
205 nFound = sText.indexOf( (sal_Unicode)'\n', nIndex );
206 if ( nFound != -1 )
207 rBoundary.endPos = nFound + 1;
209 else
211 rBoundary.startPos = nIndex;
212 rBoundary.endPos = nIndex;
216 // -----------------------------------------------------------------------------
218 void OCommonAccessibleText::implGetLineBoundary( i18n::Boundary& rBoundary, sal_Int32 nIndex )
220 ::rtl::OUString sText( implGetText() );
221 sal_Int32 nLength = sText.getLength();
223 if ( implIsValidIndex( nIndex, nLength ) || nIndex == nLength )
225 rBoundary.startPos = 0;
226 rBoundary.endPos = nLength;
228 else
230 rBoundary.startPos = nIndex;
231 rBoundary.endPos = nIndex;
235 // -----------------------------------------------------------------------------
237 sal_Unicode OCommonAccessibleText::getCharacter( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException)
239 ::rtl::OUString sText( implGetText() );
241 if ( !implIsValidIndex( nIndex, sText.getLength() ) )
242 throw IndexOutOfBoundsException();
244 return sText.getStr()[nIndex];
247 // -----------------------------------------------------------------------------
249 sal_Int32 OCommonAccessibleText::getCharacterCount() throw (RuntimeException)
251 return implGetText().getLength();
254 // -----------------------------------------------------------------------------
256 ::rtl::OUString OCommonAccessibleText::getSelectedText() throw (RuntimeException)
258 ::rtl::OUString sText;
259 sal_Int32 nStartIndex;
260 sal_Int32 nEndIndex;
262 implGetSelection( nStartIndex, nEndIndex );
266 sText = getTextRange( nStartIndex, nEndIndex );
268 catch ( IndexOutOfBoundsException& )
272 return sText;
275 // -----------------------------------------------------------------------------
277 sal_Int32 OCommonAccessibleText::getSelectionStart() throw (RuntimeException)
279 sal_Int32 nStartIndex;
280 sal_Int32 nEndIndex;
282 implGetSelection( nStartIndex, nEndIndex );
284 return nStartIndex;
287 // -----------------------------------------------------------------------------
289 sal_Int32 OCommonAccessibleText::getSelectionEnd() throw (RuntimeException)
291 sal_Int32 nStartIndex;
292 sal_Int32 nEndIndex;
294 implGetSelection( nStartIndex, nEndIndex );
296 return nEndIndex;
299 // -----------------------------------------------------------------------------
301 ::rtl::OUString OCommonAccessibleText::getText() throw (RuntimeException)
303 return implGetText();
306 // -----------------------------------------------------------------------------
308 ::rtl::OUString OCommonAccessibleText::getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (IndexOutOfBoundsException, RuntimeException)
310 ::rtl::OUString sText( implGetText() );
312 if ( !implIsValidRange( nStartIndex, nEndIndex, sText.getLength() ) )
313 throw IndexOutOfBoundsException();
315 sal_Int32 nMinIndex = ::std::min( nStartIndex, nEndIndex );
316 sal_Int32 nMaxIndex = ::std::max( nStartIndex, nEndIndex );
318 return sText.copy( nMinIndex, nMaxIndex - nMinIndex );
321 // -----------------------------------------------------------------------------
323 TextSegment OCommonAccessibleText::getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (IndexOutOfBoundsException, IllegalArgumentException, RuntimeException)
325 ::rtl::OUString sText( implGetText() );
326 sal_Int32 nLength = sText.getLength();
328 if ( !implIsValidIndex( nIndex, nLength ) && nIndex != nLength )
329 throw IndexOutOfBoundsException();
331 i18n::Boundary aBoundary;
332 TextSegment aResult;
333 aResult.SegmentStart = -1;
334 aResult.SegmentEnd = -1;
336 switch ( aTextType )
338 case AccessibleTextType::CHARACTER:
340 if ( implIsValidIndex( nIndex, nLength ) )
342 aResult.SegmentText = sText.copy( nIndex, 1 );
343 aResult.SegmentStart = nIndex;
344 aResult.SegmentEnd = nIndex+1;
347 break;
348 case AccessibleTextType::GLYPH:
350 // get glyph at index
351 implGetGlyphBoundary( aBoundary, nIndex );
352 if ( implIsValidBoundary( aBoundary, nLength ) )
354 aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
355 aResult.SegmentStart = aBoundary.startPos;
356 aResult.SegmentEnd = aBoundary.endPos;
359 break;
360 case AccessibleTextType::WORD:
362 // get word at index
363 sal_Bool bWord = implGetWordBoundary( aBoundary, nIndex );
364 if ( bWord && implIsValidBoundary( aBoundary, nLength ) )
366 aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
367 aResult.SegmentStart = aBoundary.startPos;
368 aResult.SegmentEnd = aBoundary.endPos;
371 break;
372 case AccessibleTextType::SENTENCE:
374 // get sentence at index
375 implGetSentenceBoundary( aBoundary, nIndex );
376 if ( implIsValidBoundary( aBoundary, nLength ) )
378 aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
379 aResult.SegmentStart = aBoundary.startPos;
380 aResult.SegmentEnd = aBoundary.endPos;
383 break;
384 case AccessibleTextType::PARAGRAPH:
386 // get paragraph at index
387 implGetParagraphBoundary( aBoundary, nIndex );
388 if ( implIsValidBoundary( aBoundary, nLength ) )
390 aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
391 aResult.SegmentStart = aBoundary.startPos;
392 aResult.SegmentEnd = aBoundary.endPos;
395 break;
396 case AccessibleTextType::LINE:
398 // get line at index
399 implGetLineBoundary( aBoundary, nIndex );
400 if ( implIsValidBoundary( aBoundary, nLength ) )
402 aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
403 aResult.SegmentStart = aBoundary.startPos;
404 aResult.SegmentEnd = aBoundary.endPos;
407 break;
408 case AccessibleTextType::ATTRIBUTE_RUN:
410 // TODO: implGetAttributeRunBoundary() (incompatible!)
412 aResult.SegmentText = sText;
413 aResult.SegmentStart = 0;
414 aResult.SegmentEnd = nLength;
416 break;
417 default:
419 // unknown text type
423 return aResult;
426 // -----------------------------------------------------------------------------
428 TextSegment OCommonAccessibleText::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (IndexOutOfBoundsException, IllegalArgumentException, RuntimeException)
430 ::rtl::OUString sText( implGetText() );
431 sal_Int32 nLength = sText.getLength();
433 if ( !implIsValidIndex( nIndex, nLength ) && nIndex != nLength )
434 throw IndexOutOfBoundsException();
436 i18n::Boundary aBoundary;
437 TextSegment aResult;
438 aResult.SegmentStart = -1;
439 aResult.SegmentEnd = -1;
441 switch ( aTextType )
443 case AccessibleTextType::CHARACTER:
445 if ( implIsValidIndex( nIndex - 1, nLength ) )
447 aResult.SegmentText = sText.copy( nIndex - 1, 1 );
448 aResult.SegmentStart = nIndex-1;
449 aResult.SegmentEnd = nIndex;
452 break;
453 case AccessibleTextType::GLYPH:
455 // get glyph at index
456 implGetGlyphBoundary( aBoundary, nIndex );
457 // get previous glyph
458 if ( aBoundary.startPos > 0 )
460 implGetGlyphBoundary( aBoundary, aBoundary.startPos - 1 );
461 if ( implIsValidBoundary( aBoundary, nLength ) )
463 aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
464 aResult.SegmentStart = aBoundary.startPos;
465 aResult.SegmentEnd = aBoundary.endPos;
469 break;
470 case AccessibleTextType::WORD:
472 // get word at index
473 implGetWordBoundary( aBoundary, nIndex );
474 // get previous word
475 sal_Bool bWord = sal_False;
476 while ( !bWord && aBoundary.startPos > 0 )
477 bWord = implGetWordBoundary( aBoundary, aBoundary.startPos - 1 );
478 if ( bWord && implIsValidBoundary( aBoundary, nLength ) )
480 aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
481 aResult.SegmentStart = aBoundary.startPos;
482 aResult.SegmentEnd = aBoundary.endPos;
485 break;
486 case AccessibleTextType::SENTENCE:
488 // get sentence at index
489 implGetSentenceBoundary( aBoundary, nIndex );
490 // get previous sentence
491 if ( aBoundary.startPos > 0 )
493 implGetSentenceBoundary( aBoundary, aBoundary.startPos - 1 );
494 if ( implIsValidBoundary( aBoundary, nLength ) )
496 aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
497 aResult.SegmentStart = aBoundary.startPos;
498 aResult.SegmentEnd = aBoundary.endPos;
502 break;
503 case AccessibleTextType::PARAGRAPH:
505 // get paragraph at index
506 implGetParagraphBoundary( aBoundary, nIndex );
507 // get previous paragraph
508 if ( aBoundary.startPos > 0 )
510 implGetParagraphBoundary( aBoundary, aBoundary.startPos - 1 );
511 if ( implIsValidBoundary( aBoundary, nLength ) )
513 aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
514 aResult.SegmentStart = aBoundary.startPos;
515 aResult.SegmentEnd = aBoundary.endPos;
519 break;
520 case AccessibleTextType::LINE:
522 // get line at index
523 implGetLineBoundary( aBoundary, nIndex );
524 // get previous line
525 if ( aBoundary.startPos > 0 )
527 implGetLineBoundary( aBoundary, aBoundary.startPos - 1 );
528 if ( implIsValidBoundary( aBoundary, nLength ) )
530 aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
531 aResult.SegmentStart = aBoundary.startPos;
532 aResult.SegmentEnd = aBoundary.endPos;
536 break;
537 case AccessibleTextType::ATTRIBUTE_RUN:
539 // TODO: implGetAttributeRunBoundary() (incompatible!)
541 break;
542 default:
544 // unknown text type
548 return aResult;
551 // -----------------------------------------------------------------------------
553 TextSegment OCommonAccessibleText::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (IndexOutOfBoundsException, IllegalArgumentException, RuntimeException)
555 ::rtl::OUString sText( implGetText() );
556 sal_Int32 nLength = sText.getLength();
558 if ( !implIsValidIndex( nIndex, nLength ) && nIndex != nLength )
559 throw IndexOutOfBoundsException();
561 i18n::Boundary aBoundary;
562 TextSegment aResult;
563 aResult.SegmentStart = -1;
564 aResult.SegmentEnd = -1;
566 switch ( aTextType )
568 case AccessibleTextType::CHARACTER:
570 if ( implIsValidIndex( nIndex + 1, nLength ) )
572 aResult.SegmentText = sText.copy( nIndex + 1, 1 );
573 aResult.SegmentStart = nIndex+1;
574 aResult.SegmentEnd = nIndex+2;
577 break;
578 case AccessibleTextType::GLYPH:
580 // get glyph at index
581 implGetGlyphBoundary( aBoundary, nIndex );
582 // get next glyph
583 if ( aBoundary.endPos < nLength )
585 implGetGlyphBoundary( aBoundary, aBoundary.endPos );
586 if ( implIsValidBoundary( aBoundary, nLength ) )
588 aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
589 aResult.SegmentStart = aBoundary.startPos;
590 aResult.SegmentEnd = aBoundary.endPos;
594 break;
595 case AccessibleTextType::WORD:
597 // get word at index
598 implGetWordBoundary( aBoundary, nIndex );
599 // get next word
600 sal_Bool bWord = sal_False;
601 while ( !bWord && aBoundary.endPos < nLength )
602 bWord = implGetWordBoundary( aBoundary, aBoundary.endPos );
603 if ( bWord && implIsValidBoundary( aBoundary, nLength ) )
605 aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
606 aResult.SegmentStart = aBoundary.startPos;
607 aResult.SegmentEnd = aBoundary.endPos;
610 break;
611 case AccessibleTextType::SENTENCE:
613 // get sentence at index
614 implGetSentenceBoundary( aBoundary, nIndex );
615 // get next sentence
616 sal_Int32 nEnd = aBoundary.endPos;
617 sal_Int32 nI = aBoundary.endPos;
618 sal_Bool bFound = sal_False;
619 while ( !bFound && ++nI < nLength )
621 implGetSentenceBoundary( aBoundary, nI );
622 bFound = ( aBoundary.endPos > nEnd );
624 if ( bFound && implIsValidBoundary( aBoundary, nLength ) )
626 aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
627 aResult.SegmentStart = aBoundary.startPos;
628 aResult.SegmentEnd = aBoundary.endPos;
631 break;
632 case AccessibleTextType::PARAGRAPH:
634 // get paragraph at index
635 implGetParagraphBoundary( aBoundary, nIndex );
636 // get next paragraph
637 if ( aBoundary.endPos < nLength )
639 implGetParagraphBoundary( aBoundary, aBoundary.endPos );
640 if ( implIsValidBoundary( aBoundary, nLength ) )
642 aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
643 aResult.SegmentStart = aBoundary.startPos;
644 aResult.SegmentEnd = aBoundary.endPos;
648 break;
649 case AccessibleTextType::LINE:
651 // get line at index
652 implGetLineBoundary( aBoundary, nIndex );
653 // get next line
654 if ( aBoundary.endPos < nLength )
656 implGetLineBoundary( aBoundary, aBoundary.endPos );
657 if ( implIsValidBoundary( aBoundary, nLength ) )
659 aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
660 aResult.SegmentStart = aBoundary.startPos;
661 aResult.SegmentEnd = aBoundary.endPos;
665 break;
666 case AccessibleTextType::ATTRIBUTE_RUN:
668 // TODO: implGetAttributeRunBoundary() (incompatible!)
670 break;
671 default:
673 // unknown text type
677 return aResult;
680 // -----------------------------------------------------------------------------
681 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()
687 sal_uInt32 nLenOld = rOldString.getLength();
688 sal_uInt32 nLenNew = rNewString.getLength();
690 // equal
691 if ((0 == nLenOld) && (0 == nLenNew))
692 return false;
694 TextSegment aDeletedText;
695 TextSegment aInsertedText;
697 aDeletedText.SegmentStart = -1;
698 aDeletedText.SegmentEnd = -1;
699 aInsertedText.SegmentStart = -1;
700 aInsertedText.SegmentEnd = -1;
702 // insert only
703 if ((0 == nLenOld) && (nLenNew > 0))
705 aInsertedText.SegmentStart = 0;
706 aInsertedText.SegmentEnd = nLenNew;
707 aInsertedText.SegmentText = rNewString.copy( aInsertedText.SegmentStart, aInsertedText.SegmentEnd - aInsertedText.SegmentStart );
709 rInserted <<= aInsertedText;
710 return true;
713 // delete only
714 if ((nLenOld > 0) && (0 == nLenNew))
716 aDeletedText.SegmentStart = 0;
717 aDeletedText.SegmentEnd = nLenOld;
718 aDeletedText.SegmentText = rOldString.copy( aDeletedText.SegmentStart, aDeletedText.SegmentEnd - aDeletedText.SegmentStart );
720 rDeleted <<= aDeletedText;
721 return true;
724 const sal_Unicode* pFirstDiffOld = rOldString.getStr();
725 const sal_Unicode* pLastDiffOld = rOldString.getStr() + nLenOld;
726 const sal_Unicode* pFirstDiffNew = rNewString.getStr();
727 const sal_Unicode* pLastDiffNew = rNewString.getStr() + nLenNew;
729 // find first difference
730 while ((*pFirstDiffOld == *pFirstDiffNew) &&
731 (pFirstDiffOld < pLastDiffOld) &&
732 (pFirstDiffNew < pLastDiffNew))
734 pFirstDiffOld++;
735 pFirstDiffNew++;
738 // equality test
739 if ((0 == *pFirstDiffOld) && (0 == *pFirstDiffNew))
740 return false;
742 // find last difference
743 while ( ( pLastDiffOld > pFirstDiffOld) &&
744 ( pLastDiffNew > pFirstDiffNew) &&
745 (pLastDiffOld[-1] == pLastDiffNew[-1]))
747 pLastDiffOld--;
748 pLastDiffNew--;
751 if (pFirstDiffOld < pLastDiffOld)
753 aDeletedText.SegmentStart = pFirstDiffOld - rOldString.getStr();
754 aDeletedText.SegmentEnd = pLastDiffOld - rOldString.getStr();
755 aDeletedText.SegmentText = rOldString.copy( aDeletedText.SegmentStart, aDeletedText.SegmentEnd - aDeletedText.SegmentStart );
757 rDeleted <<= aDeletedText;
760 if (pFirstDiffNew < pLastDiffNew)
762 aInsertedText.SegmentStart = pFirstDiffNew - rNewString.getStr();
763 aInsertedText.SegmentEnd = pLastDiffNew - rNewString.getStr();
764 aInsertedText.SegmentText = rNewString.copy( aInsertedText.SegmentStart, aInsertedText.SegmentEnd - aInsertedText.SegmentStart );
766 rInserted <<= aInsertedText;
768 return true;
771 //==============================================================================
772 // OAccessibleTextHelper
773 //==============================================================================
775 OAccessibleTextHelper::OAccessibleTextHelper( IMutex* _pExternalLock )
776 :OAccessibleExtendedComponentHelper( _pExternalLock )
780 // -----------------------------------------------------------------------------
781 // XInterface
782 // -----------------------------------------------------------------------------
784 IMPLEMENT_FORWARD_XINTERFACE2( OAccessibleTextHelper, OAccessibleExtendedComponentHelper, OAccessibleTextHelper_Base )
786 // -----------------------------------------------------------------------------
787 // XTypeProvider
788 // -----------------------------------------------------------------------------
790 IMPLEMENT_FORWARD_XTYPEPROVIDER2( OAccessibleTextHelper, OAccessibleExtendedComponentHelper, OAccessibleTextHelper_Base )
792 // -----------------------------------------------------------------------------
793 // XAccessibleText
794 // -----------------------------------------------------------------------------
796 sal_Unicode OAccessibleTextHelper::getCharacter( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException)
798 OExternalLockGuard aGuard( this );
800 return OCommonAccessibleText::getCharacter( nIndex );
803 // -----------------------------------------------------------------------------
805 sal_Int32 OAccessibleTextHelper::getCharacterCount() throw (RuntimeException)
807 OExternalLockGuard aGuard( this );
809 return OCommonAccessibleText::getCharacterCount();
812 // -----------------------------------------------------------------------------
814 ::rtl::OUString OAccessibleTextHelper::getSelectedText() throw (RuntimeException)
816 OExternalLockGuard aGuard( this );
818 return OCommonAccessibleText::getSelectedText();
821 // -----------------------------------------------------------------------------
823 sal_Int32 OAccessibleTextHelper::getSelectionStart() throw (RuntimeException)
825 OExternalLockGuard aGuard( this );
827 return OCommonAccessibleText::getSelectionStart();
830 // -----------------------------------------------------------------------------
832 sal_Int32 OAccessibleTextHelper::getSelectionEnd() throw (RuntimeException)
834 OExternalLockGuard aGuard( this );
836 return OCommonAccessibleText::getSelectionEnd();
839 // -----------------------------------------------------------------------------
841 ::rtl::OUString OAccessibleTextHelper::getText() throw (RuntimeException)
843 OExternalLockGuard aGuard( this );
845 return OCommonAccessibleText::getText();
848 // -----------------------------------------------------------------------------
850 ::rtl::OUString OAccessibleTextHelper::getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (IndexOutOfBoundsException, RuntimeException)
852 OExternalLockGuard aGuard( this );
854 return OCommonAccessibleText::getTextRange( nStartIndex, nEndIndex );
857 // -----------------------------------------------------------------------------
859 TextSegment OAccessibleTextHelper::getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (IndexOutOfBoundsException, IllegalArgumentException, RuntimeException)
861 OExternalLockGuard aGuard( this );
863 return OCommonAccessibleText::getTextAtIndex( nIndex, aTextType );
866 // -----------------------------------------------------------------------------
868 TextSegment OAccessibleTextHelper::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (IndexOutOfBoundsException, IllegalArgumentException, RuntimeException)
870 OExternalLockGuard aGuard( this );
872 return OCommonAccessibleText::getTextBeforeIndex( nIndex, aTextType );
875 // -----------------------------------------------------------------------------
877 TextSegment OAccessibleTextHelper::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (IndexOutOfBoundsException, IllegalArgumentException, RuntimeException)
879 OExternalLockGuard aGuard( this );
881 return OCommonAccessibleText::getTextBehindIndex( nIndex, aTextType );
884 // -----------------------------------------------------------------------------
886 //..............................................................................
887 } // namespace comphelper
888 //..............................................................................
890 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */