update dev300-m58
[ooovba.git] / comphelper / source / misc / accessibletexthelper.cxx
blob8a7d83bfacefc7601df1f430767a2beccd4c51cf
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: accessibletexthelper.cxx,v $
10 * $Revision: 1.9 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_comphelper.hxx"
34 // includes --------------------------------------------------------------
35 #include <comphelper/accessibletexthelper.hxx>
36 #include <com/sun/star/accessibility/AccessibleTextType.hpp>
37 #include <com/sun/star/i18n/CharacterIteratorMode.hpp>
38 #ifndef _COM_SUN_STAR_TEXT_WORDTYPE_HPP_
39 #include <com/sun/star/i18n/WordType.hpp>
40 #endif
41 #include <com/sun/star/i18n/KCharacterType.hpp>
42 #include <comphelper/processfactory.hxx>
43 #include <com/sun/star/accessibility/TextSegment.hpp>
45 #include <algorithm>
47 //..............................................................................
48 namespace comphelper
50 //..............................................................................
52 using namespace ::com::sun::star;
53 using namespace ::com::sun::star::uno;
54 using namespace ::com::sun::star::lang;
55 using namespace ::com::sun::star::beans;
56 using namespace ::com::sun::star::accessibility;
58 //==============================================================================
59 // OCommonAccessibleText
60 //==============================================================================
62 OCommonAccessibleText::OCommonAccessibleText()
66 // -----------------------------------------------------------------------------
68 OCommonAccessibleText::~OCommonAccessibleText()
72 // -----------------------------------------------------------------------------
74 Reference < i18n::XBreakIterator > OCommonAccessibleText::implGetBreakIterator()
76 if ( !m_xBreakIter.is() )
78 Reference< lang::XMultiServiceFactory > xMSF = ::comphelper::getProcessServiceFactory();
79 if ( xMSF.is() )
81 m_xBreakIter = Reference< i18n::XBreakIterator >
82 ( xMSF->createInstance( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.i18n.BreakIterator" ) ) ), UNO_QUERY );
86 return m_xBreakIter;
89 // -----------------------------------------------------------------------------
91 Reference < i18n::XCharacterClassification > OCommonAccessibleText::implGetCharacterClassification()
93 if ( !m_xCharClass.is() )
95 Reference< lang::XMultiServiceFactory > xMSF = ::comphelper::getProcessServiceFactory();
96 if ( xMSF.is() )
98 m_xCharClass = Reference< i18n::XCharacterClassification >
99 ( xMSF->createInstance( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.i18n.CharacterClassification" ) ) ), UNO_QUERY );
103 return m_xCharClass;
106 // -----------------------------------------------------------------------------
108 sal_Bool OCommonAccessibleText::implIsValidBoundary( i18n::Boundary& rBoundary, sal_Int32 nLength )
110 return ( rBoundary.startPos >= 0 ) && ( rBoundary.startPos < nLength ) && ( rBoundary.endPos >= 0 ) && ( rBoundary.endPos <= nLength );
113 // -----------------------------------------------------------------------------
115 sal_Bool OCommonAccessibleText::implIsValidIndex( sal_Int32 nIndex, sal_Int32 nLength )
117 return ( nIndex >= 0 ) && ( nIndex < nLength );
120 // -----------------------------------------------------------------------------
122 sal_Bool OCommonAccessibleText::implIsValidRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex, sal_Int32 nLength )
124 return ( nStartIndex >= 0 ) && ( nStartIndex <= nLength ) && ( nEndIndex >= 0 ) && ( nEndIndex <= nLength );
127 // -----------------------------------------------------------------------------
129 void OCommonAccessibleText::implGetGlyphBoundary( i18n::Boundary& rBoundary, sal_Int32 nIndex )
131 ::rtl::OUString sText( implGetText() );
133 if ( implIsValidIndex( nIndex, sText.getLength() ) )
135 Reference < i18n::XBreakIterator > xBreakIter = implGetBreakIterator();
136 if ( xBreakIter.is() )
138 sal_Int32 nCount = 1;
139 sal_Int32 nDone;
140 sal_Int32 nStartIndex = xBreakIter->previousCharacters( sText, nIndex, implGetLocale(), i18n::CharacterIteratorMode::SKIPCELL, nCount, nDone );
141 if ( nDone != 0 )
142 nStartIndex = xBreakIter->nextCharacters( sText, nStartIndex, implGetLocale(), i18n::CharacterIteratorMode::SKIPCELL, nCount, nDone );
143 sal_Int32 nEndIndex = xBreakIter->nextCharacters( sText, nStartIndex, implGetLocale(), i18n::CharacterIteratorMode::SKIPCELL, nCount, nDone );
144 if ( nDone != 0 )
146 rBoundary.startPos = nStartIndex;
147 rBoundary.endPos = nEndIndex;
151 else
153 rBoundary.startPos = nIndex;
154 rBoundary.endPos = nIndex;
158 // -----------------------------------------------------------------------------
160 sal_Bool OCommonAccessibleText::implGetWordBoundary( i18n::Boundary& rBoundary, sal_Int32 nIndex )
162 sal_Bool bWord = sal_False;
163 ::rtl::OUString sText( implGetText() );
165 if ( implIsValidIndex( nIndex, sText.getLength() ) )
167 Reference < i18n::XBreakIterator > xBreakIter = implGetBreakIterator();
168 if ( xBreakIter.is() )
170 rBoundary = xBreakIter->getWordBoundary( sText, nIndex, implGetLocale(), i18n::WordType::ANY_WORD, sal_True );
172 // it's a word, if the first character is an alpha-numeric character
173 Reference< i18n::XCharacterClassification > xCharClass = implGetCharacterClassification();
174 if ( xCharClass.is() )
176 sal_Int32 nType = xCharClass->getCharacterType( sText, rBoundary.startPos, implGetLocale() );
177 if ( ( nType & ( i18n::KCharacterType::LETTER | i18n::KCharacterType::DIGIT ) ) != 0 )
178 bWord = sal_True;
182 else
184 rBoundary.startPos = nIndex;
185 rBoundary.endPos = nIndex;
188 return bWord;
191 // -----------------------------------------------------------------------------
193 void OCommonAccessibleText::implGetSentenceBoundary( i18n::Boundary& rBoundary, sal_Int32 nIndex )
195 ::rtl::OUString sText( implGetText() );
197 if ( implIsValidIndex( nIndex, sText.getLength() ) )
199 Locale aLocale = implGetLocale();
200 Reference < i18n::XBreakIterator > xBreakIter = implGetBreakIterator();
201 if ( xBreakIter.is() )
203 rBoundary.endPos = xBreakIter->endOfSentence( sText, nIndex, aLocale );
204 rBoundary.startPos = xBreakIter->beginOfSentence( sText, rBoundary.endPos, aLocale );
207 else
209 rBoundary.startPos = nIndex;
210 rBoundary.endPos = nIndex;
214 // -----------------------------------------------------------------------------
216 void OCommonAccessibleText::implGetParagraphBoundary( i18n::Boundary& rBoundary, sal_Int32 nIndex )
218 ::rtl::OUString sText( implGetText() );
220 if ( implIsValidIndex( nIndex, sText.getLength() ) )
222 rBoundary.startPos = 0;
223 rBoundary.endPos = sText.getLength();
225 sal_Int32 nFound = sText.lastIndexOf( (sal_Unicode)'\n', nIndex );
226 if ( nFound != -1 )
227 rBoundary.startPos = nFound + 1;
229 nFound = sText.indexOf( (sal_Unicode)'\n', nIndex );
230 if ( nFound != -1 )
231 rBoundary.endPos = nFound + 1;
233 else
235 rBoundary.startPos = nIndex;
236 rBoundary.endPos = nIndex;
240 // -----------------------------------------------------------------------------
242 void OCommonAccessibleText::implGetLineBoundary( i18n::Boundary& rBoundary, sal_Int32 nIndex )
244 ::rtl::OUString sText( implGetText() );
245 sal_Int32 nLength = sText.getLength();
247 if ( implIsValidIndex( nIndex, nLength ) || nIndex == nLength )
249 rBoundary.startPos = 0;
250 rBoundary.endPos = nLength;
252 else
254 rBoundary.startPos = nIndex;
255 rBoundary.endPos = nIndex;
259 // -----------------------------------------------------------------------------
261 sal_Unicode OCommonAccessibleText::getCharacter( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException)
263 ::rtl::OUString sText( implGetText() );
265 if ( !implIsValidIndex( nIndex, sText.getLength() ) )
266 throw IndexOutOfBoundsException();
268 return sText.getStr()[nIndex];
271 // -----------------------------------------------------------------------------
273 sal_Int32 OCommonAccessibleText::getCharacterCount() throw (RuntimeException)
275 return implGetText().getLength();
278 // -----------------------------------------------------------------------------
280 ::rtl::OUString OCommonAccessibleText::getSelectedText() throw (RuntimeException)
282 ::rtl::OUString sText;
283 sal_Int32 nStartIndex;
284 sal_Int32 nEndIndex;
286 implGetSelection( nStartIndex, nEndIndex );
290 sText = getTextRange( nStartIndex, nEndIndex );
292 catch ( IndexOutOfBoundsException& )
296 return sText;
299 // -----------------------------------------------------------------------------
301 sal_Int32 OCommonAccessibleText::getSelectionStart() throw (RuntimeException)
303 sal_Int32 nStartIndex;
304 sal_Int32 nEndIndex;
306 implGetSelection( nStartIndex, nEndIndex );
308 return nStartIndex;
311 // -----------------------------------------------------------------------------
313 sal_Int32 OCommonAccessibleText::getSelectionEnd() throw (RuntimeException)
315 sal_Int32 nStartIndex;
316 sal_Int32 nEndIndex;
318 implGetSelection( nStartIndex, nEndIndex );
320 return nEndIndex;
323 // -----------------------------------------------------------------------------
325 ::rtl::OUString OCommonAccessibleText::getText() throw (RuntimeException)
327 return implGetText();
330 // -----------------------------------------------------------------------------
332 ::rtl::OUString OCommonAccessibleText::getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (IndexOutOfBoundsException, RuntimeException)
334 ::rtl::OUString sText( implGetText() );
336 if ( !implIsValidRange( nStartIndex, nEndIndex, sText.getLength() ) )
337 throw IndexOutOfBoundsException();
339 sal_Int32 nMinIndex = ::std::min( nStartIndex, nEndIndex );
340 sal_Int32 nMaxIndex = ::std::max( nStartIndex, nEndIndex );
342 return sText.copy( nMinIndex, nMaxIndex - nMinIndex );
345 // -----------------------------------------------------------------------------
347 TextSegment OCommonAccessibleText::getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (IndexOutOfBoundsException, IllegalArgumentException, RuntimeException)
349 ::rtl::OUString sText( implGetText() );
350 sal_Int32 nLength = sText.getLength();
352 if ( !implIsValidIndex( nIndex, nLength ) && nIndex != nLength )
353 throw IndexOutOfBoundsException();
355 i18n::Boundary aBoundary;
356 TextSegment aResult;
357 aResult.SegmentStart = -1;
358 aResult.SegmentEnd = -1;
360 switch ( aTextType )
362 case AccessibleTextType::CHARACTER:
364 if ( implIsValidIndex( nIndex, nLength ) )
366 aResult.SegmentText = sText.copy( nIndex, 1 );
367 aResult.SegmentStart = nIndex;
368 aResult.SegmentEnd = nIndex+1;
371 break;
372 case AccessibleTextType::GLYPH:
374 // get glyph at index
375 implGetGlyphBoundary( 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::WORD:
386 // get word at index
387 sal_Bool bWord = implGetWordBoundary( aBoundary, nIndex );
388 if ( bWord && 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::SENTENCE:
398 // get sentence at index
399 implGetSentenceBoundary( 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::PARAGRAPH:
410 // get paragraph at index
411 implGetParagraphBoundary( aBoundary, nIndex );
412 if ( implIsValidBoundary( aBoundary, nLength ) )
414 aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
415 aResult.SegmentStart = aBoundary.startPos;
416 aResult.SegmentEnd = aBoundary.endPos;
419 break;
420 case AccessibleTextType::LINE:
422 // get line at index
423 implGetLineBoundary( aBoundary, nIndex );
424 if ( implIsValidBoundary( aBoundary, nLength ) )
426 aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
427 aResult.SegmentStart = aBoundary.startPos;
428 aResult.SegmentEnd = aBoundary.endPos;
431 break;
432 case AccessibleTextType::ATTRIBUTE_RUN:
434 // TODO: implGetAttributeRunBoundary() (incompatible!)
436 aResult.SegmentText = sText;
437 aResult.SegmentStart = 0;
438 aResult.SegmentEnd = nLength;
440 break;
441 default:
443 // unknown text type
447 return aResult;
450 // -----------------------------------------------------------------------------
452 TextSegment OCommonAccessibleText::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (IndexOutOfBoundsException, IllegalArgumentException, RuntimeException)
454 ::rtl::OUString sText( implGetText() );
455 sal_Int32 nLength = sText.getLength();
457 if ( !implIsValidIndex( nIndex, nLength ) && nIndex != nLength )
458 throw IndexOutOfBoundsException();
460 i18n::Boundary aBoundary;
461 TextSegment aResult;
462 aResult.SegmentStart = -1;
463 aResult.SegmentEnd = -1;
465 switch ( aTextType )
467 case AccessibleTextType::CHARACTER:
469 if ( implIsValidIndex( nIndex - 1, nLength ) )
471 aResult.SegmentText = sText.copy( nIndex - 1, 1 );
472 aResult.SegmentStart = nIndex-1;
473 aResult.SegmentEnd = nIndex;
476 break;
477 case AccessibleTextType::GLYPH:
479 // get glyph at index
480 implGetGlyphBoundary( aBoundary, nIndex );
481 // get previous glyph
482 if ( aBoundary.startPos > 0 )
484 implGetGlyphBoundary( aBoundary, aBoundary.startPos - 1 );
485 if ( implIsValidBoundary( aBoundary, nLength ) )
487 aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
488 aResult.SegmentStart = aBoundary.startPos;
489 aResult.SegmentEnd = aBoundary.endPos;
493 break;
494 case AccessibleTextType::WORD:
496 // get word at index
497 implGetWordBoundary( aBoundary, nIndex );
498 // get previous word
499 sal_Bool bWord = sal_False;
500 while ( !bWord && aBoundary.startPos > 0 )
501 bWord = implGetWordBoundary( aBoundary, aBoundary.startPos - 1 );
502 if ( bWord && implIsValidBoundary( aBoundary, nLength ) )
504 aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
505 aResult.SegmentStart = aBoundary.startPos;
506 aResult.SegmentEnd = aBoundary.endPos;
509 break;
510 case AccessibleTextType::SENTENCE:
512 // get sentence at index
513 implGetSentenceBoundary( aBoundary, nIndex );
514 // get previous sentence
515 if ( aBoundary.startPos > 0 )
517 implGetSentenceBoundary( aBoundary, aBoundary.startPos - 1 );
518 if ( implIsValidBoundary( aBoundary, nLength ) )
520 aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
521 aResult.SegmentStart = aBoundary.startPos;
522 aResult.SegmentEnd = aBoundary.endPos;
526 break;
527 case AccessibleTextType::PARAGRAPH:
529 // get paragraph at index
530 implGetParagraphBoundary( aBoundary, nIndex );
531 // get previous paragraph
532 if ( aBoundary.startPos > 0 )
534 implGetParagraphBoundary( aBoundary, aBoundary.startPos - 1 );
535 if ( implIsValidBoundary( aBoundary, nLength ) )
537 aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
538 aResult.SegmentStart = aBoundary.startPos;
539 aResult.SegmentEnd = aBoundary.endPos;
543 break;
544 case AccessibleTextType::LINE:
546 // get line at index
547 implGetLineBoundary( aBoundary, nIndex );
548 // get previous line
549 if ( aBoundary.startPos > 0 )
551 implGetLineBoundary( aBoundary, aBoundary.startPos - 1 );
552 if ( implIsValidBoundary( aBoundary, nLength ) )
554 aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
555 aResult.SegmentStart = aBoundary.startPos;
556 aResult.SegmentEnd = aBoundary.endPos;
560 break;
561 case AccessibleTextType::ATTRIBUTE_RUN:
563 // TODO: implGetAttributeRunBoundary() (incompatible!)
565 break;
566 default:
568 // unknown text type
572 return aResult;
575 // -----------------------------------------------------------------------------
577 TextSegment OCommonAccessibleText::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (IndexOutOfBoundsException, IllegalArgumentException, RuntimeException)
579 ::rtl::OUString sText( implGetText() );
580 sal_Int32 nLength = sText.getLength();
582 if ( !implIsValidIndex( nIndex, nLength ) && nIndex != nLength )
583 throw IndexOutOfBoundsException();
585 i18n::Boundary aBoundary;
586 TextSegment aResult;
587 aResult.SegmentStart = -1;
588 aResult.SegmentEnd = -1;
590 switch ( aTextType )
592 case AccessibleTextType::CHARACTER:
594 if ( implIsValidIndex( nIndex + 1, nLength ) )
596 aResult.SegmentText = sText.copy( nIndex + 1, 1 );
597 aResult.SegmentStart = nIndex+1;
598 aResult.SegmentEnd = nIndex+2;
601 break;
602 case AccessibleTextType::GLYPH:
604 // get glyph at index
605 implGetGlyphBoundary( aBoundary, nIndex );
606 // get next glyph
607 if ( aBoundary.endPos < nLength )
609 implGetGlyphBoundary( aBoundary, aBoundary.endPos );
610 if ( implIsValidBoundary( aBoundary, nLength ) )
612 aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
613 aResult.SegmentStart = aBoundary.startPos;
614 aResult.SegmentEnd = aBoundary.endPos;
618 break;
619 case AccessibleTextType::WORD:
621 // get word at index
622 implGetWordBoundary( aBoundary, nIndex );
623 // get next word
624 sal_Bool bWord = sal_False;
625 while ( !bWord && aBoundary.endPos < nLength )
626 bWord = implGetWordBoundary( aBoundary, aBoundary.endPos );
627 if ( bWord && implIsValidBoundary( aBoundary, nLength ) )
629 aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
630 aResult.SegmentStart = aBoundary.startPos;
631 aResult.SegmentEnd = aBoundary.endPos;
634 break;
635 case AccessibleTextType::SENTENCE:
637 // get sentence at index
638 implGetSentenceBoundary( aBoundary, nIndex );
639 // get next sentence
640 sal_Int32 nEnd = aBoundary.endPos;
641 sal_Int32 nI = aBoundary.endPos;
642 sal_Bool bFound = sal_False;
643 while ( !bFound && ++nI < nLength )
645 implGetSentenceBoundary( aBoundary, nI );
646 bFound = ( aBoundary.endPos > nEnd );
648 if ( bFound && implIsValidBoundary( aBoundary, nLength ) )
650 aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
651 aResult.SegmentStart = aBoundary.startPos;
652 aResult.SegmentEnd = aBoundary.endPos;
655 break;
656 case AccessibleTextType::PARAGRAPH:
658 // get paragraph at index
659 implGetParagraphBoundary( aBoundary, nIndex );
660 // get next paragraph
661 if ( aBoundary.endPos < nLength )
663 implGetParagraphBoundary( aBoundary, aBoundary.endPos );
664 if ( implIsValidBoundary( aBoundary, nLength ) )
666 aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
667 aResult.SegmentStart = aBoundary.startPos;
668 aResult.SegmentEnd = aBoundary.endPos;
672 break;
673 case AccessibleTextType::LINE:
675 // get line at index
676 implGetLineBoundary( aBoundary, nIndex );
677 // get next line
678 if ( aBoundary.endPos < nLength )
680 implGetLineBoundary( aBoundary, aBoundary.endPos );
681 if ( implIsValidBoundary( aBoundary, nLength ) )
683 aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
684 aResult.SegmentStart = aBoundary.startPos;
685 aResult.SegmentEnd = aBoundary.endPos;
689 break;
690 case AccessibleTextType::ATTRIBUTE_RUN:
692 // TODO: implGetAttributeRunBoundary() (incompatible!)
694 break;
695 default:
697 // unknown text type
701 return aResult;
704 // -----------------------------------------------------------------------------
705 bool OCommonAccessibleText::implInitTextChangedEvent(
706 const rtl::OUString& rOldString,
707 const rtl::OUString& rNewString,
708 ::com::sun::star::uno::Any& rDeleted,
709 ::com::sun::star::uno::Any& rInserted) // throw()
711 sal_uInt32 nLenOld = rOldString.getLength();
712 sal_uInt32 nLenNew = rNewString.getLength();
714 // equal
715 if ((0 == nLenOld) && (0 == nLenNew))
716 return false;
718 TextSegment aDeletedText;
719 TextSegment aInsertedText;
721 aDeletedText.SegmentStart = -1;
722 aDeletedText.SegmentEnd = -1;
723 aInsertedText.SegmentStart = -1;
724 aInsertedText.SegmentEnd = -1;
726 // insert only
727 if ((0 == nLenOld) && (nLenNew > 0))
729 aInsertedText.SegmentStart = 0;
730 aInsertedText.SegmentEnd = nLenNew;
731 aInsertedText.SegmentText = rNewString.copy( aInsertedText.SegmentStart, aInsertedText.SegmentEnd - aInsertedText.SegmentStart );
733 rInserted <<= aInsertedText;
734 return true;
737 // delete only
738 if ((nLenOld > 0) && (0 == nLenNew))
740 aDeletedText.SegmentStart = 0;
741 aDeletedText.SegmentEnd = nLenOld;
742 aDeletedText.SegmentText = rOldString.copy( aDeletedText.SegmentStart, aDeletedText.SegmentEnd - aDeletedText.SegmentStart );
744 rDeleted <<= aDeletedText;
745 return true;
748 const sal_Unicode* pFirstDiffOld = rOldString.getStr();
749 const sal_Unicode* pLastDiffOld = rOldString.getStr() + nLenOld;
750 const sal_Unicode* pFirstDiffNew = rNewString.getStr();
751 const sal_Unicode* pLastDiffNew = rNewString.getStr() + nLenNew;
753 // find first difference
754 while ((*pFirstDiffOld == *pFirstDiffNew) &&
755 (pFirstDiffOld < pLastDiffOld) &&
756 (pFirstDiffNew < pLastDiffNew))
758 pFirstDiffOld++;
759 pFirstDiffNew++;
762 // equality test
763 if ((0 == *pFirstDiffOld) && (0 == *pFirstDiffNew))
764 return false;
766 // find last difference
767 while ( ( pLastDiffOld > pFirstDiffOld) &&
768 ( pLastDiffNew > pFirstDiffNew) &&
769 (pLastDiffOld[-1] == pLastDiffNew[-1]))
771 pLastDiffOld--;
772 pLastDiffNew--;
775 if (pFirstDiffOld < pLastDiffOld)
777 aDeletedText.SegmentStart = pFirstDiffOld - rOldString.getStr();
778 aDeletedText.SegmentEnd = pLastDiffOld - rOldString.getStr();
779 aDeletedText.SegmentText = rOldString.copy( aDeletedText.SegmentStart, aDeletedText.SegmentEnd - aDeletedText.SegmentStart );
781 rDeleted <<= aDeletedText;
784 if (pFirstDiffNew < pLastDiffNew)
786 aInsertedText.SegmentStart = pFirstDiffNew - rNewString.getStr();
787 aInsertedText.SegmentEnd = pLastDiffNew - rNewString.getStr();
788 aInsertedText.SegmentText = rNewString.copy( aInsertedText.SegmentStart, aInsertedText.SegmentEnd - aInsertedText.SegmentStart );
790 rInserted <<= aInsertedText;
792 return true;
795 //==============================================================================
796 // OAccessibleTextHelper
797 //==============================================================================
799 OAccessibleTextHelper::OAccessibleTextHelper()
803 // -----------------------------------------------------------------------------
805 OAccessibleTextHelper::OAccessibleTextHelper( IMutex* _pExternalLock )
806 :OAccessibleExtendedComponentHelper( _pExternalLock )
810 // -----------------------------------------------------------------------------
811 // XInterface
812 // -----------------------------------------------------------------------------
814 IMPLEMENT_FORWARD_XINTERFACE2( OAccessibleTextHelper, OAccessibleExtendedComponentHelper, OAccessibleTextHelper_Base )
816 // -----------------------------------------------------------------------------
817 // XTypeProvider
818 // -----------------------------------------------------------------------------
820 IMPLEMENT_FORWARD_XTYPEPROVIDER2( OAccessibleTextHelper, OAccessibleExtendedComponentHelper, OAccessibleTextHelper_Base )
822 // -----------------------------------------------------------------------------
823 // XAccessibleText
824 // -----------------------------------------------------------------------------
826 sal_Unicode OAccessibleTextHelper::getCharacter( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException)
828 OExternalLockGuard aGuard( this );
830 return OCommonAccessibleText::getCharacter( nIndex );
833 // -----------------------------------------------------------------------------
835 sal_Int32 OAccessibleTextHelper::getCharacterCount() throw (RuntimeException)
837 OExternalLockGuard aGuard( this );
839 return OCommonAccessibleText::getCharacterCount();
842 // -----------------------------------------------------------------------------
844 ::rtl::OUString OAccessibleTextHelper::getSelectedText() throw (RuntimeException)
846 OExternalLockGuard aGuard( this );
848 return OCommonAccessibleText::getSelectedText();
851 // -----------------------------------------------------------------------------
853 sal_Int32 OAccessibleTextHelper::getSelectionStart() throw (RuntimeException)
855 OExternalLockGuard aGuard( this );
857 return OCommonAccessibleText::getSelectionStart();
860 // -----------------------------------------------------------------------------
862 sal_Int32 OAccessibleTextHelper::getSelectionEnd() throw (RuntimeException)
864 OExternalLockGuard aGuard( this );
866 return OCommonAccessibleText::getSelectionEnd();
869 // -----------------------------------------------------------------------------
871 ::rtl::OUString OAccessibleTextHelper::getText() throw (RuntimeException)
873 OExternalLockGuard aGuard( this );
875 return OCommonAccessibleText::getText();
878 // -----------------------------------------------------------------------------
880 ::rtl::OUString OAccessibleTextHelper::getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (IndexOutOfBoundsException, RuntimeException)
882 OExternalLockGuard aGuard( this );
884 return OCommonAccessibleText::getTextRange( nStartIndex, nEndIndex );
887 // -----------------------------------------------------------------------------
889 TextSegment OAccessibleTextHelper::getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (IndexOutOfBoundsException, IllegalArgumentException, RuntimeException)
891 OExternalLockGuard aGuard( this );
893 return OCommonAccessibleText::getTextAtIndex( nIndex, aTextType );
896 // -----------------------------------------------------------------------------
898 TextSegment OAccessibleTextHelper::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (IndexOutOfBoundsException, IllegalArgumentException, RuntimeException)
900 OExternalLockGuard aGuard( this );
902 return OCommonAccessibleText::getTextBeforeIndex( nIndex, aTextType );
905 // -----------------------------------------------------------------------------
907 TextSegment OAccessibleTextHelper::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (IndexOutOfBoundsException, IllegalArgumentException, RuntimeException)
909 OExternalLockGuard aGuard( this );
911 return OCommonAccessibleText::getTextBehindIndex( nIndex, aTextType );
914 // -----------------------------------------------------------------------------
916 //..............................................................................
917 } // namespace comphelper
918 //..............................................................................