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