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