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_sw.hxx" 26 27 #include <txtfrm.hxx> 28 #include <flyfrm.hxx> 29 #include <ndtxt.hxx> 30 #include <pam.hxx> 31 #include <unotextrange.hxx> 32 #include <unocrsrhelper.hxx> 33 #include <crstate.hxx> 34 #include <accmap.hxx> 35 #include <fesh.hxx> 36 #include <viewopt.hxx> 37 #include <vos/mutex.hxx> 38 #include <vcl/svapp.hxx> 39 #include <vcl/window.hxx> 40 #include <rtl/ustrbuf.hxx> 41 #include <com/sun/star/accessibility/AccessibleRole.hpp> 42 #include <com/sun/star/accessibility/AccessibleStateType.hpp> 43 #include <com/sun/star/accessibility/AccessibleTextType.hpp> 44 #include <com/sun/star/accessibility/AccessibleEventId.hpp> 45 #include <unotools/accessiblestatesethelper.hxx> 46 #include <com/sun/star/i18n/CharacterIteratorMode.hpp> 47 #include <com/sun/star/i18n/WordType.hpp> 48 #include <com/sun/star/i18n/XBreakIterator.hpp> 49 #include <com/sun/star/beans/UnknownPropertyException.hpp> 50 #include <breakit.hxx> 51 #include <accpara.hxx> 52 #include <access.hrc> 53 #include <accportions.hxx> 54 #include <sfx2/viewsh.hxx> // for ExecuteAtViewShell(...) 55 #include <sfx2/viewfrm.hxx> // for ExecuteAtViewShell(...) 56 #include <sfx2/dispatch.hxx> // for ExecuteAtViewShell(...) 57 #include <unotools/charclass.hxx> // for GetWordBoundary 58 // for get/setCharacterAttribute(...) 59 60 #include <reffld.hxx> 61 #include <docufld.hxx> 62 #include <expfld.hxx> 63 #include <flddat.hxx> 64 #include <fldui.hrc> 65 #include "../../ui/inc/fldmgr.hxx" 66 #include "fldbas.hxx" // SwField 67 #include <svl/svstdarr.hxx> 68 #include <unocrsr.hxx> 69 //#include <unoobj.hxx> 70 #include <unoport.hxx> 71 #include <doc.hxx> 72 #include <crsskip.hxx> 73 #include <txtatr.hxx> 74 #include <acchyperlink.hxx> 75 #include <acchypertextdata.hxx> 76 #include <unotools/accessiblerelationsethelper.hxx> 77 #include <com/sun/star/accessibility/AccessibleRelationType.hpp> 78 #include <section.hxx> 79 #include <doctxm.hxx> 80 #include <comphelper/accessibletexthelper.hxx> 81 #include <algorithm> 82 #include <docufld.hxx> 83 #include <txtfld.hxx> 84 #include <fmtfld.hxx> 85 #include <modcfg.hxx> 86 //#include "accnote.hxx" 87 #include <com/sun/star/beans/XPropertySet.hpp> 88 #include "swmodule.hxx" 89 #include "redline.hxx" 90 #include <com/sun/star/awt/FontWeight.hpp> 91 #include <com/sun/star/awt/FontStrikeout.hpp> 92 #include <com/sun/star/awt/FontSlant.hpp> 93 #include <wrong.hxx> 94 #include <editeng/brshitem.hxx> 95 #include <swatrset.hxx> 96 #include <frmatr.hxx> 97 #include <unosett.hxx> 98 #include <paratr.hxx> 99 #include <com/sun/star/container/XIndexReplace.hpp> 100 // --> OD 2006-07-12 #i63870# 101 #include <unomap.hxx> 102 #include <unoprnms.hxx> 103 #include <com/sun/star/text/WritingMode2.hpp> 104 #include <editeng/brshitem.hxx> 105 #include <viewimp.hxx> 106 #include <boost/scoped_ptr.hpp> 107 #include <textmarkuphelper.hxx> 108 // --> OD 2010-02-22 #i10825# 109 #include <parachangetrackinginfo.hxx> 110 #include <com/sun/star/text/TextMarkupType.hpp> 111 // <-- 112 // --> OD 2010-03-08 #i92233# 113 #include <comphelper/stlunosequence.hxx> 114 // <-- 115 116 #include <algorithm> 117 118 using namespace ::com::sun::star; 119 using namespace ::com::sun::star::accessibility; 120 using namespace ::com::sun::star::container; 121 using ::rtl::OUString; 122 123 using beans::PropertyValue; 124 using beans::XMultiPropertySet; 125 using beans::UnknownPropertyException; 126 using beans::PropertyState_DIRECT_VALUE; 127 128 using std::max; 129 using std::min; 130 using std::sort; 131 132 namespace com { namespace sun { namespace star { 133 namespace text { 134 class XText; 135 } 136 } } } 137 138 139 const sal_Char sServiceName[] = "com.sun.star.text.AccessibleParagraphView"; 140 const sal_Char sImplementationName[] = "com.sun.star.comp.Writer.SwAccessibleParagraphView"; 141 const xub_StrLen MAX_DESC_TEXT_LEN = 40; 142 const SwTxtNode* SwAccessibleParagraph::GetTxtNode() const 143 { 144 const SwFrm* pFrm = GetFrm(); 145 DBG_ASSERT( pFrm->IsTxtFrm(), "The text frame has mutated!" ); 146 147 const SwTxtNode* pNode = static_cast<const SwTxtFrm*>(pFrm)->GetTxtNode(); 148 DBG_ASSERT( pNode != NULL, "A text frame without a text node." ); 149 150 return pNode; 151 } 152 153 ::rtl::OUString SwAccessibleParagraph::GetString() 154 { 155 return GetPortionData().GetAccessibleString(); 156 } 157 158 ::rtl::OUString SwAccessibleParagraph::GetDescription() 159 { 160 // --> OD 2004-09-29 #117933# - provide empty description for paragraphs 161 return ::rtl::OUString(); 162 // <-- 163 } 164 165 sal_Int32 SwAccessibleParagraph::GetCaretPos() 166 { 167 sal_Int32 nRet = -1; 168 169 // get the selection's point, and test whether it's in our node 170 // --> OD 2005-12-20 #i27301# - consider adjusted method signature 171 SwPaM* pCaret = GetCursor( false ); // caret is first PaM in PaM-ring 172 // <-- 173 if( pCaret != NULL ) 174 { 175 const SwTxtNode* pNode = GetTxtNode(); 176 177 // check whether the point points into 'our' node 178 SwPosition* pPoint = pCaret->GetPoint(); 179 if( pNode->GetIndex() == pPoint->nNode.GetIndex() ) 180 { 181 // same node? Then check whether it's also within 'our' part 182 // of the paragraph 183 sal_uInt16 nIndex = pPoint->nContent.GetIndex(); 184 if(!GetPortionData().IsValidCorePosition( nIndex ) || 185 ( GetPortionData().IsZeroCorePositionData() && nIndex== 0) ) 186 { 187 SwTxtFrm *pTxtFrm = PTR_CAST( SwTxtFrm, GetFrm() ); 188 bool bFormat = (pTxtFrm && pTxtFrm->HasPara()); 189 if(bFormat) 190 { 191 ClearPortionData(); 192 UpdatePortionData(); 193 } 194 } 195 if( GetPortionData().IsValidCorePosition( nIndex ) ) 196 { 197 // Yes, it's us! 198 // --> OD 2006-10-19 #70538# 199 // consider that cursor/caret is in front of the list label 200 if ( pCaret->IsInFrontOfLabel() ) 201 { 202 nRet = 0; 203 } 204 else 205 { 206 nRet = GetPortionData().GetAccessiblePosition( nIndex ); 207 } 208 // <-- 209 210 DBG_ASSERT( nRet >= 0, "invalid cursor?" ); 211 DBG_ASSERT( nRet <= GetPortionData().GetAccessibleString(). 212 getLength(), "invalid cursor?" ); 213 } 214 // else: in this paragraph, but in different frame 215 } 216 // else: not in this paragraph 217 } 218 // else: no cursor -> no caret 219 220 return nRet; 221 } 222 223 sal_Bool SwAccessibleParagraph::GetSelection( 224 sal_Int32& nStart, sal_Int32& nEnd) 225 { 226 sal_Bool bRet = sal_False; 227 nStart = -1; 228 nEnd = -1; 229 230 // get the selection, and test whether it affects our text node 231 // --> OD 2005-12-20 #i27301# - consider adjusted method signature 232 SwPaM* pCrsr = GetCursor( true ); 233 // <-- 234 if( pCrsr != NULL ) 235 { 236 // get SwPosition for my node 237 const SwTxtNode* pNode = GetTxtNode(); 238 sal_uLong nHere = pNode->GetIndex(); 239 240 // iterate over ring 241 SwPaM* pRingStart = pCrsr; 242 do 243 { 244 // ignore, if no mark 245 if( pCrsr->HasMark() ) 246 { 247 // check whether nHere is 'inside' pCrsr 248 SwPosition* pStart = pCrsr->Start(); 249 sal_uLong nStartIndex = pStart->nNode.GetIndex(); 250 SwPosition* pEnd = pCrsr->End(); 251 sal_uLong nEndIndex = pEnd->nNode.GetIndex(); 252 if( ( nHere >= nStartIndex ) && 253 ( nHere <= nEndIndex ) ) 254 { 255 // translate start and end positions 256 257 // start position 258 sal_Int32 nLocalStart = -1; 259 if( nHere > nStartIndex ) 260 { 261 // selection starts in previous node: 262 // then our local selection starts with the paragraph 263 nLocalStart = 0; 264 } 265 else 266 { 267 DBG_ASSERT( nHere == nStartIndex, 268 "miscalculated index" ); 269 270 // selection starts in this node: 271 // then check whether it's before or inside our part of 272 // the paragraph, and if so, get the proper position 273 sal_uInt16 nCoreStart = pStart->nContent.GetIndex(); 274 if( nCoreStart < 275 GetPortionData().GetFirstValidCorePosition() ) 276 { 277 nLocalStart = 0; 278 } 279 else if( nCoreStart <= 280 GetPortionData().GetLastValidCorePosition() ) 281 { 282 DBG_ASSERT( 283 GetPortionData().IsValidCorePosition( 284 nCoreStart ), 285 "problem determining valid core position" ); 286 287 nLocalStart = 288 GetPortionData().GetAccessiblePosition( 289 nCoreStart ); 290 } 291 } 292 293 // end position 294 sal_Int32 nLocalEnd = -1; 295 if( nHere < nEndIndex ) 296 { 297 // selection ends in following node: 298 // then our local selection extends to the end 299 nLocalEnd = GetPortionData().GetAccessibleString(). 300 getLength(); 301 } 302 else 303 { 304 DBG_ASSERT( nHere == nEndIndex, 305 "miscalculated index" ); 306 307 // selection ends in this node: then select everything 308 // before our part of the node 309 sal_uInt16 nCoreEnd = pEnd->nContent.GetIndex(); 310 if( nCoreEnd > 311 GetPortionData().GetLastValidCorePosition() ) 312 { 313 // selection extends beyond out part of this para 314 nLocalEnd = GetPortionData().GetAccessibleString(). 315 getLength(); 316 } 317 else if( nCoreEnd >= 318 GetPortionData().GetFirstValidCorePosition() ) 319 { 320 // selection is inside our part of this para 321 DBG_ASSERT( 322 GetPortionData().IsValidCorePosition( 323 nCoreEnd ), 324 "problem determining valid core position" ); 325 326 nLocalEnd = GetPortionData().GetAccessiblePosition( 327 nCoreEnd ); 328 } 329 } 330 331 if( ( nLocalStart != -1 ) && ( nLocalEnd != -1 ) ) 332 { 333 nStart = nLocalStart; 334 nEnd = nLocalEnd; 335 bRet = sal_True; 336 } 337 } 338 // else: this PaM doesn't point to this paragraph 339 } 340 // else: this PaM is collapsed and doesn't select anything 341 342 // next PaM in ring 343 pCrsr = static_cast<SwPaM*>( pCrsr->GetNext() ); 344 } 345 while( !bRet && (pCrsr != pRingStart) ); 346 } 347 // else: nocursor -> no selection 348 349 return bRet; 350 } 351 352 // --> OD 2005-12-20 #i27301# - new parameter <_bForSelection> 353 SwPaM* SwAccessibleParagraph::GetCursor( const bool _bForSelection ) 354 { 355 // get the cursor shell; if we don't have any, we don't have a 356 // cursor/selection either 357 SwPaM* pCrsr = NULL; 358 SwCrsrShell* pCrsrShell = SwAccessibleParagraph::GetCrsrShell(); 359 // --> OD 2005-12-20 #i27301# 360 // - if cursor is retrieved for selection, the cursors for a table selection 361 // has to be returned. 362 if ( pCrsrShell != NULL && 363 ( _bForSelection || !pCrsrShell->IsTableMode() ) ) 364 // <-- 365 { 366 SwFEShell *pFESh = pCrsrShell->ISA( SwFEShell ) 367 ? static_cast< SwFEShell * >( pCrsrShell ) : 0; 368 if( !pFESh || 369 !(pFESh->IsFrmSelected() || pFESh->IsObjSelected() > 0) ) 370 { 371 // get the selection, and test whether it affects our text node 372 pCrsr = pCrsrShell->GetCrsr( sal_False /* ??? */ ); 373 } 374 } 375 376 return pCrsr; 377 } 378 379 sal_Bool SwAccessibleParagraph::IsHeading() const 380 { 381 const SwTxtNode *pTxtNd = GetTxtNode(); 382 return pTxtNd->IsOutline(); 383 } 384 385 void SwAccessibleParagraph::GetStates( 386 ::utl::AccessibleStateSetHelper& rStateSet ) 387 { 388 SwAccessibleContext::GetStates( rStateSet ); 389 390 // MULTILINE 391 rStateSet.AddState( AccessibleStateType::MULTI_LINE ); 392 393 // MULTISELECTABLE 394 SwCrsrShell *pCrsrSh = GetCrsrShell(); 395 if( pCrsrSh ) 396 rStateSet.AddState( AccessibleStateType::MULTI_SELECTABLE ); 397 398 // FOCUSABLE 399 if( pCrsrSh ) 400 rStateSet.AddState( AccessibleStateType::FOCUSABLE ); 401 402 // FOCUSED (simulates node index of cursor) 403 // --> OD 2005-12-20 #i27301# - consider adjusted method signature 404 SwPaM* pCaret = GetCursor( false ); 405 // <-- 406 const SwTxtNode* pTxtNd = GetTxtNode(); 407 if( pCaret != 0 && pTxtNd != 0 && 408 pTxtNd->GetIndex() == pCaret->GetPoint()->nNode.GetIndex() && 409 nOldCaretPos != -1) 410 { 411 Window *pWin = GetWindow(); 412 if( pWin && pWin->HasFocus() ) 413 rStateSet.AddState( AccessibleStateType::FOCUSED ); 414 ::vos::ORef < SwAccessibleContext > xThis( this ); 415 GetMap()->SetCursorContext( xThis ); 416 } 417 } 418 419 void SwAccessibleParagraph::_InvalidateContent( sal_Bool bVisibleDataFired ) 420 { 421 ::rtl::OUString sOldText( GetString() ); 422 423 ClearPortionData(); 424 425 const ::rtl::OUString& rText = GetString(); 426 427 if( rText != sOldText ) 428 { 429 // The text is changed 430 AccessibleEventObject aEvent; 431 aEvent.EventId = AccessibleEventId::TEXT_CHANGED; 432 433 // determine exact changes between sOldText and rText 434 comphelper::OCommonAccessibleText::implInitTextChangedEvent( 435 sOldText, rText, 436 aEvent.OldValue, aEvent.NewValue ); 437 438 FireAccessibleEvent( aEvent ); 439 uno::Reference< XAccessible > xparent = getAccessibleParent(); 440 uno::Reference< XAccessibleContext > xAccContext(xparent,uno::UNO_QUERY); 441 if (xAccContext.is() && xAccContext->getAccessibleRole() == AccessibleRole::TABLE_CELL) 442 { 443 SwAccessibleContext* pPara = static_cast< SwAccessibleContext* >(xparent.get()); 444 if(pPara) 445 { 446 AccessibleEventObject aParaEvent; 447 aParaEvent.EventId = AccessibleEventId::VALUE_CHANGED; 448 pPara->FireAccessibleEvent(aParaEvent); 449 } 450 } 451 } 452 else if( !bVisibleDataFired ) 453 { 454 FireVisibleDataEvent(); 455 } 456 457 sal_Bool bNewIsHeading = IsHeading(); 458 //Get the real heading level, Heading1 ~ Heading10 459 nHeadingLevel = GetRealHeadingLevel(); 460 sal_Bool bOldIsHeading; 461 { 462 vos::OGuard aGuard( aMutex ); 463 bOldIsHeading = bIsHeading; 464 if( bIsHeading != bNewIsHeading ) 465 bIsHeading = bNewIsHeading; 466 } 467 468 469 if( bNewIsHeading != bOldIsHeading || rText != sOldText ) 470 { 471 ::rtl::OUString sNewDesc( GetDescription() ); 472 ::rtl::OUString sOldDesc; 473 { 474 vos::OGuard aGuard( aMutex ); 475 sOldDesc = sDesc; 476 if( sDesc != sNewDesc ) 477 sDesc = sNewDesc; 478 } 479 480 if( sNewDesc != sOldDesc ) 481 { 482 // The text is changed 483 AccessibleEventObject aEvent; 484 aEvent.EventId = AccessibleEventId::DESCRIPTION_CHANGED; 485 aEvent.OldValue <<= sOldDesc; 486 aEvent.NewValue <<= sNewDesc; 487 488 FireAccessibleEvent( aEvent ); 489 } 490 } 491 } 492 493 void SwAccessibleParagraph::_InvalidateCursorPos() 494 { 495 // The text is changed 496 sal_Int32 nNew = GetCaretPos(); 497 sal_Int32 nOld; 498 { 499 vos::OGuard aGuard( aMutex ); 500 nOld = nOldCaretPos; 501 nOldCaretPos = nNew; 502 } 503 if( -1 != nNew ) 504 { 505 // remember that object as the one that has the caret. This is 506 // necessary to notify that object if the cursor leaves it. 507 ::vos::ORef < SwAccessibleContext > xThis( this ); 508 GetMap()->SetCursorContext( xThis ); 509 } 510 511 Window *pWin = GetWindow(); 512 if( nOld != nNew ) 513 { 514 // The cursor's node position is sumilated by the focus! 515 if( pWin && pWin->HasFocus() && -1 == nOld ) 516 FireStateChangedEvent( AccessibleStateType::FOCUSED, sal_True ); 517 518 519 AccessibleEventObject aEvent; 520 aEvent.EventId = AccessibleEventId::CARET_CHANGED; 521 aEvent.OldValue <<= nOld; 522 aEvent.NewValue <<= nNew; 523 524 FireAccessibleEvent( aEvent ); 525 526 if( pWin && pWin->HasFocus() && -1 == nNew ) 527 FireStateChangedEvent( AccessibleStateType::FOCUSED, sal_False ); 528 //To send TEXT_SELECTION_CHANGED event 529 sal_Int32 nStart=0; 530 sal_Int32 nEnd =0; 531 sal_Bool bCurSelection=GetSelection(nStart,nEnd); 532 if(m_bLastHasSelection || bCurSelection ) 533 { 534 aEvent.EventId = AccessibleEventId::TEXT_SELECTION_CHANGED; 535 aEvent.OldValue <<= uno::Any(); 536 aEvent.NewValue <<= uno::Any(); 537 FireAccessibleEvent(aEvent); 538 } 539 m_bLastHasSelection =bCurSelection; 540 } 541 } 542 543 void SwAccessibleParagraph::_InvalidateFocus() 544 { 545 Window *pWin = GetWindow(); 546 if( pWin ) 547 { 548 sal_Int32 nPos; 549 { 550 vos::OGuard aGuard( aMutex ); 551 nPos = nOldCaretPos; 552 } 553 ASSERT( nPos != -1, "focus object should be selected" ); 554 555 FireStateChangedEvent( AccessibleStateType::FOCUSED, 556 pWin->HasFocus() && nPos != -1 ); 557 } 558 } 559 560 SwAccessibleParagraph::SwAccessibleParagraph( 561 SwAccessibleMap& rInitMap, 562 const SwTxtFrm& rTxtFrm ) 563 // --> OD 2010-02-24 #i108125# 564 : SwClient( const_cast<SwTxtNode*>(rTxtFrm.GetTxtNode()) ) 565 // <-- 566 , SwAccessibleContext( &rInitMap, AccessibleRole::PARAGRAPH, &rTxtFrm ) 567 , sDesc() 568 , pPortionData( NULL ) 569 , pHyperTextData( NULL ) 570 , nOldCaretPos( -1 ) 571 , bIsHeading( sal_False ) 572 //Get the real heading level, Heading1 ~ Heading10 573 , nHeadingLevel (-1) 574 , aSelectionHelper( *this ) 575 // --> OD 2010-02-19 #i108125# 576 , mpParaChangeTrackInfo( new SwParaChangeTrackingInfo( rTxtFrm ) ) 577 // <-- 578 , m_bLastHasSelection(false) //To add TEXT_SELECTION_CHANGED event 579 { 580 vos::OGuard aGuard(Application::GetSolarMutex()); 581 582 bIsHeading = IsHeading(); 583 //Get the real heading level, Heading1 ~ Heading10 584 nHeadingLevel = GetRealHeadingLevel(); 585 // --> OD 2004-09-27 #117970# - set an empty accessibility name for paragraphs 586 SetName( ::rtl::OUString() ); 587 // <-- 588 589 // If this object has the focus, then it is remembered by the map itself. 590 // not necessary to remember this pos here. Generally, the pos will be updated in invalidateXXX method, which may fire the 591 //Focus event based on the difference of new & old caret pos. 592 //nOldCaretPos = GetCaretPos(); 593 } 594 595 SwAccessibleParagraph::~SwAccessibleParagraph() 596 { 597 if(Application::GetUnoWrapper()) 598 vos::OGuard aGuard(Application::GetSolarMutex()); 599 600 delete pPortionData; 601 delete pHyperTextData; 602 // --> OD 2010-02-22 #i108125# 603 delete mpParaChangeTrackInfo; 604 // <-- 605 } 606 607 sal_Bool SwAccessibleParagraph::HasCursor() 608 { 609 vos::OGuard aGuard( aMutex ); 610 return nOldCaretPos != -1; 611 } 612 613 void SwAccessibleParagraph::UpdatePortionData() 614 throw( uno::RuntimeException ) 615 { 616 // obtain the text frame 617 DBG_ASSERT( GetFrm() != NULL, "The text frame has vanished!" ); 618 DBG_ASSERT( GetFrm()->IsTxtFrm(), "The text frame has mutated!" ); 619 const SwTxtFrm* pFrm = static_cast<const SwTxtFrm*>( GetFrm() ); 620 621 // build new portion data 622 delete pPortionData; 623 pPortionData = new SwAccessiblePortionData( 624 pFrm->GetTxtNode(), GetMap()->GetShell()->GetViewOptions() ); 625 pFrm->VisitPortions( *pPortionData ); 626 627 DBG_ASSERT( pPortionData != NULL, "UpdatePortionData() failed" ); 628 } 629 630 void SwAccessibleParagraph::ClearPortionData() 631 { 632 delete pPortionData; 633 pPortionData = NULL; 634 635 delete pHyperTextData; 636 pHyperTextData = 0; 637 } 638 639 640 void SwAccessibleParagraph::ExecuteAtViewShell( sal_uInt16 nSlot ) 641 { 642 DBG_ASSERT( GetMap() != NULL, "no map?" ); 643 ViewShell* pViewShell = GetMap()->GetShell(); 644 645 DBG_ASSERT( pViewShell != NULL, "View shell exptected!" ); 646 SfxViewShell* pSfxShell = pViewShell->GetSfxViewShell(); 647 648 DBG_ASSERT( pSfxShell != NULL, "SfxViewShell shell exptected!" ); 649 if( !pSfxShell ) 650 return; 651 652 SfxViewFrame *pFrame = pSfxShell->GetViewFrame(); 653 DBG_ASSERT( pFrame != NULL, "View frame exptected!" ); 654 if( !pFrame ) 655 return; 656 657 SfxDispatcher *pDispatcher = pFrame->GetDispatcher(); 658 DBG_ASSERT( pDispatcher != NULL, "Dispatcher exptected!" ); 659 if( !pDispatcher ) 660 return; 661 662 pDispatcher->Execute( nSlot ); 663 } 664 665 SwXTextPortion* SwAccessibleParagraph::CreateUnoPortion( 666 sal_Int32 nStartIndex, 667 sal_Int32 nEndIndex ) 668 { 669 DBG_ASSERT( (IsValidChar(nStartIndex, GetString().getLength()) && 670 (nEndIndex == -1)) || 671 IsValidRange(nStartIndex, nEndIndex, GetString().getLength()), 672 "please check parameters before calling this method" ); 673 674 sal_uInt16 nStart = GetPortionData().GetModelPosition( nStartIndex ); 675 sal_uInt16 nEnd = (nEndIndex == -1) ? (nStart + 1) : 676 GetPortionData().GetModelPosition( nEndIndex ); 677 678 // create UNO cursor 679 SwTxtNode* pTxtNode = const_cast<SwTxtNode*>( GetTxtNode() ); 680 SwIndex aIndex( pTxtNode, nStart ); 681 SwPosition aStartPos( *pTxtNode, aIndex ); 682 SwUnoCrsr* pUnoCursor = pTxtNode->GetDoc()->CreateUnoCrsr( aStartPos ); 683 pUnoCursor->SetMark(); 684 pUnoCursor->GetMark()->nContent = nEnd; 685 686 // create a (dummy) text portion to be returned 687 uno::Reference<text::XText> aEmpty; 688 SwXTextPortion* pPortion = 689 new SwXTextPortion ( pUnoCursor, aEmpty, PORTION_TEXT); 690 delete pUnoCursor; 691 692 return pPortion; 693 } 694 695 696 // 697 // range checking for parameter 698 // 699 700 sal_Bool SwAccessibleParagraph::IsValidChar( 701 sal_Int32 nPos, sal_Int32 nLength) 702 { 703 return (nPos >= 0) && (nPos < nLength); 704 } 705 706 sal_Bool SwAccessibleParagraph::IsValidPosition( 707 sal_Int32 nPos, sal_Int32 nLength) 708 { 709 return (nPos >= 0) && (nPos <= nLength); 710 } 711 712 sal_Bool SwAccessibleParagraph::IsValidRange( 713 sal_Int32 nBegin, sal_Int32 nEnd, sal_Int32 nLength) 714 { 715 return IsValidPosition(nBegin, nLength) && IsValidPosition(nEnd, nLength); 716 } 717 SwTOXSortTabBase* SwAccessibleParagraph::GetTOXSortTabBase() 718 { 719 const SwTxtNode* pTxtNd = GetTxtNode(); 720 if( pTxtNd ) 721 { 722 const SwSectionNode * pSectNd = pTxtNd->FindSectionNode(); 723 if( pSectNd ) 724 { 725 const SwSection * pSect = &pSectNd->GetSection(); 726 SwTOXBaseSection *pTOXBaseSect = (SwTOXBaseSection *)pSect; 727 if( pSect->GetType() == TOX_CONTENT_SECTION ) 728 { 729 SwTOXSortTabBase* pSortBase = 0; 730 int nSize = pTOXBaseSect->GetTOXSortTabBases()->Count(); 731 732 for(int nIndex = 0; nIndex<nSize; nIndex++ ) 733 { 734 pSortBase = (*(pTOXBaseSect->GetTOXSortTabBases()))[nIndex]; 735 if( pSortBase->pTOXNd == pTxtNd ) 736 break; 737 } 738 739 if (pSortBase) 740 { 741 return pSortBase; 742 } 743 } 744 } 745 } 746 return NULL; 747 } 748 749 short SwAccessibleParagraph::GetTOCLevel() 750 { 751 SwTOXSortTabBase* pToxBase = GetTOXSortTabBase(); 752 if( pToxBase ) 753 { 754 const SwCntntNode* pNd = pToxBase->aTOXSources[0].pNd; 755 if( pNd ) 756 return pToxBase->GetLevel(); 757 else 758 return -1; 759 } 760 else 761 return -1; 762 } 763 764 //the function is to check whether the position is in a redline range. 765 const SwRedline* SwAccessibleParagraph::GetRedlineAtIndex( sal_Int32 ) 766 { 767 const SwRedline* pRedline = NULL; 768 SwPaM* pCrSr = GetCursor( true ); 769 if ( pCrSr ) 770 { 771 SwPosition* pStart = pCrSr->Start(); 772 const SwTxtNode* pNode = GetTxtNode(); 773 if ( pNode ) 774 { 775 const SwDoc* pDoc = pNode->GetDoc(); 776 if ( pDoc ) 777 { 778 pRedline = pDoc->GetRedline( *pStart, NULL ); 779 } 780 } 781 } 782 783 return pRedline; 784 } 785 786 // 787 // text boundaries 788 // 789 790 791 sal_Bool SwAccessibleParagraph::GetCharBoundary( 792 i18n::Boundary& rBound, 793 const ::rtl::OUString&, 794 sal_Int32 nPos ) 795 { 796 if( GetPortionData().FillBoundaryIFDateField( rBound, nPos) ) 797 return sal_True; 798 799 rBound.startPos = nPos; 800 rBound.endPos = nPos+1; 801 return sal_True; 802 } 803 804 sal_Bool SwAccessibleParagraph::GetWordBoundary( 805 i18n::Boundary& rBound, 806 const ::rtl::OUString& rText, 807 sal_Int32 nPos ) 808 { 809 sal_Bool bRet = sal_False; 810 811 // now ask the Break-Iterator for the word 812 DBG_ASSERT( pBreakIt != NULL, "We always need a break." ); 813 DBG_ASSERT( pBreakIt->GetBreakIter().is(), "No break-iterator." ); 814 if( pBreakIt->GetBreakIter().is() ) 815 { 816 // get locale for this position 817 sal_uInt16 nModelPos = GetPortionData().GetModelPosition( nPos ); 818 lang::Locale aLocale = pBreakIt->GetLocale( 819 GetTxtNode()->GetLang( nModelPos ) ); 820 821 // which type of word are we interested in? 822 // (DICTIONARY_WORD includes punctuation, ANY_WORD doesn't.) 823 const sal_uInt16 nWordType = i18n::WordType::ANY_WORD; 824 825 /* 826 // get word boundary, as the Break-Iterator sees fit. 827 sal_Unicode SpaceChar(' '); 828 if (rText.getCodePointAt(nPos) == SpaceChar) 829 { 830 int nStartPos = nPos; 831 int nEndPos = nPos+1; 832 while (nStartPos >= 0 && rText.getCodePointAt(nStartPos) == SpaceChar) 833 --nStartPos; 834 while (nEndPos < rText.getLength() && rText.getCodePointAt(nEndPos) == SpaceChar) 835 ++nEndPos; 836 //Get the previous word boundary + the followed space characters 837 if (nStartPos >= 0) 838 { 839 rBound = pBreakIt->xBreak->getWordBoundary( rText, nStartPos, aLocale, nWordType, sal_True ); 840 rBound.endPos += (nEndPos-nStartPos - 1); 841 } 842 //When the frontal characters are whitespace, return the all space characters directly. 843 else 844 { 845 rBound.startPos = 0; 846 rBound.endPos = nEndPos; 847 } 848 } 849 // add the " " into the word boundary 850 else 851 { 852 rBound = pBreakIt->xBreak->getWordBoundary(rText, nPos, aLocale, nWordType, sal_True ); 853 sal_Int32 nEndPos = rBound.endPos, nLength = rText.getLength(); 854 while ( nEndPos < nLength && rText.getCodePointAt(nEndPos) == SpaceChar ) 855 nEndPos++; 856 rBound.endPos = nEndPos; 857 } 858 tabCharInWord( nPos, rBound); 859 if( GetPortionData().FillBoundaryIFDateField( rBound, rBound.startPos) ) 860 return sal_True; 861 return sal_True; // MT: So why do we need the return TRUE above??? 862 */ 863 // get word boundary, as the Break-Iterator sees fit. 864 rBound = pBreakIt->GetBreakIter()->getWordBoundary( 865 rText, nPos, aLocale, nWordType, sal_True ); 866 867 // It's a word if the first character is an alpha-numeric character. 868 bRet = GetAppCharClass().isLetterNumeric( 869 rText.getStr()[ rBound.startPos ] ); 870 } 871 else 872 { 873 // no break Iterator -> no word 874 rBound.startPos = nPos; 875 rBound.endPos = nPos; 876 } 877 878 return bRet; 879 } 880 881 sal_Bool SwAccessibleParagraph::GetSentenceBoundary( 882 i18n::Boundary& rBound, 883 const ::rtl::OUString& rText, 884 sal_Int32 nPos ) 885 { 886 const sal_Unicode* pStr = rText.getStr(); 887 if (pStr) 888 { 889 while( pStr[nPos] == sal_Unicode(' ') && nPos < rText.getLength()) 890 nPos++; 891 } 892 GetPortionData().GetSentenceBoundary( rBound, nPos ); 893 return sal_True; 894 } 895 896 sal_Bool SwAccessibleParagraph::GetLineBoundary( 897 i18n::Boundary& rBound, 898 const ::rtl::OUString& rText, 899 sal_Int32 nPos ) 900 { 901 if( rText.getLength() == nPos ) 902 GetPortionData().GetLastLineBoundary( rBound ); 903 else 904 GetPortionData().GetLineBoundary( rBound, nPos ); 905 return sal_True; 906 } 907 908 sal_Bool SwAccessibleParagraph::GetParagraphBoundary( 909 i18n::Boundary& rBound, 910 const ::rtl::OUString& rText, 911 sal_Int32 ) 912 { 913 rBound.startPos = 0; 914 rBound.endPos = rText.getLength(); 915 return sal_True; 916 } 917 918 sal_Bool SwAccessibleParagraph::GetAttributeBoundary( 919 i18n::Boundary& rBound, 920 const ::rtl::OUString&, 921 sal_Int32 nPos ) 922 { 923 GetPortionData().GetAttributeBoundary( rBound, nPos ); 924 return sal_True; 925 } 926 927 sal_Bool SwAccessibleParagraph::GetGlyphBoundary( 928 i18n::Boundary& rBound, 929 const ::rtl::OUString& rText, 930 sal_Int32 nPos ) 931 { 932 sal_Bool bRet = sal_False; 933 934 // ask the Break-Iterator for the glyph by moving one cell 935 // forward, and then one cell back 936 DBG_ASSERT( pBreakIt != NULL, "We always need a break." ); 937 DBG_ASSERT( pBreakIt->GetBreakIter().is(), "No break-iterator." ); 938 if( pBreakIt->GetBreakIter().is() ) 939 { 940 // get locale for this position 941 sal_uInt16 nModelPos = GetPortionData().GetModelPosition( nPos ); 942 lang::Locale aLocale = pBreakIt->GetLocale( 943 GetTxtNode()->GetLang( nModelPos ) ); 944 945 // get word boundary, as the Break-Iterator sees fit. 946 const sal_uInt16 nIterMode = i18n::CharacterIteratorMode::SKIPCELL; 947 sal_Int32 nDone = 0; 948 rBound.endPos = pBreakIt->GetBreakIter()->nextCharacters( 949 rText, nPos, aLocale, nIterMode, 1, nDone ); 950 rBound.startPos = pBreakIt->GetBreakIter()->previousCharacters( 951 rText, rBound.endPos, aLocale, nIterMode, 1, nDone ); 952 953 bRet = ((rBound.startPos <= nPos) && (nPos <= rBound.endPos)); 954 DBG_ASSERT( rBound.startPos <= nPos, "start pos too high" ); 955 DBG_ASSERT( rBound.endPos >= nPos, "end pos too low" ); 956 } 957 else 958 { 959 // no break Iterator -> no glyph 960 rBound.startPos = nPos; 961 rBound.endPos = nPos; 962 } 963 964 return bRet; 965 } 966 967 968 sal_Bool SwAccessibleParagraph::GetTextBoundary( 969 i18n::Boundary& rBound, 970 const ::rtl::OUString& rText, 971 sal_Int32 nPos, 972 sal_Int16 nTextType ) 973 throw ( 974 lang::IndexOutOfBoundsException, 975 lang::IllegalArgumentException, 976 uno::RuntimeException) 977 { 978 // error checking 979 if( !( AccessibleTextType::LINE == nTextType 980 ? IsValidPosition( nPos, rText.getLength() ) 981 : IsValidChar( nPos, rText.getLength() ) ) ) 982 throw lang::IndexOutOfBoundsException(); 983 984 sal_Bool bRet; 985 986 switch( nTextType ) 987 { 988 case AccessibleTextType::WORD: 989 bRet = GetWordBoundary( rBound, rText, nPos ); 990 break; 991 992 case AccessibleTextType::SENTENCE: 993 bRet = GetSentenceBoundary( rBound, rText, nPos ); 994 break; 995 996 case AccessibleTextType::PARAGRAPH: 997 bRet = GetParagraphBoundary( rBound, rText, nPos ); 998 break; 999 1000 case AccessibleTextType::CHARACTER: 1001 bRet = GetCharBoundary( rBound, rText, nPos ); 1002 break; 1003 1004 case AccessibleTextType::LINE: 1005 //Solve the problem of returning wrong LINE and PARAGRAPH 1006 if((nPos == rText.getLength()) && nPos > 0) 1007 bRet = GetLineBoundary( rBound, rText, nPos - 1); 1008 else 1009 bRet = GetLineBoundary( rBound, rText, nPos ); 1010 break; 1011 1012 case AccessibleTextType::ATTRIBUTE_RUN: 1013 bRet = GetAttributeBoundary( rBound, rText, nPos ); 1014 if(bRet) 1015 { 1016 SwCrsrShell* pCrsrShell = GetCrsrShell(); 1017 if( pCrsrShell != NULL && pCrsrShell->GetViewOptions() && pCrsrShell->GetViewOptions()->IsOnlineSpell()) 1018 { 1019 SwTxtNode* pTxtNode = const_cast<SwTxtNode*>( GetTxtNode() ); 1020 if(pTxtNode) 1021 { 1022 const SwWrongList* pWrongList = pTxtNode->GetWrong(); 1023 if( NULL != pWrongList ) 1024 { 1025 xub_StrLen nBegin = nPos; 1026 xub_StrLen nLen = 1; 1027 const xub_StrLen nNext = pWrongList->NextWrong(nBegin); 1028 xub_StrLen nLast; 1029 xub_StrLen nWrongPos = pWrongList->GetWrongPos( nBegin ); 1030 if ( nWrongPos >= pWrongList->Count() || 1031 ( nLast = pWrongList->Pos( nWrongPos ) ) >= nBegin ) 1032 { 1033 nLast = nWrongPos 1034 ? pWrongList->Pos( --nWrongPos ) 1035 : STRING_LEN; 1036 } 1037 if ( nBegin > pWrongList->GetBeginInv() && 1038 ( nLast == STRING_LEN || nLast < pWrongList->GetEndInv() ) ) 1039 { 1040 nLast = nBegin > pWrongList->GetEndInv() 1041 ? pWrongList->GetEndInv() 1042 : nBegin; 1043 } 1044 else if ( nLast < STRING_LEN ) 1045 { 1046 nLast += pWrongList->Len( nWrongPos ); 1047 } 1048 // 1049 sal_Bool bIn = pWrongList->InWrongWord(nBegin,nLen); // && !pTxtNode->IsSymbol(nBegin) ) 1050 if(bIn) 1051 { 1052 rBound.startPos = max(nNext,(xub_StrLen)rBound.startPos); 1053 rBound.endPos = min(xub_StrLen(nNext + nLen),(xub_StrLen)rBound.endPos); 1054 } 1055 else 1056 { 1057 if (STRING_LEN == nLast)//first 1058 { 1059 rBound.endPos = min(nNext,(xub_StrLen)rBound.endPos); 1060 } 1061 else if(STRING_LEN == nNext) 1062 { 1063 rBound.startPos = max(nLast,(xub_StrLen)rBound.startPos); 1064 } 1065 else 1066 { 1067 rBound.startPos = max(nLast,(xub_StrLen)rBound.startPos); 1068 rBound.endPos = min(nNext,(xub_StrLen)rBound.endPos); 1069 } 1070 } 1071 } 1072 } 1073 } 1074 } 1075 break; 1076 1077 case AccessibleTextType::GLYPH: 1078 bRet = GetGlyphBoundary( rBound, rText, nPos ); 1079 break; 1080 1081 default: 1082 throw lang::IllegalArgumentException( ); 1083 } 1084 1085 return bRet; 1086 } 1087 1088 ::rtl::OUString SAL_CALL SwAccessibleParagraph::getAccessibleDescription (void) 1089 throw (uno::RuntimeException) 1090 { 1091 vos::OGuard aGuard(Application::GetSolarMutex()); 1092 1093 CHECK_FOR_DEFUNC( XAccessibleContext ); 1094 1095 vos::OGuard aGuard2( aMutex ); 1096 if( !sDesc.getLength() ) 1097 sDesc = GetDescription(); 1098 1099 return sDesc; 1100 } 1101 1102 lang::Locale SAL_CALL SwAccessibleParagraph::getLocale (void) 1103 throw (IllegalAccessibleComponentStateException, uno::RuntimeException) 1104 { 1105 vos::OGuard aGuard(Application::GetSolarMutex()); 1106 1107 SwTxtFrm *pTxtFrm = PTR_CAST( SwTxtFrm, GetFrm() ); 1108 if( !pTxtFrm ) 1109 { 1110 THROW_RUNTIME_EXCEPTION( XAccessibleContext, "internal error (no text frame)" ); 1111 } 1112 1113 const SwTxtNode *pTxtNd = pTxtFrm->GetTxtNode(); 1114 lang::Locale aLoc( pBreakIt->GetLocale( pTxtNd->GetLang( 0 ) ) ); 1115 1116 return aLoc; 1117 } 1118 1119 /** paragraphs are in relation CONTENT_FLOWS_FROM and/or CONTENT_FLOWS_TO 1120 1121 OD 2005-12-02 #i27138# 1122 1123 @author OD 1124 */ 1125 uno::Reference<XAccessibleRelationSet> SAL_CALL SwAccessibleParagraph::getAccessibleRelationSet() 1126 throw ( uno::RuntimeException ) 1127 { 1128 vos::OGuard aGuard(Application::GetSolarMutex()); 1129 CHECK_FOR_DEFUNC( XAccessibleContext ); 1130 1131 utl::AccessibleRelationSetHelper* pHelper = new utl::AccessibleRelationSetHelper(); 1132 1133 const SwTxtFrm* pTxtFrm = dynamic_cast<const SwTxtFrm*>(GetFrm()); 1134 ASSERT( pTxtFrm, 1135 "<SwAccessibleParagraph::getAccessibleRelationSet()> - missing text frame"); 1136 if ( pTxtFrm ) 1137 { 1138 const SwCntntFrm* pPrevCntFrm( pTxtFrm->FindPrevCnt( true ) ); 1139 if ( pPrevCntFrm ) 1140 { 1141 uno::Sequence< uno::Reference<XInterface> > aSequence(1); 1142 aSequence[0] = GetMap()->GetContext( pPrevCntFrm ); 1143 AccessibleRelation aAccRel( AccessibleRelationType::CONTENT_FLOWS_FROM, 1144 aSequence ); 1145 pHelper->AddRelation( aAccRel ); 1146 } 1147 1148 const SwCntntFrm* pNextCntFrm( pTxtFrm->FindNextCnt( true ) ); 1149 if ( pNextCntFrm ) 1150 { 1151 uno::Sequence< uno::Reference<XInterface> > aSequence(1); 1152 aSequence[0] = GetMap()->GetContext( pNextCntFrm ); 1153 AccessibleRelation aAccRel( AccessibleRelationType::CONTENT_FLOWS_TO, 1154 aSequence ); 1155 pHelper->AddRelation( aAccRel ); 1156 } 1157 } 1158 1159 return pHelper; 1160 } 1161 1162 void SAL_CALL SwAccessibleParagraph::grabFocus() 1163 throw (uno::RuntimeException) 1164 { 1165 vos::OGuard aGuard(Application::GetSolarMutex()); 1166 1167 CHECK_FOR_DEFUNC( XAccessibleContext ); 1168 1169 // get cursor shell 1170 SwCrsrShell *pCrsrSh = GetCrsrShell(); 1171 // --> OD 2005-12-20 #i27301# - consider new method signature 1172 SwPaM *pCrsr = GetCursor( false ); 1173 // <-- 1174 const SwTxtFrm *pTxtFrm = static_cast<const SwTxtFrm*>( GetFrm() ); 1175 const SwTxtNode* pTxtNd = pTxtFrm->GetTxtNode(); 1176 1177 if( pCrsrSh != 0 && pTxtNd != 0 && 1178 ( pCrsr == 0 || 1179 pCrsr->GetPoint()->nNode.GetIndex() != pTxtNd->GetIndex() || 1180 !pTxtFrm->IsInside( pCrsr->GetPoint()->nContent.GetIndex()) ) ) 1181 { 1182 // create pam for selection 1183 SwIndex aIndex( const_cast< SwTxtNode * >( pTxtNd ), 1184 pTxtFrm->GetOfst() ); 1185 SwPosition aStartPos( *pTxtNd, aIndex ); 1186 SwPaM aPaM( aStartPos ); 1187 1188 // set PaM at cursor shell 1189 Select( aPaM ); 1190 1191 1192 } 1193 1194 /* ->#i13955# */ 1195 Window * pWindow = GetWindow(); 1196 1197 if (pWindow != NULL) 1198 pWindow->GrabFocus(); 1199 /* <-#i13955# */ 1200 } 1201 1202 // --> OD 2007-01-17 #i71385# 1203 bool lcl_GetBackgroundColor( Color & rColor, 1204 const SwFrm* pFrm, 1205 SwCrsrShell* pCrsrSh ) 1206 { 1207 const SvxBrushItem* pBackgrdBrush = 0; 1208 const Color* pSectionTOXColor = 0; 1209 SwRect aDummyRect; 1210 1211 //UUUU 1212 drawinglayer::attribute::SdrAllFillAttributesHelperPtr aFillAttributes; 1213 1214 if ( pFrm && 1215 pFrm->GetBackgroundBrush( aFillAttributes, pBackgrdBrush, pSectionTOXColor, aDummyRect, false ) ) 1216 { 1217 if ( pSectionTOXColor ) 1218 { 1219 rColor = *pSectionTOXColor; 1220 return true; 1221 } 1222 else 1223 { 1224 rColor = pBackgrdBrush->GetColor(); 1225 return true; 1226 } 1227 } 1228 else if ( pCrsrSh ) 1229 { 1230 rColor = pCrsrSh->Imp()->GetRetoucheColor(); 1231 return true; 1232 } 1233 1234 return false; 1235 } 1236 1237 sal_Int32 SAL_CALL SwAccessibleParagraph::getForeground() 1238 throw (uno::RuntimeException) 1239 { 1240 Color aBackgroundCol; 1241 1242 if ( lcl_GetBackgroundColor( aBackgroundCol, GetFrm(), GetCrsrShell() ) ) 1243 { 1244 if ( aBackgroundCol.IsDark() ) 1245 { 1246 return COL_WHITE; 1247 } 1248 else 1249 { 1250 return COL_BLACK; 1251 } 1252 } 1253 1254 return SwAccessibleContext::getForeground(); 1255 } 1256 1257 sal_Int32 SAL_CALL SwAccessibleParagraph::getBackground() 1258 throw (uno::RuntimeException) 1259 { 1260 Color aBackgroundCol; 1261 1262 if ( lcl_GetBackgroundColor( aBackgroundCol, GetFrm(), GetCrsrShell() ) ) 1263 { 1264 return aBackgroundCol.GetColor(); 1265 } 1266 1267 return SwAccessibleContext::getBackground(); 1268 } 1269 // <-- 1270 1271 ::rtl::OUString SAL_CALL SwAccessibleParagraph::getImplementationName() 1272 throw( uno::RuntimeException ) 1273 { 1274 return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(sImplementationName)); 1275 } 1276 1277 sal_Bool SAL_CALL SwAccessibleParagraph::supportsService( 1278 const ::rtl::OUString& sTestServiceName) 1279 throw (uno::RuntimeException) 1280 { 1281 return sTestServiceName.equalsAsciiL( sServiceName, 1282 sizeof(sServiceName)-1 ) || 1283 sTestServiceName.equalsAsciiL( sAccessibleServiceName, 1284 sizeof(sAccessibleServiceName)-1 ); 1285 } 1286 1287 uno::Sequence< ::rtl::OUString > SAL_CALL SwAccessibleParagraph::getSupportedServiceNames() 1288 throw( uno::RuntimeException ) 1289 { 1290 uno::Sequence< ::rtl::OUString > aRet(2); 1291 ::rtl::OUString* pArray = aRet.getArray(); 1292 pArray[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(sServiceName) ); 1293 pArray[1] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(sAccessibleServiceName) ); 1294 return aRet; 1295 } 1296 1297 uno::Sequence< ::rtl::OUString > getAttributeNames() 1298 { 1299 static uno::Sequence< ::rtl::OUString >* pNames = NULL; 1300 1301 if( pNames == NULL ) 1302 { 1303 // Add the font name to attribute list 1304 uno::Sequence< ::rtl::OUString >* pSeq = new uno::Sequence< ::rtl::OUString >( 13 ); 1305 1306 ::rtl::OUString* pStrings = pSeq->getArray(); 1307 1308 // sorted list of strings 1309 sal_Int32 i = 0; 1310 1311 #define STR(x) pStrings[i++] = OUString::createFromAscii(x) 1312 STR( GetPropName( UNO_NAME_CHAR_BACK_COLOR ).pName ); 1313 STR( GetPropName( UNO_NAME_CHAR_COLOR ).pName ); 1314 STR( GetPropName( UNO_NAME_CHAR_CONTOURED ).pName ); 1315 STR( GetPropName( UNO_NAME_CHAR_EMPHASIS ).pName ); 1316 STR( GetPropName( UNO_NAME_CHAR_ESCAPEMENT ).pName ); 1317 STR( GetPropName( UNO_NAME_CHAR_FONT_NAME ).pName ); 1318 STR( GetPropName( UNO_NAME_CHAR_HEIGHT ).pName ); 1319 STR( GetPropName( UNO_NAME_CHAR_POSTURE ).pName ); 1320 STR( GetPropName( UNO_NAME_CHAR_SHADOWED ).pName ); 1321 STR( GetPropName( UNO_NAME_CHAR_STRIKEOUT ).pName ); 1322 STR( GetPropName( UNO_NAME_CHAR_UNDERLINE ).pName ); 1323 STR( GetPropName( UNO_NAME_CHAR_UNDERLINE_COLOR ).pName ); 1324 STR( GetPropName( UNO_NAME_CHAR_WEIGHT ).pName ); 1325 #undef STR 1326 DBG_ASSERT( i == pSeq->getLength(), "Please adjust length" ); 1327 if( i != pSeq->getLength() ) 1328 pSeq->realloc( i ); 1329 pNames = pSeq; 1330 } 1331 return *pNames; 1332 } 1333 1334 uno::Sequence< ::rtl::OUString > getSupplementalAttributeNames() 1335 { 1336 static uno::Sequence< ::rtl::OUString >* pNames = NULL; 1337 1338 if( pNames == NULL ) 1339 { 1340 uno::Sequence< ::rtl::OUString >* pSeq = new uno::Sequence< ::rtl::OUString >( 9 ); 1341 1342 ::rtl::OUString* pStrings = pSeq->getArray(); 1343 1344 // sorted list of strings 1345 sal_Int32 i = 0; 1346 1347 #define STR(x) pStrings[i++] = OUString::createFromAscii(x) 1348 STR( GetPropName( UNO_NAME_NUMBERING_LEVEL ).pName ); 1349 STR( GetPropName( UNO_NAME_NUMBERING_RULES ).pName ); 1350 STR( GetPropName( UNO_NAME_PARA_ADJUST ).pName ); 1351 STR( GetPropName( UNO_NAME_PARA_BOTTOM_MARGIN ).pName ); 1352 STR( GetPropName( UNO_NAME_PARA_FIRST_LINE_INDENT ).pName ); 1353 STR( GetPropName( UNO_NAME_PARA_LEFT_MARGIN ).pName ); 1354 STR( GetPropName( UNO_NAME_PARA_LINE_SPACING ).pName ); 1355 STR( GetPropName( UNO_NAME_PARA_RIGHT_MARGIN ).pName ); 1356 STR( GetPropName( UNO_NAME_TABSTOPS ).pName ); 1357 #undef STR 1358 DBG_ASSERT( i == pSeq->getLength(), "Please adjust length" ); 1359 if( i != pSeq->getLength() ) 1360 pSeq->realloc( i ); 1361 pNames = pSeq; 1362 } 1363 return *pNames; 1364 } 1365 // 1366 //===== XInterface ======================================================= 1367 // 1368 1369 uno::Any SwAccessibleParagraph::queryInterface( const uno::Type& rType ) 1370 throw (uno::RuntimeException) 1371 { 1372 uno::Any aRet; 1373 if ( rType == ::getCppuType((uno::Reference<XAccessibleText> *)0) ) 1374 { 1375 uno::Reference<XAccessibleText> aAccText = (XAccessibleText *) *this; // resolve ambiguity 1376 aRet <<= aAccText; 1377 } 1378 else if ( rType == ::getCppuType((uno::Reference<XAccessibleEditableText> *)0) ) 1379 { 1380 uno::Reference<XAccessibleEditableText> aAccEditText = this; 1381 aRet <<= aAccEditText; 1382 } 1383 else if ( rType == ::getCppuType((uno::Reference<XAccessibleSelection> *)0) ) 1384 { 1385 uno::Reference<XAccessibleSelection> aAccSel = this; 1386 aRet <<= aAccSel; 1387 } 1388 else if ( rType == ::getCppuType((uno::Reference<XAccessibleHypertext> *)0) ) 1389 { 1390 uno::Reference<XAccessibleHypertext> aAccHyp = this; 1391 aRet <<= aAccHyp; 1392 } 1393 // --> OD 2006-07-13 #i63870# 1394 // add interface com::sun:star:accessibility::XAccessibleTextAttributes 1395 else if ( rType == ::getCppuType((uno::Reference<XAccessibleTextAttributes> *)0) ) 1396 { 1397 uno::Reference<XAccessibleTextAttributes> aAccTextAttr = this; 1398 aRet <<= aAccTextAttr; 1399 } 1400 // <-- 1401 // --> OD 2008-06-10 #i89175# 1402 // add interface com::sun:star:accessibility::XAccessibleTextMarkup 1403 else if ( rType == ::getCppuType((uno::Reference<XAccessibleTextMarkup> *)0) ) 1404 { 1405 uno::Reference<XAccessibleTextMarkup> aAccTextMarkup = this; 1406 aRet <<= aAccTextMarkup; 1407 } 1408 // add interface com::sun:star:accessibility::XAccessibleMultiLineText 1409 else if ( rType == ::getCppuType((uno::Reference<XAccessibleMultiLineText> *)0) ) 1410 { 1411 uno::Reference<XAccessibleMultiLineText> aAccMultiLineText = this; 1412 aRet <<= aAccMultiLineText; 1413 } 1414 // <-- 1415 //MSAA Extension Implementation in app module 1416 else if ( rType == ::getCppuType((uno::Reference<XAccessibleTextSelection> *)NULL) ) 1417 { 1418 uno::Reference< com::sun::star::accessibility::XAccessibleTextSelection > aTextExtension = this; 1419 aRet <<= aTextExtension; 1420 } 1421 else if ( rType == ::getCppuType((uno::Reference<XAccessibleExtendedAttributes> *)NULL) ) 1422 { 1423 uno::Reference<XAccessibleExtendedAttributes> xAttr = this; 1424 aRet <<= xAttr; 1425 } 1426 else 1427 { 1428 aRet = SwAccessibleContext::queryInterface(rType); 1429 } 1430 1431 return aRet; 1432 } 1433 1434 //====== XTypeProvider ==================================================== 1435 uno::Sequence< uno::Type > SAL_CALL SwAccessibleParagraph::getTypes() throw(uno::RuntimeException) 1436 { 1437 uno::Sequence< uno::Type > aTypes( SwAccessibleContext::getTypes() ); 1438 1439 sal_Int32 nIndex = aTypes.getLength(); 1440 // --> OD 2006-07-13 #i63870# 1441 // add type accessibility::XAccessibleTextAttributes 1442 // --> OD 2008-06-10 #i89175# 1443 // add type accessibility::XAccessibleTextMarkup and accessibility::XAccessibleMultiLineText 1444 aTypes.realloc( nIndex + 6 ); 1445 1446 uno::Type* pTypes = aTypes.getArray(); 1447 pTypes[nIndex++] = ::getCppuType( static_cast< uno::Reference< XAccessibleEditableText > * >( 0 ) ); 1448 pTypes[nIndex++] = ::getCppuType( static_cast< uno::Reference< XAccessibleTextAttributes > * >( 0 ) ); 1449 pTypes[nIndex++] = ::getCppuType( static_cast< uno::Reference< XAccessibleSelection > * >( 0 ) ); 1450 pTypes[nIndex++] = ::getCppuType( static_cast< uno::Reference< XAccessibleTextMarkup > * >( 0 ) ); 1451 pTypes[nIndex++] = ::getCppuType( static_cast< uno::Reference< XAccessibleMultiLineText > * >( 0 ) ); 1452 pTypes[nIndex] = ::getCppuType( static_cast< uno::Reference< XAccessibleHypertext > * >( 0 ) ); 1453 // <-- 1454 1455 return aTypes; 1456 } 1457 1458 uno::Sequence< sal_Int8 > SAL_CALL SwAccessibleParagraph::getImplementationId() 1459 throw(uno::RuntimeException) 1460 { 1461 vos::OGuard aGuard(Application::GetSolarMutex()); 1462 static uno::Sequence< sal_Int8 > aId( 16 ); 1463 static sal_Bool bInit = sal_False; 1464 if(!bInit) 1465 { 1466 rtl_createUuid( (sal_uInt8 *)(aId.getArray() ), 0, sal_True ); 1467 bInit = sal_True; 1468 } 1469 return aId; 1470 } 1471 1472 1473 // 1474 //===== XAccesibleText =================================================== 1475 // 1476 1477 sal_Int32 SwAccessibleParagraph::getCaretPosition() 1478 throw (uno::RuntimeException) 1479 { 1480 vos::OGuard aGuard(Application::GetSolarMutex()); 1481 1482 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); 1483 1484 sal_Int32 nRet = GetCaretPos(); 1485 { 1486 vos::OGuard aOldCaretPosGuard( aMutex ); 1487 ASSERT( nRet == nOldCaretPos, "caret pos out of sync" ); 1488 nOldCaretPos = nRet; 1489 } 1490 if( -1 != nRet ) 1491 { 1492 ::vos::ORef < SwAccessibleContext > xThis( this ); 1493 GetMap()->SetCursorContext( xThis ); 1494 } 1495 1496 return nRet; 1497 } 1498 1499 sal_Bool SAL_CALL SwAccessibleParagraph::setCaretPosition( sal_Int32 nIndex ) 1500 throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 1501 { 1502 vos::OGuard aGuard(Application::GetSolarMutex()); 1503 1504 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); 1505 1506 // parameter checking 1507 sal_Int32 nLength = GetString().getLength(); 1508 if ( ! IsValidPosition( nIndex, nLength ) ) 1509 { 1510 throw lang::IndexOutOfBoundsException(); 1511 } 1512 1513 sal_Bool bRet = sal_False; 1514 1515 // get cursor shell 1516 SwCrsrShell* pCrsrShell = GetCrsrShell(); 1517 if( pCrsrShell != NULL ) 1518 { 1519 // create pam for selection 1520 SwTxtNode* pNode = const_cast<SwTxtNode*>( GetTxtNode() ); 1521 SwIndex aIndex( pNode, GetPortionData().GetModelPosition(nIndex)); 1522 SwPosition aStartPos( *pNode, aIndex ); 1523 SwPaM aPaM( aStartPos ); 1524 1525 // set PaM at cursor shell 1526 bRet = Select( aPaM ); 1527 } 1528 1529 return bRet; 1530 } 1531 1532 sal_Unicode SwAccessibleParagraph::getCharacter( sal_Int32 nIndex ) 1533 throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 1534 { 1535 vos::OGuard aGuard(Application::GetSolarMutex()); 1536 1537 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); 1538 1539 ::rtl::OUString sText( GetString() ); 1540 1541 // return character (if valid) 1542 if( IsValidChar(nIndex, sText.getLength() ) ) 1543 { 1544 return sText.getStr()[nIndex]; 1545 } 1546 else 1547 throw lang::IndexOutOfBoundsException(); 1548 } 1549 1550 com::sun::star::uno::Sequence< ::com::sun::star::style::TabStop > SwAccessibleParagraph::GetCurrentTabStop( sal_Int32 nIndex ) 1551 { 1552 vos::OGuard aGuard(Application::GetSolarMutex()); 1553 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); 1554 1555 1556 1557 /* #i12332# The position after the string needs special treatment. 1558 IsValidChar -> IsValidPosition 1559 */ 1560 if( ! (IsValidPosition( nIndex, GetString().getLength() ) ) ) 1561 throw lang::IndexOutOfBoundsException(); 1562 1563 /* #i12332# */ 1564 sal_Bool bBehindText = sal_False; 1565 if ( nIndex == GetString().getLength() ) 1566 bBehindText = sal_True; 1567 1568 // get model position & prepare GetCharRect() arguments 1569 SwCrsrMoveState aMoveState; 1570 aMoveState.bRealHeight = sal_True; 1571 aMoveState.bRealWidth = sal_True; 1572 SwSpecialPos aSpecialPos; 1573 SwTxtNode* pNode = const_cast<SwTxtNode*>( GetTxtNode() ); 1574 1575 sal_uInt16 nPos = 0; 1576 1577 /* #i12332# FillSpecialPos does not accept nIndex == 1578 GetString().getLength(). In that case nPos is set to the 1579 length of the string in the core. This way GetCharRect 1580 returns the rectangle for a cursor at the end of the 1581 paragraph. */ 1582 if (bBehindText) 1583 { 1584 nPos = pNode->GetTxt().Len(); 1585 } 1586 else 1587 nPos = GetPortionData().FillSpecialPos 1588 (nIndex, aSpecialPos, aMoveState.pSpecialPos ); 1589 1590 // call GetCharRect 1591 SwRect aCoreRect; 1592 SwIndex aIndex( pNode, nPos ); 1593 SwPosition aPosition( *pNode, aIndex ); 1594 GetFrm()->GetCharRect( aCoreRect, aPosition, &aMoveState ); 1595 1596 // already get the caret postion 1597 1598 /*SwFrm* pTFrm = const_cast<SwFrm*>(GetFrm()); 1599 com::sun::star::uno::Sequence< ::com::sun::star::style::TabStop > tabs = 1600 pTFrm->GetTabStopInfo(aCoreRect.Left());*/ 1601 1602 com::sun::star::uno::Sequence< ::com::sun::star::style::TabStop > tabs; 1603 const xub_StrLen nStrLen = GetTxtNode()->GetTxt().Len(); 1604 if( nStrLen > 0 ) 1605 { 1606 SwFrm* pTFrm = const_cast<SwFrm*>(GetFrm()); 1607 tabs = pTFrm->GetTabStopInfo(aCoreRect.Left()); 1608 } 1609 1610 if( tabs.hasElements() ) 1611 { 1612 // translate core coordinates into accessibility coordinates 1613 Window *pWin = GetWindow(); 1614 CHECK_FOR_WINDOW( XAccessibleComponent, pWin ); 1615 1616 SwRect aTmpRect(0, 0, tabs[0].Position, 0); 1617 1618 Rectangle aScreenRect( GetMap()->CoreToPixel( aTmpRect.SVRect() )); 1619 SwRect aFrmLogBounds( GetBounds( *(GetMap()) ) ); // twip rel to doc root 1620 1621 Point aFrmPixPos( GetMap()->CoreToPixel( aFrmLogBounds.SVRect() ).TopLeft() ); 1622 aScreenRect.Move( -aFrmPixPos.X(), -aFrmPixPos.Y() ); 1623 1624 tabs[0].Position = aScreenRect.GetWidth(); 1625 } 1626 1627 return tabs; 1628 } 1629 1630 struct IndexCompare 1631 { 1632 const PropertyValue* pValues; 1633 IndexCompare( const PropertyValue* pVals ) : pValues(pVals) {} 1634 bool operator() ( const sal_Int32& a, const sal_Int32& b ) const 1635 { 1636 return (pValues[a].Name < pValues[b].Name) ? true : false; 1637 } 1638 }; 1639 1640 String SwAccessibleParagraph::GetFieldTypeNameAtIndex(sal_Int32 nIndex) 1641 { 1642 String strTypeName; 1643 SwFldMgr aMgr; 1644 SwTxtFld* pTxtFld = NULL; 1645 SwTxtNode* pTxtNd = const_cast<SwTxtNode*>( GetTxtNode() ); 1646 SwIndex fldIndex( pTxtNd, nIndex ); 1647 sal_Int32 nFldIndex = GetPortionData().GetFieldIndex(nIndex); 1648 if (nFldIndex >= 0) 1649 { 1650 const SwpHints* pSwpHints = GetTxtNode()->GetpSwpHints(); 1651 if (pSwpHints) 1652 { 1653 const sal_uInt16 nSize = pSwpHints ? pSwpHints->Count() : 0; 1654 for( sal_uInt16 i = 0; i < nSize; ++i ) 1655 { 1656 const SwTxtAttr* pHt = (*pSwpHints)[i]; 1657 if ( ( pHt->Which() == RES_TXTATR_FIELD 1658 || pHt->Which() == RES_TXTATR_ANNOTATION 1659 || pHt->Which() == RES_TXTATR_INPUTFIELD ) 1660 && (nFldIndex-- == 0)) 1661 { 1662 pTxtFld = (SwTxtFld *)pHt; 1663 break; 1664 } 1665 else if ( pHt->Which() == RES_TXTATR_REFMARK 1666 && (nFldIndex-- == 0) ) 1667 strTypeName = String(OUString(RTL_CONSTASCII_USTRINGPARAM("set reference"))); 1668 } 1669 } 1670 } 1671 if (pTxtFld) 1672 { 1673 const SwField* pField = (pTxtFld->GetFmtFld()).GetField(); 1674 if (pField) 1675 { 1676 strTypeName = pField->GetTyp()->GetTypeStr(pField->GetTypeId()); 1677 sal_uInt16 nWhich = pField->GetTyp()->Which(); 1678 rtl::OUString sEntry; 1679 sal_Int32 subType = 0; 1680 switch (nWhich) 1681 { 1682 case RES_DOCSTATFLD: 1683 subType = ((SwDocStatField*)pField)->GetSubType(); 1684 break; 1685 case RES_GETREFFLD: 1686 { 1687 sal_uInt16 nSub = pField->GetSubType(); 1688 switch( nSub ) 1689 { 1690 case REF_BOOKMARK: 1691 { 1692 const SwGetRefField* pRefFld = dynamic_cast<const SwGetRefField*>(pField); 1693 if ( pRefFld && pRefFld->IsRefToHeadingCrossRefBookmark() ) 1694 sEntry = OUString(RTL_CONSTASCII_USTRINGPARAM("Headings")); 1695 else if ( pRefFld && pRefFld->IsRefToNumItemCrossRefBookmark() ) 1696 sEntry = OUString(RTL_CONSTASCII_USTRINGPARAM("Numbered Paragraphs")); 1697 else 1698 sEntry = OUString(RTL_CONSTASCII_USTRINGPARAM("Bookmarks")); 1699 } 1700 break; 1701 case REF_FOOTNOTE: 1702 sEntry = OUString(RTL_CONSTASCII_USTRINGPARAM("Footnotes")); 1703 break; 1704 case REF_ENDNOTE: 1705 sEntry = OUString(RTL_CONSTASCII_USTRINGPARAM("Endnotes")); 1706 break; 1707 case REF_SETREFATTR: 1708 sEntry = OUString(RTL_CONSTASCII_USTRINGPARAM("Insert Reference")); 1709 break; 1710 case REF_SEQUENCEFLD: 1711 sEntry = ((SwGetRefField*)pField)->GetSetRefName(); 1712 break; 1713 } 1714 //Get format string 1715 strTypeName = sEntry; 1716 // <pField->GetFormat() >= 0> is always true as <pField->GetFormat()> is unsigned 1717 // if (pField->GetFormat() >= 0) 1718 { 1719 sEntry = aMgr.GetFormatStr( pField->GetTypeId(), pField->GetFormat() ); 1720 if (sEntry.getLength() > 0) 1721 { 1722 strTypeName.AppendAscii("-"); 1723 strTypeName += String(sEntry); 1724 } 1725 } 1726 } 1727 break; 1728 case RES_DATETIMEFLD: 1729 subType = ((SwDateTimeField*)pField)->GetSubType(); 1730 break; 1731 case RES_JUMPEDITFLD: 1732 { 1733 sal_uInt16 nFormat= pField->GetFormat(); 1734 sal_uInt16 nSize = aMgr.GetFormatCount(pField->GetTypeId(), sal_False); 1735 if (nFormat < nSize) 1736 { 1737 sEntry = aMgr.GetFormatStr(pField->GetTypeId(), nFormat); 1738 if (sEntry.getLength() > 0) 1739 { 1740 strTypeName.AppendAscii("-"); 1741 strTypeName += String(sEntry); 1742 } 1743 } 1744 } 1745 break; 1746 case RES_EXTUSERFLD: 1747 subType = ((SwExtUserField*)pField)->GetSubType(); 1748 break; 1749 case RES_HIDDENTXTFLD: 1750 case RES_SETEXPFLD: 1751 { 1752 sEntry = pField->GetTyp()->GetName(); 1753 if (sEntry.getLength() > 0) 1754 { 1755 strTypeName.AppendAscii("-"); 1756 strTypeName += String(sEntry); 1757 } 1758 } 1759 break; 1760 case RES_DOCINFOFLD: 1761 subType = pField->GetSubType(); 1762 subType &= 0x00ff; 1763 break; 1764 case RES_REFPAGESETFLD: 1765 { 1766 SwRefPageSetField* pRPld = (SwRefPageSetField*)pField; 1767 sal_Bool bOn = pRPld->IsOn(); 1768 strTypeName.AppendAscii("-"); 1769 if (bOn) 1770 strTypeName += String(OUString(RTL_CONSTASCII_USTRINGPARAM("on"))); 1771 else 1772 strTypeName += String(OUString(RTL_CONSTASCII_USTRINGPARAM("off"))); 1773 } 1774 break; 1775 case RES_AUTHORFLD: 1776 { 1777 strTypeName.AppendAscii("-"); 1778 strTypeName += aMgr.GetFormatStr(pField->GetTypeId(), pField->GetFormat() & 0xff); 1779 } 1780 break; 1781 } 1782 if (subType > 0 || (subType == 0 && (nWhich == RES_DOCINFOFLD || nWhich == RES_EXTUSERFLD || nWhich == RES_DOCSTATFLD))) 1783 { 1784 SvStringsDtor aLst; 1785 aMgr.GetSubTypes(pField->GetTypeId(), aLst); 1786 if (subType < aLst.Count()) 1787 sEntry = *aLst[subType]; 1788 if (sEntry.getLength() > 0) 1789 { 1790 if (nWhich == RES_DOCINFOFLD) 1791 { 1792 strTypeName = String(sEntry); 1793 sal_uInt32 nSize = aMgr.GetFormatCount(pField->GetTypeId(), sal_False); 1794 sal_uInt16 nExSub = pField->GetSubType() & 0xff00; 1795 if (nSize > 0 && nExSub > 0) 1796 { 1797 //Get extra subtype string 1798 strTypeName.AppendAscii("-"); 1799 sEntry = aMgr.GetFormatStr(pField->GetTypeId(), nExSub/0x0100-1); 1800 strTypeName += String(sEntry); 1801 } 1802 } 1803 else 1804 { 1805 strTypeName.AppendAscii("-"); 1806 strTypeName += String(sEntry); 1807 } 1808 } 1809 } 1810 } 1811 } 1812 return strTypeName; 1813 } 1814 // --> OD 2006-07-20 #i63870# 1815 // re-implement method on behalf of methods <_getDefaultAttributesImpl(..)> and 1816 // <_getRunAttributesImpl(..)> 1817 uno::Sequence<PropertyValue> SwAccessibleParagraph::getCharacterAttributes( 1818 sal_Int32 nIndex, 1819 const uno::Sequence< ::rtl::OUString >& aRequestedAttributes ) 1820 throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 1821 { 1822 1823 vos::OGuard aGuard(Application::GetSolarMutex()); 1824 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); 1825 1826 const ::rtl::OUString& rText = GetString(); 1827 1828 if( ! IsValidChar( nIndex, rText.getLength()+1 ) ) 1829 throw lang::IndexOutOfBoundsException(); 1830 1831 bool bSupplementalMode = false; 1832 uno::Sequence< ::rtl::OUString > aNames = aRequestedAttributes; 1833 if (aNames.getLength() == 0) 1834 { 1835 bSupplementalMode = true; 1836 aNames = getAttributeNames(); 1837 } 1838 // retrieve default character attributes 1839 tAccParaPropValMap aDefAttrSeq; 1840 _getDefaultAttributesImpl( aNames, aDefAttrSeq, true ); 1841 1842 // retrieved run character attributes 1843 tAccParaPropValMap aRunAttrSeq; 1844 _getRunAttributesImpl( nIndex, aNames, aRunAttrSeq ); 1845 1846 // merge default and run attributes 1847 uno::Sequence< PropertyValue > aValues( aDefAttrSeq.size() ); 1848 PropertyValue* pValues = aValues.getArray(); 1849 sal_Int32 i = 0; 1850 for ( tAccParaPropValMap::const_iterator aDefIter = aDefAttrSeq.begin(); 1851 aDefIter != aDefAttrSeq.end(); 1852 ++aDefIter ) 1853 { 1854 tAccParaPropValMap::const_iterator aRunIter = 1855 aRunAttrSeq.find( aDefIter->first ); 1856 if ( aRunIter != aRunAttrSeq.end() ) 1857 { 1858 pValues[i] = aRunIter->second; 1859 } 1860 else 1861 { 1862 pValues[i] = aDefIter->second; 1863 } 1864 ++i; 1865 } 1866 if( bSupplementalMode ) 1867 { 1868 uno::Sequence< ::rtl::OUString > aSupplementalNames = aRequestedAttributes; 1869 if (aSupplementalNames.getLength() == 0) 1870 aSupplementalNames = getSupplementalAttributeNames(); 1871 1872 tAccParaPropValMap aSupplementalAttrSeq; 1873 _getSupplementalAttributesImpl( nIndex, aSupplementalNames, aSupplementalAttrSeq ); 1874 1875 aValues.realloc( aValues.getLength() + aSupplementalAttrSeq.size() ); 1876 pValues = aValues.getArray(); 1877 1878 for ( tAccParaPropValMap::const_iterator aSupplementalIter = aSupplementalAttrSeq.begin(); 1879 aSupplementalIter != aSupplementalAttrSeq.end(); 1880 ++aSupplementalIter ) 1881 { 1882 pValues[i] = aSupplementalIter->second; 1883 ++i; 1884 } 1885 1886 _correctValues( nIndex, aValues ); 1887 1888 aValues.realloc( aValues.getLength() + 1 ); 1889 1890 pValues = aValues.getArray(); 1891 1892 const SwTxtNode* pTxtNode( GetTxtNode() ); 1893 PropertyValue& rValue = pValues[aValues.getLength() - 1 ]; 1894 rValue.Name = OUString::createFromAscii("NumberingPrefix"); 1895 OUString sNumBullet = pTxtNode->GetNumString(); 1896 rValue.Value <<= sNumBullet; 1897 rValue.Handle = -1; 1898 rValue.State = PropertyState_DIRECT_VALUE; 1899 1900 String strTypeName = GetFieldTypeNameAtIndex(nIndex); 1901 if (strTypeName.Len() > 0) 1902 { 1903 aValues.realloc( aValues.getLength() + 1 ); 1904 pValues = aValues.getArray(); 1905 PropertyValue& rValueFT = pValues[aValues.getLength() - 1]; 1906 rValueFT.Name = OUString::createFromAscii("FieldType"); 1907 rValueFT.Value <<= rtl::OUString(strTypeName.ToLowerAscii()); 1908 rValueFT.Handle = -1; 1909 rValueFT.State = PropertyState_DIRECT_VALUE; 1910 } 1911 1912 //sort property values 1913 // build sorted index array 1914 sal_Int32 nLength = aValues.getLength(); 1915 const PropertyValue* pPairs = aValues.getConstArray(); 1916 sal_Int32* pIndices = new sal_Int32[nLength]; 1917 for( i = 0; i < nLength; i++ ) 1918 pIndices[i] = i; 1919 sort( &pIndices[0], &pIndices[nLength], IndexCompare(pPairs) ); 1920 // create sorted sequences according to index array 1921 uno::Sequence<PropertyValue> aNewValues( nLength ); 1922 PropertyValue* pNewValues = aNewValues.getArray(); 1923 for( i = 0; i < nLength; i++ ) 1924 { 1925 pNewValues[i] = pPairs[pIndices[i]]; 1926 } 1927 delete[] pIndices; 1928 return aNewValues; 1929 } 1930 1931 // // create a (dummy) text portion for the sole purpose of calling 1932 // // getPropertyValues on it 1933 // Reference<XMultiPropertySet> xPortion = CreateUnoPortion( nIndex, nIndex + 1 ); 1934 1935 // // get values 1936 // Sequence<OUString> aNames = getAttributeNames(); 1937 // sal_Int32 nLength = aNames.getLength(); 1938 // Sequence<Any> aAnys( nLength ); 1939 // aAnys = xPortion->getPropertyValues( aNames ); 1940 1941 // // copy names + anys into return sequence 1942 // Sequence<PropertyValue> aValues( aNames.getLength() ); 1943 // const OUString* pNames = aNames.getConstArray(); 1944 // const Any* pAnys = aAnys.getConstArray(); 1945 // PropertyValue* pValues = aValues.getArray(); 1946 // for( sal_Int32 i = 0; i < nLength; i++ ) 1947 // { 1948 // PropertyValue& rValue = pValues[i]; 1949 // rValue.Name = pNames[i]; 1950 // rValue.Value = pAnys[i]; 1951 // rValue.Handle = -1; // handle not supported 1952 // rValue.State = PropertyState_DIRECT_VALUE; // states not supported 1953 // } 1954 1955 // // adjust background color if we're in a gray portion 1956 // DBG_ASSERT( pValues[CHAR_BACK_COLOR_POS].Name. 1957 // equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("CharBackColor")), 1958 // "Please adjust CHAR_BACK_COLOR_POS constant." ); 1959 // if( GetPortionData().IsInGrayPortion( nIndex ) ) 1960 // pValues[CHAR_BACK_COLOR_POS].Value <<= SwViewOption::GetFieldShadingsColor().GetColor(); 1961 1962 return aValues; 1963 } 1964 1965 // --> OD 2006-07-11 #i63870# 1966 void SwAccessibleParagraph::_getDefaultAttributesImpl( 1967 const uno::Sequence< ::rtl::OUString >& aRequestedAttributes, 1968 tAccParaPropValMap& rDefAttrSeq, 1969 const bool bOnlyCharAttrs ) 1970 { 1971 // retrieve default attributes 1972 const SwTxtNode* pTxtNode( GetTxtNode() ); 1973 ::boost::scoped_ptr<SfxItemSet> pSet; 1974 if ( !bOnlyCharAttrs ) 1975 { 1976 pSet.reset( new SfxItemSet( const_cast<SwAttrPool&>(pTxtNode->GetDoc()->GetAttrPool()), 1977 RES_CHRATR_BEGIN, RES_CHRATR_END - 1, 1978 RES_PARATR_BEGIN, RES_PARATR_END - 1, 1979 RES_FRMATR_BEGIN, RES_FRMATR_END - 1, 1980 0 ) ); 1981 } 1982 else 1983 { 1984 pSet.reset( new SfxItemSet( const_cast<SwAttrPool&>(pTxtNode->GetDoc()->GetAttrPool()), 1985 RES_CHRATR_BEGIN, RES_CHRATR_END - 1, 1986 0 ) ); 1987 } 1988 // --> OD 2007-11-12 #i82637# 1989 // From the perspective of the a11y API the default character attributes 1990 // are the character attributes, which are set at the paragraph style 1991 // of the paragraph. The character attributes set at the automatic paragraph 1992 // style of the paragraph are treated as run attributes. 1993 // pTxtNode->SwCntntNode::GetAttr( *pSet ); 1994 // get default paragraph attributes, if needed, and merge these into <pSet> 1995 if ( !bOnlyCharAttrs ) 1996 { 1997 SfxItemSet aParaSet( const_cast<SwAttrPool&>(pTxtNode->GetDoc()->GetAttrPool()), 1998 RES_PARATR_BEGIN, RES_PARATR_END - 1, 1999 RES_FRMATR_BEGIN, RES_FRMATR_END - 1, 2000 0 ); 2001 pTxtNode->SwCntntNode::GetAttr( aParaSet ); 2002 pSet->Put( aParaSet ); 2003 } 2004 // get default character attributes and merge these into <pSet> 2005 ASSERT( pTxtNode->GetTxtColl(), 2006 "<SwAccessibleParagraph::_getDefaultAttributesImpl(..)> - missing paragraph style. Serious defect, please inform OD!" ); 2007 if ( pTxtNode->GetTxtColl() ) 2008 { 2009 SfxItemSet aCharSet( const_cast<SwAttrPool&>(pTxtNode->GetDoc()->GetAttrPool()), 2010 RES_CHRATR_BEGIN, RES_CHRATR_END - 1, 2011 0 ); 2012 aCharSet.Put( pTxtNode->GetTxtColl()->GetAttrSet() ); 2013 pSet->Put( aCharSet ); 2014 } 2015 // <-- 2016 2017 // build-up sequence containing the run attributes <rDefAttrSeq> 2018 tAccParaPropValMap aDefAttrSeq; 2019 { 2020 const SfxItemPropertyMap* pPropMap = 2021 aSwMapProvider.GetPropertySet( PROPERTY_MAP_TEXT_CURSOR )->getPropertyMap(); 2022 PropertyEntryVector_t aPropertyEntries = pPropMap->getPropertyEntries(); 2023 PropertyEntryVector_t::const_iterator aPropIt = aPropertyEntries.begin(); 2024 while ( aPropIt != aPropertyEntries.end() ) 2025 { 2026 const SfxPoolItem* pItem = pSet->GetItem( aPropIt->nWID ); 2027 if ( pItem ) 2028 { 2029 uno::Any aVal; 2030 pItem->QueryValue( aVal, aPropIt->nMemberId ); 2031 2032 PropertyValue rPropVal; 2033 rPropVal.Name = aPropIt->sName; 2034 rPropVal.Value = aVal; 2035 rPropVal.Handle = -1; 2036 rPropVal.State = beans::PropertyState_DEFAULT_VALUE; 2037 2038 aDefAttrSeq[rPropVal.Name] = rPropVal; 2039 } 2040 ++aPropIt; 2041 } 2042 2043 // --> OD 2007-01-15 #i72800# 2044 // add property value entry for the paragraph style 2045 if ( !bOnlyCharAttrs && pTxtNode->GetTxtColl() ) 2046 { 2047 const ::rtl::OUString sParaStyleName = 2048 ::rtl::OUString::createFromAscii( 2049 GetPropName( UNO_NAME_PARA_STYLE_NAME ).pName ); 2050 if ( aDefAttrSeq.find( sParaStyleName ) == aDefAttrSeq.end() ) 2051 { 2052 PropertyValue rPropVal; 2053 rPropVal.Name = sParaStyleName; 2054 uno::Any aVal( uno::makeAny( ::rtl::OUString( pTxtNode->GetTxtColl()->GetName() ) ) ); 2055 rPropVal.Value = aVal; 2056 rPropVal.Handle = -1; 2057 rPropVal.State = beans::PropertyState_DEFAULT_VALUE; 2058 2059 aDefAttrSeq[rPropVal.Name] = rPropVal; 2060 } 2061 } 2062 // <-- 2063 2064 // --> OD 2007-01-15 #i73371# 2065 // resolve value text::WritingMode2::PAGE of property value entry WritingMode 2066 if ( !bOnlyCharAttrs && GetFrm() ) 2067 { 2068 const ::rtl::OUString sWritingMode = 2069 ::rtl::OUString::createFromAscii( 2070 GetPropName( UNO_NAME_WRITING_MODE ).pName ); 2071 tAccParaPropValMap::iterator aIter = aDefAttrSeq.find( sWritingMode ); 2072 if ( aIter != aDefAttrSeq.end() ) 2073 { 2074 PropertyValue rPropVal( aIter->second ); 2075 sal_Int16 nVal = rPropVal.Value.get<sal_Int16>(); 2076 if ( nVal == text::WritingMode2::PAGE ) 2077 { 2078 const SwFrm* pUpperFrm( GetFrm()->GetUpper() ); 2079 while ( pUpperFrm ) 2080 { 2081 if ( pUpperFrm->GetType() & 2082 ( FRM_PAGE | FRM_FLY | FRM_SECTION | FRM_TAB | FRM_CELL ) ) 2083 { 2084 if ( pUpperFrm->IsVertical() ) 2085 { 2086 nVal = text::WritingMode2::TB_RL; 2087 } 2088 else if ( pUpperFrm->IsRightToLeft() ) 2089 { 2090 nVal = text::WritingMode2::RL_TB; 2091 } 2092 else 2093 { 2094 nVal = text::WritingMode2::LR_TB; 2095 } 2096 rPropVal.Value <<= nVal; 2097 aDefAttrSeq[rPropVal.Name] = rPropVal; 2098 break; 2099 } 2100 2101 if ( dynamic_cast<const SwFlyFrm*>(pUpperFrm) ) 2102 { 2103 pUpperFrm = dynamic_cast<const SwFlyFrm*>(pUpperFrm)->GetAnchorFrm(); 2104 } 2105 else 2106 { 2107 pUpperFrm = pUpperFrm->GetUpper(); 2108 } 2109 } 2110 } 2111 } 2112 } 2113 // <-- 2114 } 2115 2116 if ( aRequestedAttributes.getLength() == 0 ) 2117 { 2118 rDefAttrSeq = aDefAttrSeq; 2119 } 2120 else 2121 { 2122 const ::rtl::OUString* pReqAttrs = aRequestedAttributes.getConstArray(); 2123 const sal_Int32 nLength = aRequestedAttributes.getLength(); 2124 for( sal_Int32 i = 0; i < nLength; ++i ) 2125 { 2126 tAccParaPropValMap::const_iterator const aIter = aDefAttrSeq.find( pReqAttrs[i] ); 2127 if ( aIter != aDefAttrSeq.end() ) 2128 { 2129 rDefAttrSeq[ aIter->first ] = aIter->second; 2130 } 2131 } 2132 } 2133 } 2134 2135 uno::Sequence< PropertyValue > SwAccessibleParagraph::getDefaultAttributes( 2136 const uno::Sequence< ::rtl::OUString >& aRequestedAttributes ) 2137 throw ( uno::RuntimeException ) 2138 { 2139 vos::OGuard aGuard(Application::GetSolarMutex()); 2140 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); 2141 2142 tAccParaPropValMap aDefAttrSeq; 2143 _getDefaultAttributesImpl( aRequestedAttributes, aDefAttrSeq ); 2144 2145 // --> OD 2010-03-08 #i92233# 2146 static rtl::OUString sMMToPixelRatio( rtl::OUString::createFromAscii( "MMToPixelRatio" ) ); 2147 bool bProvideMMToPixelRatio( false ); 2148 { 2149 if ( aRequestedAttributes.getLength() == 0 ) 2150 { 2151 bProvideMMToPixelRatio = true; 2152 } 2153 else 2154 { 2155 const rtl::OUString* aRequestedAttrIter = 2156 ::std::find( ::comphelper::stl_begin( aRequestedAttributes ), 2157 ::comphelper::stl_end( aRequestedAttributes ), 2158 sMMToPixelRatio ); 2159 if ( aRequestedAttrIter != ::comphelper::stl_end( aRequestedAttributes ) ) 2160 { 2161 bProvideMMToPixelRatio = true; 2162 } 2163 } 2164 } 2165 // <-- 2166 2167 uno::Sequence< PropertyValue > aValues( aDefAttrSeq.size() + 2168 ( bProvideMMToPixelRatio ? 1 : 0 ) ); 2169 PropertyValue* pValues = aValues.getArray(); 2170 sal_Int32 i = 0; 2171 for ( tAccParaPropValMap::const_iterator aIter = aDefAttrSeq.begin(); 2172 aIter != aDefAttrSeq.end(); 2173 ++aIter ) 2174 { 2175 pValues[i] = aIter->second; 2176 ++i; 2177 } 2178 2179 // --> OD 2010-03-08 #i92233# 2180 if ( bProvideMMToPixelRatio ) 2181 { 2182 PropertyValue rPropVal; 2183 rPropVal.Name = sMMToPixelRatio; 2184 const Size a100thMMSize( 1000, 1000 ); 2185 const Size aPixelSize = GetMap()->LogicToPixel( a100thMMSize ); 2186 const float fRatio = ((float)a100thMMSize.Width()/100)/aPixelSize.Width(); 2187 rPropVal.Value = uno::makeAny( fRatio ); 2188 rPropVal.Handle = -1; 2189 rPropVal.State = beans::PropertyState_DEFAULT_VALUE; 2190 pValues[ aValues.getLength() - 1 ] = rPropVal; 2191 } 2192 // <-- 2193 2194 return aValues; 2195 } 2196 2197 void SwAccessibleParagraph::_getRunAttributesImpl( 2198 const sal_Int32 nIndex, 2199 const uno::Sequence< ::rtl::OUString >& aRequestedAttributes, 2200 tAccParaPropValMap& rRunAttrSeq ) 2201 { 2202 // create PaM for character at position <nIndex> 2203 SwPaM* pPaM( 0 ); 2204 { 2205 const SwTxtNode* pTxtNode( GetTxtNode() ); 2206 SwPosition* pStartPos = new SwPosition( *pTxtNode ); 2207 pStartPos->nContent.Assign( const_cast<SwTxtNode*>(pTxtNode), static_cast<sal_uInt16>(nIndex) ); 2208 SwPosition* pEndPos = new SwPosition( *pTxtNode ); 2209 pEndPos->nContent.Assign( const_cast<SwTxtNode*>(pTxtNode), static_cast<sal_uInt16>(nIndex+1) ); 2210 2211 pPaM = new SwPaM( *pStartPos, *pEndPos ); 2212 2213 delete pStartPos; 2214 delete pEndPos; 2215 } 2216 2217 // retrieve character attributes for the created PaM <pPaM> 2218 SfxItemSet aSet( pPaM->GetDoc()->GetAttrPool(), 2219 RES_CHRATR_BEGIN, RES_CHRATR_END -1, 2220 0 ); 2221 // --> OD 2007-11-12 #i82637# 2222 // From the perspective of the a11y API the character attributes, which 2223 // are set at the automatic paragraph style of the paragraph are treated 2224 // as run attributes. 2225 // SwXTextCursor::GetCrsrAttr( *pPaM, aSet, sal_True, sal_True ); 2226 // get character attributes from automatic paragraph style and merge these into <aSet> 2227 { 2228 const SwTxtNode* pTxtNode( GetTxtNode() ); 2229 if ( pTxtNode->HasSwAttrSet() ) 2230 { 2231 SfxItemSet aAutomaticParaStyleCharAttrs( pPaM->GetDoc()->GetAttrPool(), 2232 RES_CHRATR_BEGIN, RES_CHRATR_END -1, 2233 0 ); 2234 aAutomaticParaStyleCharAttrs.Put( *(pTxtNode->GetpSwAttrSet()), sal_False ); 2235 aSet.Put( aAutomaticParaStyleCharAttrs ); 2236 } 2237 } 2238 // get character attributes at <pPaM> and merge these into <aSet> 2239 { 2240 SfxItemSet aCharAttrsAtPaM( pPaM->GetDoc()->GetAttrPool(), 2241 RES_CHRATR_BEGIN, RES_CHRATR_END -1, 2242 0 ); 2243 SwUnoCursorHelper::GetCrsrAttr(*pPaM, aCharAttrsAtPaM, sal_True, sal_True); 2244 aSet.Put( aCharAttrsAtPaM ); 2245 } 2246 // <-- 2247 2248 // build-up sequence containing the run attributes <rRunAttrSeq> 2249 { 2250 tAccParaPropValMap aRunAttrSeq; 2251 { 2252 // --> OD 2007-11-12 #i82637# 2253 tAccParaPropValMap aDefAttrSeq; 2254 uno::Sequence< ::rtl::OUString > aDummy; 2255 _getDefaultAttributesImpl( aDummy, aDefAttrSeq, true ); 2256 // <-- 2257 2258 const SfxItemPropertyMap* pPropMap = 2259 aSwMapProvider.GetPropertySet( PROPERTY_MAP_TEXT_CURSOR )->getPropertyMap(); 2260 PropertyEntryVector_t aPropertyEntries = pPropMap->getPropertyEntries(); 2261 PropertyEntryVector_t::const_iterator aPropIt = aPropertyEntries.begin(); 2262 while ( aPropIt != aPropertyEntries.end() ) 2263 { 2264 const SfxPoolItem* pItem( 0 ); 2265 // --> OD 2007-11-12 #i82637# 2266 // Found character attributes, whose value equals the value of 2267 // the corresponding default character attributes, are excluded. 2268 if ( aSet.GetItemState( aPropIt->nWID, sal_True, &pItem ) == SFX_ITEM_SET ) 2269 { 2270 uno::Any aVal; 2271 pItem->QueryValue( aVal, aPropIt->nMemberId ); 2272 2273 PropertyValue rPropVal; 2274 rPropVal.Name = aPropIt->sName; 2275 rPropVal.Value = aVal; 2276 rPropVal.Handle = -1; 2277 rPropVal.State = PropertyState_DIRECT_VALUE; 2278 2279 tAccParaPropValMap::const_iterator aDefIter = 2280 aDefAttrSeq.find( rPropVal.Name ); 2281 if ( aDefIter == aDefAttrSeq.end() || 2282 rPropVal.Value != aDefIter->second.Value ) 2283 { 2284 aRunAttrSeq[rPropVal.Name] = rPropVal; 2285 } 2286 } 2287 2288 ++aPropIt; 2289 } 2290 } 2291 2292 if ( aRequestedAttributes.getLength() == 0 ) 2293 { 2294 rRunAttrSeq = aRunAttrSeq; 2295 } 2296 else 2297 { 2298 const ::rtl::OUString* pReqAttrs = aRequestedAttributes.getConstArray(); 2299 const sal_Int32 nLength = aRequestedAttributes.getLength(); 2300 for( sal_Int32 i = 0; i < nLength; ++i ) 2301 { 2302 tAccParaPropValMap::iterator aIter = aRunAttrSeq.find( pReqAttrs[i] ); 2303 if ( aIter != aRunAttrSeq.end() ) 2304 { 2305 rRunAttrSeq[ (*aIter).first ] = (*aIter).second; 2306 } 2307 } 2308 } 2309 } 2310 2311 delete pPaM; 2312 } 2313 2314 uno::Sequence< PropertyValue > SwAccessibleParagraph::getRunAttributes( 2315 sal_Int32 nIndex, 2316 const uno::Sequence< ::rtl::OUString >& aRequestedAttributes ) 2317 throw ( lang::IndexOutOfBoundsException, 2318 uno::RuntimeException ) 2319 { 2320 vos::OGuard aGuard(Application::GetSolarMutex()); 2321 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); 2322 2323 { 2324 const ::rtl::OUString& rText = GetString(); 2325 if ( !IsValidChar( nIndex, rText.getLength() ) ) 2326 { 2327 throw lang::IndexOutOfBoundsException(); 2328 } 2329 } 2330 2331 tAccParaPropValMap aRunAttrSeq; 2332 _getRunAttributesImpl( nIndex, aRequestedAttributes, aRunAttrSeq ); 2333 2334 uno::Sequence< PropertyValue > aValues( aRunAttrSeq.size() ); 2335 PropertyValue* pValues = aValues.getArray(); 2336 sal_Int32 i = 0; 2337 for ( tAccParaPropValMap::const_iterator aIter = aRunAttrSeq.begin(); 2338 aIter != aRunAttrSeq.end(); 2339 ++aIter ) 2340 { 2341 pValues[i] = aIter->second; 2342 ++i; 2343 } 2344 2345 return aValues; 2346 } 2347 // <-- 2348 void SwAccessibleParagraph::_getSupplementalAttributesImpl( 2349 const sal_Int32, 2350 const uno::Sequence< ::rtl::OUString >& aRequestedAttributes, 2351 tAccParaPropValMap& rSupplementalAttrSeq ) 2352 { 2353 const SwTxtNode* pTxtNode( GetTxtNode() ); 2354 ::boost::scoped_ptr<SfxItemSet> pSet; 2355 pSet.reset( new SfxItemSet( const_cast<SwAttrPool&>(pTxtNode->GetDoc()->GetAttrPool()), 2356 RES_PARATR_ADJUST, RES_PARATR_ADJUST, 2357 RES_PARATR_TABSTOP, RES_PARATR_TABSTOP, 2358 RES_PARATR_LINESPACING, RES_PARATR_LINESPACING, 2359 RES_UL_SPACE, RES_UL_SPACE, 2360 RES_LR_SPACE, RES_LR_SPACE, 2361 RES_PARATR_NUMRULE, RES_PARATR_NUMRULE, 2362 RES_PARATR_LIST_BEGIN, RES_PARATR_LIST_END-1, 2363 0 ) ); 2364 2365 if ( pTxtNode->HasBullet() || pTxtNode->HasNumber() ) 2366 { 2367 pSet->Put( pTxtNode->GetAttr(RES_PARATR_LIST_LEVEL, RES_PARATR_LIST_LEVEL) ); 2368 } 2369 pSet->Put( pTxtNode->SwCntntNode::GetAttr(RES_UL_SPACE) ); 2370 pSet->Put( pTxtNode->SwCntntNode::GetAttr(RES_LR_SPACE) ); 2371 pSet->Put( pTxtNode->SwCntntNode::GetAttr(RES_PARATR_ADJUST) ); 2372 2373 tAccParaPropValMap aSupplementalAttrSeq; 2374 { 2375 const SfxItemPropertyMapEntry* pPropMap( 2376 aSwMapProvider.GetPropertyMapEntries( PROPERTY_MAP_ACCESSIBILITY_TEXT_ATTRIBUTE ) ); 2377 while ( pPropMap->pName ) 2378 { 2379 const SfxPoolItem* pItem = pSet->GetItem( pPropMap->nWID ); 2380 if ( pItem ) 2381 { 2382 uno::Any aVal; 2383 pItem->QueryValue( aVal, pPropMap->nMemberId ); 2384 2385 PropertyValue rPropVal; 2386 rPropVal.Name = OUString::createFromAscii( pPropMap->pName ); 2387 rPropVal.Value = aVal; 2388 rPropVal.Handle = -1; 2389 rPropVal.State = beans::PropertyState_DEFAULT_VALUE; 2390 2391 aSupplementalAttrSeq[rPropVal.Name] = rPropVal; 2392 } 2393 2394 ++pPropMap; 2395 } 2396 } 2397 2398 const OUString* pSupplementalAttrs = aRequestedAttributes.getConstArray(); 2399 const sal_Int32 nSupplementalLength = aRequestedAttributes.getLength(); 2400 2401 for( sal_Int32 index = 0; index < nSupplementalLength; ++index ) 2402 { 2403 tAccParaPropValMap::const_iterator const aIter = aSupplementalAttrSeq.find( pSupplementalAttrs[index] ); 2404 if ( aIter != aSupplementalAttrSeq.end() ) 2405 { 2406 rSupplementalAttrSeq[ aIter->first ] = aIter->second; 2407 } 2408 } 2409 } 2410 2411 void SwAccessibleParagraph::_correctValues( const sal_Int32 nIndex, 2412 uno::Sequence< PropertyValue >& rValues) 2413 { 2414 PropertyValue ChangeAttr, ChangeAttrColor; 2415 2416 const SwRedline* pRedline = GetRedlineAtIndex( nIndex ); 2417 if ( pRedline ) 2418 { 2419 2420 const SwModuleOptions *pOpt = SW_MOD()->GetModuleConfig(); 2421 AuthorCharAttr aChangeAttr; 2422 if ( pOpt ) 2423 { 2424 switch( pRedline->GetType()) 2425 { 2426 case nsRedlineType_t::REDLINE_INSERT: 2427 aChangeAttr = pOpt->GetInsertAuthorAttr(); 2428 break; 2429 case nsRedlineType_t::REDLINE_DELETE: 2430 aChangeAttr = pOpt->GetDeletedAuthorAttr(); 2431 break; 2432 case nsRedlineType_t::REDLINE_FORMAT: 2433 aChangeAttr = pOpt->GetFormatAuthorAttr(); 2434 break; 2435 } 2436 } 2437 switch( aChangeAttr.nItemId ) 2438 { 2439 case SID_ATTR_CHAR_WEIGHT: 2440 ChangeAttr.Name = OUString::createFromAscii( GetPropName( UNO_NAME_CHAR_WEIGHT).pName ); 2441 ChangeAttr.Value <<= awt::FontWeight::BOLD; 2442 break; 2443 case SID_ATTR_CHAR_POSTURE: 2444 ChangeAttr.Name = OUString::createFromAscii( GetPropName( UNO_NAME_CHAR_POSTURE).pName ); 2445 ChangeAttr.Value <<= awt::FontSlant_ITALIC; //char posture 2446 break; 2447 case SID_ATTR_CHAR_STRIKEOUT: 2448 ChangeAttr.Name = OUString::createFromAscii( GetPropName( UNO_NAME_CHAR_STRIKEOUT).pName ); 2449 ChangeAttr.Value <<= awt::FontStrikeout::SINGLE; //char strikeout 2450 break; 2451 case SID_ATTR_CHAR_UNDERLINE: 2452 ChangeAttr.Name = OUString::createFromAscii( GetPropName( UNO_NAME_CHAR_UNDERLINE).pName ); 2453 ChangeAttr.Value <<= aChangeAttr.nAttr; //underline line 2454 break; 2455 } 2456 if( aChangeAttr.nColor != COL_NONE ) 2457 { 2458 if( aChangeAttr.nItemId == SID_ATTR_BRUSH ) 2459 { 2460 ChangeAttrColor.Name = OUString::createFromAscii( GetPropName( UNO_NAME_CHAR_BACK_COLOR).pName ); 2461 if( aChangeAttr.nColor == COL_TRANSPARENT )//char backcolor 2462 ChangeAttrColor.Value <<= COL_BLUE; 2463 else 2464 ChangeAttrColor.Value <<= aChangeAttr.nColor; 2465 } 2466 else 2467 { 2468 ChangeAttrColor.Name = OUString::createFromAscii( GetPropName( UNO_NAME_CHAR_COLOR ).pName ); 2469 if( aChangeAttr.nColor == COL_TRANSPARENT )//char color 2470 ChangeAttrColor.Value <<= COL_BLUE; 2471 else 2472 ChangeAttrColor.Value <<= aChangeAttr.nColor; 2473 } 2474 } 2475 } 2476 2477 PropertyValue* pValues = rValues.getArray(); 2478 2479 const SwTxtNode* pTxtNode( GetTxtNode() ); 2480 2481 sal_Int32 nValues = rValues.getLength(); 2482 for (sal_Int32 i = 0; i < nValues; ++i) 2483 { 2484 PropertyValue& rValue = pValues[i]; 2485 2486 if (rValue.Name.compareTo( ChangeAttr.Name )==0) 2487 { 2488 rValue.Value = ChangeAttr.Value; 2489 continue; 2490 } 2491 2492 if (rValue.Name.compareTo( ChangeAttrColor.Name )==0) 2493 { 2494 rValue.Value = ChangeAttr.Value; 2495 continue; 2496 } 2497 2498 //back color 2499 if (rValue.Name.compareTo(::rtl::OUString::createFromAscii( GetPropName( UNO_NAME_CHAR_BACK_COLOR ).pName ) )==0) 2500 { 2501 uno::Any &anyChar = rValue.Value; 2502 sal_uInt32 crBack = static_cast<sal_uInt32>( reinterpret_cast<sal_uIntPtr>(anyChar.pReserved)); 2503 if (COL_AUTO == crBack) 2504 { 2505 uno::Reference<XAccessibleComponent> xComponent(this); 2506 if (xComponent.is()) 2507 { 2508 crBack = (sal_uInt32)xComponent->getBackground(); 2509 } 2510 rValue.Value <<= crBack; 2511 } 2512 continue; 2513 } 2514 2515 //char color 2516 if (rValue.Name.compareTo(::rtl::OUString::createFromAscii( GetPropName( UNO_NAME_CHAR_COLOR ).pName ) )==0) 2517 { 2518 if( GetPortionData().IsInGrayPortion( nIndex ) ) 2519 rValue.Value <<= SwViewOption::GetFieldShadingsColor().GetColor(); 2520 uno::Any &anyChar = rValue.Value; 2521 sal_uInt32 crChar = static_cast<sal_uInt32>( reinterpret_cast<sal_uIntPtr>(anyChar.pReserved)); 2522 2523 if( COL_AUTO == crChar ) 2524 { 2525 uno::Reference<XAccessibleComponent> xComponent(this); 2526 if (xComponent.is()) 2527 { 2528 Color cr(xComponent->getBackground()); 2529 crChar = cr.IsDark() ? COL_WHITE : COL_BLACK; 2530 rValue.Value <<= crChar; 2531 } 2532 } 2533 continue; 2534 } 2535 2536 // UnderLine 2537 if (rValue.Name.compareTo(::rtl::OUString::createFromAscii( GetPropName( UNO_NAME_CHAR_UNDERLINE ).pName ) )==0) 2538 { 2539 //misspelled word 2540 SwCrsrShell* pCrsrShell = GetCrsrShell(); 2541 if( pCrsrShell != NULL && pCrsrShell->GetViewOptions() && pCrsrShell->GetViewOptions()->IsOnlineSpell()) 2542 { 2543 const SwWrongList* pWrongList = pTxtNode->GetWrong(); 2544 if( NULL != pWrongList ) 2545 { 2546 xub_StrLen nBegin = nIndex; 2547 xub_StrLen nLen = 1; 2548 if( pWrongList->InWrongWord(nBegin,nLen) && !pTxtNode->IsSymbol(nBegin) ) 2549 { 2550 rValue.Value <<= (sal_uInt16)UNDERLINE_WAVE; 2551 } 2552 } 2553 } 2554 continue; 2555 } 2556 2557 // UnderLineColor 2558 if (rValue.Name.compareTo(::rtl::OUString::createFromAscii( GetPropName( UNO_NAME_CHAR_UNDERLINE_COLOR ).pName ) )==0) 2559 { 2560 //misspelled word 2561 SwCrsrShell* pCrsrShell = GetCrsrShell(); 2562 if( pCrsrShell != NULL && pCrsrShell->GetViewOptions() && pCrsrShell->GetViewOptions()->IsOnlineSpell()) 2563 { 2564 const SwWrongList* pWrongList = pTxtNode->GetWrong(); 2565 if( NULL != pWrongList ) 2566 { 2567 xub_StrLen nBegin = nIndex; 2568 xub_StrLen nLen = 1; 2569 if( pWrongList->InWrongWord(nBegin,nLen) && !pTxtNode->IsSymbol(nBegin) ) 2570 { 2571 rValue.Value <<= (sal_Int32)0x00ff0000; 2572 continue; 2573 } 2574 } 2575 } 2576 2577 uno::Any &anyChar = rValue.Value; 2578 sal_uInt32 crUnderline = static_cast<sal_uInt32>( reinterpret_cast<sal_uIntPtr>(anyChar.pReserved)); 2579 if ( COL_AUTO == crUnderline ) 2580 { 2581 uno::Reference<XAccessibleComponent> xComponent(this); 2582 if (xComponent.is()) 2583 { 2584 Color cr(xComponent->getBackground()); 2585 crUnderline = cr.IsDark() ? COL_WHITE : COL_BLACK; 2586 rValue.Value <<= crUnderline; 2587 } 2588 } 2589 2590 continue; 2591 } 2592 2593 //tab stop 2594 if (rValue.Name.compareTo(::rtl::OUString::createFromAscii( GetPropName( UNO_NAME_TABSTOPS ).pName ) )==0) 2595 { 2596 com::sun::star::uno::Sequence< ::com::sun::star::style::TabStop > tabs = GetCurrentTabStop( nIndex ); 2597 if( !tabs.hasElements() ) 2598 { 2599 tabs.realloc(1); 2600 ::com::sun::star::style::TabStop ts; 2601 com::sun::star::awt::Rectangle rc0 = getCharacterBounds(0); 2602 com::sun::star::awt::Rectangle rc1 = getCharacterBounds(nIndex); 2603 if( rc1.X - rc0.X >= 48 ) 2604 ts.Position = (rc1.X - rc0.X) - (rc1.X - rc0.X - 48)% 47 + 47; 2605 else 2606 ts.Position = 48; 2607 ts.DecimalChar = ' '; 2608 ts.FillChar = ' '; 2609 ts.Alignment = ::com::sun::star::style::TabAlign_LEFT; 2610 tabs[0] = ts; 2611 } 2612 rValue.Value <<= tabs; 2613 continue; 2614 } 2615 2616 //number bullet 2617 if (rValue.Name.compareTo(::rtl::OUString::createFromAscii( GetPropName( UNO_NAME_NUMBERING_RULES ).pName ) )==0) 2618 { 2619 if ( pTxtNode->HasBullet() || pTxtNode->HasNumber() ) 2620 { 2621 uno::Any aVal; 2622 SwNumRule* pNumRule = pTxtNode->GetNumRule(); 2623 if (pNumRule) 2624 { 2625 uno::Reference< container::XIndexReplace > xNum = new SwXNumberingRules(*pNumRule); 2626 aVal.setValue(&xNum, ::getCppuType((const uno::Reference< container::XIndexReplace >*)0)); 2627 } 2628 rValue.Value <<= aVal; 2629 } 2630 continue; 2631 } 2632 2633 //footnote & endnote 2634 if (rValue.Name.compareTo(::rtl::OUString::createFromAscii( GetPropName( UNO_NAME_CHAR_ESCAPEMENT ).pName ) )==0) 2635 { 2636 if ( GetPortionData().IsIndexInFootnode(nIndex) ) 2637 { 2638 const OUString sEscapmentName = OUString::createFromAscii( GetPropName( UNO_NAME_CHAR_ESCAPEMENT ).pName ); 2639 rValue.Value <<= (sal_Int32)101; 2640 } 2641 continue; 2642 } 2643 } 2644 } 2645 2646 awt::Rectangle SwAccessibleParagraph::getCharacterBounds( 2647 sal_Int32 nIndex ) 2648 throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 2649 { 2650 vos::OGuard aGuard(Application::GetSolarMutex()); 2651 2652 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); 2653 2654 2655 /* #i12332# The position after the string needs special treatment. 2656 IsValidChar -> IsValidPosition 2657 */ 2658 if( ! (IsValidPosition( nIndex, GetString().getLength() ) ) ) 2659 throw lang::IndexOutOfBoundsException(); 2660 2661 /* #i12332# */ 2662 sal_Bool bBehindText = sal_False; 2663 if ( nIndex == GetString().getLength() ) 2664 bBehindText = sal_True; 2665 2666 // get model position & prepare GetCharRect() arguments 2667 SwCrsrMoveState aMoveState; 2668 aMoveState.bRealHeight = sal_True; 2669 aMoveState.bRealWidth = sal_True; 2670 SwSpecialPos aSpecialPos; 2671 SwTxtNode* pNode = const_cast<SwTxtNode*>( GetTxtNode() ); 2672 2673 sal_uInt16 nPos = 0; 2674 2675 /* #i12332# FillSpecialPos does not accept nIndex == 2676 GetString().getLength(). In that case nPos is set to the 2677 length of the string in the core. This way GetCharRect 2678 returns the rectangle for a cursor at the end of the 2679 paragraph. */ 2680 if (bBehindText) 2681 { 2682 nPos = pNode->GetTxt().Len(); 2683 } 2684 else 2685 nPos = GetPortionData().FillSpecialPos 2686 (nIndex, aSpecialPos, aMoveState.pSpecialPos ); 2687 2688 // call GetCharRect 2689 SwRect aCoreRect; 2690 SwIndex aIndex( pNode, nPos ); 2691 SwPosition aPosition( *pNode, aIndex ); 2692 GetFrm()->GetCharRect( aCoreRect, aPosition, &aMoveState ); 2693 2694 // translate core coordinates into accessibility coordinates 2695 Window *pWin = GetWindow(); 2696 CHECK_FOR_WINDOW( XAccessibleComponent, pWin ); 2697 2698 Rectangle aScreenRect( GetMap()->CoreToPixel( aCoreRect.SVRect() )); 2699 SwRect aFrmLogBounds( GetBounds( *(GetMap()) ) ); // twip rel to doc root 2700 2701 Point aFrmPixPos( GetMap()->CoreToPixel( aFrmLogBounds.SVRect() ).TopLeft() ); 2702 aScreenRect.Move( -aFrmPixPos.X(), -aFrmPixPos.Y() ); 2703 2704 // convert into AWT Rectangle 2705 return awt::Rectangle( 2706 aScreenRect.Left(), aScreenRect.Top(), 2707 aScreenRect.GetWidth(), aScreenRect.GetHeight() ); 2708 } 2709 2710 sal_Int32 SwAccessibleParagraph::getCharacterCount() 2711 throw (uno::RuntimeException) 2712 { 2713 vos::OGuard aGuard(Application::GetSolarMutex()); 2714 2715 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); 2716 2717 return GetString().getLength(); 2718 } 2719 2720 sal_Int32 SwAccessibleParagraph::getIndexAtPoint( const awt::Point& rPoint ) 2721 throw (uno::RuntimeException) 2722 { 2723 vos::OGuard aGuard(Application::GetSolarMutex()); 2724 2725 2726 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); 2727 2728 // construct SwPosition (where GetCrsrOfst() will put the result into) 2729 SwTxtNode* pNode = const_cast<SwTxtNode*>( GetTxtNode() ); 2730 SwIndex aIndex( pNode, 0); 2731 SwPosition aPos( *pNode, aIndex ); 2732 2733 // construct Point (translate into layout coordinates) 2734 Window *pWin = GetWindow(); 2735 CHECK_FOR_WINDOW( XAccessibleComponent, pWin ); 2736 Point aPoint( rPoint.X, rPoint.Y ); 2737 SwRect aLogBounds( GetBounds( *(GetMap()), GetFrm() ) ); // twip rel to doc root 2738 Point aPixPos( GetMap()->CoreToPixel( aLogBounds.SVRect() ).TopLeft() ); 2739 aPoint.X() += aPixPos.X(); 2740 aPoint.Y() += aPixPos.Y(); 2741 MapMode aMapMode = pWin->GetMapMode(); 2742 Point aCorePoint( GetMap()->PixelToCore( aPoint ) ); 2743 if( !aLogBounds.IsInside( aCorePoint ) ) 2744 { 2745 /* #i12332# rPoint is may also be in rectangle returned by 2746 getCharacterBounds(getCharacterCount() */ 2747 2748 awt::Rectangle aRectEndPos = 2749 getCharacterBounds(getCharacterCount()); 2750 2751 if (rPoint.X - aRectEndPos.X >= 0 && 2752 rPoint.X - aRectEndPos.X < aRectEndPos.Width && 2753 rPoint.Y - aRectEndPos.Y >= 0 && 2754 rPoint.Y - aRectEndPos.Y < aRectEndPos.Height) 2755 return getCharacterCount(); 2756 2757 return -1; 2758 } 2759 2760 // ask core for position 2761 DBG_ASSERT( GetFrm() != NULL, "The text frame has vanished!" ); 2762 DBG_ASSERT( GetFrm()->IsTxtFrm(), "The text frame has mutated!" ); 2763 const SwTxtFrm* pFrm = static_cast<const SwTxtFrm*>( GetFrm() ); 2764 SwCrsrMoveState aMoveState; 2765 aMoveState.bPosMatchesBounds = sal_True; 2766 sal_Bool bSuccess = pFrm->GetCrsrOfst( &aPos, aCorePoint, &aMoveState ); 2767 2768 SwIndex aCntntIdx = aPos.nContent; 2769 const xub_StrLen nIndex = aCntntIdx.GetIndex(); 2770 if ( nIndex > 0 ) 2771 { 2772 SwRect aResultRect; 2773 pFrm->GetCharRect( aResultRect, aPos ); 2774 bool bVert = pFrm->IsVertical(); 2775 bool bR2L = pFrm->IsRightToLeft(); 2776 2777 if ( (!bVert && aResultRect.Pos().X() > aCorePoint.X()) || 2778 ( bVert && aResultRect.Pos().Y() > aCorePoint.Y()) || 2779 ( bR2L && aResultRect.Right() < aCorePoint.X()) ) 2780 { 2781 SwIndex aIdxPrev( pNode, nIndex - 1); 2782 SwPosition aPosPrev( *pNode, aIdxPrev ); 2783 SwRect aResultRectPrev; 2784 pFrm->GetCharRect( aResultRectPrev, aPosPrev ); 2785 if ( (!bVert && aResultRectPrev.Pos().X() < aCorePoint.X() && aResultRect.Pos().Y() == aResultRectPrev.Pos().Y()) || 2786 ( bVert && aResultRectPrev.Pos().Y() < aCorePoint.Y() && aResultRect.Pos().X() == aResultRectPrev.Pos().X()) || 2787 ( bR2L && aResultRectPrev.Right() > aCorePoint.X() && aResultRect.Pos().Y() == aResultRectPrev.Pos().Y()) ) 2788 aPos = aPosPrev; 2789 } 2790 } 2791 2792 return bSuccess ? 2793 GetPortionData().GetAccessiblePosition( aPos.nContent.GetIndex() ) 2794 : -1L; 2795 } 2796 2797 ::rtl::OUString SwAccessibleParagraph::getSelectedText() 2798 throw (uno::RuntimeException) 2799 { 2800 vos::OGuard aGuard(Application::GetSolarMutex()); 2801 2802 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); 2803 2804 sal_Int32 nStart, nEnd; 2805 sal_Bool bSelected = GetSelection( nStart, nEnd ); 2806 return bSelected 2807 ? GetString().copy( nStart, nEnd - nStart ) 2808 : ::rtl::OUString(); 2809 } 2810 2811 sal_Int32 SwAccessibleParagraph::getSelectionStart() 2812 throw (uno::RuntimeException) 2813 { 2814 vos::OGuard aGuard(Application::GetSolarMutex()); 2815 2816 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); 2817 2818 sal_Int32 nStart, nEnd; 2819 GetSelection( nStart, nEnd ); 2820 return nStart; 2821 } 2822 2823 sal_Int32 SwAccessibleParagraph::getSelectionEnd() 2824 throw (uno::RuntimeException) 2825 { 2826 vos::OGuard aGuard(Application::GetSolarMutex()); 2827 2828 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); 2829 2830 sal_Int32 nStart, nEnd; 2831 GetSelection( nStart, nEnd ); 2832 return nEnd; 2833 } 2834 2835 sal_Bool SwAccessibleParagraph::setSelection( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) 2836 throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 2837 { 2838 vos::OGuard aGuard(Application::GetSolarMutex()); 2839 2840 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); 2841 2842 // parameter checking 2843 sal_Int32 nLength = GetString().getLength(); 2844 if ( ! IsValidRange( nStartIndex, nEndIndex, nLength ) ) 2845 { 2846 throw lang::IndexOutOfBoundsException(); 2847 } 2848 2849 sal_Bool bRet = sal_False; 2850 2851 // get cursor shell 2852 SwCrsrShell* pCrsrShell = GetCrsrShell(); 2853 if( pCrsrShell != NULL ) 2854 { 2855 // create pam for selection 2856 SwTxtNode* pNode = const_cast<SwTxtNode*>( GetTxtNode() ); 2857 SwIndex aIndex( pNode, GetPortionData().GetModelPosition(nStartIndex)); 2858 SwPosition aStartPos( *pNode, aIndex ); 2859 SwPaM aPaM( aStartPos ); 2860 aPaM.SetMark(); 2861 aPaM.GetPoint()->nContent = 2862 GetPortionData().GetModelPosition(nEndIndex); 2863 2864 // set PaM at cursor shell 2865 bRet = Select( aPaM ); 2866 } 2867 2868 return bRet; 2869 } 2870 2871 ::rtl::OUString SwAccessibleParagraph::getText() 2872 throw (uno::RuntimeException) 2873 { 2874 vos::OGuard aGuard(Application::GetSolarMutex()); 2875 2876 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); 2877 2878 return GetString(); 2879 } 2880 2881 ::rtl::OUString SwAccessibleParagraph::getTextRange( 2882 sal_Int32 nStartIndex, sal_Int32 nEndIndex ) 2883 throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 2884 { 2885 vos::OGuard aGuard(Application::GetSolarMutex()); 2886 2887 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); 2888 2889 ::rtl::OUString sText( GetString() ); 2890 2891 if ( IsValidRange( nStartIndex, nEndIndex, sText.getLength() ) ) 2892 { 2893 OrderRange( nStartIndex, nEndIndex ); 2894 return sText.copy(nStartIndex, nEndIndex-nStartIndex ); 2895 } 2896 else 2897 throw lang::IndexOutOfBoundsException(); 2898 } 2899 2900 /*accessibility::*/TextSegment SwAccessibleParagraph::getTextAtIndex( sal_Int32 nIndex, sal_Int16 nTextType ) throw (lang::IndexOutOfBoundsException, lang::IllegalArgumentException, uno::RuntimeException) 2901 { 2902 vos::OGuard aGuard(Application::GetSolarMutex()); 2903 2904 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); 2905 2906 /*accessibility::*/TextSegment aResult; 2907 aResult.SegmentStart = -1; 2908 aResult.SegmentEnd = -1; 2909 2910 const ::rtl::OUString rText = GetString(); 2911 // implement the silly specification that first position after 2912 // text must return an empty string, rather than throwing an 2913 // IndexOutOfBoundsException, except for LINE, where the last 2914 // line is returned 2915 if( nIndex == rText.getLength() && AccessibleTextType::LINE != nTextType ) 2916 return aResult; 2917 2918 // with error checking 2919 i18n::Boundary aBound; 2920 sal_Bool bWord = GetTextBoundary( aBound, rText, nIndex, nTextType ); 2921 2922 DBG_ASSERT( aBound.startPos >= 0, "illegal boundary" ); 2923 DBG_ASSERT( aBound.startPos <= aBound.endPos, "illegal boundary" ); 2924 2925 // return word (if present) 2926 if ( bWord ) 2927 { 2928 aResult.SegmentText = rText.copy( aBound.startPos, aBound.endPos - aBound.startPos ); 2929 aResult.SegmentStart = aBound.startPos; 2930 aResult.SegmentEnd = aBound.endPos; 2931 } 2932 2933 return aResult; 2934 } 2935 2936 /*accessibility::*/TextSegment SwAccessibleParagraph::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 nTextType ) throw (lang::IndexOutOfBoundsException, lang::IllegalArgumentException, uno::RuntimeException) 2937 { 2938 vos::OGuard aGuard(Application::GetSolarMutex()); 2939 2940 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); 2941 2942 const ::rtl::OUString rText = GetString(); 2943 2944 /*accessibility::*/TextSegment aResult; 2945 aResult.SegmentStart = -1; 2946 aResult.SegmentEnd = -1; 2947 //If nIndex = 0, then nobefore text so return -1 directly. 2948 if( nIndex == 0 ) 2949 return aResult; 2950 //Tab will be return when call WORDTYPE 2951 2952 // get starting pos 2953 i18n::Boundary aBound; 2954 if (nIndex == rText.getLength()) 2955 aBound.startPos = aBound.endPos = nIndex; 2956 else 2957 { 2958 sal_Bool bTmp = GetTextBoundary( aBound, rText, nIndex, nTextType ); 2959 2960 if ( ! bTmp ) 2961 aBound.startPos = aBound.endPos = nIndex; 2962 } 2963 2964 // now skip to previous word 2965 if (nTextType==2 || nTextType == 3) 2966 { 2967 i18n::Boundary preBound = aBound; 2968 while(preBound.startPos==aBound.startPos && nIndex > 0) 2969 { 2970 nIndex = min( nIndex, preBound.startPos ) - 1; 2971 if( nIndex < 0 ) break; 2972 GetTextBoundary( preBound, rText, nIndex, nTextType ); 2973 } 2974 //if (nIndex>0) 2975 if (nIndex>=0) 2976 //Tab will be return when call WORDTYPE 2977 { 2978 aResult.SegmentText = rText.copy( preBound.startPos, preBound.endPos - preBound.startPos ); 2979 aResult.SegmentStart = preBound.startPos; 2980 aResult.SegmentEnd = preBound.endPos; 2981 } 2982 } 2983 else 2984 { 2985 sal_Bool bWord = sal_False; 2986 while( !bWord ) 2987 { 2988 nIndex = min( nIndex, aBound.startPos ) - 1; 2989 if( nIndex >= 0 ) 2990 { 2991 bWord = GetTextBoundary( aBound, rText, nIndex, nTextType ); 2992 } 2993 else 2994 break; // exit if beginning of string is reached 2995 } 2996 2997 if (bWord && nIndex<rText.getLength()) 2998 { 2999 aResult.SegmentText = rText.copy( aBound.startPos, aBound.endPos - aBound.startPos ); 3000 aResult.SegmentStart = aBound.startPos; 3001 aResult.SegmentEnd = aBound.endPos; 3002 } 3003 } 3004 return aResult; 3005 } 3006 3007 /*accessibility::*/TextSegment SwAccessibleParagraph::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 nTextType ) throw (lang::IndexOutOfBoundsException, lang::IllegalArgumentException, uno::RuntimeException) 3008 { 3009 vos::OGuard aGuard(Application::GetSolarMutex()); 3010 3011 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); 3012 3013 /*accessibility::*/TextSegment aResult; 3014 aResult.SegmentStart = -1; 3015 aResult.SegmentEnd = -1; 3016 const ::rtl::OUString rText = GetString(); 3017 3018 // implement the silly specification that first position after 3019 // text must return an empty string, rather than throwing an 3020 // IndexOutOfBoundsException 3021 if( nIndex == rText.getLength() ) 3022 return aResult; 3023 3024 3025 // get first word, then skip to next word 3026 i18n::Boundary aBound; 3027 GetTextBoundary( aBound, rText, nIndex, nTextType ); 3028 sal_Bool bWord = sal_False; 3029 while( !bWord ) 3030 { 3031 nIndex = max( sal_Int32(nIndex+1), aBound.endPos ); 3032 if( nIndex < rText.getLength() ) 3033 bWord = GetTextBoundary( aBound, rText, nIndex, nTextType ); 3034 else 3035 break; // exit if end of string is reached 3036 } 3037 3038 if ( bWord ) 3039 { 3040 aResult.SegmentText = rText.copy( aBound.startPos, aBound.endPos - aBound.startPos ); 3041 aResult.SegmentStart = aBound.startPos; 3042 aResult.SegmentEnd = aBound.endPos; 3043 } 3044 3045 /* 3046 sal_Bool bWord = sal_False; 3047 bWord = GetTextBoundary( aBound, rText, nIndex, nTextType ); 3048 3049 if (nTextType==2) 3050 { 3051 Boundary nexBound=aBound; 3052 3053 // real current word 3054 if( nIndex <= aBound.endPos && nIndex >= aBound.startPos ) 3055 { 3056 while(nexBound.endPos==aBound.endPos&&nIndex<rText.getLength()) 3057 { 3058 // nIndex = max( (sal_Int32)(nIndex), nexBound.endPos) + 1; 3059 nIndex = max( (sal_Int32)(nIndex), nexBound.endPos) ; 3060 const sal_Unicode* pStr = rText.getStr(); 3061 if (pStr) 3062 { 3063 if( pStr[nIndex] == sal_Unicode(' ') ) 3064 nIndex++; 3065 } 3066 if( nIndex < rText.getLength() ) 3067 { 3068 bWord = GetTextBoundary( nexBound, rText, nIndex, nTextType ); 3069 } 3070 } 3071 } 3072 3073 if (bWord && nIndex<rText.getLength()) 3074 { 3075 aResult.SegmentText = rText.copy( nexBound.startPos, nexBound.endPos - nexBound.startPos ); 3076 aResult.SegmentStart = nexBound.startPos; 3077 aResult.SegmentEnd = nexBound.endPos; 3078 } 3079 3080 } 3081 else 3082 { 3083 bWord = sal_False; 3084 while( !bWord ) 3085 { 3086 nIndex = max( (sal_Int32)(nIndex+1), aBound.endPos ); 3087 if( nIndex < rText.getLength() ) 3088 { 3089 bWord = GetTextBoundary( aBound, rText, nIndex, nTextType ); 3090 } 3091 else 3092 break; // exit if end of string is reached 3093 } 3094 if (bWord && nIndex<rText.getLength()) 3095 { 3096 aResult.SegmentText = rText.copy( aBound.startPos, aBound.endPos - aBound.startPos ); 3097 aResult.SegmentStart = aBound.startPos; 3098 aResult.SegmentEnd = aBound.endPos; 3099 } 3100 } 3101 */ 3102 return aResult; 3103 } 3104 3105 sal_Bool SwAccessibleParagraph::copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) 3106 throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 3107 { 3108 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); 3109 vos::OGuard aGuard(Application::GetSolarMutex()); 3110 3111 // select and copy (through dispatch mechanism) 3112 setSelection( nStartIndex, nEndIndex ); 3113 ExecuteAtViewShell( SID_COPY ); 3114 return sal_True; 3115 } 3116 3117 3118 // 3119 //===== XAccesibleEditableText ========================================== 3120 // 3121 3122 sal_Bool SwAccessibleParagraph::cutText( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) 3123 throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 3124 { 3125 CHECK_FOR_DEFUNC( XAccessibleEditableText ); 3126 vos::OGuard aGuard(Application::GetSolarMutex()); 3127 3128 if( !IsEditableState() ) 3129 return sal_False; 3130 3131 // select and cut (through dispatch mechanism) 3132 setSelection( nStartIndex, nEndIndex ); 3133 ExecuteAtViewShell( SID_CUT ); 3134 return sal_True; 3135 } 3136 3137 sal_Bool SwAccessibleParagraph::pasteText( sal_Int32 nIndex ) 3138 throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 3139 { 3140 CHECK_FOR_DEFUNC( XAccessibleEditableText ); 3141 vos::OGuard aGuard(Application::GetSolarMutex()); 3142 3143 if( !IsEditableState() ) 3144 return sal_False; 3145 3146 // select and paste (through dispatch mechanism) 3147 setSelection( nIndex, nIndex ); 3148 ExecuteAtViewShell( SID_PASTE ); 3149 return sal_True; 3150 } 3151 3152 sal_Bool SwAccessibleParagraph::deleteText( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) 3153 throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 3154 { 3155 return replaceText( nStartIndex, nEndIndex, ::rtl::OUString() ); 3156 } 3157 3158 sal_Bool SwAccessibleParagraph::insertText( const ::rtl::OUString& sText, sal_Int32 nIndex ) 3159 throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 3160 { 3161 return replaceText( nIndex, nIndex, sText ); 3162 } 3163 3164 sal_Bool SwAccessibleParagraph::replaceText( 3165 sal_Int32 nStartIndex, sal_Int32 nEndIndex, 3166 const ::rtl::OUString& sReplacement ) 3167 throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 3168 { 3169 vos::OGuard aGuard(Application::GetSolarMutex()); 3170 3171 CHECK_FOR_DEFUNC( XAccessibleEditableText ); 3172 3173 const ::rtl::OUString& rText = GetString(); 3174 3175 if( IsValidRange( nStartIndex, nEndIndex, rText.getLength() ) ) 3176 { 3177 if( !IsEditableState() ) 3178 return sal_False; 3179 3180 SwTxtNode* pNode = const_cast<SwTxtNode*>( GetTxtNode() ); 3181 3182 // translate positions 3183 sal_uInt16 nStart, nEnd; 3184 sal_Bool bSuccess = GetPortionData().GetEditableRange( 3185 nStartIndex, nEndIndex, nStart, nEnd ); 3186 3187 // edit only if the range is editable 3188 if( bSuccess ) 3189 { 3190 // create SwPosition for nStartIndex 3191 SwIndex aIndex( pNode, nStart ); 3192 SwPosition aStartPos( *pNode, aIndex ); 3193 3194 // create SwPosition for nEndIndex 3195 SwPosition aEndPos( aStartPos ); 3196 aEndPos.nContent = nEnd; 3197 3198 // now create XTextRange as helper and set string 3199 const uno::Reference<text::XTextRange> xRange( 3200 SwXTextRange::CreateXTextRange( 3201 *pNode->GetDoc(), aStartPos, &aEndPos)); 3202 xRange->setString(sReplacement); 3203 3204 // delete portion data 3205 ClearPortionData(); 3206 } 3207 3208 return bSuccess; 3209 } 3210 else 3211 throw lang::IndexOutOfBoundsException(); 3212 } 3213 3214 3215 sal_Bool SwAccessibleParagraph::setAttributes( 3216 sal_Int32 nStartIndex, 3217 sal_Int32 nEndIndex, 3218 const uno::Sequence<PropertyValue>& rAttributeSet ) 3219 throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 3220 { 3221 vos::OGuard aGuard(Application::GetSolarMutex()); 3222 CHECK_FOR_DEFUNC( XAccessibleEditableText ); 3223 3224 const ::rtl::OUString& rText = GetString(); 3225 3226 if( ! IsValidRange( nStartIndex, nEndIndex, rText.getLength() ) ) 3227 throw lang::IndexOutOfBoundsException(); 3228 3229 if( !IsEditableState() ) 3230 return sal_False; 3231 3232 3233 // create a (dummy) text portion for the sole purpose of calling 3234 // setPropertyValue on it 3235 uno::Reference<XMultiPropertySet> xPortion = CreateUnoPortion( nStartIndex, 3236 nEndIndex ); 3237 3238 // build sorted index array 3239 sal_Int32 nLength = rAttributeSet.getLength(); 3240 const PropertyValue* pPairs = rAttributeSet.getConstArray(); 3241 sal_Int32* pIndices = new sal_Int32[nLength]; 3242 sal_Int32 i; 3243 for( i = 0; i < nLength; i++ ) 3244 pIndices[i] = i; 3245 sort( &pIndices[0], &pIndices[nLength], IndexCompare(pPairs) ); 3246 3247 // create sorted sequences according to index array 3248 uno::Sequence< ::rtl::OUString > aNames( nLength ); 3249 ::rtl::OUString* pNames = aNames.getArray(); 3250 uno::Sequence< uno::Any > aValues( nLength ); 3251 uno::Any* pValues = aValues.getArray(); 3252 for( i = 0; i < nLength; i++ ) 3253 { 3254 const PropertyValue& rVal = pPairs[pIndices[i]]; 3255 pNames[i] = rVal.Name; 3256 pValues[i] = rVal.Value; 3257 } 3258 delete[] pIndices; 3259 3260 // now set the values 3261 sal_Bool bRet = sal_True; 3262 try 3263 { 3264 xPortion->setPropertyValues( aNames, aValues ); 3265 } 3266 catch( UnknownPropertyException e ) 3267 { 3268 // error handling through return code! 3269 bRet = sal_False; 3270 } 3271 3272 return bRet; 3273 } 3274 3275 sal_Bool SwAccessibleParagraph::setText( const ::rtl::OUString& sText ) 3276 throw (uno::RuntimeException) 3277 { 3278 return replaceText(0, GetString().getLength(), sText); 3279 } 3280 3281 //===== XAccessibleSelection ============================================ 3282 3283 void SwAccessibleParagraph::selectAccessibleChild( 3284 sal_Int32 nChildIndex ) 3285 throw ( lang::IndexOutOfBoundsException, 3286 uno::RuntimeException ) 3287 { 3288 CHECK_FOR_DEFUNC( XAccessibleSelection ); 3289 3290 aSelectionHelper.selectAccessibleChild(nChildIndex); 3291 } 3292 3293 sal_Bool SwAccessibleParagraph::isAccessibleChildSelected( 3294 sal_Int32 nChildIndex ) 3295 throw ( lang::IndexOutOfBoundsException, 3296 uno::RuntimeException ) 3297 { 3298 CHECK_FOR_DEFUNC( XAccessibleSelection ); 3299 3300 return aSelectionHelper.isAccessibleChildSelected(nChildIndex); 3301 } 3302 3303 void SwAccessibleParagraph::clearAccessibleSelection( ) 3304 throw ( uno::RuntimeException ) 3305 { 3306 CHECK_FOR_DEFUNC( XAccessibleSelection ); 3307 3308 aSelectionHelper.clearAccessibleSelection(); 3309 } 3310 3311 void SwAccessibleParagraph::selectAllAccessibleChildren( ) 3312 throw ( uno::RuntimeException ) 3313 { 3314 CHECK_FOR_DEFUNC( XAccessibleSelection ); 3315 3316 aSelectionHelper.selectAllAccessibleChildren(); 3317 } 3318 3319 sal_Int32 SwAccessibleParagraph::getSelectedAccessibleChildCount( ) 3320 throw ( uno::RuntimeException ) 3321 { 3322 CHECK_FOR_DEFUNC( XAccessibleSelection ); 3323 3324 return aSelectionHelper.getSelectedAccessibleChildCount(); 3325 } 3326 3327 uno::Reference<XAccessible> SwAccessibleParagraph::getSelectedAccessibleChild( 3328 sal_Int32 nSelectedChildIndex ) 3329 throw ( lang::IndexOutOfBoundsException, 3330 uno::RuntimeException) 3331 { 3332 CHECK_FOR_DEFUNC( XAccessibleSelection ); 3333 3334 return aSelectionHelper.getSelectedAccessibleChild(nSelectedChildIndex); 3335 } 3336 3337 // --> OD 2004-11-16 #111714# - index has to be treated as global child index. 3338 void SwAccessibleParagraph::deselectAccessibleChild( 3339 sal_Int32 nChildIndex ) 3340 throw ( lang::IndexOutOfBoundsException, 3341 uno::RuntimeException ) 3342 { 3343 CHECK_FOR_DEFUNC( XAccessibleSelection ); 3344 3345 aSelectionHelper.deselectAccessibleChild( nChildIndex ); 3346 } 3347 3348 //===== XAccessibleHypertext ============================================ 3349 3350 class SwHyperlinkIter_Impl 3351 { 3352 const SwpHints *pHints; 3353 xub_StrLen nStt; 3354 xub_StrLen nEnd; 3355 sal_uInt16 nPos; 3356 3357 public: 3358 SwHyperlinkIter_Impl( const SwTxtFrm *pTxtFrm ); 3359 const SwTxtAttr *next(); 3360 sal_uInt16 getCurrHintPos() const { return nPos-1; } 3361 3362 xub_StrLen startIdx() const { return nStt; } 3363 xub_StrLen endIdx() const { return nEnd; } 3364 }; 3365 3366 SwHyperlinkIter_Impl::SwHyperlinkIter_Impl( const SwTxtFrm *pTxtFrm ) : 3367 pHints( pTxtFrm->GetTxtNode()->GetpSwpHints() ), 3368 nStt( pTxtFrm->GetOfst() ), 3369 nPos( 0 ) 3370 { 3371 const SwTxtFrm *pFollFrm = pTxtFrm->GetFollow(); 3372 nEnd = pFollFrm ? pFollFrm->GetOfst() : pTxtFrm->GetTxtNode()->Len(); 3373 } 3374 3375 const SwTxtAttr *SwHyperlinkIter_Impl::next() 3376 { 3377 const SwTxtAttr *pAttr = 0; 3378 if( pHints ) 3379 { 3380 while( !pAttr && nPos < pHints->Count() ) 3381 { 3382 const SwTxtAttr *pHt = (*pHints)[nPos]; 3383 if( RES_TXTATR_INETFMT == pHt->Which() ) 3384 { 3385 xub_StrLen nHtStt = *pHt->GetStart(); 3386 xub_StrLen nHtEnd = *pHt->GetAnyEnd(); 3387 if( nHtEnd > nHtStt && 3388 ( (nHtStt >= nStt && nHtStt < nEnd) || 3389 (nHtEnd > nStt && nHtEnd <= nEnd) ) ) 3390 { 3391 pAttr = pHt; 3392 } 3393 } 3394 ++nPos; 3395 } 3396 } 3397 3398 return pAttr; 3399 }; 3400 3401 sal_Int32 SAL_CALL SwAccessibleParagraph::getHyperLinkCount() 3402 throw (uno::RuntimeException) 3403 { 3404 vos::OGuard aGuard(Application::GetSolarMutex()); 3405 3406 CHECK_FOR_DEFUNC( XAccessibleHypertext ); 3407 3408 sal_Int32 nCount = 0; 3409 // --> OD 2007-06-27 #i77108# - provide hyperlinks also in editable documents. 3410 // if( !IsEditableState() ) 3411 // <-- 3412 { 3413 const SwTxtFrm *pTxtFrm = static_cast<const SwTxtFrm*>( GetFrm() ); 3414 SwHyperlinkIter_Impl aIter( pTxtFrm ); 3415 while( aIter.next() ) 3416 nCount++; 3417 } 3418 3419 return nCount; 3420 } 3421 3422 uno::Reference< XAccessibleHyperlink > SAL_CALL 3423 SwAccessibleParagraph::getHyperLink( sal_Int32 nLinkIndex ) 3424 throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 3425 { 3426 vos::OGuard aGuard(Application::GetSolarMutex()); 3427 CHECK_FOR_DEFUNC( XAccessibleHypertext ); 3428 3429 uno::Reference< XAccessibleHyperlink > xRet; 3430 3431 // --> OD 2007-06-27 #i77108# - provide hyperlinks also in editable documents. 3432 // if( !IsEditableState() ) 3433 const SwTxtFrm *pTxtFrm = static_cast<const SwTxtFrm*>( GetFrm() ); 3434 SwHyperlinkIter_Impl aHIter( pTxtFrm ); 3435 //SwAccessibleAutoRecognizerHelper_Impl aARHelper( pTxtFrm ); 3436 sal_Int32 nARCount = 0; 3437 sal_Int32 nARIndex = 0; 3438 sal_Int32 nTIndex = -1; 3439 sal_Int32 nTOCEndIndex = -1; 3440 SwTxtNode* pNode = NULL; 3441 SwTOXSortTabBase* pTBase = GetTOXSortTabBase(); 3442 if( pTBase ) 3443 { 3444 pNode = const_cast<SwTxtNode*>(GetTxtNode()); 3445 } 3446 nTOCEndIndex = -1; 3447 SwTxtAttr* pHt = (SwTxtAttr*)(aHIter.next()); 3448 while( (nLinkIndex < getHyperLinkCount()) && nTIndex < nLinkIndex) 3449 { 3450 // no candidates, exit 3451 //if( (!pHt) && (nARIndex >= nARCount) && nTOCEndIndex <= 0) 3452 // break; 3453 3454 sal_Int32 nHStt = -1; 3455 sal_Int32 nAStt = -1; 3456 sal_Bool bH = sal_False; 3457 sal_Bool bA = sal_False; 3458 3459 3460 if( pHt ) 3461 nHStt = *pHt->GetStart(); 3462 if( nARIndex < nARCount ) 3463 { 3464 /* 3465 sal_Int32 nAEnd; 3466 aARHelper.getPosition( nARIndex, nAStt, nAEnd ); 3467 */ 3468 } 3469 sal_Bool bTOC = sal_False; 3470 // Inside TOC & get the first link 3471 if( pTBase && nTIndex == -1 ) 3472 { 3473 nTIndex++; 3474 bTOC = sal_True; 3475 } 3476 else 3477 { 3478 if( nHStt >=0 && nAStt >=0 ) 3479 { // both hyperlink and smart tag available 3480 nTIndex++; 3481 if( nHStt <= nAStt ) 3482 bH = sal_True; 3483 else 3484 bA = sal_True; 3485 } 3486 else if( nHStt >= 0 ) 3487 { // only hyperlink available 3488 nTIndex++; 3489 bH = sal_True; 3490 } 3491 else if( nAStt >= 0 ) 3492 { // only smart tag available 3493 nTIndex++; 3494 bA = sal_True; 3495 } 3496 } 3497 3498 if( nTIndex == nLinkIndex ) 3499 { // found 3500 if( bH ) 3501 { // it's a hyperlink 3502 if( pHt ) 3503 { 3504 // const SwField* pFFld = pHt->GetFld().GetFld(); 3505 { 3506 if( !pHyperTextData ) 3507 pHyperTextData = new SwAccessibleHyperTextData; 3508 SwAccessibleHyperTextData::iterator aIter = 3509 pHyperTextData ->find( pHt ); 3510 if( aIter != pHyperTextData->end() ) 3511 { 3512 xRet = (*aIter).second; 3513 } 3514 if( !xRet.is() ) 3515 { 3516 { 3517 const sal_Int32 nTmpHStt= GetPortionData().GetAccessiblePosition( 3518 max( aHIter.startIdx(), *pHt->GetStart() ) ); 3519 const sal_Int32 nTmpHEnd= GetPortionData().GetAccessiblePosition( 3520 min( aHIter.endIdx(), *pHt->GetAnyEnd() ) ); 3521 xRet = new SwAccessibleHyperlink( aHIter.getCurrHintPos(), 3522 this, nTmpHStt, nTmpHEnd ); 3523 } 3524 if( aIter != pHyperTextData->end() ) 3525 { 3526 (*aIter).second = xRet; 3527 } 3528 else 3529 { 3530 SwAccessibleHyperTextData::value_type aEntry( pHt, xRet ); 3531 pHyperTextData->insert( aEntry ); 3532 } 3533 } 3534 } 3535 } 3536 } 3537 else if( bTOC ) 3538 { 3539 //xRet = new SwAccessibleTOCLink( this ); 3540 } 3541 else if( bA ) 3542 { 3543 /* 3544 // it's a smart tag 3545 if( !pAutoRecognizerData ) 3546 pAutoRecognizerData = new SwAccessibleAutoRecognizerData; 3547 SwAccessibleAutoRecognizerData::iterator aIter = 3548 pAutoRecognizerData ->find( nARIndex ); 3549 if( aIter != pAutoRecognizerData->end() ) 3550 { 3551 xRet = (*aIter).second; 3552 } 3553 if( !xRet.is() ) 3554 { 3555 sal_Int32 nAStt = 0; 3556 sal_Int32 nAEnd = 0; 3557 //aARHelper.getPosition( nARIndex, nAStt, nAEnd ); 3558 xRet = new SwAccessibleAutoRecognizer( this, nAStt, nAEnd ); 3559 if( aIter != pAutoRecognizerData->end() ) 3560 { 3561 (*aIter).second = xRet; 3562 } 3563 else 3564 { 3565 SwAccessibleAutoRecognizerData::value_type aEntry( nARIndex, xRet ); 3566 pAutoRecognizerData->insert( aEntry ); 3567 } 3568 } 3569 */ 3570 } 3571 break; 3572 } 3573 3574 // iterate next 3575 if( bH ) 3576 // iterate next hyperlink 3577 pHt = (SwTxtAttr*)(aHIter.next()); 3578 else if( bA ) 3579 // iterate next smart tag 3580 nARIndex++; 3581 else if(bTOC) 3582 continue; 3583 else 3584 // no candidate, exit 3585 break; 3586 } 3587 /* 3588 const SwTxtFrm *pTxtFrm = static_cast<const SwTxtFrm*>( GetFrm() ); 3589 SwHyperlinkIter_Impl aHIter( pTxtFrm ); 3590 while( nLinkIndex-- ) 3591 aHIter.next(); 3592 3593 const SwTxtAttr *pHt = aHIter.next(); 3594 if( pHt ) 3595 { 3596 if( !pHyperTextData ) 3597 pHyperTextData = new SwAccessibleHyperTextData; 3598 SwAccessibleHyperTextData::iterator aIter = 3599 pHyperTextData ->find( pHt ); 3600 if( aIter != pHyperTextData->end() ) 3601 { 3602 xRet = (*aIter).second; 3603 } 3604 if( !xRet.is() ) 3605 { 3606 sal_Int32 nHStt= GetPortionData().GetAccessiblePosition( 3607 max( aHIter.startIdx(), *pHt->GetStart() ) ); 3608 sal_Int32 nHEnd= GetPortionData().GetAccessiblePosition( 3609 min( aHIter.endIdx(), *pHt->GetAnyEnd() ) ); 3610 xRet = new SwAccessibleHyperlink( aHIter.getCurrHintPos(), 3611 this, nHStt, nHEnd ); 3612 if( aIter != pHyperTextData->end() ) 3613 { 3614 (*aIter).second = xRet; 3615 } 3616 else 3617 { 3618 SwAccessibleHyperTextData::value_type aEntry( pHt, xRet ); 3619 pHyperTextData->insert( aEntry ); 3620 } 3621 } 3622 } 3623 } 3624 */ 3625 if( !xRet.is() ) 3626 throw lang::IndexOutOfBoundsException(); 3627 3628 return xRet; 3629 } 3630 3631 sal_Int32 SAL_CALL SwAccessibleParagraph::getHyperLinkIndex( sal_Int32 nCharIndex ) 3632 throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 3633 { 3634 vos::OGuard aGuard(Application::GetSolarMutex()); 3635 CHECK_FOR_DEFUNC( XAccessibleHypertext ); 3636 3637 // parameter checking 3638 sal_Int32 nLength = GetString().getLength(); 3639 if ( ! IsValidPosition( nCharIndex, nLength ) ) 3640 { 3641 throw lang::IndexOutOfBoundsException(); 3642 } 3643 3644 sal_Int32 nRet = -1; 3645 // --> OD 2007-06-27 #i77108# - provide hyperlinks also in editable documents. 3646 // if( !IsEditableState() ) 3647 // <-- 3648 { 3649 const SwTxtFrm *pTxtFrm = static_cast<const SwTxtFrm*>( GetFrm() ); 3650 SwHyperlinkIter_Impl aHIter( pTxtFrm ); 3651 3652 xub_StrLen nIdx = GetPortionData().GetModelPosition( nCharIndex ); 3653 sal_Int32 nPos = 0; 3654 const SwTxtAttr *pHt = aHIter.next(); 3655 while( pHt && !(nIdx >= *pHt->GetStart() && nIdx < *pHt->GetAnyEnd()) ) 3656 { 3657 pHt = aHIter.next(); 3658 nPos++; 3659 } 3660 3661 if( pHt ) 3662 nRet = nPos; 3663 } 3664 3665 if (nRet == -1) 3666 throw lang::IndexOutOfBoundsException(); 3667 else 3668 return nRet; 3669 //return nRet; 3670 } 3671 3672 // --> OD 2008-05-26 #i71360# 3673 // --> OD 2010-02-22 #i108125# - adjustments for change tracking text markup 3674 sal_Int32 SAL_CALL SwAccessibleParagraph::getTextMarkupCount( sal_Int32 nTextMarkupType ) 3675 throw (lang::IllegalArgumentException, 3676 uno::RuntimeException) 3677 { 3678 std::auto_ptr<SwTextMarkupHelper> pTextMarkupHelper; 3679 switch ( nTextMarkupType ) 3680 { 3681 case text::TextMarkupType::TRACK_CHANGE_INSERTION: 3682 case text::TextMarkupType::TRACK_CHANGE_DELETION: 3683 case text::TextMarkupType::TRACK_CHANGE_FORMATCHANGE: 3684 { 3685 pTextMarkupHelper.reset( new SwTextMarkupHelper( 3686 GetPortionData(), 3687 *(mpParaChangeTrackInfo->getChangeTrackingTextMarkupList( nTextMarkupType ) )) ); 3688 } 3689 break; 3690 default: 3691 { 3692 pTextMarkupHelper.reset( new SwTextMarkupHelper( GetPortionData(), *GetTxtNode() ) ); 3693 } 3694 } 3695 3696 return pTextMarkupHelper->getTextMarkupCount( nTextMarkupType ); 3697 } 3698 //MSAA Extension Implementation in app module 3699 sal_Bool SAL_CALL SwAccessibleParagraph::scrollToPosition( const ::com::sun::star::awt::Point&, sal_Bool ) 3700 throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) 3701 { 3702 return sal_False; 3703 } 3704 3705 sal_Int32 SAL_CALL SwAccessibleParagraph::getSelectedPortionCount( ) 3706 throw (::com::sun::star::uno::RuntimeException) 3707 { 3708 sal_Int32 nSeleted = 0; 3709 SwPaM* pCrsr = GetCursor( true ); 3710 if( pCrsr != NULL ) 3711 { 3712 // get SwPosition for my node 3713 const SwTxtNode* pNode = GetTxtNode(); 3714 sal_uLong nHere = pNode->GetIndex(); 3715 3716 // iterate over ring 3717 SwPaM* pRingStart = pCrsr; 3718 do 3719 { 3720 // ignore, if no mark 3721 if( pCrsr->HasMark() ) 3722 { 3723 // check whether nHere is 'inside' pCrsr 3724 SwPosition* pStart = pCrsr->Start(); 3725 sal_uLong nStartIndex = pStart->nNode.GetIndex(); 3726 SwPosition* pEnd = pCrsr->End(); 3727 sal_uLong nEndIndex = pEnd->nNode.GetIndex(); 3728 if( ( nHere >= nStartIndex ) && 3729 ( nHere <= nEndIndex ) ) 3730 { 3731 nSeleted++; 3732 } 3733 // else: this PaM doesn't point to this paragraph 3734 } 3735 // else: this PaM is collapsed and doesn't select anything 3736 3737 // next PaM in ring 3738 pCrsr = static_cast<SwPaM*>( pCrsr->GetNext() ); 3739 } 3740 while( pCrsr != pRingStart ); 3741 } 3742 return nSeleted; 3743 3744 } 3745 3746 sal_Int32 SAL_CALL SwAccessibleParagraph::getSeletedPositionStart( sal_Int32 nSelectedPortionIndex ) 3747 throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException) 3748 { 3749 vos::OGuard aGuard(Application::GetSolarMutex()); 3750 3751 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); 3752 3753 sal_Int32 nStart, nEnd; 3754 /*sal_Bool bSelected = */GetSelectionAtIndex(nSelectedPortionIndex, nStart, nEnd ); 3755 return nStart; 3756 } 3757 3758 sal_Int32 SAL_CALL SwAccessibleParagraph::getSeletedPositionEnd( sal_Int32 nSelectedPortionIndex ) 3759 throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException) 3760 { 3761 vos::OGuard aGuard(Application::GetSolarMutex()); 3762 3763 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); 3764 3765 sal_Int32 nStart, nEnd; 3766 /*sal_Bool bSelected = */GetSelectionAtIndex(nSelectedPortionIndex, nStart, nEnd ); 3767 return nEnd; 3768 } 3769 3770 sal_Bool SAL_CALL SwAccessibleParagraph::removeSelection( sal_Int32 selectionIndex ) 3771 throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException) 3772 { 3773 if(selectionIndex < 0) return sal_False; 3774 3775 sal_Bool bRet = sal_False; 3776 sal_Int32 nSelected = selectionIndex; 3777 3778 // get the selection, and test whether it affects our text node 3779 SwPaM* pCrsr = GetCursor( true ); 3780 // SwPaM* pFirst = pCrsr; 3781 SwPaM* pPrev = pCrsr; 3782 3783 if( pCrsr != NULL ) 3784 { 3785 // get SwPosition for my node 3786 const SwTxtNode* pNode = GetTxtNode(); 3787 sal_uLong nHere = pNode->GetIndex(); 3788 3789 // iterate over ring 3790 SwPaM* pRingStart = pCrsr; 3791 do 3792 { 3793 // ignore, if no mark 3794 if( pCrsr->HasMark() ) 3795 { 3796 // check whether nHere is 'inside' pCrsr 3797 SwPosition* pStart = pCrsr->Start(); 3798 sal_uLong nStartIndex = pStart->nNode.GetIndex(); 3799 SwPosition* pEnd = pCrsr->End(); 3800 sal_uLong nEndIndex = pEnd->nNode.GetIndex(); 3801 if( ( nHere >= nStartIndex ) && 3802 ( nHere <= nEndIndex ) ) 3803 { 3804 if( nSelected == 0 ) 3805 { 3806 pCrsr->MoveTo((Ring*)0); 3807 delete pCrsr; 3808 bRet = sal_True; 3809 } 3810 else 3811 { 3812 nSelected--; 3813 } 3814 } 3815 } 3816 // else: this PaM is collapsed and doesn't select anything 3817 pPrev = pCrsr; 3818 if(!bRet) 3819 pCrsr = static_cast<SwPaM*>( pCrsr->GetNext() ); 3820 } 3821 while( !bRet && (pCrsr != pRingStart) ); 3822 } 3823 return sal_True; 3824 } 3825 3826 sal_Int32 SAL_CALL SwAccessibleParagraph::addSelection( sal_Int32, sal_Int32 startOffset, sal_Int32 endOffset) 3827 throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException) 3828 { 3829 vos::OGuard aGuard(Application::GetSolarMutex()); 3830 3831 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); 3832 3833 // parameter checking 3834 sal_Int32 nLength = GetString().getLength(); 3835 if ( ! IsValidRange( startOffset, endOffset, nLength ) ) 3836 { 3837 throw lang::IndexOutOfBoundsException(); 3838 } 3839 3840 sal_Int32 nSelectedCount = getSelectedPortionCount(); 3841 for ( sal_Int32 i = nSelectedCount ; i >= 0 ; i--) 3842 { 3843 sal_Int32 nStart, nEnd; 3844 sal_Bool bSelected = GetSelectionAtIndex(i, nStart, nEnd ); 3845 if(bSelected) 3846 { 3847 if(nStart <= nEnd ) 3848 { 3849 if (( startOffset>=nStart && startOffset <=nEnd ) || //startOffset in a selection 3850 ( endOffset>=nStart && endOffset <=nEnd ) || //endOffset in a selection 3851 ( startOffset <= nStart && endOffset >=nEnd) || //start and end include the old selection 3852 ( startOffset >= nStart && endOffset <=nEnd) ) 3853 { 3854 removeSelection(i); 3855 } 3856 3857 } 3858 else 3859 { 3860 if (( startOffset>=nEnd && startOffset <=nStart ) || //startOffset in a selection 3861 ( endOffset>=nEnd && endOffset <=nStart ) || //endOffset in a selection 3862 ( startOffset <= nStart && endOffset >=nEnd) || //start and end include the old selection 3863 ( startOffset >= nStart && endOffset <=nEnd) ) 3864 3865 { 3866 removeSelection(i); 3867 } 3868 } 3869 } 3870 3871 } 3872 3873 sal_Bool bRet = sal_False; 3874 3875 // get cursor shell 3876 SwCrsrShell* pCrsrShell = GetCrsrShell(); 3877 if( pCrsrShell != NULL ) 3878 { 3879 // create pam for selection 3880 pCrsrShell->StartAction(); 3881 // SwTxtNode* pNode = const_cast<SwTxtNode*>( GetTxtNode() ); 3882 SwPaM* aPaM = pCrsrShell->CreateCrsr(); 3883 aPaM->SetMark(); 3884 aPaM->GetPoint()->nContent = GetPortionData().GetModelPosition(startOffset); 3885 aPaM->GetMark()->nContent = GetPortionData().GetModelPosition(endOffset); 3886 //pCrsrShell->ShowCrsr(); 3887 pCrsrShell->EndAction(); 3888 // set PaM at cursor shell 3889 //bRet = Select( aPaM ); 3890 } 3891 3892 return bRet; 3893 } 3894 3895 /*accessibility::*/TextSegment SAL_CALL 3896 SwAccessibleParagraph::getTextMarkup( sal_Int32 nTextMarkupIndex, 3897 sal_Int32 nTextMarkupType ) 3898 throw (lang::IndexOutOfBoundsException, 3899 lang::IllegalArgumentException, 3900 uno::RuntimeException) 3901 { 3902 std::auto_ptr<SwTextMarkupHelper> pTextMarkupHelper; 3903 switch ( nTextMarkupType ) 3904 { 3905 case text::TextMarkupType::TRACK_CHANGE_INSERTION: 3906 case text::TextMarkupType::TRACK_CHANGE_DELETION: 3907 case text::TextMarkupType::TRACK_CHANGE_FORMATCHANGE: 3908 { 3909 pTextMarkupHelper.reset( new SwTextMarkupHelper( 3910 GetPortionData(), 3911 *(mpParaChangeTrackInfo->getChangeTrackingTextMarkupList( nTextMarkupType ) )) ); 3912 } 3913 break; 3914 default: 3915 { 3916 pTextMarkupHelper.reset( new SwTextMarkupHelper( GetPortionData(), *GetTxtNode() ) ); 3917 } 3918 } 3919 3920 return pTextMarkupHelper->getTextMarkup( nTextMarkupIndex, nTextMarkupType ); 3921 } 3922 3923 uno::Sequence< /*accessibility::*/TextSegment > SAL_CALL 3924 SwAccessibleParagraph::getTextMarkupAtIndex( sal_Int32 nCharIndex, 3925 sal_Int32 nTextMarkupType ) 3926 throw (lang::IndexOutOfBoundsException, 3927 lang::IllegalArgumentException, 3928 uno::RuntimeException) 3929 { 3930 // parameter checking 3931 const sal_Int32 nLength = GetString().getLength(); 3932 if ( ! IsValidPosition( nCharIndex, nLength ) ) 3933 { 3934 throw lang::IndexOutOfBoundsException(); 3935 } 3936 3937 std::auto_ptr<SwTextMarkupHelper> pTextMarkupHelper; 3938 switch ( nTextMarkupType ) 3939 { 3940 case text::TextMarkupType::TRACK_CHANGE_INSERTION: 3941 case text::TextMarkupType::TRACK_CHANGE_DELETION: 3942 case text::TextMarkupType::TRACK_CHANGE_FORMATCHANGE: 3943 { 3944 pTextMarkupHelper.reset( new SwTextMarkupHelper( 3945 GetPortionData(), 3946 *(mpParaChangeTrackInfo->getChangeTrackingTextMarkupList( nTextMarkupType ) )) ); 3947 } 3948 break; 3949 default: 3950 { 3951 pTextMarkupHelper.reset( new SwTextMarkupHelper( GetPortionData(), *GetTxtNode() ) ); 3952 } 3953 } 3954 3955 return pTextMarkupHelper->getTextMarkupAtIndex( nCharIndex, nTextMarkupType ); 3956 } 3957 // <-- 3958 3959 // --> OD 2008-05-29 #i89175# 3960 sal_Int32 SAL_CALL SwAccessibleParagraph::getLineNumberAtIndex( sal_Int32 nIndex ) 3961 throw (lang::IndexOutOfBoundsException, 3962 uno::RuntimeException) 3963 { 3964 // parameter checking 3965 const sal_Int32 nLength = GetString().getLength(); 3966 if ( ! IsValidPosition( nIndex, nLength ) ) 3967 { 3968 throw lang::IndexOutOfBoundsException(); 3969 } 3970 3971 const sal_Int32 nLineNo = GetPortionData().GetLineNo( nIndex ); 3972 return nLineNo; 3973 } 3974 3975 /*accessibility::*/TextSegment SAL_CALL 3976 SwAccessibleParagraph::getTextAtLineNumber( sal_Int32 nLineNo ) 3977 throw (lang::IndexOutOfBoundsException, 3978 uno::RuntimeException) 3979 { 3980 // parameter checking 3981 if ( nLineNo < 0 || 3982 nLineNo >= GetPortionData().GetLineCount() ) 3983 { 3984 throw lang::IndexOutOfBoundsException(); 3985 } 3986 3987 i18n::Boundary aLineBound; 3988 GetPortionData().GetBoundaryOfLine( nLineNo, aLineBound ); 3989 3990 /*accessibility::*/TextSegment aTextAtLine; 3991 const ::rtl::OUString rText = GetString(); 3992 aTextAtLine.SegmentText = rText.copy( aLineBound.startPos, 3993 aLineBound.endPos - aLineBound.startPos ); 3994 aTextAtLine.SegmentStart = aLineBound.startPos; 3995 aTextAtLine.SegmentEnd = aLineBound.endPos; 3996 3997 return aTextAtLine; 3998 } 3999 4000 /*accessibility::*/TextSegment SAL_CALL SwAccessibleParagraph::getTextAtLineWithCaret() 4001 throw (uno::RuntimeException) 4002 { 4003 const sal_Int32 nLineNoOfCaret = getNumberOfLineWithCaret(); 4004 4005 if ( nLineNoOfCaret >= 0 && 4006 nLineNoOfCaret < GetPortionData().GetLineCount() ) 4007 { 4008 return getTextAtLineNumber( nLineNoOfCaret ); 4009 } 4010 4011 return /*accessibility::*/TextSegment(); 4012 } 4013 4014 sal_Int32 SAL_CALL SwAccessibleParagraph::getNumberOfLineWithCaret() 4015 throw (uno::RuntimeException) 4016 { 4017 const sal_Int32 nCaretPos = getCaretPosition(); 4018 const sal_Int32 nLength = GetString().getLength(); 4019 if ( !IsValidPosition( nCaretPos, nLength ) ) 4020 { 4021 return -1; 4022 } 4023 4024 sal_Int32 nLineNo = GetPortionData().GetLineNo( nCaretPos ); 4025 4026 // special handling for cursor positioned at end of text line via End key 4027 if ( nCaretPos != 0 ) 4028 { 4029 i18n::Boundary aLineBound; 4030 GetPortionData().GetBoundaryOfLine( nLineNo, aLineBound ); 4031 if ( nCaretPos == aLineBound.startPos ) 4032 { 4033 SwCrsrShell* pCrsrShell = SwAccessibleParagraph::GetCrsrShell(); 4034 if ( pCrsrShell != 0 ) 4035 { 4036 const awt::Rectangle aCharRect = getCharacterBounds( nCaretPos ); 4037 4038 const SwRect& aCursorCoreRect = pCrsrShell->GetCharRect(); 4039 // translate core coordinates into accessibility coordinates 4040 Window *pWin = GetWindow(); 4041 CHECK_FOR_WINDOW( XAccessibleComponent, pWin ); 4042 4043 Rectangle aScreenRect( GetMap()->CoreToPixel( aCursorCoreRect.SVRect() )); 4044 4045 SwRect aFrmLogBounds( GetBounds( *(GetMap()) ) ); // twip rel to doc root 4046 Point aFrmPixPos( GetMap()->CoreToPixel( aFrmLogBounds.SVRect() ).TopLeft() ); 4047 aScreenRect.Move( -aFrmPixPos.X(), -aFrmPixPos.Y() ); 4048 4049 // convert into AWT Rectangle 4050 const awt::Rectangle aCursorRect( aScreenRect.Left(), 4051 aScreenRect.Top(), 4052 aScreenRect.GetWidth(), 4053 aScreenRect.GetHeight() ); 4054 4055 if ( aCharRect.X != aCursorRect.X || 4056 aCharRect.Y != aCursorRect.Y ) 4057 { 4058 --nLineNo; 4059 } 4060 } 4061 } 4062 } 4063 4064 return nLineNo; 4065 } 4066 4067 // --> OD 2010-02-19 #i108125# 4068 void SwAccessibleParagraph::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew ) 4069 { 4070 mpParaChangeTrackInfo->reset(); 4071 4072 CheckRegistration( pOld, pNew ); 4073 } 4074 // <-- 4075 4076 sal_Bool SwAccessibleParagraph::GetSelectionAtIndex( 4077 sal_Int32& nIndex, sal_Int32& nStart, sal_Int32& nEnd) 4078 { 4079 if(nIndex < 0) return sal_False; 4080 4081 4082 sal_Bool bRet = sal_False; 4083 nStart = -1; 4084 nEnd = -1; 4085 sal_Int32 nSelected = nIndex; 4086 4087 // get the selection, and test whether it affects our text node 4088 SwPaM* pCrsr = GetCursor( true ); 4089 if( pCrsr != NULL ) 4090 { 4091 // get SwPosition for my node 4092 const SwTxtNode* pNode = GetTxtNode(); 4093 sal_uLong nHere = pNode->GetIndex(); 4094 4095 // iterate over ring 4096 SwPaM* pRingStart = pCrsr; 4097 do 4098 { 4099 // ignore, if no mark 4100 if( pCrsr->HasMark() ) 4101 { 4102 // check whether nHere is 'inside' pCrsr 4103 SwPosition* pStart = pCrsr->Start(); 4104 sal_uLong nStartIndex = pStart->nNode.GetIndex(); 4105 SwPosition* pEnd = pCrsr->End(); 4106 sal_uLong nEndIndex = pEnd->nNode.GetIndex(); 4107 if( ( nHere >= nStartIndex ) && 4108 ( nHere <= nEndIndex ) ) 4109 { 4110 if( nSelected == 0 ) 4111 { 4112 // translate start and end positions 4113 4114 // start position 4115 sal_Int32 nLocalStart = -1; 4116 if( nHere > nStartIndex ) 4117 { 4118 // selection starts in previous node: 4119 // then our local selection starts with the paragraph 4120 nLocalStart = 0; 4121 } 4122 else 4123 { 4124 DBG_ASSERT( nHere == nStartIndex, 4125 "miscalculated index" ); 4126 4127 // selection starts in this node: 4128 // then check whether it's before or inside our part of 4129 // the paragraph, and if so, get the proper position 4130 sal_uInt16 nCoreStart = pStart->nContent.GetIndex(); 4131 if( nCoreStart < 4132 GetPortionData().GetFirstValidCorePosition() ) 4133 { 4134 nLocalStart = 0; 4135 } 4136 else if( nCoreStart <= 4137 GetPortionData().GetLastValidCorePosition() ) 4138 { 4139 DBG_ASSERT( 4140 GetPortionData().IsValidCorePosition( 4141 nCoreStart ), 4142 "problem determining valid core position" ); 4143 4144 nLocalStart = 4145 GetPortionData().GetAccessiblePosition( 4146 nCoreStart ); 4147 } 4148 } 4149 4150 // end position 4151 sal_Int32 nLocalEnd = -1; 4152 if( nHere < nEndIndex ) 4153 { 4154 // selection ends in following node: 4155 // then our local selection extends to the end 4156 nLocalEnd = GetPortionData().GetAccessibleString(). 4157 getLength(); 4158 } 4159 else 4160 { 4161 DBG_ASSERT( nHere == nStartIndex, 4162 "miscalculated index" ); 4163 4164 // selection ends in this node: then select everything 4165 // before our part of the node 4166 sal_uInt16 nCoreEnd = pEnd->nContent.GetIndex(); 4167 if( nCoreEnd > 4168 GetPortionData().GetLastValidCorePosition() ) 4169 { 4170 // selection extends beyond out part of this para 4171 nLocalEnd = GetPortionData().GetAccessibleString(). 4172 getLength(); 4173 } 4174 else if( nCoreEnd >= 4175 GetPortionData().GetFirstValidCorePosition() ) 4176 { 4177 // selection is inside our part of this para 4178 DBG_ASSERT( 4179 GetPortionData().IsValidCorePosition( 4180 nCoreEnd ), 4181 "problem determining valid core position" ); 4182 4183 nLocalEnd = GetPortionData().GetAccessiblePosition( 4184 nCoreEnd ); 4185 } 4186 } 4187 4188 if( ( nLocalStart != -1 ) && ( nLocalEnd != -1 ) ) 4189 { 4190 nStart = nLocalStart; 4191 nEnd = nLocalEnd; 4192 bRet = sal_True; 4193 } 4194 } // if hit the index 4195 else 4196 { 4197 nSelected--; 4198 } 4199 } 4200 // else: this PaM doesn't point to this paragraph 4201 } 4202 // else: this PaM is collapsed and doesn't select anything 4203 4204 // next PaM in ring 4205 pCrsr = static_cast<SwPaM*>( pCrsr->GetNext() ); 4206 } 4207 while( !bRet && (pCrsr != pRingStart) ); 4208 } 4209 // else: nocursor -> no selection 4210 4211 if( bRet ) 4212 { 4213 sal_Int32 nCaretPos = GetCaretPos(); 4214 if( nStart == nCaretPos ) 4215 { 4216 sal_Int32 tmp = nStart; 4217 nStart = nEnd; 4218 nEnd = tmp; 4219 } 4220 } 4221 return bRet; 4222 } 4223 4224 sal_Int16 SAL_CALL SwAccessibleParagraph::getAccessibleRole (void) throw (::com::sun::star::uno::RuntimeException) 4225 { 4226 //Get the real heading level, Heading1 ~ Heading10 4227 if (nHeadingLevel > 0) 4228 { 4229 return AccessibleRole::HEADING; 4230 } 4231 else 4232 { 4233 return AccessibleRole::PARAGRAPH; 4234 } 4235 } 4236 4237 4238 //Get the real heading level, Heading1 ~ Heading10 4239 sal_Int32 SwAccessibleParagraph::GetRealHeadingLevel() 4240 { 4241 uno::Reference< ::com::sun::star::beans::XPropertySet > xPortion = CreateUnoPortion( 0, 0 ); 4242 ::rtl::OUString pString = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ParaStyleName")); 4243 uno::Any styleAny = xPortion->getPropertyValue( pString ); 4244 ::rtl::OUString sValue; 4245 if (styleAny >>= sValue) 4246 { 4247 sal_Int32 length = sValue.getLength(); 4248 if (length == 9 || length == 10) 4249 { 4250 ::rtl::OUString headStr = sValue.copy(0, 7); 4251 if (headStr.equals(::rtl::OUString::createFromAscii("Heading"))) 4252 { 4253 ::rtl::OUString intStr = sValue.copy(8); 4254 sal_Int32 headingLevel = intStr.toInt32(10); 4255 return headingLevel; 4256 } 4257 } 4258 } 4259 return -1; 4260 } 4261 4262 uno::Any SAL_CALL SwAccessibleParagraph::getExtendedAttributes() 4263 throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException) 4264 { 4265 uno::Any Ret; 4266 ::rtl::OUString strHeading(::rtl::OUString::createFromAscii("heading-level:")); 4267 if( nHeadingLevel >= 0 ) 4268 strHeading += OUString::valueOf(nHeadingLevel, 10); 4269 strHeading += OUString::createFromAscii(";"); 4270 4271 Ret <<= strHeading; 4272 4273 return Ret; 4274 } 4275 4276 //Tab will be return when call WORDTYPE 4277 sal_Bool SwAccessibleParagraph::tabCharInWord( sal_Int32 nIndex, i18n::Boundary& aBound) 4278 { 4279 sal_Bool bFind = sal_False; 4280 if( aBound.startPos != nIndex) 4281 { 4282 OUString tabStr; 4283 if(aBound.startPos>nIndex) 4284 tabStr = GetString().copy(nIndex,(aBound.startPos - nIndex) ); 4285 4286 sal_Unicode tabChar('\t'); 4287 sal_Int32 tabIndex = tabStr.indexOf(tabChar); 4288 if( tabIndex > -1 ) 4289 { 4290 aBound.startPos = nIndex + tabIndex ; 4291 aBound.endPos = aBound.startPos + 1; 4292 bFind = sal_True; 4293 } 4294 } 4295 return bFind; 4296 } 4297