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_editeng.hxx" 26 27 //------------------------------------------------------------------------ 28 // 29 // Global header 30 // 31 //------------------------------------------------------------------------ 32 33 #include <limits.h> 34 #include <vector> 35 #include <algorithm> 36 #include <boost/bind.hpp> 37 #include <vos/mutex.hxx> 38 #include <vcl/window.hxx> 39 #include <vcl/svapp.hxx> 40 #include <comphelper/sequenceasvector.hxx> 41 #include <com/sun/star/uno/Any.hxx> 42 #include <com/sun/star/uno/Reference.hxx> 43 #include <com/sun/star/awt/Point.hpp> 44 #include <com/sun/star/awt/Rectangle.hpp> 45 #include <com/sun/star/accessibility/AccessibleTextType.hpp> 46 47 //------------------------------------------------------------------------ 48 // 49 // Project-local header 50 // 51 //------------------------------------------------------------------------ 52 53 #include <editeng/editdata.hxx> 54 #include <editeng/unopracc.hxx> 55 #include "editeng/unoedprx.hxx" 56 #include <editeng/AccessibleStaticTextBase.hxx> 57 #include "editeng/AccessibleEditableTextPara.hxx" 58 59 60 using namespace ::com::sun::star; 61 using namespace ::com::sun::star::accessibility; 62 63 /* TODO: 64 ===== 65 66 - separate adapter functionality from AccessibleStaticText class 67 68 - refactor common loops into templates, using mem_fun 69 70 */ 71 72 namespace accessibility 73 { 74 typedef ::comphelper::SequenceAsVector< beans::PropertyValue > PropertyValueVector; 75 76 class PropertyValueEqualFunctor : public ::std::binary_function< beans::PropertyValue, beans::PropertyValue, bool > 77 { 78 public: 79 PropertyValueEqualFunctor() 80 {} 81 bool operator() ( const beans::PropertyValue& lhs, const beans::PropertyValue& rhs ) const 82 { 83 return ( lhs.Name == rhs.Name && lhs.Value == rhs.Value ); 84 } 85 }; 86 //IAccessibility2 Implementation 2009----- 87 sal_Unicode cNewLine(0x0a); 88 //-----IAccessibility2 Implementation 2009 89 //------------------------------------------------------------------------ 90 // 91 // Static Helper 92 // 93 //------------------------------------------------------------------------ 94 ESelection MakeSelection( sal_Int32 nStartPara, sal_Int32 nStartIndex, 95 sal_Int32 nEndPara, sal_Int32 nEndIndex ) 96 { 97 DBG_ASSERT(nStartPara >= 0 && nStartPara <= USHRT_MAX && 98 nStartIndex >= 0 && nStartIndex <= USHRT_MAX && 99 nEndPara >= 0 && nEndPara <= USHRT_MAX && 100 nEndIndex >= 0 && nEndIndex <= USHRT_MAX , 101 "AccessibleStaticTextBase_Impl::MakeSelection: index value overflow"); 102 103 return ESelection( static_cast< sal_uInt16 >(nStartPara), static_cast< sal_uInt16 >(nStartIndex), 104 static_cast< sal_uInt16 >(nEndPara), static_cast< sal_uInt16 >(nEndIndex) ); 105 } 106 107 //------------------------------------------------------------------------ 108 // 109 // AccessibleStaticTextBase_Impl declaration 110 // 111 //------------------------------------------------------------------------ 112 113 DBG_NAME( AccessibleStaticTextBase_Impl ); 114 115 /** AccessibleStaticTextBase_Impl 116 117 This class implements the AccessibleStaticTextBase 118 functionality, mainly by forwarding the calls to an aggregated 119 AccessibleEditableTextPara. As this is a therefore non-trivial 120 adapter, factoring out the common functionality from 121 AccessibleEditableTextPara might be a profitable future task. 122 */ 123 class AccessibleStaticTextBase_Impl 124 { 125 //IAccessibility2 Implementation 2009----- 126 friend class AccessibleStaticTextBase; 127 //-----IAccessibility2 Implementation 2009 128 public: 129 130 // receive pointer to our frontend class and view window 131 AccessibleStaticTextBase_Impl(); 132 ~AccessibleStaticTextBase_Impl(); 133 134 SvxEditSourceAdapter& GetEditSource() const SAL_THROW((uno::RuntimeException)) 135 { 136 DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL ); 137 138 return maEditSource; 139 } 140 void SetEditSource( ::std::auto_ptr< SvxEditSource > pEditSource ) SAL_THROW((uno::RuntimeException)); 141 142 void SetEventSource( const uno::Reference< XAccessible >& rInterface ) 143 { 144 DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL ); 145 146 mxThis = rInterface; 147 } 148 uno::Reference< XAccessible > GetEventSource() const 149 { 150 DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL ); 151 152 return mxThis; 153 } 154 155 void SetOffset( const Point& ); 156 Point GetOffset() const 157 { 158 DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL ); 159 160 ::osl::MutexGuard aGuard( maMutex ); Point aPoint( maOffset ); 161 return aPoint; 162 } 163 164 void UpdateChildren(); 165 void Dispose(); 166 167 #ifdef DBG_UTIL 168 void CheckInvariants() const; 169 #endif 170 171 AccessibleEditableTextPara& GetParagraph( sal_Int32 nPara ) const; 172 sal_Int32 GetParagraphCount() const; 173 sal_Int32 GetParagraphIndex() const; 174 sal_Int32 GetLineCount( sal_Int32 nParagraph ) const; 175 176 EPosition Index2Internal( sal_Int32 nFlatIndex ) const 177 { 178 DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL ); 179 180 return ImpCalcInternal( nFlatIndex, false ); 181 } 182 183 EPosition Range2Internal( sal_Int32 nFlatIndex ) const 184 { 185 DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL ); 186 187 return ImpCalcInternal( nFlatIndex, true ); 188 } 189 190 sal_Int32 Internal2Index( EPosition nEEIndex ) const; 191 192 void CorrectTextSegment( TextSegment& aTextSegment, 193 int nPara ) const; 194 195 sal_Bool SetSelection( sal_Int32 nStartPara, sal_Int32 nStartIndex, 196 sal_Int32 nEndPara, sal_Int32 nEndIndex ); 197 sal_Bool CopyText( sal_Int32 nStartPara, sal_Int32 nStartIndex, 198 sal_Int32 nEndPara, sal_Int32 nEndIndex ); 199 200 Rectangle GetParagraphBoundingBox() const; 201 //IAccessibility2 Implementation 2009----- 202 sal_Bool RemoveLineBreakCount( sal_Int32& rIndex ); 203 //-----IAccessibility2 Implementation 2009 204 205 private: 206 207 EPosition ImpCalcInternal( sal_Int32 nFlatIndex, bool bExclusive ) const; 208 209 // our frontend class (the one implementing the actual 210 // interface). That's not necessarily the one containing the impl 211 // pointer 212 uno::Reference< XAccessible > mxThis; 213 214 // implements our functionality, we're just an adapter (guarded by solar mutex) 215 mutable AccessibleEditableTextPara* mpTextParagraph; 216 217 uno::Reference< XAccessible > mxParagraph; 218 219 // a wrapper for the text forwarders (guarded by solar mutex) 220 mutable SvxEditSourceAdapter maEditSource; 221 222 // guard for maOffset 223 mutable ::osl::Mutex maMutex; 224 225 /// our current offset to the containing shape/cell (guarded by maMutex) 226 Point maOffset; 227 228 }; 229 230 //------------------------------------------------------------------------ 231 // 232 // AccessibleStaticTextBase_Impl implementation 233 // 234 //------------------------------------------------------------------------ 235 236 AccessibleStaticTextBase_Impl::AccessibleStaticTextBase_Impl() : 237 mxThis( NULL ), 238 mpTextParagraph( new AccessibleEditableTextPara(NULL) ), 239 mxParagraph( mpTextParagraph ), 240 maEditSource(), 241 maMutex(), 242 maOffset(0,0) 243 { 244 DBG_CTOR( AccessibleStaticTextBase_Impl, NULL ); 245 246 // TODO: this is still somewhat of a hack, all the more since 247 // now the maTextParagraph has an empty parent reference set 248 } 249 250 AccessibleStaticTextBase_Impl::~AccessibleStaticTextBase_Impl() 251 { 252 DBG_DTOR( AccessibleStaticTextBase_Impl, NULL ); 253 } 254 255 void AccessibleStaticTextBase_Impl::SetEditSource( ::std::auto_ptr< SvxEditSource > pEditSource ) SAL_THROW((uno::RuntimeException)) 256 { 257 DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL ); 258 259 maEditSource.SetEditSource( pEditSource ); 260 if( mpTextParagraph ) 261 mpTextParagraph->SetEditSource( &maEditSource ); 262 } 263 264 void AccessibleStaticTextBase_Impl::SetOffset( const Point& rPoint ) 265 { 266 DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL ); 267 268 // guard against non-atomic access to maOffset data structure 269 { 270 ::osl::MutexGuard aGuard( maMutex ); 271 maOffset = rPoint; 272 } 273 274 if( mpTextParagraph ) 275 mpTextParagraph->SetEEOffset( rPoint ); 276 277 // in all cases, check visibility afterwards. 278 UpdateChildren(); 279 } 280 281 void AccessibleStaticTextBase_Impl::UpdateChildren() 282 { 283 DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL ); 284 285 // currently no children 286 } 287 288 void AccessibleStaticTextBase_Impl::Dispose() 289 { 290 DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL ); 291 292 // we're the owner of the paragraph, so destroy it, too 293 if( mpTextParagraph ) 294 mpTextParagraph->Dispose(); 295 296 // drop references 297 mxParagraph = NULL; 298 mxThis = NULL; 299 mpTextParagraph = NULL; 300 } 301 302 #ifdef DBG_UTIL 303 void AccessibleStaticTextBase_Impl::CheckInvariants() const 304 { 305 // TODO 306 } 307 #endif 308 309 AccessibleEditableTextPara& AccessibleStaticTextBase_Impl::GetParagraph( sal_Int32 nPara ) const 310 { 311 DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL ); 312 313 if( !mpTextParagraph ) 314 throw lang::DisposedException ( 315 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("object has been already disposed")), mxThis ); 316 317 // TODO: Have a differnt method on AccessibleEditableTextPara 318 // that does not care about state changes 319 mpTextParagraph->SetParagraphIndex( nPara ); 320 321 return *mpTextParagraph; 322 } 323 324 sal_Int32 AccessibleStaticTextBase_Impl::GetParagraphCount() const 325 { 326 DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL ); 327 328 if( !mpTextParagraph ) 329 return 0; 330 else 331 return mpTextParagraph->GetTextForwarder().GetParagraphCount(); 332 } 333 334 sal_Int32 AccessibleStaticTextBase_Impl::GetParagraphIndex() const 335 { 336 DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL ); 337 338 sal_Int32 nIndex = -1; 339 if( mpTextParagraph ) 340 nIndex = mpTextParagraph->GetParagraphIndex(); 341 return nIndex; 342 } 343 344 sal_Int32 AccessibleStaticTextBase_Impl::GetLineCount( sal_Int32 nParagraph ) const 345 { 346 DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL ); 347 348 sal_Int32 nIndex = 0; 349 if( mpTextParagraph ) 350 nIndex = mpTextParagraph->GetTextForwarder().GetLineCount( static_cast< sal_uInt16 >(nParagraph) ); 351 return nIndex; 352 } 353 354 sal_Int32 AccessibleStaticTextBase_Impl::Internal2Index( EPosition nEEIndex ) const 355 { 356 sal_Int32 aRes(0); 357 int i; 358 for(i=0; i<nEEIndex.nPara; ++i) 359 aRes += GetParagraph(i).getCharacterCount(); 360 361 return aRes + nEEIndex.nIndex; 362 } 363 364 void AccessibleStaticTextBase_Impl::CorrectTextSegment( TextSegment& aTextSegment, 365 int nPara ) const 366 { 367 // Keep 'invalid' values at the TextSegment 368 if( aTextSegment.SegmentStart != -1 && 369 aTextSegment.SegmentStart != -1 ) 370 { 371 // #112814# Correct TextSegment by paragraph offset 372 sal_Int32 nOffset(0); 373 int i; 374 for(i=0; i<nPara; ++i) 375 nOffset += GetParagraph(i).getCharacterCount(); 376 377 aTextSegment.SegmentStart += nOffset; 378 aTextSegment.SegmentEnd += nOffset; 379 } 380 } 381 382 EPosition AccessibleStaticTextBase_Impl::ImpCalcInternal( sal_Int32 nFlatIndex, bool bExclusive ) const 383 { 384 DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL ); 385 386 if( nFlatIndex < 0 ) 387 throw lang::IndexOutOfBoundsException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AccessibleStaticTextBase_Impl::Index2Internal: character index out of bounds")), 388 mxThis); 389 // gratuitously accepting larger indices here, AccessibleEditableTextPara will throw eventually 390 391 sal_Int32 nCurrPara, nCurrIndex, nParas, nCurrCount; 392 for( nCurrPara=0, nParas=GetParagraphCount(), nCurrCount=0, nCurrIndex=0; nCurrPara<nParas; ++nCurrPara ) 393 { 394 nCurrCount = GetParagraph( nCurrPara ).getCharacterCount(); 395 nCurrIndex += nCurrCount; 396 //IAccessibility2 Implementation 2009----- 397 if( nCurrIndex >= nFlatIndex ) 398 //-----IAccessibility2 Implementation 2009 399 { 400 // check overflow 401 DBG_ASSERT(nCurrPara >= 0 && nCurrPara <= USHRT_MAX && 402 nFlatIndex - nCurrIndex + nCurrCount >= 0 && nFlatIndex - nCurrIndex + nCurrCount <= USHRT_MAX , 403 "AccessibleStaticTextBase_Impl::Index2Internal: index value overflow"); 404 405 return EPosition( static_cast< sal_uInt16 >(nCurrPara), static_cast< sal_uInt16 >(nFlatIndex - nCurrIndex + nCurrCount) ); 406 } 407 } 408 409 // #102170# Allow one-past the end for ranges 410 if( bExclusive && nCurrIndex == nFlatIndex ) 411 { 412 // check overflow 413 DBG_ASSERT(nCurrPara >= 0 && nCurrPara <= USHRT_MAX && 414 nFlatIndex - nCurrIndex + nCurrCount >= 0 && nFlatIndex - nCurrIndex + nCurrCount <= USHRT_MAX , 415 "AccessibleStaticTextBase_Impl::Index2Internal: index value overflow"); 416 417 return EPosition( static_cast< sal_uInt16 >(nCurrPara-1), static_cast< sal_uInt16 >(nFlatIndex - nCurrIndex + nCurrCount) ); 418 } 419 420 // not found? Out of bounds 421 throw lang::IndexOutOfBoundsException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AccessibleStaticTextBase_Impl::Index2Internal: character index out of bounds")), 422 mxThis); 423 } 424 425 sal_Bool AccessibleStaticTextBase_Impl::SetSelection( sal_Int32 nStartPara, sal_Int32 nStartIndex, 426 sal_Int32 nEndPara, sal_Int32 nEndIndex ) 427 { 428 DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL ); 429 430 if( !mpTextParagraph ) 431 return sal_False; 432 433 try 434 { 435 SvxEditViewForwarder& rCacheVF = mpTextParagraph->GetEditViewForwarder( sal_True ); 436 return rCacheVF.SetSelection( MakeSelection(nStartPara, nStartIndex, nEndPara, nEndIndex) ); 437 } 438 catch( const uno::RuntimeException& ) 439 { 440 return sal_False; 441 } 442 } 443 444 sal_Bool AccessibleStaticTextBase_Impl::CopyText( sal_Int32 nStartPara, sal_Int32 nStartIndex, 445 sal_Int32 nEndPara, sal_Int32 nEndIndex ) 446 { 447 DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL ); 448 449 if( !mpTextParagraph ) 450 return sal_False; 451 452 try 453 { 454 SvxEditViewForwarder& rCacheVF = mpTextParagraph->GetEditViewForwarder( sal_True ); 455 mpTextParagraph->GetTextForwarder(); // MUST be after GetEditViewForwarder(), see method docs 456 sal_Bool aRetVal; 457 458 // save current selection 459 ESelection aOldSelection; 460 461 rCacheVF.GetSelection( aOldSelection ); 462 rCacheVF.SetSelection( MakeSelection(nStartPara, nStartIndex, nEndPara, nEndIndex) ); 463 aRetVal = rCacheVF.Copy(); 464 rCacheVF.SetSelection( aOldSelection ); // restore 465 466 return aRetVal; 467 } 468 catch( const uno::RuntimeException& ) 469 { 470 return sal_False; 471 } 472 } 473 474 Rectangle AccessibleStaticTextBase_Impl::GetParagraphBoundingBox() const 475 { 476 Rectangle aRect; 477 if( mpTextParagraph ) 478 { 479 awt::Rectangle aAwtRect = mpTextParagraph->getBounds(); 480 aRect = Rectangle( Point( aAwtRect.X, aAwtRect.Y ), Size( aAwtRect.Width, aAwtRect.Height ) ); 481 } 482 else 483 { 484 aRect.SetEmpty(); 485 } 486 return aRect; 487 } 488 //IAccessibility2 Implementation 2009----- 489 //the input argument is the index(including "\n" ) in the string. 490 //the function will calculate the actual index(not including "\n") in the string. 491 //and return true if the index is just at a "\n" 492 sal_Bool AccessibleStaticTextBase_Impl::RemoveLineBreakCount( sal_Int32& rIndex ) 493 { 494 // get the total char number inside the cell. 495 sal_Int32 i, nCount, nParas; 496 for( i=0, nCount=0, nParas=GetParagraphCount(); i<nParas; ++i ) 497 nCount += GetParagraph(i).getCharacterCount(); 498 nCount = nCount + (nParas-1); 499 if( nCount == 0 && rIndex == 0) return sal_False; 500 501 502 sal_Int32 nCurrPara, nCurrCount; 503 sal_Int32 nLineBreakPos = 0, nLineBreakCount = 0; 504 sal_Int32 nParaCount = GetParagraphCount(); 505 for ( nCurrCount = 0, nCurrPara = 0; nCurrPara < nParaCount; nCurrPara++ ) 506 { 507 nCurrCount += GetParagraph( nCurrPara ).getCharacterCount(); 508 nLineBreakPos = nCurrCount++; 509 if ( rIndex == nLineBreakPos ) 510 { 511 rIndex -= (++nLineBreakCount);//(++nLineBreakCount); 512 if ( rIndex < 0) 513 { 514 rIndex = 0; 515 } 516 //if the index is at the last position of the last paragraph 517 //there is no "\n" , so we should increase rIndex by 1 and return false. 518 if ( (nCurrPara+1) == nParaCount ) 519 { 520 rIndex++; 521 return sal_False; 522 } 523 else 524 { 525 return sal_True; 526 } 527 } 528 else if ( rIndex < nLineBreakPos ) 529 { 530 rIndex -= nLineBreakCount; 531 return sal_False; 532 } 533 else 534 { 535 nLineBreakCount++; 536 } 537 } 538 return sal_False; 539 } 540 //-----IAccessibility2 Implementation 2009 541 //------------------------------------------------------------------------ 542 // 543 // AccessibleStaticTextBase implementation 544 // 545 //------------------------------------------------------------------------ 546 547 AccessibleStaticTextBase::AccessibleStaticTextBase( ::std::auto_ptr< SvxEditSource > pEditSource ) : 548 mpImpl( new AccessibleStaticTextBase_Impl() ) 549 { 550 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 551 552 SetEditSource( pEditSource ); 553 } 554 555 AccessibleStaticTextBase::~AccessibleStaticTextBase() 556 { 557 } 558 559 const SvxEditSource& AccessibleStaticTextBase::GetEditSource() const SAL_THROW((::com::sun::star::uno::RuntimeException)) 560 { 561 #ifdef DBG_UTIL 562 mpImpl->CheckInvariants(); 563 564 const SvxEditSource& aEditSource = mpImpl->GetEditSource(); 565 566 mpImpl->CheckInvariants(); 567 568 return aEditSource; 569 #else 570 return mpImpl->GetEditSource(); 571 #endif 572 } 573 574 void AccessibleStaticTextBase::SetEditSource( ::std::auto_ptr< SvxEditSource > pEditSource ) SAL_THROW((::com::sun::star::uno::RuntimeException)) 575 { 576 #ifdef DBG_UTIL 577 // precondition: solar mutex locked 578 DBG_TESTSOLARMUTEX(); 579 580 mpImpl->CheckInvariants(); 581 582 mpImpl->SetEditSource( pEditSource ); 583 584 mpImpl->CheckInvariants(); 585 #else 586 mpImpl->SetEditSource( pEditSource ); 587 #endif 588 } 589 590 void AccessibleStaticTextBase::SetEventSource( const uno::Reference< XAccessible >& rInterface ) 591 { 592 #ifdef DBG_UTIL 593 mpImpl->CheckInvariants(); 594 #endif 595 596 mpImpl->SetEventSource( rInterface ); 597 598 #ifdef DBG_UTIL 599 mpImpl->CheckInvariants(); 600 #endif 601 } 602 603 uno::Reference< XAccessible > AccessibleStaticTextBase::GetEventSource() const 604 { 605 #ifdef DBG_UTIL 606 mpImpl->CheckInvariants(); 607 608 uno::Reference< XAccessible > xRet( mpImpl->GetEventSource() ); 609 610 mpImpl->CheckInvariants(); 611 612 return xRet; 613 #else 614 return mpImpl->GetEventSource(); 615 #endif 616 } 617 618 void AccessibleStaticTextBase::SetOffset( const Point& rPoint ) 619 { 620 #ifdef DBG_UTIL 621 // precondition: solar mutex locked 622 DBG_TESTSOLARMUTEX(); 623 624 mpImpl->CheckInvariants(); 625 626 mpImpl->SetOffset( rPoint ); 627 628 mpImpl->CheckInvariants(); 629 #else 630 mpImpl->SetOffset( rPoint ); 631 #endif 632 } 633 634 Point AccessibleStaticTextBase::GetOffset() const 635 { 636 #ifdef DBG_UTIL 637 mpImpl->CheckInvariants(); 638 639 Point aPoint( mpImpl->GetOffset() ); 640 641 mpImpl->CheckInvariants(); 642 643 return aPoint; 644 #else 645 return mpImpl->GetOffset(); 646 #endif 647 } 648 649 void AccessibleStaticTextBase::UpdateChildren() SAL_THROW((::com::sun::star::uno::RuntimeException)) 650 { 651 #ifdef DBG_UTIL 652 // precondition: solar mutex locked 653 DBG_TESTSOLARMUTEX(); 654 655 mpImpl->CheckInvariants(); 656 657 mpImpl->UpdateChildren(); 658 659 mpImpl->CheckInvariants(); 660 #else 661 mpImpl->UpdateChildren(); 662 #endif 663 } 664 665 void AccessibleStaticTextBase::Dispose() 666 { 667 #ifdef DBG_UTIL 668 mpImpl->CheckInvariants(); 669 #endif 670 671 mpImpl->Dispose(); 672 673 #ifdef DBG_UTIL 674 mpImpl->CheckInvariants(); 675 #endif 676 } 677 678 // XAccessibleContext 679 sal_Int32 SAL_CALL AccessibleStaticTextBase::getAccessibleChildCount() throw (uno::RuntimeException) 680 { 681 // no children at all 682 return 0; 683 } 684 685 uno::Reference< XAccessible > SAL_CALL AccessibleStaticTextBase::getAccessibleChild( sal_Int32 /*i*/ ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 686 { 687 // no children at all 688 return uno::Reference< XAccessible >(); 689 } 690 691 uno::Reference< XAccessible > SAL_CALL AccessibleStaticTextBase::getAccessibleAtPoint( const awt::Point& /*_aPoint*/ ) throw (uno::RuntimeException) 692 { 693 // no children at all 694 return uno::Reference< XAccessible >(); 695 } 696 697 // XAccessibleText 698 sal_Int32 SAL_CALL AccessibleStaticTextBase::getCaretPosition() throw (uno::RuntimeException) 699 { 700 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 701 702 sal_Int32 i, nPos, nParas; 703 for( i=0, nPos=-1, nParas=mpImpl->GetParagraphCount(); i<nParas; ++i ) 704 { 705 if( (nPos=mpImpl->GetParagraph(i).getCaretPosition()) != -1 ) 706 return nPos; 707 } 708 709 return nPos; 710 } 711 712 sal_Bool SAL_CALL AccessibleStaticTextBase::setCaretPosition( sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 713 { 714 return setSelection(nIndex, nIndex); 715 } 716 717 sal_Unicode SAL_CALL AccessibleStaticTextBase::getCharacter( sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 718 { 719 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 720 721 EPosition aPos( mpImpl->Index2Internal(nIndex) ); 722 723 return mpImpl->GetParagraph( aPos.nPara ).getCharacter( aPos.nIndex ); 724 } 725 726 uno::Sequence< beans::PropertyValue > SAL_CALL AccessibleStaticTextBase::getCharacterAttributes( sal_Int32 nIndex, const ::com::sun::star::uno::Sequence< ::rtl::OUString >& aRequestedAttributes ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 727 { 728 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 729 //IAccessibility2 Implementation 2009----- 730 //get the actual index without "\n" 731 mpImpl->RemoveLineBreakCount( nIndex ); 732 //IAccessibility2 Implementation 2009----- 733 734 EPosition aPos( mpImpl->Index2Internal(nIndex) ); 735 736 return mpImpl->GetParagraph( aPos.nPara ).getCharacterAttributes( aPos.nIndex, aRequestedAttributes ); 737 } 738 739 awt::Rectangle SAL_CALL AccessibleStaticTextBase::getCharacterBounds( sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 740 { 741 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 742 743 // #108900# Allow ranges for nIndex, as one-past-the-end 744 // values are now legal, too. 745 EPosition aPos( mpImpl->Range2Internal(nIndex) ); 746 747 // #i70916# Text in spread sheet cells return the wrong extents 748 AccessibleEditableTextPara& rPara = mpImpl->GetParagraph( aPos.nPara ); 749 awt::Rectangle aParaBounds( rPara.getBounds() ); 750 awt::Rectangle aBounds( rPara.getCharacterBounds( aPos.nIndex ) ); 751 aBounds.X += aParaBounds.X; 752 aBounds.Y += aParaBounds.Y; 753 754 return aBounds; 755 } 756 757 sal_Int32 SAL_CALL AccessibleStaticTextBase::getCharacterCount() throw (uno::RuntimeException) 758 { 759 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 760 761 sal_Int32 i, nCount, nParas; 762 for( i=0, nCount=0, nParas=mpImpl->GetParagraphCount(); i<nParas; ++i ) 763 nCount += mpImpl->GetParagraph(i).getCharacterCount(); 764 //IAccessibility2 Implementation 2009----- 765 //count on the number of "\n" which equals number of paragraphs decrease 1. 766 nCount = nCount + (nParas-1); 767 //IAccessibility2 Implementation 2009----- 768 return nCount; 769 } 770 771 sal_Int32 SAL_CALL AccessibleStaticTextBase::getIndexAtPoint( const awt::Point& rPoint ) throw (uno::RuntimeException) 772 { 773 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 774 775 const sal_Int32 nParas( mpImpl->GetParagraphCount() ); 776 sal_Int32 nIndex; 777 int i; 778 for( i=0; i<nParas; ++i ) 779 { 780 // TODO: maybe exploit the fact that paragraphs are 781 // ordered vertically for early exit 782 783 // #i70916# Text in spread sheet cells return the wrong extents 784 AccessibleEditableTextPara& rPara = mpImpl->GetParagraph( i ); 785 awt::Rectangle aParaBounds( rPara.getBounds() ); 786 awt::Point aPoint( rPoint ); 787 aPoint.X -= aParaBounds.X; 788 aPoint.Y -= aParaBounds.Y; 789 790 // #112814# Use correct index offset 791 if ( ( nIndex = rPara.getIndexAtPoint( aPoint ) ) != -1 ) 792 return mpImpl->Internal2Index( EPosition(sal::static_int_cast<sal_uInt16>(i), 793 sal::static_int_cast<sal_uInt16>(nIndex)) ); 794 } 795 796 return -1; 797 } 798 799 ::rtl::OUString SAL_CALL AccessibleStaticTextBase::getSelectedText() throw (uno::RuntimeException) 800 { 801 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 802 803 sal_Int32 nStart( getSelectionStart() ); 804 sal_Int32 nEnd( getSelectionEnd() ); 805 806 // #104481# Return the empty string for 'no selection' 807 if( nStart < 0 || nEnd < 0 ) 808 return ::rtl::OUString(); 809 810 return getTextRange( nStart, nEnd ); 811 } 812 813 sal_Int32 SAL_CALL AccessibleStaticTextBase::getSelectionStart() throw (uno::RuntimeException) 814 { 815 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 816 817 sal_Int32 i, nPos, nParas; 818 for( i=0, nPos=-1, nParas=mpImpl->GetParagraphCount(); i<nParas; ++i ) 819 { 820 if( (nPos=mpImpl->GetParagraph(i).getSelectionStart()) != -1 ) 821 return nPos; 822 } 823 824 return nPos; 825 } 826 827 sal_Int32 SAL_CALL AccessibleStaticTextBase::getSelectionEnd() throw (uno::RuntimeException) 828 { 829 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 830 831 sal_Int32 i, nPos, nParas; 832 for( i=0, nPos=-1, nParas=mpImpl->GetParagraphCount(); i<nParas; ++i ) 833 { 834 if( (nPos=mpImpl->GetParagraph(i).getSelectionEnd()) != -1 ) 835 return nPos; 836 } 837 838 return nPos; 839 } 840 841 sal_Bool SAL_CALL AccessibleStaticTextBase::setSelection( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 842 { 843 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 844 845 EPosition aStartIndex( mpImpl->Range2Internal(nStartIndex) ); 846 EPosition aEndIndex( mpImpl->Range2Internal(nEndIndex) ); 847 848 return mpImpl->SetSelection( aStartIndex.nPara, aStartIndex.nIndex, 849 aEndIndex.nPara, aEndIndex.nIndex ); 850 } 851 852 ::rtl::OUString SAL_CALL AccessibleStaticTextBase::getText() throw (uno::RuntimeException) 853 { 854 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 855 856 sal_Int32 i, nParas; 857 ::rtl::OUString aRes; 858 for( i=0, nParas=mpImpl->GetParagraphCount(); i<nParas; ++i ) 859 aRes += mpImpl->GetParagraph(i).getText(); 860 861 return aRes; 862 } 863 864 ::rtl::OUString SAL_CALL AccessibleStaticTextBase::getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 865 { 866 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 867 868 if( nStartIndex > nEndIndex ) 869 ::std::swap(nStartIndex, nEndIndex); 870 //IAccessibility2 Implementation 2009----- 871 //if startindex equals endindex we will get nothing. So return an empty string directly. 872 if ( nStartIndex == nEndIndex ) 873 { 874 ::rtl::OUString sEmptyStr; 875 return sEmptyStr; 876 } 877 sal_Bool bStart = mpImpl->RemoveLineBreakCount( nStartIndex ); 878 //if the start index is just at a "\n", we need to begin from the next char 879 if ( bStart ) 880 { 881 nStartIndex++; 882 } 883 //we need to find out whether the previous position of the current endindex is at "\n" or not 884 //if yes we need to mark it and add "\n" at the end of the result 885 sal_Int32 nTemp = nEndIndex - 1; 886 sal_Bool bEnd = mpImpl->RemoveLineBreakCount( nTemp ); 887 sal_Bool bTemp = mpImpl->RemoveLineBreakCount( nEndIndex ); 888 //if the below condition is true it indicates an empty paragraph with just a "\n" 889 //so we need to set one "\n" flag to avoid duplication. 890 if ( bStart && bEnd && ( nStartIndex == nEndIndex) ) 891 { 892 bEnd = sal_False; 893 } 894 //if the current endindex is at a "\n", we need to increase endindex by 1 to make sure 895 //the char before "\n" is included. Because string returned by this function will not include 896 //the char at the endindex. 897 if ( bTemp ) 898 { 899 nEndIndex++; 900 } 901 ::rtl::OUString aRes; 902 EPosition aStartIndex( mpImpl->Range2Internal(nStartIndex) ); 903 EPosition aEndIndex( mpImpl->Range2Internal(nEndIndex) ); 904 905 // #102170# Special case: start and end paragraph are identical 906 if( aStartIndex.nPara == aEndIndex.nPara ) 907 { 908 //we don't return the string directly now for that we have to do some further process for "\n" 909 aRes = mpImpl->GetParagraph( aStartIndex.nPara ).getTextRange( aStartIndex.nIndex, aEndIndex.nIndex ); 910 //return mpImpl->GetParagraph( aStartIndex.nPara ).getTextRange( aStartIndex.nIndex, aEndIndex.nIndex ); 911 //-----IAccessibility2 Implementation 2009 912 } 913 else 914 { 915 sal_Int32 i( aStartIndex.nPara ); 916 //IAccessibility2 Implementation 2009----- 917 aRes = mpImpl->GetParagraph(i).getTextRange( aStartIndex.nIndex, 918 mpImpl->GetParagraph(i).getCharacterCount()/*-1*/); 919 //-----IAccessibility2 Implementation 2009 920 ++i; 921 922 // paragraphs inbetween are fully included 923 for( ; i<aEndIndex.nPara; ++i ) 924 //IAccessibility2 Implementation 2009----- 925 { 926 aRes += rtl::OUString(cNewLine); 927 aRes += mpImpl->GetParagraph(i).getText(); 928 } 929 930 if( i<=aEndIndex.nPara ) 931 { 932 //if the below condition is mathed it means the endindex is at mid of the last paragraph 933 //we need to add a "\n" before we add the last part of the string. 934 if ( !bEnd && aEndIndex.nIndex ) 935 { 936 aRes += rtl::OUString(cNewLine); 937 } 938 aRes += mpImpl->GetParagraph(i).getTextRange( 0, aEndIndex.nIndex ); 939 } 940 //return aRes; 941 } 942 //According the the flag we marked before, we have to add "\n" at the beginning 943 //or at the end of the result string. 944 if ( bStart ) 945 { 946 aRes = rtl::OUString(cNewLine) + aRes; 947 } 948 if ( bEnd ) 949 { 950 aRes += rtl::OUString(cNewLine); 951 } 952 return aRes; 953 //-----IAccessibility2 Implementation 2009 954 } 955 956 ::com::sun::star::accessibility::TextSegment SAL_CALL AccessibleStaticTextBase::getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) 957 { 958 //IAccessibility2 Implementation 2009----- 959 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 960 961 sal_Bool bLineBreak = mpImpl->RemoveLineBreakCount( nIndex ); 962 //-----IAccessibility2 Implementation 2009 963 EPosition aPos( mpImpl->Range2Internal(nIndex) ); 964 965 ::com::sun::star::accessibility::TextSegment aResult; 966 967 if( AccessibleTextType::PARAGRAPH == aTextType ) 968 { 969 // #106393# Special casing one behind last paragraph is 970 // not necessary, since then, we return the content and 971 // boundary of that last paragraph. Range2Internal is 972 // tolerant against that, and returns the last paragraph 973 // in aPos.nPara. 974 975 // retrieve full text of the paragraph 976 aResult.SegmentText = mpImpl->GetParagraph( aPos.nPara ).getText(); 977 978 // #112814# Adapt the start index with the paragraph offset 979 aResult.SegmentStart = mpImpl->Internal2Index( EPosition( aPos.nPara, 0 ) ); 980 aResult.SegmentEnd = aResult.SegmentStart + aResult.SegmentText.getLength(); 981 } 982 //IAccessibility2 Implementation 2009----- 983 else if ( AccessibleTextType::ATTRIBUTE_RUN == aTextType ) 984 { 985 SvxAccessibleTextAdapter& rTextForwarder = mpImpl->GetParagraph( aPos.nIndex ).GetTextForwarder(); 986 sal_uInt16 nStartIndex, nEndIndex; 987 if ( rTextForwarder.GetAttributeRun( nStartIndex, nEndIndex, aPos.nPara, aPos.nIndex, sal_True ) ) 988 { 989 aResult.SegmentText = getTextRange( nStartIndex, nEndIndex ); 990 aResult.SegmentStart = nStartIndex; 991 aResult.SegmentEnd = nEndIndex; 992 } 993 } 994 //-----IAccessibility2 Implementation 2009 995 else 996 { 997 // No special handling required, forward to wrapped class 998 aResult = mpImpl->GetParagraph( aPos.nPara ).getTextAtIndex( aPos.nIndex, aTextType ); 999 1000 // #112814# Adapt the start index with the paragraph offset 1001 mpImpl->CorrectTextSegment( aResult, aPos.nPara ); 1002 //IAccessibility2 Implementation 2009----- 1003 if ( bLineBreak ) 1004 { 1005 aResult.SegmentText = rtl::OUString(cNewLine); 1006 } 1007 //-----IAccessibility2 Implementation 2009 1008 } 1009 1010 return aResult; 1011 } 1012 1013 ::com::sun::star::accessibility::TextSegment SAL_CALL AccessibleStaticTextBase::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) 1014 { 1015 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 1016 //IAccessibility2 Implementation 2009----- 1017 sal_Int32 nOldIdx = nIndex; 1018 sal_Bool bLineBreak = mpImpl->RemoveLineBreakCount( nIndex ); 1019 //-----IAccessibility2 Implementation 2009 1020 EPosition aPos( mpImpl->Range2Internal(nIndex) ); 1021 1022 ::com::sun::star::accessibility::TextSegment aResult; 1023 1024 if( AccessibleTextType::PARAGRAPH == aTextType ) 1025 { 1026 if( aPos.nIndex == mpImpl->GetParagraph( aPos.nPara ).getCharacterCount() ) 1027 { 1028 // #103589# Special casing one behind the last paragraph 1029 aResult.SegmentText = mpImpl->GetParagraph( aPos.nPara ).getText(); 1030 1031 // #112814# Adapt the start index with the paragraph offset 1032 aResult.SegmentStart = mpImpl->Internal2Index( EPosition( aPos.nPara, 0 ) ); 1033 } 1034 else if( aPos.nPara > 0 ) 1035 { 1036 aResult.SegmentText = mpImpl->GetParagraph( aPos.nPara - 1 ).getText(); 1037 1038 // #112814# Adapt the start index with the paragraph offset 1039 aResult.SegmentStart = mpImpl->Internal2Index( EPosition( aPos.nPara - 1, 0 ) ); 1040 } 1041 1042 aResult.SegmentEnd = aResult.SegmentStart + aResult.SegmentText.getLength(); 1043 } 1044 else 1045 { 1046 // No special handling required, forward to wrapped class 1047 aResult = mpImpl->GetParagraph( aPos.nPara ).getTextBeforeIndex( aPos.nIndex, aTextType ); 1048 1049 // #112814# Adapt the start index with the paragraph offset 1050 mpImpl->CorrectTextSegment( aResult, aPos.nPara ); 1051 //IAccessibility2 Implementation 2009----- 1052 if ( bLineBreak && (nOldIdx-1) >= 0) 1053 { 1054 aResult = getTextAtIndex( nOldIdx-1, aTextType ); 1055 } 1056 //-----IAccessibility2 Implementation 2009 1057 } 1058 1059 return aResult; 1060 } 1061 1062 ::com::sun::star::accessibility::TextSegment SAL_CALL AccessibleStaticTextBase::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) 1063 { 1064 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 1065 //IAccessibility2 Implementation 2009----- 1066 sal_Int32 nTemp = nIndex+1; 1067 sal_Bool bLineBreak = mpImpl->RemoveLineBreakCount( nTemp ); 1068 mpImpl->RemoveLineBreakCount( nIndex ); 1069 //-----IAccessibility2 Implementation 2009 1070 EPosition aPos( mpImpl->Range2Internal(nIndex) ); 1071 1072 ::com::sun::star::accessibility::TextSegment aResult; 1073 1074 if( AccessibleTextType::PARAGRAPH == aTextType ) 1075 { 1076 // Special casing one behind the last paragraph is not 1077 // necessary, this case is invalid here for 1078 // getTextBehindIndex 1079 if( aPos.nPara + 1 < mpImpl->GetParagraphCount() ) 1080 { 1081 aResult.SegmentText = mpImpl->GetParagraph( aPos.nPara + 1 ).getText(); 1082 1083 // #112814# Adapt the start index with the paragraph offset 1084 aResult.SegmentStart = mpImpl->Internal2Index( EPosition( aPos.nPara + 1, 0 ) ); 1085 aResult.SegmentEnd = aResult.SegmentStart + aResult.SegmentText.getLength(); 1086 } 1087 } 1088 else 1089 { 1090 // No special handling required, forward to wrapped class 1091 aResult = mpImpl->GetParagraph( aPos.nPara ).getTextBehindIndex( aPos.nIndex, aTextType ); 1092 1093 // #112814# Adapt the start index with the paragraph offset 1094 mpImpl->CorrectTextSegment( aResult, aPos.nPara ); 1095 //IAccessibility2 Implementation 2009----- 1096 if ( bLineBreak ) 1097 { 1098 aResult.SegmentText = rtl::OUString(cNewLine) + aResult.SegmentText; 1099 } 1100 //-----IAccessibility2 Implementation 2009 1101 } 1102 1103 return aResult; 1104 } 1105 1106 sal_Bool SAL_CALL AccessibleStaticTextBase::copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 1107 { 1108 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 1109 1110 if( nStartIndex > nEndIndex ) 1111 ::std::swap(nStartIndex, nEndIndex); 1112 1113 EPosition aStartIndex( mpImpl->Range2Internal(nStartIndex) ); 1114 EPosition aEndIndex( mpImpl->Range2Internal(nEndIndex) ); 1115 1116 return mpImpl->CopyText( aStartIndex.nPara, aStartIndex.nIndex, 1117 aEndIndex.nPara, aEndIndex.nIndex ); 1118 } 1119 1120 // XAccessibleTextAttributes 1121 uno::Sequence< beans::PropertyValue > AccessibleStaticTextBase::getDefaultAttributes( const uno::Sequence< ::rtl::OUString >& RequestedAttributes ) throw (uno::RuntimeException) 1122 { 1123 // get the intersection of the default attributes of all paragraphs 1124 1125 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 1126 1127 PropertyValueVector aDefAttrVec( mpImpl->GetParagraph( 0 ).getDefaultAttributes( RequestedAttributes ) ); 1128 1129 const sal_Int32 nParaCount = mpImpl->GetParagraphCount(); 1130 for ( sal_Int32 nPara = 1; nPara < nParaCount; ++nPara ) 1131 { 1132 uno::Sequence< beans::PropertyValue > aSeq = mpImpl->GetParagraph( nPara ).getDefaultAttributes( RequestedAttributes ); 1133 PropertyValueVector aIntersectionVec; 1134 1135 PropertyValueVector::const_iterator aEnd = aDefAttrVec.end(); 1136 for ( PropertyValueVector::const_iterator aItr = aDefAttrVec.begin(); aItr != aEnd; ++aItr ) 1137 { 1138 const beans::PropertyValue* pItr = aSeq.getConstArray(); 1139 const beans::PropertyValue* pEnd = pItr + aSeq.getLength(); 1140 const beans::PropertyValue* pFind = ::std::find_if( pItr, pEnd, ::std::bind2nd( PropertyValueEqualFunctor(), boost::cref( *aItr ) ) ); 1141 if ( pFind != pEnd ) 1142 { 1143 aIntersectionVec.push_back( *pFind ); 1144 } 1145 } 1146 1147 aDefAttrVec.swap( aIntersectionVec ); 1148 1149 if ( aDefAttrVec.empty() ) 1150 { 1151 break; 1152 } 1153 } 1154 1155 return aDefAttrVec.getAsConstList(); 1156 } 1157 1158 uno::Sequence< beans::PropertyValue > SAL_CALL AccessibleStaticTextBase::getRunAttributes( sal_Int32 nIndex, const uno::Sequence< ::rtl::OUString >& RequestedAttributes ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 1159 { 1160 // get those default attributes of the paragraph, which are not part 1161 // of the intersection of all paragraphs and add them to the run attributes 1162 1163 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 1164 1165 EPosition aPos( mpImpl->Index2Internal( nIndex ) ); 1166 AccessibleEditableTextPara& rPara = mpImpl->GetParagraph( aPos.nPara ); 1167 uno::Sequence< beans::PropertyValue > aDefAttrSeq = rPara.getDefaultAttributes( RequestedAttributes ); 1168 uno::Sequence< beans::PropertyValue > aRunAttrSeq = rPara.getRunAttributes( aPos.nIndex, RequestedAttributes ); 1169 uno::Sequence< beans::PropertyValue > aIntersectionSeq = getDefaultAttributes( RequestedAttributes ); 1170 PropertyValueVector aDiffVec; 1171 1172 const beans::PropertyValue* pDefAttr = aDefAttrSeq.getConstArray(); 1173 const sal_Int32 nLength = aDefAttrSeq.getLength(); 1174 for ( sal_Int32 i = 0; i < nLength; ++i ) 1175 { 1176 const beans::PropertyValue* pItr = aIntersectionSeq.getConstArray(); 1177 const beans::PropertyValue* pEnd = pItr + aIntersectionSeq.getLength(); 1178 const beans::PropertyValue* pFind = ::std::find_if( pItr, pEnd, ::std::bind2nd( PropertyValueEqualFunctor(), boost::cref( pDefAttr[i] ) ) ); 1179 if ( pFind == pEnd && pDefAttr[i].Handle != 0) 1180 { 1181 aDiffVec.push_back( pDefAttr[i] ); 1182 } 1183 } 1184 1185 return ::comphelper::concatSequences( aRunAttrSeq, aDiffVec.getAsConstList() ); 1186 } 1187 1188 Rectangle AccessibleStaticTextBase::GetParagraphBoundingBox() const 1189 { 1190 return mpImpl->GetParagraphBoundingBox(); 1191 } 1192 1193 sal_Int32 AccessibleStaticTextBase::GetParagraphIndex() const 1194 { 1195 return mpImpl->GetParagraphIndex(); 1196 } 1197 1198 sal_Int32 AccessibleStaticTextBase::GetParagraphCount() const 1199 { 1200 return mpImpl->GetParagraphCount(); 1201 } 1202 1203 sal_Int32 AccessibleStaticTextBase::GetLineCount( sal_Int32 nParagraph ) const 1204 { 1205 return mpImpl->GetLineCount( nParagraph ); 1206 } 1207 1208 } // end of namespace accessibility 1209 1210 //------------------------------------------------------------------------ 1211