CWS-TOOLING: integrate CWS os146
[LibreOffice.git] / comphelper / source / misc / accessibletexthelper.cxx
blobe3247cae5b60556f494afb8dccb701ea23195357
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_comphelper.hxx"
31 // includes --------------------------------------------------------------
32 #include <comphelper/accessibletexthelper.hxx>
33 #include <com/sun/star/accessibility/AccessibleTextType.hpp>
34 #include <com/sun/star/i18n/CharacterIteratorMode.hpp>
35 #ifndef _COM_SUN_STAR_TEXT_WORDTYPE_HPP_
36 #include <com/sun/star/i18n/WordType.hpp>
37 #endif
38 #include <com/sun/star/i18n/KCharacterType.hpp>
39 #include <comphelper/processfactory.hxx>
40 #include <com/sun/star/accessibility/TextSegment.hpp>
42 #include <algorithm>
44 //..............................................................................
45 namespace comphelper
47 //..............................................................................
49 using namespace ::com::sun::star;
50 using namespace ::com::sun::star::uno;
51 using namespace ::com::sun::star::lang;
52 using namespace ::com::sun::star::beans;
53 using namespace ::com::sun::star::accessibility;
55 //==============================================================================
56 // OCommonAccessibleText
57 //==============================================================================
59 OCommonAccessibleText::OCommonAccessibleText()
63 // -----------------------------------------------------------------------------
65 OCommonAccessibleText::~OCommonAccessibleText()
69 // -----------------------------------------------------------------------------
71 Reference < i18n::XBreakIterator > OCommonAccessibleText::implGetBreakIterator()
73 if ( !m_xBreakIter.is() )
75 Reference< lang::XMultiServiceFactory > xMSF = ::comphelper::getProcessServiceFactory();
76 if ( xMSF.is() )
78 m_xBreakIter = Reference< i18n::XBreakIterator >
79 ( xMSF->createInstance( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.i18n.BreakIterator" ) ) ), UNO_QUERY );
83 return m_xBreakIter;
86 // -----------------------------------------------------------------------------
88 Reference < i18n::XCharacterClassification > OCommonAccessibleText::implGetCharacterClassification()
90 if ( !m_xCharClass.is() )
92 Reference< lang::XMultiServiceFactory > xMSF = ::comphelper::getProcessServiceFactory();
93 if ( xMSF.is() )
95 m_xCharClass = Reference< i18n::XCharacterClassification >
96 ( xMSF->createInstance( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.i18n.CharacterClassification" ) ) ), UNO_QUERY );
100 return m_xCharClass;
103 // -----------------------------------------------------------------------------
105 sal_Bool OCommonAccessibleText::implIsValidBoundary( i18n::Boundary& rBoundary, sal_Int32 nLength )
107 return ( rBoundary.startPos >= 0 ) && ( rBoundary.startPos < nLength ) && ( rBoundary.endPos >= 0 ) && ( rBoundary.endPos <= nLength );
110 // -----------------------------------------------------------------------------
112 sal_Bool OCommonAccessibleText::implIsValidIndex( sal_Int32 nIndex, sal_Int32 nLength )
114 return ( nIndex >= 0 ) && ( nIndex < nLength );
117 // -----------------------------------------------------------------------------
119 sal_Bool OCommonAccessibleText::implIsValidRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex, sal_Int32 nLength )
121 return ( nStartIndex >= 0 ) && ( nStartIndex <= nLength ) && ( nEndIndex >= 0 ) && ( nEndIndex <= nLength );
124 // -----------------------------------------------------------------------------
126 void OCommonAccessibleText::implGetGlyphBoundary( i18n::Boundary& rBoundary, sal_Int32 nIndex )
128 ::rtl::OUString sText( implGetText() );
130 if ( implIsValidIndex( nIndex, sText.getLength() ) )
132 Reference < i18n::XBreakIterator > xBreakIter = implGetBreakIterator();
133 if ( xBreakIter.is() )
135 sal_Int32 nCount = 1;
136 sal_Int32 nDone;
137 sal_Int32 nStartIndex = xBreakIter->previousCharacters( sText, nIndex, implGetLocale(), i18n::CharacterIteratorMode::SKIPCELL, nCount, nDone );
138 if ( nDone != 0 )
139 nStartIndex = xBreakIter->nextCharacters( sText, nStartIndex, implGetLocale(), i18n::CharacterIteratorMode::SKIPCELL, nCount, nDone );
140 sal_Int32 nEndIndex = xBreakIter->nextCharacters( sText, nStartIndex, implGetLocale(), i18n::CharacterIteratorMode::SKIPCELL, nCount, nDone );
141 if ( nDone != 0 )
143 rBoundary.startPos = nStartIndex;
144 rBoundary.endPos = nEndIndex;
148 else
150 rBoundary.startPos = nIndex;
151 rBoundary.endPos = nIndex;
155 // -----------------------------------------------------------------------------
157 sal_Bool OCommonAccessibleText::implGetWordBoundary( i18n::Boundary& rBoundary, sal_Int32 nIndex )
159 sal_Bool bWord = sal_False;
160 ::rtl::OUString sText( implGetText() );
162 if ( implIsValidIndex( nIndex, sText.getLength() ) )
164 Reference < i18n::XBreakIterator > xBreakIter = implGetBreakIterator();
165 if ( xBreakIter.is() )
167 rBoundary = xBreakIter->getWordBoundary( sText, nIndex, implGetLocale(), i18n::WordType::ANY_WORD, sal_True );
169 // it's a word, if the first character is an alpha-numeric character
170 Reference< i18n::XCharacterClassification > xCharClass = implGetCharacterClassification();
171 if ( xCharClass.is() )
173 sal_Int32 nType = xCharClass->getCharacterType( sText, rBoundary.startPos, implGetLocale() );
174 if ( ( nType & ( i18n::KCharacterType::LETTER | i18n::KCharacterType::DIGIT ) ) != 0 )
175 bWord = sal_True;
179 else
181 rBoundary.startPos = nIndex;
182 rBoundary.endPos = nIndex;
185 return bWord;
188 // -----------------------------------------------------------------------------
190 void OCommonAccessibleText::implGetSentenceBoundary( i18n::Boundary& rBoundary, sal_Int32 nIndex )
192 ::rtl::OUString sText( implGetText() );
194 if ( implIsValidIndex( nIndex, sText.getLength() ) )
196 Locale aLocale = implGetLocale();
197 Reference < i18n::XBreakIterator > xBreakIter = implGetBreakIterator();
198 if ( xBreakIter.is() )
200 rBoundary.endPos = xBreakIter->endOfSentence( sText, nIndex, aLocale );
201 rBoundary.startPos = xBreakIter->beginOfSentence( sText, rBoundary.endPos, aLocale );
204 else
206 rBoundary.startPos = nIndex;
207 rBoundary.endPos = nIndex;
211 // -----------------------------------------------------------------------------
213 void OCommonAccessibleText::implGetParagraphBoundary( i18n::Boundary& rBoundary, sal_Int32 nIndex )
215 ::rtl::OUString sText( implGetText() );
217 if ( implIsValidIndex( nIndex, sText.getLength() ) )
219 rBoundary.startPos = 0;
220 rBoundary.endPos = sText.getLength();
222 sal_Int32 nFound = sText.lastIndexOf( (sal_Unicode)'\n', nIndex );
223 if ( nFound != -1 )
224 rBoundary.startPos = nFound + 1;
226 nFound = sText.indexOf( (sal_Unicode)'\n', nIndex );
227 if ( nFound != -1 )
228 rBoundary.endPos = nFound + 1;
230 else
232 rBoundary.startPos = nIndex;
233 rBoundary.endPos = nIndex;
237 // -----------------------------------------------------------------------------
239 void OCommonAccessibleText::implGetLineBoundary( i18n::Boundary& rBoundary, sal_Int32 nIndex )
241 ::rtl::OUString sText( implGetText() );
242 sal_Int32 nLength = sText.getLength();
244 if ( implIsValidIndex( nIndex, nLength ) || nIndex == nLength )
246 rBoundary.startPos = 0;
247 rBoundary.endPos = nLength;
249 else
251 rBoundary.startPos = nIndex;
252 rBoundary.endPos = nIndex;
256 // -----------------------------------------------------------------------------
258 sal_Unicode OCommonAccessibleText::getCharacter( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException)
260 ::rtl::OUString sText( implGetText() );
262 if ( !implIsValidIndex( nIndex, sText.getLength() ) )
263 throw IndexOutOfBoundsException();
265 return sText.getStr()[nIndex];
268 // -----------------------------------------------------------------------------
270 sal_Int32 OCommonAccessibleText::getCharacterCount() throw (RuntimeException)
272 return implGetText().getLength();
275 // -----------------------------------------------------------------------------
277 ::rtl::OUString OCommonAccessibleText::getSelectedText() throw (RuntimeException)
279 ::rtl::OUString sText;
280 sal_Int32 nStartIndex;
281 sal_Int32 nEndIndex;
283 implGetSelection( nStartIndex, nEndIndex );
287 sText = getTextRange( nStartIndex, nEndIndex );
289 catch ( IndexOutOfBoundsException& )
293 return sText;
296 // -----------------------------------------------------------------------------
298 sal_Int32 OCommonAccessibleText::getSelectionStart() throw (RuntimeException)
300 sal_Int32 nStartIndex;
301 sal_Int32 nEndIndex;
303 implGetSelection( nStartIndex, nEndIndex );
305 return nStartIndex;
308 // -----------------------------------------------------------------------------
310 sal_Int32 OCommonAccessibleText::getSelectionEnd() throw (RuntimeException)
312 sal_Int32 nStartIndex;
313 sal_Int32 nEndIndex;
315 implGetSelection( nStartIndex, nEndIndex );
317 return nEndIndex;
320 // -----------------------------------------------------------------------------
322 ::rtl::OUString OCommonAccessibleText::getText() throw (RuntimeException)
324 return implGetText();
327 // -----------------------------------------------------------------------------
329 ::rtl::OUString OCommonAccessibleText::getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (IndexOutOfBoundsException, RuntimeException)
331 ::rtl::OUString sText( implGetText() );
333 if ( !implIsValidRange( nStartIndex, nEndIndex, sText.getLength() ) )
334 throw IndexOutOfBoundsException();
336 sal_Int32 nMinIndex = ::std::min( nStartIndex, nEndIndex );
337 sal_Int32 nMaxIndex = ::std::max( nStartIndex, nEndIndex );
339 return sText.copy( nMinIndex, nMaxIndex - nMinIndex );
342 // -----------------------------------------------------------------------------
344 TextSegment OCommonAccessibleText::getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (IndexOutOfBoundsException, IllegalArgumentException, RuntimeException)
346 ::rtl::OUString sText( implGetText() );
347 sal_Int32 nLength = sText.getLength();
349 if ( !implIsValidIndex( nIndex, nLength ) && nIndex != nLength )
350 throw IndexOutOfBoundsException();
352 i18n::Boundary aBoundary;
353 TextSegment aResult;
354 aResult.SegmentStart = -1;
355 aResult.SegmentEnd = -1;
357 switch ( aTextType )
359 case AccessibleTextType::CHARACTER:
361 if ( implIsValidIndex( nIndex, nLength ) )
363 aResult.SegmentText = sText.copy( nIndex, 1 );
364 aResult.SegmentStart = nIndex;
365 aResult.SegmentEnd = nIndex+1;
368 break;
369 case AccessibleTextType::GLYPH:
371 // get glyph at index
372 implGetGlyphBoundary( aBoundary, nIndex );
373 if ( implIsValidBoundary( aBoundary, nLength ) )
375 aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
376 aResult.SegmentStart = aBoundary.startPos;
377 aResult.SegmentEnd = aBoundary.endPos;
380 break;
381 case AccessibleTextType::WORD:
383 // get word at index
384 sal_Bool bWord = implGetWordBoundary( aBoundary, nIndex );
385 if ( bWord && implIsValidBoundary( aBoundary, nLength ) )
387 aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
388 aResult.SegmentStart = aBoundary.startPos;
389 aResult.SegmentEnd = aBoundary.endPos;
392 break;
393 case AccessibleTextType::SENTENCE:
395 // get sentence at index
396 implGetSentenceBoundary( aBoundary, nIndex );
397 if ( implIsValidBoundary( aBoundary, nLength ) )
399 aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
400 aResult.SegmentStart = aBoundary.startPos;
401 aResult.SegmentEnd = aBoundary.endPos;
404 break;
405 case AccessibleTextType::PARAGRAPH:
407 // get paragraph at index
408 implGetParagraphBoundary( aBoundary, nIndex );
409 if ( implIsValidBoundary( aBoundary, nLength ) )
411 aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
412 aResult.SegmentStart = aBoundary.startPos;
413 aResult.SegmentEnd = aBoundary.endPos;
416 break;
417 case AccessibleTextType::LINE:
419 // get line at index
420 implGetLineBoundary( aBoundary, nIndex );
421 if ( implIsValidBoundary( aBoundary, nLength ) )
423 aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
424 aResult.SegmentStart = aBoundary.startPos;
425 aResult.SegmentEnd = aBoundary.endPos;
428 break;
429 case AccessibleTextType::ATTRIBUTE_RUN:
431 // TODO: implGetAttributeRunBoundary() (incompatible!)
433 aResult.SegmentText = sText;
434 aResult.SegmentStart = 0;
435 aResult.SegmentEnd = nLength;
437 break;
438 default:
440 // unknown text type
444 return aResult;
447 // -----------------------------------------------------------------------------
449 TextSegment OCommonAccessibleText::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (IndexOutOfBoundsException, IllegalArgumentException, RuntimeException)
451 ::rtl::OUString sText( implGetText() );
452 sal_Int32 nLength = sText.getLength();
454 if ( !implIsValidIndex( nIndex, nLength ) && nIndex != nLength )
455 throw IndexOutOfBoundsException();
457 i18n::Boundary aBoundary;
458 TextSegment aResult;
459 aResult.SegmentStart = -1;
460 aResult.SegmentEnd = -1;
462 switch ( aTextType )
464 case AccessibleTextType::CHARACTER:
466 if ( implIsValidIndex( nIndex - 1, nLength ) )
468 aResult.SegmentText = sText.copy( nIndex - 1, 1 );
469 aResult.SegmentStart = nIndex-1;
470 aResult.SegmentEnd = nIndex;
473 break;
474 case AccessibleTextType::GLYPH:
476 // get glyph at index
477 implGetGlyphBoundary( aBoundary, nIndex );
478 // get previous glyph
479 if ( aBoundary.startPos > 0 )
481 implGetGlyphBoundary( aBoundary, aBoundary.startPos - 1 );
482 if ( implIsValidBoundary( aBoundary, nLength ) )
484 aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
485 aResult.SegmentStart = aBoundary.startPos;
486 aResult.SegmentEnd = aBoundary.endPos;
490 break;
491 case AccessibleTextType::WORD:
493 // get word at index
494 implGetWordBoundary( aBoundary, nIndex );
495 // get previous word
496 sal_Bool bWord = sal_False;
497 while ( !bWord && aBoundary.startPos > 0 )
498 bWord = implGetWordBoundary( aBoundary, aBoundary.startPos - 1 );
499 if ( bWord && implIsValidBoundary( aBoundary, nLength ) )
501 aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
502 aResult.SegmentStart = aBoundary.startPos;
503 aResult.SegmentEnd = aBoundary.endPos;
506 break;
507 case AccessibleTextType::SENTENCE:
509 // get sentence at index
510 implGetSentenceBoundary( aBoundary, nIndex );
511 // get previous sentence
512 if ( aBoundary.startPos > 0 )
514 implGetSentenceBoundary( aBoundary, aBoundary.startPos - 1 );
515 if ( implIsValidBoundary( aBoundary, nLength ) )
517 aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
518 aResult.SegmentStart = aBoundary.startPos;
519 aResult.SegmentEnd = aBoundary.endPos;
523 break;
524 case AccessibleTextType::PARAGRAPH:
526 // get paragraph at index
527 implGetParagraphBoundary( aBoundary, nIndex );
528 // get previous paragraph
529 if ( aBoundary.startPos > 0 )
531 implGetParagraphBoundary( aBoundary, aBoundary.startPos - 1 );
532 if ( implIsValidBoundary( aBoundary, nLength ) )
534 aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
535 aResult.SegmentStart = aBoundary.startPos;
536 aResult.SegmentEnd = aBoundary.endPos;
540 break;
541 case AccessibleTextType::LINE:
543 // get line at index
544 implGetLineBoundary( aBoundary, nIndex );
545 // get previous line
546 if ( aBoundary.startPos > 0 )
548 implGetLineBoundary( aBoundary, aBoundary.startPos - 1 );
549 if ( implIsValidBoundary( aBoundary, nLength ) )
551 aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
552 aResult.SegmentStart = aBoundary.startPos;
553 aResult.SegmentEnd = aBoundary.endPos;
557 break;
558 case AccessibleTextType::ATTRIBUTE_RUN:
560 // TODO: implGetAttributeRunBoundary() (incompatible!)
562 break;
563 default:
565 // unknown text type
569 return aResult;
572 // -----------------------------------------------------------------------------
574 TextSegment OCommonAccessibleText::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (IndexOutOfBoundsException, IllegalArgumentException, RuntimeException)
576 ::rtl::OUString sText( implGetText() );
577 sal_Int32 nLength = sText.getLength();
579 if ( !implIsValidIndex( nIndex, nLength ) && nIndex != nLength )
580 throw IndexOutOfBoundsException();
582 i18n::Boundary aBoundary;
583 TextSegment aResult;
584 aResult.SegmentStart = -1;
585 aResult.SegmentEnd = -1;
587 switch ( aTextType )
589 case AccessibleTextType::CHARACTER:
591 if ( implIsValidIndex( nIndex + 1, nLength ) )
593 aResult.SegmentText = sText.copy( nIndex + 1, 1 );
594 aResult.SegmentStart = nIndex+1;
595 aResult.SegmentEnd = nIndex+2;
598 break;
599 case AccessibleTextType::GLYPH:
601 // get glyph at index
602 implGetGlyphBoundary( aBoundary, nIndex );
603 // get next glyph
604 if ( aBoundary.endPos < nLength )
606 implGetGlyphBoundary( aBoundary, aBoundary.endPos );
607 if ( implIsValidBoundary( aBoundary, nLength ) )
609 aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
610 aResult.SegmentStart = aBoundary.startPos;
611 aResult.SegmentEnd = aBoundary.endPos;
615 break;
616 case AccessibleTextType::WORD:
618 // get word at index
619 implGetWordBoundary( aBoundary, nIndex );
620 // get next word
621 sal_Bool bWord = sal_False;
622 while ( !bWord && aBoundary.endPos < nLength )
623 bWord = implGetWordBoundary( aBoundary, aBoundary.endPos );
624 if ( bWord && 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::SENTENCE:
634 // get sentence at index
635 implGetSentenceBoundary( aBoundary, nIndex );
636 // get next sentence
637 sal_Int32 nEnd = aBoundary.endPos;
638 sal_Int32 nI = aBoundary.endPos;
639 sal_Bool bFound = sal_False;
640 while ( !bFound && ++nI < nLength )
642 implGetSentenceBoundary( aBoundary, nI );
643 bFound = ( aBoundary.endPos > nEnd );
645 if ( bFound && implIsValidBoundary( aBoundary, nLength ) )
647 aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
648 aResult.SegmentStart = aBoundary.startPos;
649 aResult.SegmentEnd = aBoundary.endPos;
652 break;
653 case AccessibleTextType::PARAGRAPH:
655 // get paragraph at index
656 implGetParagraphBoundary( aBoundary, nIndex );
657 // get next paragraph
658 if ( aBoundary.endPos < nLength )
660 implGetParagraphBoundary( aBoundary, aBoundary.endPos );
661 if ( implIsValidBoundary( aBoundary, nLength ) )
663 aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
664 aResult.SegmentStart = aBoundary.startPos;
665 aResult.SegmentEnd = aBoundary.endPos;
669 break;
670 case AccessibleTextType::LINE:
672 // get line at index
673 implGetLineBoundary( aBoundary, nIndex );
674 // get next line
675 if ( aBoundary.endPos < nLength )
677 implGetLineBoundary( aBoundary, aBoundary.endPos );
678 if ( implIsValidBoundary( aBoundary, nLength ) )
680 aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
681 aResult.SegmentStart = aBoundary.startPos;
682 aResult.SegmentEnd = aBoundary.endPos;
686 break;
687 case AccessibleTextType::ATTRIBUTE_RUN:
689 // TODO: implGetAttributeRunBoundary() (incompatible!)
691 break;
692 default:
694 // unknown text type
698 return aResult;
701 // -----------------------------------------------------------------------------
702 bool OCommonAccessibleText::implInitTextChangedEvent(
703 const rtl::OUString& rOldString,
704 const rtl::OUString& rNewString,
705 ::com::sun::star::uno::Any& rDeleted,
706 ::com::sun::star::uno::Any& rInserted) // throw()
708 sal_uInt32 nLenOld = rOldString.getLength();
709 sal_uInt32 nLenNew = rNewString.getLength();
711 // equal
712 if ((0 == nLenOld) && (0 == nLenNew))
713 return false;
715 TextSegment aDeletedText;
716 TextSegment aInsertedText;
718 aDeletedText.SegmentStart = -1;
719 aDeletedText.SegmentEnd = -1;
720 aInsertedText.SegmentStart = -1;
721 aInsertedText.SegmentEnd = -1;
723 // insert only
724 if ((0 == nLenOld) && (nLenNew > 0))
726 aInsertedText.SegmentStart = 0;
727 aInsertedText.SegmentEnd = nLenNew;
728 aInsertedText.SegmentText = rNewString.copy( aInsertedText.SegmentStart, aInsertedText.SegmentEnd - aInsertedText.SegmentStart );
730 rInserted <<= aInsertedText;
731 return true;
734 // delete only
735 if ((nLenOld > 0) && (0 == nLenNew))
737 aDeletedText.SegmentStart = 0;
738 aDeletedText.SegmentEnd = nLenOld;
739 aDeletedText.SegmentText = rOldString.copy( aDeletedText.SegmentStart, aDeletedText.SegmentEnd - aDeletedText.SegmentStart );
741 rDeleted <<= aDeletedText;
742 return true;
745 const sal_Unicode* pFirstDiffOld = rOldString.getStr();
746 const sal_Unicode* pLastDiffOld = rOldString.getStr() + nLenOld;
747 const sal_Unicode* pFirstDiffNew = rNewString.getStr();
748 const sal_Unicode* pLastDiffNew = rNewString.getStr() + nLenNew;
750 // find first difference
751 while ((*pFirstDiffOld == *pFirstDiffNew) &&
752 (pFirstDiffOld < pLastDiffOld) &&
753 (pFirstDiffNew < pLastDiffNew))
755 pFirstDiffOld++;
756 pFirstDiffNew++;
759 // equality test
760 if ((0 == *pFirstDiffOld) && (0 == *pFirstDiffNew))
761 return false;
763 // find last difference
764 while ( ( pLastDiffOld > pFirstDiffOld) &&
765 ( pLastDiffNew > pFirstDiffNew) &&
766 (pLastDiffOld[-1] == pLastDiffNew[-1]))
768 pLastDiffOld--;
769 pLastDiffNew--;
772 if (pFirstDiffOld < pLastDiffOld)
774 aDeletedText.SegmentStart = pFirstDiffOld - rOldString.getStr();
775 aDeletedText.SegmentEnd = pLastDiffOld - rOldString.getStr();
776 aDeletedText.SegmentText = rOldString.copy( aDeletedText.SegmentStart, aDeletedText.SegmentEnd - aDeletedText.SegmentStart );
778 rDeleted <<= aDeletedText;
781 if (pFirstDiffNew < pLastDiffNew)
783 aInsertedText.SegmentStart = pFirstDiffNew - rNewString.getStr();
784 aInsertedText.SegmentEnd = pLastDiffNew - rNewString.getStr();
785 aInsertedText.SegmentText = rNewString.copy( aInsertedText.SegmentStart, aInsertedText.SegmentEnd - aInsertedText.SegmentStart );
787 rInserted <<= aInsertedText;
789 return true;
792 //==============================================================================
793 // OAccessibleTextHelper
794 //==============================================================================
796 OAccessibleTextHelper::OAccessibleTextHelper()
800 // -----------------------------------------------------------------------------
802 OAccessibleTextHelper::OAccessibleTextHelper( IMutex* _pExternalLock )
803 :OAccessibleExtendedComponentHelper( _pExternalLock )
807 // -----------------------------------------------------------------------------
808 // XInterface
809 // -----------------------------------------------------------------------------
811 IMPLEMENT_FORWARD_XINTERFACE2( OAccessibleTextHelper, OAccessibleExtendedComponentHelper, OAccessibleTextHelper_Base )
813 // -----------------------------------------------------------------------------
814 // XTypeProvider
815 // -----------------------------------------------------------------------------
817 IMPLEMENT_FORWARD_XTYPEPROVIDER2( OAccessibleTextHelper, OAccessibleExtendedComponentHelper, OAccessibleTextHelper_Base )
819 // -----------------------------------------------------------------------------
820 // XAccessibleText
821 // -----------------------------------------------------------------------------
823 sal_Unicode OAccessibleTextHelper::getCharacter( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException)
825 OExternalLockGuard aGuard( this );
827 return OCommonAccessibleText::getCharacter( nIndex );
830 // -----------------------------------------------------------------------------
832 sal_Int32 OAccessibleTextHelper::getCharacterCount() throw (RuntimeException)
834 OExternalLockGuard aGuard( this );
836 return OCommonAccessibleText::getCharacterCount();
839 // -----------------------------------------------------------------------------
841 ::rtl::OUString OAccessibleTextHelper::getSelectedText() throw (RuntimeException)
843 OExternalLockGuard aGuard( this );
845 return OCommonAccessibleText::getSelectedText();
848 // -----------------------------------------------------------------------------
850 sal_Int32 OAccessibleTextHelper::getSelectionStart() throw (RuntimeException)
852 OExternalLockGuard aGuard( this );
854 return OCommonAccessibleText::getSelectionStart();
857 // -----------------------------------------------------------------------------
859 sal_Int32 OAccessibleTextHelper::getSelectionEnd() throw (RuntimeException)
861 OExternalLockGuard aGuard( this );
863 return OCommonAccessibleText::getSelectionEnd();
866 // -----------------------------------------------------------------------------
868 ::rtl::OUString OAccessibleTextHelper::getText() throw (RuntimeException)
870 OExternalLockGuard aGuard( this );
872 return OCommonAccessibleText::getText();
875 // -----------------------------------------------------------------------------
877 ::rtl::OUString OAccessibleTextHelper::getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (IndexOutOfBoundsException, RuntimeException)
879 OExternalLockGuard aGuard( this );
881 return OCommonAccessibleText::getTextRange( nStartIndex, nEndIndex );
884 // -----------------------------------------------------------------------------
886 TextSegment OAccessibleTextHelper::getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (IndexOutOfBoundsException, IllegalArgumentException, RuntimeException)
888 OExternalLockGuard aGuard( this );
890 return OCommonAccessibleText::getTextAtIndex( nIndex, aTextType );
893 // -----------------------------------------------------------------------------
895 TextSegment OAccessibleTextHelper::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (IndexOutOfBoundsException, IllegalArgumentException, RuntimeException)
897 OExternalLockGuard aGuard( this );
899 return OCommonAccessibleText::getTextBeforeIndex( nIndex, aTextType );
902 // -----------------------------------------------------------------------------
904 TextSegment OAccessibleTextHelper::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (IndexOutOfBoundsException, IllegalArgumentException, RuntimeException)
906 OExternalLockGuard aGuard( this );
908 return OCommonAccessibleText::getTextBehindIndex( nIndex, aTextType );
911 // -----------------------------------------------------------------------------
913 //..............................................................................
914 } // namespace comphelper
915 //..............................................................................