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