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
34namespace 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 {
62 Reference< uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
63 m_xBreakIter = i18n::BreakIterator::create(xContext);
64 }
65
66 return m_xBreakIter;
67 }
68
69
70 Reference < i18n::XCharacterClassification > const & OCommonAccessibleText::implGetCharacterClassification()
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
139 Reference< i18n::XCharacterClassification > xCharClass = implGetCharacterClassification();
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
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( std::u16string_view rText, sal_Int32 nIndex )
219 {
220 if ( !implIsValidIndex( nIndex, rText.size() ) )
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( std::u16string_view rText, sal_Int32 nStartIndex, sal_Int32 nEndIndex )
269 {
270
271 if ( !implIsValidRange( nStartIndex, nEndIndex, rText.size() ) )
272 throw IndexOutOfBoundsException();
273
274 sal_Int32 nMinIndex = std::min( nStartIndex, nEndIndex );
275 sal_Int32 nMaxIndex = std::max( nStartIndex, nEndIndex );
276
277 return OUString(rText.substr( 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
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 {
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
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
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 std::u16string_view rOldString,
638 std::u16string_view rNewString,
639 css::uno::Any& rDeleted,
640 css::uno::Any& rInserted) // throw()
641 {
642 size_t nLenOld = rOldString.size();
643 size_t nLenNew = rNewString.size();
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.substr( 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.substr( aDeletedText.SegmentStart, aDeletedText.SegmentEnd - aDeletedText.SegmentStart );
674
675 rDeleted <<= aDeletedText;
676 return true;
677 }
678
679 auto pFirstDiffOld = rOldString.begin();
680 auto pLastDiffOld = rOldString.end();
681 auto pFirstDiffNew = rNewString.begin();
682 auto pLastDiffNew = rNewString.end();
683
684 // find first difference
685 while ((pFirstDiffOld < pLastDiffOld) && (pFirstDiffNew < pLastDiffNew)
686 && (*pFirstDiffOld == *pFirstDiffNew))
687 {
688 pFirstDiffOld++;
689 pFirstDiffNew++;
690 }
691
692 // equality test
693 if (pFirstDiffOld == pLastDiffOld && pFirstDiffNew == pLastDiffNew)
694 return false;
695
696 // find last difference
697 while ( ( pLastDiffOld > pFirstDiffOld) &&
698 ( pLastDiffNew > pFirstDiffNew) &&
699 (pLastDiffOld[-1] == pLastDiffNew[-1]))
700 {
701 pLastDiffOld--;
702 pLastDiffNew--;
703 }
704
705 if (pFirstDiffOld < pLastDiffOld)
706 {
707 aDeletedText.SegmentStart = pFirstDiffOld - rOldString.begin();
708 aDeletedText.SegmentEnd = pLastDiffOld - rOldString.begin();
709 aDeletedText.SegmentText = rOldString.substr( aDeletedText.SegmentStart, aDeletedText.SegmentEnd - aDeletedText.SegmentStart );
710
711 rDeleted <<= aDeletedText;
712 }
713
714 if (pFirstDiffNew < pLastDiffNew)
715 {
716 aInsertedText.SegmentStart = pFirstDiffNew - rNewString.begin();
717 aInsertedText.SegmentEnd = pLastDiffNew - rNewString.begin();
718 aInsertedText.SegmentText = rNewString.substr( aInsertedText.SegmentStart, aInsertedText.SegmentEnd - aInsertedText.SegmentStart );
719
720 rInserted <<= aInsertedText;
721 }
722 return true;
723 }
724
725
726 // OAccessibleTextHelper
727
728
730 {
731 }
732
733
734 // XInterface
735
736
738
739
740 // XTypeProvider
741
742
744
745
746 // XAccessibleText
747
748
749 OUString OAccessibleTextHelper::getSelectedText()
750 {
751 OExternalLockGuard aGuard( this );
752
754 }
755
756
758 {
759 OExternalLockGuard aGuard( this );
760
762 }
763
764
766 {
767 OExternalLockGuard aGuard( this );
768
770 }
771
772
773 TextSegment OAccessibleTextHelper::getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType )
774 {
775 OExternalLockGuard aGuard( this );
776
778 }
779
780
781 TextSegment OAccessibleTextHelper::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType )
782 {
783 OExternalLockGuard aGuard( this );
784
786 }
787
788
789 TextSegment OAccessibleTextHelper::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType )
790 {
791 OExternalLockGuard aGuard( this );
792
794 }
795
796
797} // namespace comphelper
798
799
800/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
a helper class for implementing an AccessibleContext which at the same time supports an XAccessibleEx...
a helper class for implementing an AccessibleExtendedComponent which at the same time supports an XAc...
virtual css::accessibility::TextSegment SAL_CALL getTextBeforeIndex(sal_Int32 nIndex, sal_Int16 aTextType) override
virtual css::accessibility::TextSegment SAL_CALL getTextAtIndex(sal_Int32 nIndex, sal_Int16 aTextType) override
virtual sal_Int32 SAL_CALL getSelectionEnd() override
virtual css::accessibility::TextSegment SAL_CALL getTextBehindIndex(sal_Int32 nIndex, sal_Int16 aTextType) override
virtual sal_Int32 SAL_CALL getSelectionStart() override
css::uno::Reference< css::i18n::XBreakIterator > m_xBreakIter
css::accessibility::TextSegment getTextBeforeIndex(sal_Int32 nIndex, sal_Int16 aTextType)
static bool implIsValidBoundary(css::i18n::Boundary const &rBoundary, sal_Int32 nLength)
virtual void implGetParagraphBoundary(const OUString &rText, css::i18n::Boundary &rBoundary, sal_Int32 nIndex)
css::accessibility::TextSegment getTextAtIndex(sal_Int32 nIndex, sal_Int16 aTextType)
virtual OUString implGetText()=0
static bool implIsValidIndex(sal_Int32 nIndex, sal_Int32 nLength)
static bool implIsValidRange(sal_Int32 nStartIndex, sal_Int32 nEndIndex, sal_Int32 nLength)
css::uno::Reference< css::i18n::XBreakIterator > const & implGetBreakIterator()
virtual void implGetLineBoundary(const OUString &rText, css::i18n::Boundary &rBoundary, sal_Int32 nIndex)
css::uno::Reference< css::i18n::XCharacterClassification > const & implGetCharacterClassification()
bool implGetWordBoundary(const OUString &rText, css::i18n::Boundary &rBoundary, sal_Int32 nIndex)
OUString getSelectedText()
non-virtual versions of the methods
static bool implInitTextChangedEvent(std::u16string_view rOldString, std::u16string_view rNewString, css::uno::Any &rDeleted, css::uno::Any &rInserted)
Helper method, that detects the difference between two strings and returns the deleted selection and ...
virtual void implGetSelection(sal_Int32 &nStartIndex, sal_Int32 &nEndIndex)=0
static sal_Unicode implGetCharacter(std::u16string_view rText, sal_Int32 nIndex)
virtual css::lang::Locale implGetLocale()=0
css::uno::Reference< css::i18n::XCharacterClassification > m_xCharClass
void implGetGlyphBoundary(const OUString &rText, css::i18n::Boundary &rBoundary, sal_Int32 nIndex)
css::accessibility::TextSegment getTextBehindIndex(sal_Int32 nIndex, sal_Int16 aTextType)
void implGetSentenceBoundary(const OUString &rText, css::i18n::Boundary &rBoundary, sal_Int32 nIndex)
static OUString implGetTextRange(std::u16string_view rText, sal_Int32 nStartIndex, sal_Int32 nEndIndex)
int nCount
sal_Int32 nIndex
Reference< XComponentContext > getProcessComponentContext()
This function gets the process service factory's default component context.
QPRO_FUNC_TYPE nType
sal_uInt16 sal_Unicode
#define IMPLEMENT_FORWARD_XTYPEPROVIDER2(classname, baseclass1, baseclass2)
Definition: uno3.hxx:136
#define IMPLEMENT_FORWARD_XINTERFACE2(classname, refcountbase, baseclass2)
Definition: uno3.hxx:99
sal_Int32 nLength