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 // neccessary 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 boundry 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 if ( pFrm && 1211 pFrm->GetBackgroundBrush( pBackgrdBrush, pSectionTOXColor, aDummyRect, false ) ) 1212 { 1213 if ( pSectionTOXColor ) 1214 { 1215 rColor = *pSectionTOXColor; 1216 return true; 1217 } 1218 else 1219 { 1220 rColor = pBackgrdBrush->GetColor(); 1221 return true; 1222 } 1223 } 1224 else if ( pCrsrSh ) 1225 { 1226 rColor = pCrsrSh->Imp()->GetRetoucheColor(); 1227 return true; 1228 } 1229 1230 return false; 1231 } 1232 1233 sal_Int32 SAL_CALL SwAccessibleParagraph::getForeground() 1234 throw (uno::RuntimeException) 1235 { 1236 Color aBackgroundCol; 1237 1238 if ( lcl_GetBackgroundColor( aBackgroundCol, GetFrm(), GetCrsrShell() ) ) 1239 { 1240 if ( aBackgroundCol.IsDark() ) 1241 { 1242 return COL_WHITE; 1243 } 1244 else 1245 { 1246 return COL_BLACK; 1247 } 1248 } 1249 1250 return SwAccessibleContext::getForeground(); 1251 } 1252 1253 sal_Int32 SAL_CALL SwAccessibleParagraph::getBackground() 1254 throw (uno::RuntimeException) 1255 { 1256 Color aBackgroundCol; 1257 1258 if ( lcl_GetBackgroundColor( aBackgroundCol, GetFrm(), GetCrsrShell() ) ) 1259 { 1260 return aBackgroundCol.GetColor(); 1261 } 1262 1263 return SwAccessibleContext::getBackground(); 1264 } 1265 // <-- 1266 1267 ::rtl::OUString SAL_CALL SwAccessibleParagraph::getImplementationName() 1268 throw( uno::RuntimeException ) 1269 { 1270 return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(sImplementationName)); 1271 } 1272 1273 sal_Bool SAL_CALL SwAccessibleParagraph::supportsService( 1274 const ::rtl::OUString& sTestServiceName) 1275 throw (uno::RuntimeException) 1276 { 1277 return sTestServiceName.equalsAsciiL( sServiceName, 1278 sizeof(sServiceName)-1 ) || 1279 sTestServiceName.equalsAsciiL( sAccessibleServiceName, 1280 sizeof(sAccessibleServiceName)-1 ); 1281 } 1282 1283 uno::Sequence< ::rtl::OUString > SAL_CALL SwAccessibleParagraph::getSupportedServiceNames() 1284 throw( uno::RuntimeException ) 1285 { 1286 uno::Sequence< ::rtl::OUString > aRet(2); 1287 ::rtl::OUString* pArray = aRet.getArray(); 1288 pArray[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(sServiceName) ); 1289 pArray[1] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(sAccessibleServiceName) ); 1290 return aRet; 1291 } 1292 1293 uno::Sequence< ::rtl::OUString > getAttributeNames() 1294 { 1295 static uno::Sequence< ::rtl::OUString >* pNames = NULL; 1296 1297 if( pNames == NULL ) 1298 { 1299 // Add the font name to attribute list 1300 uno::Sequence< ::rtl::OUString >* pSeq = new uno::Sequence< ::rtl::OUString >( 13 ); 1301 1302 ::rtl::OUString* pStrings = pSeq->getArray(); 1303 1304 // sorted list of strings 1305 sal_Int32 i = 0; 1306 1307 #define STR(x) pStrings[i++] = OUString::createFromAscii(x) 1308 STR( GetPropName( UNO_NAME_CHAR_BACK_COLOR ).pName ); 1309 STR( GetPropName( UNO_NAME_CHAR_COLOR ).pName ); 1310 STR( GetPropName( UNO_NAME_CHAR_CONTOURED ).pName ); 1311 STR( GetPropName( UNO_NAME_CHAR_EMPHASIS ).pName ); 1312 STR( GetPropName( UNO_NAME_CHAR_ESCAPEMENT ).pName ); 1313 STR( GetPropName( UNO_NAME_CHAR_FONT_NAME ).pName ); 1314 STR( GetPropName( UNO_NAME_CHAR_HEIGHT ).pName ); 1315 STR( GetPropName( UNO_NAME_CHAR_POSTURE ).pName ); 1316 STR( GetPropName( UNO_NAME_CHAR_SHADOWED ).pName ); 1317 STR( GetPropName( UNO_NAME_CHAR_STRIKEOUT ).pName ); 1318 STR( GetPropName( UNO_NAME_CHAR_UNDERLINE ).pName ); 1319 STR( GetPropName( UNO_NAME_CHAR_UNDERLINE_COLOR ).pName ); 1320 STR( GetPropName( UNO_NAME_CHAR_WEIGHT ).pName ); 1321 #undef STR 1322 DBG_ASSERT( i == pSeq->getLength(), "Please adjust length" ); 1323 if( i != pSeq->getLength() ) 1324 pSeq->realloc( i ); 1325 pNames = pSeq; 1326 } 1327 return *pNames; 1328 } 1329 1330 uno::Sequence< ::rtl::OUString > getSupplementalAttributeNames() 1331 { 1332 static uno::Sequence< ::rtl::OUString >* pNames = NULL; 1333 1334 if( pNames == NULL ) 1335 { 1336 uno::Sequence< ::rtl::OUString >* pSeq = new uno::Sequence< ::rtl::OUString >( 9 ); 1337 1338 ::rtl::OUString* pStrings = pSeq->getArray(); 1339 1340 // sorted list of strings 1341 sal_Int32 i = 0; 1342 1343 #define STR(x) pStrings[i++] = OUString::createFromAscii(x) 1344 STR( GetPropName( UNO_NAME_NUMBERING_LEVEL ).pName ); 1345 STR( GetPropName( UNO_NAME_NUMBERING_RULES ).pName ); 1346 STR( GetPropName( UNO_NAME_PARA_ADJUST ).pName ); 1347 STR( GetPropName( UNO_NAME_PARA_BOTTOM_MARGIN ).pName ); 1348 STR( GetPropName( UNO_NAME_PARA_FIRST_LINE_INDENT ).pName ); 1349 STR( GetPropName( UNO_NAME_PARA_LEFT_MARGIN ).pName ); 1350 STR( GetPropName( UNO_NAME_PARA_LINE_SPACING ).pName ); 1351 STR( GetPropName( UNO_NAME_PARA_RIGHT_MARGIN ).pName ); 1352 STR( GetPropName( UNO_NAME_TABSTOPS ).pName ); 1353 #undef STR 1354 DBG_ASSERT( i == pSeq->getLength(), "Please adjust length" ); 1355 if( i != pSeq->getLength() ) 1356 pSeq->realloc( i ); 1357 pNames = pSeq; 1358 } 1359 return *pNames; 1360 } 1361 // 1362 //===== XInterface ======================================================= 1363 // 1364 1365 uno::Any SwAccessibleParagraph::queryInterface( const uno::Type& rType ) 1366 throw (uno::RuntimeException) 1367 { 1368 uno::Any aRet; 1369 if ( rType == ::getCppuType((uno::Reference<XAccessibleText> *)0) ) 1370 { 1371 uno::Reference<XAccessibleText> aAccText = (XAccessibleText *) *this; // resolve ambiguity 1372 aRet <<= aAccText; 1373 } 1374 else if ( rType == ::getCppuType((uno::Reference<XAccessibleEditableText> *)0) ) 1375 { 1376 uno::Reference<XAccessibleEditableText> aAccEditText = this; 1377 aRet <<= aAccEditText; 1378 } 1379 else if ( rType == ::getCppuType((uno::Reference<XAccessibleSelection> *)0) ) 1380 { 1381 uno::Reference<XAccessibleSelection> aAccSel = this; 1382 aRet <<= aAccSel; 1383 } 1384 else if ( rType == ::getCppuType((uno::Reference<XAccessibleHypertext> *)0) ) 1385 { 1386 uno::Reference<XAccessibleHypertext> aAccHyp = this; 1387 aRet <<= aAccHyp; 1388 } 1389 // --> OD 2006-07-13 #i63870# 1390 // add interface com::sun:star:accessibility::XAccessibleTextAttributes 1391 else if ( rType == ::getCppuType((uno::Reference<XAccessibleTextAttributes> *)0) ) 1392 { 1393 uno::Reference<XAccessibleTextAttributes> aAccTextAttr = this; 1394 aRet <<= aAccTextAttr; 1395 } 1396 // <-- 1397 // --> OD 2008-06-10 #i89175# 1398 // add interface com::sun:star:accessibility::XAccessibleTextMarkup 1399 else if ( rType == ::getCppuType((uno::Reference<XAccessibleTextMarkup> *)0) ) 1400 { 1401 uno::Reference<XAccessibleTextMarkup> aAccTextMarkup = this; 1402 aRet <<= aAccTextMarkup; 1403 } 1404 // add interface com::sun:star:accessibility::XAccessibleMultiLineText 1405 else if ( rType == ::getCppuType((uno::Reference<XAccessibleMultiLineText> *)0) ) 1406 { 1407 uno::Reference<XAccessibleMultiLineText> aAccMultiLineText = this; 1408 aRet <<= aAccMultiLineText; 1409 } 1410 // <-- 1411 //MSAA Extension Implementation in app module 1412 else if ( rType == ::getCppuType((uno::Reference<XAccessibleTextSelection> *)NULL) ) 1413 { 1414 uno::Reference< com::sun::star::accessibility::XAccessibleTextSelection > aTextExtension = this; 1415 aRet <<= aTextExtension; 1416 } 1417 else if ( rType == ::getCppuType((uno::Reference<XAccessibleExtendedAttributes> *)NULL) ) 1418 { 1419 uno::Reference<XAccessibleExtendedAttributes> xAttr = this; 1420 aRet <<= xAttr; 1421 } 1422 else 1423 { 1424 aRet = SwAccessibleContext::queryInterface(rType); 1425 } 1426 1427 return aRet; 1428 } 1429 1430 //====== XTypeProvider ==================================================== 1431 uno::Sequence< uno::Type > SAL_CALL SwAccessibleParagraph::getTypes() throw(uno::RuntimeException) 1432 { 1433 uno::Sequence< uno::Type > aTypes( SwAccessibleContext::getTypes() ); 1434 1435 sal_Int32 nIndex = aTypes.getLength(); 1436 // --> OD 2006-07-13 #i63870# 1437 // add type accessibility::XAccessibleTextAttributes 1438 // --> OD 2008-06-10 #i89175# 1439 // add type accessibility::XAccessibleTextMarkup and accessibility::XAccessibleMultiLineText 1440 aTypes.realloc( nIndex + 6 ); 1441 1442 uno::Type* pTypes = aTypes.getArray(); 1443 pTypes[nIndex++] = ::getCppuType( static_cast< uno::Reference< XAccessibleEditableText > * >( 0 ) ); 1444 pTypes[nIndex++] = ::getCppuType( static_cast< uno::Reference< XAccessibleTextAttributes > * >( 0 ) ); 1445 pTypes[nIndex++] = ::getCppuType( static_cast< uno::Reference< XAccessibleSelection > * >( 0 ) ); 1446 pTypes[nIndex++] = ::getCppuType( static_cast< uno::Reference< XAccessibleTextMarkup > * >( 0 ) ); 1447 pTypes[nIndex++] = ::getCppuType( static_cast< uno::Reference< XAccessibleMultiLineText > * >( 0 ) ); 1448 pTypes[nIndex] = ::getCppuType( static_cast< uno::Reference< XAccessibleHypertext > * >( 0 ) ); 1449 // <-- 1450 1451 return aTypes; 1452 } 1453 1454 uno::Sequence< sal_Int8 > SAL_CALL SwAccessibleParagraph::getImplementationId() 1455 throw(uno::RuntimeException) 1456 { 1457 vos::OGuard aGuard(Application::GetSolarMutex()); 1458 static uno::Sequence< sal_Int8 > aId( 16 ); 1459 static sal_Bool bInit = sal_False; 1460 if(!bInit) 1461 { 1462 rtl_createUuid( (sal_uInt8 *)(aId.getArray() ), 0, sal_True ); 1463 bInit = sal_True; 1464 } 1465 return aId; 1466 } 1467 1468 1469 // 1470 //===== XAccesibleText =================================================== 1471 // 1472 1473 sal_Int32 SwAccessibleParagraph::getCaretPosition() 1474 throw (uno::RuntimeException) 1475 { 1476 vos::OGuard aGuard(Application::GetSolarMutex()); 1477 1478 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); 1479 1480 sal_Int32 nRet = GetCaretPos(); 1481 { 1482 vos::OGuard aOldCaretPosGuard( aMutex ); 1483 ASSERT( nRet == nOldCaretPos, "caret pos out of sync" ); 1484 nOldCaretPos = nRet; 1485 } 1486 if( -1 != nRet ) 1487 { 1488 ::vos::ORef < SwAccessibleContext > xThis( this ); 1489 GetMap()->SetCursorContext( xThis ); 1490 } 1491 1492 return nRet; 1493 } 1494 1495 sal_Bool SAL_CALL SwAccessibleParagraph::setCaretPosition( sal_Int32 nIndex ) 1496 throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 1497 { 1498 vos::OGuard aGuard(Application::GetSolarMutex()); 1499 1500 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); 1501 1502 // parameter checking 1503 sal_Int32 nLength = GetString().getLength(); 1504 if ( ! IsValidPosition( nIndex, nLength ) ) 1505 { 1506 throw lang::IndexOutOfBoundsException(); 1507 } 1508 1509 sal_Bool bRet = sal_False; 1510 1511 // get cursor shell 1512 SwCrsrShell* pCrsrShell = GetCrsrShell(); 1513 if( pCrsrShell != NULL ) 1514 { 1515 // create pam for selection 1516 SwTxtNode* pNode = const_cast<SwTxtNode*>( GetTxtNode() ); 1517 SwIndex aIndex( pNode, GetPortionData().GetModelPosition(nIndex)); 1518 SwPosition aStartPos( *pNode, aIndex ); 1519 SwPaM aPaM( aStartPos ); 1520 1521 // set PaM at cursor shell 1522 bRet = Select( aPaM ); 1523 } 1524 1525 return bRet; 1526 } 1527 1528 sal_Unicode SwAccessibleParagraph::getCharacter( sal_Int32 nIndex ) 1529 throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 1530 { 1531 vos::OGuard aGuard(Application::GetSolarMutex()); 1532 1533 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); 1534 1535 ::rtl::OUString sText( GetString() ); 1536 1537 // return character (if valid) 1538 if( IsValidChar(nIndex, sText.getLength() ) ) 1539 { 1540 return sText.getStr()[nIndex]; 1541 } 1542 else 1543 throw lang::IndexOutOfBoundsException(); 1544 } 1545 1546 com::sun::star::uno::Sequence< ::com::sun::star::style::TabStop > SwAccessibleParagraph::GetCurrentTabStop( sal_Int32 nIndex ) 1547 { 1548 vos::OGuard aGuard(Application::GetSolarMutex()); 1549 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); 1550 1551 1552 1553 /* #i12332# The position after the string needs special treatment. 1554 IsValidChar -> IsValidPosition 1555 */ 1556 if( ! (IsValidPosition( nIndex, GetString().getLength() ) ) ) 1557 throw lang::IndexOutOfBoundsException(); 1558 1559 /* #i12332# */ 1560 sal_Bool bBehindText = sal_False; 1561 if ( nIndex == GetString().getLength() ) 1562 bBehindText = sal_True; 1563 1564 // get model position & prepare GetCharRect() arguments 1565 SwCrsrMoveState aMoveState; 1566 aMoveState.bRealHeight = sal_True; 1567 aMoveState.bRealWidth = sal_True; 1568 SwSpecialPos aSpecialPos; 1569 SwTxtNode* pNode = const_cast<SwTxtNode*>( GetTxtNode() ); 1570 1571 sal_uInt16 nPos = 0; 1572 1573 /* #i12332# FillSpecialPos does not accept nIndex == 1574 GetString().getLength(). In that case nPos is set to the 1575 length of the string in the core. This way GetCharRect 1576 returns the rectangle for a cursor at the end of the 1577 paragraph. */ 1578 if (bBehindText) 1579 { 1580 nPos = pNode->GetTxt().Len(); 1581 } 1582 else 1583 nPos = GetPortionData().FillSpecialPos 1584 (nIndex, aSpecialPos, aMoveState.pSpecialPos ); 1585 1586 // call GetCharRect 1587 SwRect aCoreRect; 1588 SwIndex aIndex( pNode, nPos ); 1589 SwPosition aPosition( *pNode, aIndex ); 1590 GetFrm()->GetCharRect( aCoreRect, aPosition, &aMoveState ); 1591 1592 // already get the caret postion 1593 1594 /*SwFrm* pTFrm = const_cast<SwFrm*>(GetFrm()); 1595 com::sun::star::uno::Sequence< ::com::sun::star::style::TabStop > tabs = 1596 pTFrm->GetTabStopInfo(aCoreRect.Left());*/ 1597 1598 com::sun::star::uno::Sequence< ::com::sun::star::style::TabStop > tabs; 1599 const xub_StrLen nStrLen = GetTxtNode()->GetTxt().Len(); 1600 if( nStrLen > 0 ) 1601 { 1602 SwFrm* pTFrm = const_cast<SwFrm*>(GetFrm()); 1603 tabs = pTFrm->GetTabStopInfo(aCoreRect.Left()); 1604 } 1605 1606 if( tabs.hasElements() ) 1607 { 1608 // translate core coordinates into accessibility coordinates 1609 Window *pWin = GetWindow(); 1610 CHECK_FOR_WINDOW( XAccessibleComponent, pWin ); 1611 1612 SwRect aTmpRect(0, 0, tabs[0].Position, 0); 1613 1614 Rectangle aScreenRect( GetMap()->CoreToPixel( aTmpRect.SVRect() )); 1615 SwRect aFrmLogBounds( GetBounds( *(GetMap()) ) ); // twip rel to doc root 1616 1617 Point aFrmPixPos( GetMap()->CoreToPixel( aFrmLogBounds.SVRect() ).TopLeft() ); 1618 aScreenRect.Move( -aFrmPixPos.X(), -aFrmPixPos.Y() ); 1619 1620 tabs[0].Position = aScreenRect.GetWidth(); 1621 } 1622 1623 return tabs; 1624 } 1625 1626 struct IndexCompare 1627 { 1628 const PropertyValue* pValues; 1629 IndexCompare( const PropertyValue* pVals ) : pValues(pVals) {} 1630 bool operator() ( const sal_Int32& a, const sal_Int32& b ) const 1631 { 1632 return (pValues[a].Name < pValues[b].Name) ? true : false; 1633 } 1634 }; 1635 1636 String SwAccessibleParagraph::GetFieldTypeNameAtIndex(sal_Int32 nIndex) 1637 { 1638 String strTypeName; 1639 SwFldMgr aMgr; 1640 SwTxtFld* pTxtFld = NULL; 1641 SwTxtNode* pTxtNd = const_cast<SwTxtNode*>( GetTxtNode() ); 1642 SwIndex fldIndex( pTxtNd, nIndex ); 1643 sal_Int32 nFldIndex = GetPortionData().GetFieldIndex(nIndex); 1644 if (nFldIndex >= 0) 1645 { 1646 const SwpHints* pSwpHints = GetTxtNode()->GetpSwpHints(); 1647 if (pSwpHints) 1648 { 1649 const sal_uInt16 nSize = pSwpHints ? pSwpHints->Count() : 0; 1650 for( sal_uInt16 i = 0; i < nSize; ++i ) 1651 { 1652 const SwTxtAttr* pHt = (*pSwpHints)[i]; 1653 if ( ( pHt->Which() == RES_TXTATR_FIELD 1654 || pHt->Which() == RES_TXTATR_ANNOTATION 1655 || pHt->Which() == RES_TXTATR_INPUTFIELD ) 1656 && (nFldIndex-- == 0)) 1657 { 1658 pTxtFld = (SwTxtFld *)pHt; 1659 break; 1660 } 1661 else if ( pHt->Which() == RES_TXTATR_REFMARK 1662 && (nFldIndex-- == 0) ) 1663 strTypeName = String(OUString(RTL_CONSTASCII_USTRINGPARAM("set reference"))); 1664 } 1665 } 1666 } 1667 if (pTxtFld) 1668 { 1669 const SwField* pField = (pTxtFld->GetFmtFld()).GetField(); 1670 if (pField) 1671 { 1672 strTypeName = pField->GetTyp()->GetTypeStr(pField->GetTypeId()); 1673 sal_uInt16 nWhich = pField->GetTyp()->Which(); 1674 rtl::OUString sEntry; 1675 sal_Int32 subType = 0; 1676 switch (nWhich) 1677 { 1678 case RES_DOCSTATFLD: 1679 subType = ((SwDocStatField*)pField)->GetSubType(); 1680 break; 1681 case RES_GETREFFLD: 1682 { 1683 sal_uInt16 nSub = pField->GetSubType(); 1684 switch( nSub ) 1685 { 1686 case REF_BOOKMARK: 1687 { 1688 const SwGetRefField* pRefFld = dynamic_cast<const SwGetRefField*>(pField); 1689 if ( pRefFld && pRefFld->IsRefToHeadingCrossRefBookmark() ) 1690 sEntry = OUString(RTL_CONSTASCII_USTRINGPARAM("Headings")); 1691 else if ( pRefFld && pRefFld->IsRefToNumItemCrossRefBookmark() ) 1692 sEntry = OUString(RTL_CONSTASCII_USTRINGPARAM("Numbered Paragraphs")); 1693 else 1694 sEntry = OUString(RTL_CONSTASCII_USTRINGPARAM("Bookmarks")); 1695 } 1696 break; 1697 case REF_FOOTNOTE: 1698 sEntry = OUString(RTL_CONSTASCII_USTRINGPARAM("Footnotes")); 1699 break; 1700 case REF_ENDNOTE: 1701 sEntry = OUString(RTL_CONSTASCII_USTRINGPARAM("Endnotes")); 1702 break; 1703 case REF_SETREFATTR: 1704 sEntry = OUString(RTL_CONSTASCII_USTRINGPARAM("Insert Reference")); 1705 break; 1706 case REF_SEQUENCEFLD: 1707 sEntry = ((SwGetRefField*)pField)->GetSetRefName(); 1708 break; 1709 } 1710 //Get format string 1711 strTypeName = sEntry; 1712 // <pField->GetFormat() >= 0> is always true as <pField->GetFormat()> is unsigned 1713 // if (pField->GetFormat() >= 0) 1714 { 1715 sEntry = aMgr.GetFormatStr( pField->GetTypeId(), pField->GetFormat() ); 1716 if (sEntry.getLength() > 0) 1717 { 1718 strTypeName.AppendAscii("-"); 1719 strTypeName += String(sEntry); 1720 } 1721 } 1722 } 1723 break; 1724 case RES_DATETIMEFLD: 1725 subType = ((SwDateTimeField*)pField)->GetSubType(); 1726 break; 1727 case RES_JUMPEDITFLD: 1728 { 1729 sal_uInt16 nFormat= pField->GetFormat(); 1730 sal_uInt16 nSize = aMgr.GetFormatCount(pField->GetTypeId(), sal_False); 1731 if (nFormat < nSize) 1732 { 1733 sEntry = aMgr.GetFormatStr(pField->GetTypeId(), nFormat); 1734 if (sEntry.getLength() > 0) 1735 { 1736 strTypeName.AppendAscii("-"); 1737 strTypeName += String(sEntry); 1738 } 1739 } 1740 } 1741 break; 1742 case RES_EXTUSERFLD: 1743 subType = ((SwExtUserField*)pField)->GetSubType(); 1744 break; 1745 case RES_HIDDENTXTFLD: 1746 case RES_SETEXPFLD: 1747 { 1748 sEntry = pField->GetTyp()->GetName(); 1749 if (sEntry.getLength() > 0) 1750 { 1751 strTypeName.AppendAscii("-"); 1752 strTypeName += String(sEntry); 1753 } 1754 } 1755 break; 1756 case RES_DOCINFOFLD: 1757 subType = pField->GetSubType(); 1758 subType &= 0x00ff; 1759 break; 1760 case RES_REFPAGESETFLD: 1761 { 1762 SwRefPageSetField* pRPld = (SwRefPageSetField*)pField; 1763 sal_Bool bOn = pRPld->IsOn(); 1764 strTypeName.AppendAscii("-"); 1765 if (bOn) 1766 strTypeName += String(OUString(RTL_CONSTASCII_USTRINGPARAM("on"))); 1767 else 1768 strTypeName += String(OUString(RTL_CONSTASCII_USTRINGPARAM("off"))); 1769 } 1770 break; 1771 case RES_AUTHORFLD: 1772 { 1773 strTypeName.AppendAscii("-"); 1774 strTypeName += aMgr.GetFormatStr(pField->GetTypeId(), pField->GetFormat() & 0xff); 1775 } 1776 break; 1777 } 1778 if (subType > 0 || (subType == 0 && (nWhich == RES_DOCINFOFLD || nWhich == RES_EXTUSERFLD || nWhich == RES_DOCSTATFLD))) 1779 { 1780 SvStringsDtor aLst; 1781 aMgr.GetSubTypes(pField->GetTypeId(), aLst); 1782 if (subType < aLst.Count()) 1783 sEntry = *aLst[subType]; 1784 if (sEntry.getLength() > 0) 1785 { 1786 if (nWhich == RES_DOCINFOFLD) 1787 { 1788 strTypeName = String(sEntry); 1789 sal_uInt32 nSize = aMgr.GetFormatCount(pField->GetTypeId(), sal_False); 1790 sal_uInt16 nExSub = pField->GetSubType() & 0xff00; 1791 if (nSize > 0 && nExSub > 0) 1792 { 1793 //Get extra subtype string 1794 strTypeName.AppendAscii("-"); 1795 sEntry = aMgr.GetFormatStr(pField->GetTypeId(), nExSub/0x0100-1); 1796 strTypeName += String(sEntry); 1797 } 1798 } 1799 else 1800 { 1801 strTypeName.AppendAscii("-"); 1802 strTypeName += String(sEntry); 1803 } 1804 } 1805 } 1806 } 1807 } 1808 return strTypeName; 1809 } 1810 // --> OD 2006-07-20 #i63870# 1811 // re-implement method on behalf of methods <_getDefaultAttributesImpl(..)> and 1812 // <_getRunAttributesImpl(..)> 1813 uno::Sequence<PropertyValue> SwAccessibleParagraph::getCharacterAttributes( 1814 sal_Int32 nIndex, 1815 const uno::Sequence< ::rtl::OUString >& aRequestedAttributes ) 1816 throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 1817 { 1818 1819 vos::OGuard aGuard(Application::GetSolarMutex()); 1820 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); 1821 1822 const ::rtl::OUString& rText = GetString(); 1823 1824 if( ! IsValidChar( nIndex, rText.getLength()+1 ) ) 1825 throw lang::IndexOutOfBoundsException(); 1826 1827 bool bSupplementalMode = false; 1828 uno::Sequence< ::rtl::OUString > aNames = aRequestedAttributes; 1829 if (aNames.getLength() == 0) 1830 { 1831 bSupplementalMode = true; 1832 aNames = getAttributeNames(); 1833 } 1834 // retrieve default character attributes 1835 tAccParaPropValMap aDefAttrSeq; 1836 _getDefaultAttributesImpl( aNames, aDefAttrSeq, true ); 1837 1838 // retrieved run character attributes 1839 tAccParaPropValMap aRunAttrSeq; 1840 _getRunAttributesImpl( nIndex, aNames, aRunAttrSeq ); 1841 1842 // merge default and run attributes 1843 uno::Sequence< PropertyValue > aValues( aDefAttrSeq.size() ); 1844 PropertyValue* pValues = aValues.getArray(); 1845 sal_Int32 i = 0; 1846 for ( tAccParaPropValMap::const_iterator aDefIter = aDefAttrSeq.begin(); 1847 aDefIter != aDefAttrSeq.end(); 1848 ++aDefIter ) 1849 { 1850 tAccParaPropValMap::const_iterator aRunIter = 1851 aRunAttrSeq.find( aDefIter->first ); 1852 if ( aRunIter != aRunAttrSeq.end() ) 1853 { 1854 pValues[i] = aRunIter->second; 1855 } 1856 else 1857 { 1858 pValues[i] = aDefIter->second; 1859 } 1860 ++i; 1861 } 1862 if( bSupplementalMode ) 1863 { 1864 uno::Sequence< ::rtl::OUString > aSupplementalNames = aRequestedAttributes; 1865 if (aSupplementalNames.getLength() == 0) 1866 aSupplementalNames = getSupplementalAttributeNames(); 1867 1868 tAccParaPropValMap aSupplementalAttrSeq; 1869 _getSupplementalAttributesImpl( nIndex, aSupplementalNames, aSupplementalAttrSeq ); 1870 1871 aValues.realloc( aValues.getLength() + aSupplementalAttrSeq.size() ); 1872 pValues = aValues.getArray(); 1873 1874 for ( tAccParaPropValMap::const_iterator aSupplementalIter = aSupplementalAttrSeq.begin(); 1875 aSupplementalIter != aSupplementalAttrSeq.end(); 1876 ++aSupplementalIter ) 1877 { 1878 pValues[i] = aSupplementalIter->second; 1879 ++i; 1880 } 1881 1882 _correctValues( nIndex, aValues ); 1883 1884 aValues.realloc( aValues.getLength() + 1 ); 1885 1886 pValues = aValues.getArray(); 1887 1888 const SwTxtNode* pTxtNode( GetTxtNode() ); 1889 PropertyValue& rValue = pValues[aValues.getLength() - 1 ]; 1890 rValue.Name = OUString::createFromAscii("NumberingPrefix"); 1891 OUString sNumBullet = pTxtNode->GetNumString(); 1892 rValue.Value <<= sNumBullet; 1893 rValue.Handle = -1; 1894 rValue.State = PropertyState_DIRECT_VALUE; 1895 1896 String strTypeName = GetFieldTypeNameAtIndex(nIndex); 1897 if (strTypeName.Len() > 0) 1898 { 1899 aValues.realloc( aValues.getLength() + 1 ); 1900 pValues = aValues.getArray(); 1901 rValue = pValues[aValues.getLength() - 1]; 1902 rValue.Name = OUString::createFromAscii("FieldType"); 1903 rValue.Value <<= rtl::OUString(strTypeName.ToLowerAscii()); 1904 rValue.Handle = -1; 1905 rValue.State = PropertyState_DIRECT_VALUE; 1906 } 1907 1908 //sort property values 1909 // build sorted index array 1910 sal_Int32 nLength = aValues.getLength(); 1911 const PropertyValue* pPairs = aValues.getConstArray(); 1912 sal_Int32* pIndices = new sal_Int32[nLength]; 1913 for( i = 0; i < nLength; i++ ) 1914 pIndices[i] = i; 1915 sort( &pIndices[0], &pIndices[nLength], IndexCompare(pPairs) ); 1916 // create sorted sequences accoring to index array 1917 uno::Sequence<PropertyValue> aNewValues( nLength ); 1918 PropertyValue* pNewValues = aNewValues.getArray(); 1919 for( i = 0; i < nLength; i++ ) 1920 { 1921 pNewValues[i] = pPairs[pIndices[i]]; 1922 } 1923 delete[] pIndices; 1924 return aNewValues; 1925 } 1926 1927 // // create a (dummy) text portion for the sole purpose of calling 1928 // // getPropertyValues on it 1929 // Reference<XMultiPropertySet> xPortion = CreateUnoPortion( nIndex, nIndex + 1 ); 1930 1931 // // get values 1932 // Sequence<OUString> aNames = getAttributeNames(); 1933 // sal_Int32 nLength = aNames.getLength(); 1934 // Sequence<Any> aAnys( nLength ); 1935 // aAnys = xPortion->getPropertyValues( aNames ); 1936 1937 // // copy names + anys into return sequence 1938 // Sequence<PropertyValue> aValues( aNames.getLength() ); 1939 // const OUString* pNames = aNames.getConstArray(); 1940 // const Any* pAnys = aAnys.getConstArray(); 1941 // PropertyValue* pValues = aValues.getArray(); 1942 // for( sal_Int32 i = 0; i < nLength; i++ ) 1943 // { 1944 // PropertyValue& rValue = pValues[i]; 1945 // rValue.Name = pNames[i]; 1946 // rValue.Value = pAnys[i]; 1947 // rValue.Handle = -1; // handle not supported 1948 // rValue.State = PropertyState_DIRECT_VALUE; // states not supported 1949 // } 1950 1951 // // adjust background color if we're in a gray portion 1952 // DBG_ASSERT( pValues[CHAR_BACK_COLOR_POS].Name. 1953 // equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("CharBackColor")), 1954 // "Please adjust CHAR_BACK_COLOR_POS constant." ); 1955 // if( GetPortionData().IsInGrayPortion( nIndex ) ) 1956 // pValues[CHAR_BACK_COLOR_POS].Value <<= SwViewOption::GetFieldShadingsColor().GetColor(); 1957 1958 return aValues; 1959 } 1960 1961 // --> OD 2006-07-11 #i63870# 1962 void SwAccessibleParagraph::_getDefaultAttributesImpl( 1963 const uno::Sequence< ::rtl::OUString >& aRequestedAttributes, 1964 tAccParaPropValMap& rDefAttrSeq, 1965 const bool bOnlyCharAttrs ) 1966 { 1967 // retrieve default attributes 1968 const SwTxtNode* pTxtNode( GetTxtNode() ); 1969 ::boost::scoped_ptr<SfxItemSet> pSet; 1970 if ( !bOnlyCharAttrs ) 1971 { 1972 pSet.reset( new SfxItemSet( const_cast<SwAttrPool&>(pTxtNode->GetDoc()->GetAttrPool()), 1973 RES_CHRATR_BEGIN, RES_CHRATR_END - 1, 1974 RES_PARATR_BEGIN, RES_PARATR_END - 1, 1975 RES_FRMATR_BEGIN, RES_FRMATR_END - 1, 1976 0 ) ); 1977 } 1978 else 1979 { 1980 pSet.reset( new SfxItemSet( const_cast<SwAttrPool&>(pTxtNode->GetDoc()->GetAttrPool()), 1981 RES_CHRATR_BEGIN, RES_CHRATR_END - 1, 1982 0 ) ); 1983 } 1984 // --> OD 2007-11-12 #i82637# 1985 // From the perspective of the a11y API the default character attributes 1986 // are the character attributes, which are set at the paragraph style 1987 // of the paragraph. The character attributes set at the automatic paragraph 1988 // style of the paragraph are treated as run attributes. 1989 // pTxtNode->SwCntntNode::GetAttr( *pSet ); 1990 // get default paragraph attributes, if needed, and merge these into <pSet> 1991 if ( !bOnlyCharAttrs ) 1992 { 1993 SfxItemSet aParaSet( const_cast<SwAttrPool&>(pTxtNode->GetDoc()->GetAttrPool()), 1994 RES_PARATR_BEGIN, RES_PARATR_END - 1, 1995 RES_FRMATR_BEGIN, RES_FRMATR_END - 1, 1996 0 ); 1997 pTxtNode->SwCntntNode::GetAttr( aParaSet ); 1998 pSet->Put( aParaSet ); 1999 } 2000 // get default character attributes and merge these into <pSet> 2001 ASSERT( pTxtNode->GetTxtColl(), 2002 "<SwAccessibleParagraph::_getDefaultAttributesImpl(..)> - missing paragraph style. Serious defect, please inform OD!" ); 2003 if ( pTxtNode->GetTxtColl() ) 2004 { 2005 SfxItemSet aCharSet( const_cast<SwAttrPool&>(pTxtNode->GetDoc()->GetAttrPool()), 2006 RES_CHRATR_BEGIN, RES_CHRATR_END - 1, 2007 0 ); 2008 aCharSet.Put( pTxtNode->GetTxtColl()->GetAttrSet() ); 2009 pSet->Put( aCharSet ); 2010 } 2011 // <-- 2012 2013 // build-up sequence containing the run attributes <rDefAttrSeq> 2014 tAccParaPropValMap aDefAttrSeq; 2015 { 2016 const SfxItemPropertyMap* pPropMap = 2017 aSwMapProvider.GetPropertySet( PROPERTY_MAP_TEXT_CURSOR )->getPropertyMap(); 2018 PropertyEntryVector_t aPropertyEntries = pPropMap->getPropertyEntries(); 2019 PropertyEntryVector_t::const_iterator aPropIt = aPropertyEntries.begin(); 2020 while ( aPropIt != aPropertyEntries.end() ) 2021 { 2022 const SfxPoolItem* pItem = pSet->GetItem( aPropIt->nWID ); 2023 if ( pItem ) 2024 { 2025 uno::Any aVal; 2026 pItem->QueryValue( aVal, aPropIt->nMemberId ); 2027 2028 PropertyValue rPropVal; 2029 rPropVal.Name = aPropIt->sName; 2030 rPropVal.Value = aVal; 2031 rPropVal.Handle = -1; 2032 rPropVal.State = beans::PropertyState_DEFAULT_VALUE; 2033 2034 aDefAttrSeq[rPropVal.Name] = rPropVal; 2035 } 2036 ++aPropIt; 2037 } 2038 2039 // --> OD 2007-01-15 #i72800# 2040 // add property value entry for the paragraph style 2041 if ( !bOnlyCharAttrs && pTxtNode->GetTxtColl() ) 2042 { 2043 const ::rtl::OUString sParaStyleName = 2044 ::rtl::OUString::createFromAscii( 2045 GetPropName( UNO_NAME_PARA_STYLE_NAME ).pName ); 2046 if ( aDefAttrSeq.find( sParaStyleName ) == aDefAttrSeq.end() ) 2047 { 2048 PropertyValue rPropVal; 2049 rPropVal.Name = sParaStyleName; 2050 uno::Any aVal( uno::makeAny( ::rtl::OUString( pTxtNode->GetTxtColl()->GetName() ) ) ); 2051 rPropVal.Value = aVal; 2052 rPropVal.Handle = -1; 2053 rPropVal.State = beans::PropertyState_DEFAULT_VALUE; 2054 2055 aDefAttrSeq[rPropVal.Name] = rPropVal; 2056 } 2057 } 2058 // <-- 2059 2060 // --> OD 2007-01-15 #i73371# 2061 // resolve value text::WritingMode2::PAGE of property value entry WritingMode 2062 if ( !bOnlyCharAttrs && GetFrm() ) 2063 { 2064 const ::rtl::OUString sWritingMode = 2065 ::rtl::OUString::createFromAscii( 2066 GetPropName( UNO_NAME_WRITING_MODE ).pName ); 2067 tAccParaPropValMap::iterator aIter = aDefAttrSeq.find( sWritingMode ); 2068 if ( aIter != aDefAttrSeq.end() ) 2069 { 2070 PropertyValue rPropVal( aIter->second ); 2071 sal_Int16 nVal = rPropVal.Value.get<sal_Int16>(); 2072 if ( nVal == text::WritingMode2::PAGE ) 2073 { 2074 const SwFrm* pUpperFrm( GetFrm()->GetUpper() ); 2075 while ( pUpperFrm ) 2076 { 2077 if ( pUpperFrm->GetType() & 2078 ( FRM_PAGE | FRM_FLY | FRM_SECTION | FRM_TAB | FRM_CELL ) ) 2079 { 2080 if ( pUpperFrm->IsVertical() ) 2081 { 2082 nVal = text::WritingMode2::TB_RL; 2083 } 2084 else if ( pUpperFrm->IsRightToLeft() ) 2085 { 2086 nVal = text::WritingMode2::RL_TB; 2087 } 2088 else 2089 { 2090 nVal = text::WritingMode2::LR_TB; 2091 } 2092 rPropVal.Value <<= nVal; 2093 aDefAttrSeq[rPropVal.Name] = rPropVal; 2094 break; 2095 } 2096 2097 if ( dynamic_cast<const SwFlyFrm*>(pUpperFrm) ) 2098 { 2099 pUpperFrm = dynamic_cast<const SwFlyFrm*>(pUpperFrm)->GetAnchorFrm(); 2100 } 2101 else 2102 { 2103 pUpperFrm = pUpperFrm->GetUpper(); 2104 } 2105 } 2106 } 2107 } 2108 } 2109 // <-- 2110 } 2111 2112 if ( aRequestedAttributes.getLength() == 0 ) 2113 { 2114 rDefAttrSeq = aDefAttrSeq; 2115 } 2116 else 2117 { 2118 const ::rtl::OUString* pReqAttrs = aRequestedAttributes.getConstArray(); 2119 const sal_Int32 nLength = aRequestedAttributes.getLength(); 2120 for( sal_Int32 i = 0; i < nLength; ++i ) 2121 { 2122 tAccParaPropValMap::const_iterator const aIter = aDefAttrSeq.find( pReqAttrs[i] ); 2123 if ( aIter != aDefAttrSeq.end() ) 2124 { 2125 rDefAttrSeq[ aIter->first ] = aIter->second; 2126 } 2127 } 2128 } 2129 } 2130 2131 uno::Sequence< PropertyValue > SwAccessibleParagraph::getDefaultAttributes( 2132 const uno::Sequence< ::rtl::OUString >& aRequestedAttributes ) 2133 throw ( uno::RuntimeException ) 2134 { 2135 vos::OGuard aGuard(Application::GetSolarMutex()); 2136 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); 2137 2138 tAccParaPropValMap aDefAttrSeq; 2139 _getDefaultAttributesImpl( aRequestedAttributes, aDefAttrSeq ); 2140 2141 // --> OD 2010-03-08 #i92233# 2142 static rtl::OUString sMMToPixelRatio( rtl::OUString::createFromAscii( "MMToPixelRatio" ) ); 2143 bool bProvideMMToPixelRatio( false ); 2144 { 2145 if ( aRequestedAttributes.getLength() == 0 ) 2146 { 2147 bProvideMMToPixelRatio = true; 2148 } 2149 else 2150 { 2151 const rtl::OUString* aRequestedAttrIter = 2152 ::std::find( ::comphelper::stl_begin( aRequestedAttributes ), 2153 ::comphelper::stl_end( aRequestedAttributes ), 2154 sMMToPixelRatio ); 2155 if ( aRequestedAttrIter != ::comphelper::stl_end( aRequestedAttributes ) ) 2156 { 2157 bProvideMMToPixelRatio = true; 2158 } 2159 } 2160 } 2161 // <-- 2162 2163 uno::Sequence< PropertyValue > aValues( aDefAttrSeq.size() + 2164 ( bProvideMMToPixelRatio ? 1 : 0 ) ); 2165 PropertyValue* pValues = aValues.getArray(); 2166 sal_Int32 i = 0; 2167 for ( tAccParaPropValMap::const_iterator aIter = aDefAttrSeq.begin(); 2168 aIter != aDefAttrSeq.end(); 2169 ++aIter ) 2170 { 2171 pValues[i] = aIter->second; 2172 ++i; 2173 } 2174 2175 // --> OD 2010-03-08 #i92233# 2176 if ( bProvideMMToPixelRatio ) 2177 { 2178 PropertyValue rPropVal; 2179 rPropVal.Name = sMMToPixelRatio; 2180 const Size a100thMMSize( 1000, 1000 ); 2181 const Size aPixelSize = GetMap()->LogicToPixel( a100thMMSize ); 2182 const float fRatio = ((float)a100thMMSize.Width()/100)/aPixelSize.Width(); 2183 rPropVal.Value = uno::makeAny( fRatio ); 2184 rPropVal.Handle = -1; 2185 rPropVal.State = beans::PropertyState_DEFAULT_VALUE; 2186 pValues[ aValues.getLength() - 1 ] = rPropVal; 2187 } 2188 // <-- 2189 2190 return aValues; 2191 } 2192 2193 void SwAccessibleParagraph::_getRunAttributesImpl( 2194 const sal_Int32 nIndex, 2195 const uno::Sequence< ::rtl::OUString >& aRequestedAttributes, 2196 tAccParaPropValMap& rRunAttrSeq ) 2197 { 2198 // create PaM for character at position <nIndex> 2199 SwPaM* pPaM( 0 ); 2200 { 2201 const SwTxtNode* pTxtNode( GetTxtNode() ); 2202 SwPosition* pStartPos = new SwPosition( *pTxtNode ); 2203 pStartPos->nContent.Assign( const_cast<SwTxtNode*>(pTxtNode), static_cast<sal_uInt16>(nIndex) ); 2204 SwPosition* pEndPos = new SwPosition( *pTxtNode ); 2205 pEndPos->nContent.Assign( const_cast<SwTxtNode*>(pTxtNode), static_cast<sal_uInt16>(nIndex+1) ); 2206 2207 pPaM = new SwPaM( *pStartPos, *pEndPos ); 2208 2209 delete pStartPos; 2210 delete pEndPos; 2211 } 2212 2213 // retrieve character attributes for the created PaM <pPaM> 2214 SfxItemSet aSet( pPaM->GetDoc()->GetAttrPool(), 2215 RES_CHRATR_BEGIN, RES_CHRATR_END -1, 2216 0 ); 2217 // --> OD 2007-11-12 #i82637# 2218 // From the perspective of the a11y API the character attributes, which 2219 // are set at the automatic paragraph style of the paragraph are treated 2220 // as run attributes. 2221 // SwXTextCursor::GetCrsrAttr( *pPaM, aSet, sal_True, sal_True ); 2222 // get character attributes from automatic paragraph style and merge these into <aSet> 2223 { 2224 const SwTxtNode* pTxtNode( GetTxtNode() ); 2225 if ( pTxtNode->HasSwAttrSet() ) 2226 { 2227 SfxItemSet aAutomaticParaStyleCharAttrs( pPaM->GetDoc()->GetAttrPool(), 2228 RES_CHRATR_BEGIN, RES_CHRATR_END -1, 2229 0 ); 2230 aAutomaticParaStyleCharAttrs.Put( *(pTxtNode->GetpSwAttrSet()), sal_False ); 2231 aSet.Put( aAutomaticParaStyleCharAttrs ); 2232 } 2233 } 2234 // get character attributes at <pPaM> and merge these into <aSet> 2235 { 2236 SfxItemSet aCharAttrsAtPaM( pPaM->GetDoc()->GetAttrPool(), 2237 RES_CHRATR_BEGIN, RES_CHRATR_END -1, 2238 0 ); 2239 SwUnoCursorHelper::GetCrsrAttr(*pPaM, aCharAttrsAtPaM, sal_True, sal_True); 2240 aSet.Put( aCharAttrsAtPaM ); 2241 } 2242 // <-- 2243 2244 // build-up sequence containing the run attributes <rRunAttrSeq> 2245 { 2246 tAccParaPropValMap aRunAttrSeq; 2247 { 2248 // --> OD 2007-11-12 #i82637# 2249 tAccParaPropValMap aDefAttrSeq; 2250 uno::Sequence< ::rtl::OUString > aDummy; 2251 _getDefaultAttributesImpl( aDummy, aDefAttrSeq, true ); 2252 // <-- 2253 2254 const SfxItemPropertyMap* pPropMap = 2255 aSwMapProvider.GetPropertySet( PROPERTY_MAP_TEXT_CURSOR )->getPropertyMap(); 2256 PropertyEntryVector_t aPropertyEntries = pPropMap->getPropertyEntries(); 2257 PropertyEntryVector_t::const_iterator aPropIt = aPropertyEntries.begin(); 2258 while ( aPropIt != aPropertyEntries.end() ) 2259 { 2260 const SfxPoolItem* pItem( 0 ); 2261 // --> OD 2007-11-12 #i82637# 2262 // Found character attributes, whose value equals the value of 2263 // the corresponding default character attributes, are excluded. 2264 if ( aSet.GetItemState( aPropIt->nWID, sal_True, &pItem ) == SFX_ITEM_SET ) 2265 { 2266 uno::Any aVal; 2267 pItem->QueryValue( aVal, aPropIt->nMemberId ); 2268 2269 PropertyValue rPropVal; 2270 rPropVal.Name = aPropIt->sName; 2271 rPropVal.Value = aVal; 2272 rPropVal.Handle = -1; 2273 rPropVal.State = PropertyState_DIRECT_VALUE; 2274 2275 tAccParaPropValMap::const_iterator aDefIter = 2276 aDefAttrSeq.find( rPropVal.Name ); 2277 if ( aDefIter == aDefAttrSeq.end() || 2278 rPropVal.Value != aDefIter->second.Value ) 2279 { 2280 aRunAttrSeq[rPropVal.Name] = rPropVal; 2281 } 2282 } 2283 2284 ++aPropIt; 2285 } 2286 } 2287 2288 if ( aRequestedAttributes.getLength() == 0 ) 2289 { 2290 rRunAttrSeq = aRunAttrSeq; 2291 } 2292 else 2293 { 2294 const ::rtl::OUString* pReqAttrs = aRequestedAttributes.getConstArray(); 2295 const sal_Int32 nLength = aRequestedAttributes.getLength(); 2296 for( sal_Int32 i = 0; i < nLength; ++i ) 2297 { 2298 tAccParaPropValMap::iterator aIter = aRunAttrSeq.find( pReqAttrs[i] ); 2299 if ( aIter != aRunAttrSeq.end() ) 2300 { 2301 rRunAttrSeq[ (*aIter).first ] = (*aIter).second; 2302 } 2303 } 2304 } 2305 } 2306 2307 delete pPaM; 2308 } 2309 2310 uno::Sequence< PropertyValue > SwAccessibleParagraph::getRunAttributes( 2311 sal_Int32 nIndex, 2312 const uno::Sequence< ::rtl::OUString >& aRequestedAttributes ) 2313 throw ( lang::IndexOutOfBoundsException, 2314 uno::RuntimeException ) 2315 { 2316 vos::OGuard aGuard(Application::GetSolarMutex()); 2317 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); 2318 2319 { 2320 const ::rtl::OUString& rText = GetString(); 2321 if ( !IsValidChar( nIndex, rText.getLength() ) ) 2322 { 2323 throw lang::IndexOutOfBoundsException(); 2324 } 2325 } 2326 2327 tAccParaPropValMap aRunAttrSeq; 2328 _getRunAttributesImpl( nIndex, aRequestedAttributes, aRunAttrSeq ); 2329 2330 uno::Sequence< PropertyValue > aValues( aRunAttrSeq.size() ); 2331 PropertyValue* pValues = aValues.getArray(); 2332 sal_Int32 i = 0; 2333 for ( tAccParaPropValMap::const_iterator aIter = aRunAttrSeq.begin(); 2334 aIter != aRunAttrSeq.end(); 2335 ++aIter ) 2336 { 2337 pValues[i] = aIter->second; 2338 ++i; 2339 } 2340 2341 return aValues; 2342 } 2343 // <-- 2344 void SwAccessibleParagraph::_getSupplementalAttributesImpl( 2345 const sal_Int32, 2346 const uno::Sequence< ::rtl::OUString >& aRequestedAttributes, 2347 tAccParaPropValMap& rSupplementalAttrSeq ) 2348 { 2349 const SwTxtNode* pTxtNode( GetTxtNode() ); 2350 ::boost::scoped_ptr<SfxItemSet> pSet; 2351 pSet.reset( new SfxItemSet( const_cast<SwAttrPool&>(pTxtNode->GetDoc()->GetAttrPool()), 2352 RES_PARATR_ADJUST, RES_PARATR_ADJUST, 2353 RES_PARATR_TABSTOP, RES_PARATR_TABSTOP, 2354 RES_PARATR_LINESPACING, RES_PARATR_LINESPACING, 2355 RES_UL_SPACE, RES_UL_SPACE, 2356 RES_LR_SPACE, RES_LR_SPACE, 2357 RES_PARATR_NUMRULE, RES_PARATR_NUMRULE, 2358 RES_PARATR_LIST_BEGIN, RES_PARATR_LIST_END-1, 2359 0 ) ); 2360 2361 if ( pTxtNode->HasBullet() || pTxtNode->HasNumber() ) 2362 { 2363 pSet->Put( pTxtNode->GetAttr(RES_PARATR_LIST_LEVEL, RES_PARATR_LIST_LEVEL) ); 2364 } 2365 pSet->Put( pTxtNode->SwCntntNode::GetAttr(RES_UL_SPACE) ); 2366 pSet->Put( pTxtNode->SwCntntNode::GetAttr(RES_LR_SPACE) ); 2367 pSet->Put( pTxtNode->SwCntntNode::GetAttr(RES_PARATR_ADJUST) ); 2368 2369 tAccParaPropValMap aSupplementalAttrSeq; 2370 { 2371 // const SfxItemPropertySet& rPropSet = 2372 // aSwMapProvider.GetPropertyMap( PROPERTY_MAP_ACCESSIBILITY_TEXT_ATTRIBUTE ); 2373 // const SfxItemPropertyMap* pPropMap( rPropSet.getPropertyMap() ); 2374 const SfxItemPropertyMapEntry* pPropMap( 2375 aSwMapProvider.GetPropertyMapEntries( PROPERTY_MAP_ACCESSIBILITY_TEXT_ATTRIBUTE ) ); 2376 while ( pPropMap->pName ) 2377 { 2378 const SfxPoolItem* pItem = pSet->GetItem( pPropMap->nWID ); 2379 if ( pItem ) 2380 { 2381 uno::Any aVal; 2382 pItem->QueryValue( aVal, pPropMap->nMemberId ); 2383 2384 PropertyValue rPropVal; 2385 rPropVal.Name = OUString::createFromAscii( pPropMap->pName ); 2386 rPropVal.Value = aVal; 2387 rPropVal.Handle = -1; 2388 rPropVal.State = beans::PropertyState_DEFAULT_VALUE; 2389 2390 aSupplementalAttrSeq[rPropVal.Name] = rPropVal; 2391 } 2392 2393 ++pPropMap; 2394 } 2395 } 2396 2397 const OUString* pSupplementalAttrs = aRequestedAttributes.getConstArray(); 2398 const sal_Int32 nSupplementalLength = aRequestedAttributes.getLength(); 2399 2400 for( sal_Int32 index = 0; index < nSupplementalLength; ++index ) 2401 { 2402 tAccParaPropValMap::const_iterator const aIter = aSupplementalAttrSeq.find( pSupplementalAttrs[index] ); 2403 if ( aIter != aSupplementalAttrSeq.end() ) 2404 { 2405 rSupplementalAttrSeq[ aIter->first ] = aIter->second; 2406 } 2407 } 2408 } 2409 2410 void SwAccessibleParagraph::_correctValues( const sal_Int32 nIndex, 2411 uno::Sequence< PropertyValue >& rValues) 2412 { 2413 PropertyValue ChangeAttr, ChangeAttrColor; 2414 2415 const SwRedline* pRedline = GetRedlineAtIndex( nIndex ); 2416 if ( pRedline ) 2417 { 2418 2419 const SwModuleOptions *pOpt = SW_MOD()->GetModuleConfig(); 2420 AuthorCharAttr aChangeAttr; 2421 if ( pOpt ) 2422 { 2423 switch( pRedline->GetType()) 2424 { 2425 case nsRedlineType_t::REDLINE_INSERT: 2426 aChangeAttr = pOpt->GetInsertAuthorAttr(); 2427 break; 2428 case nsRedlineType_t::REDLINE_DELETE: 2429 aChangeAttr = pOpt->GetDeletedAuthorAttr(); 2430 break; 2431 case nsRedlineType_t::REDLINE_FORMAT: 2432 aChangeAttr = pOpt->GetFormatAuthorAttr(); 2433 break; 2434 } 2435 } 2436 switch( aChangeAttr.nItemId ) 2437 { 2438 case SID_ATTR_CHAR_WEIGHT: 2439 ChangeAttr.Name = OUString::createFromAscii( GetPropName( UNO_NAME_CHAR_WEIGHT).pName ); 2440 ChangeAttr.Value <<= awt::FontWeight::BOLD; 2441 break; 2442 case SID_ATTR_CHAR_POSTURE: 2443 ChangeAttr.Name = OUString::createFromAscii( GetPropName( UNO_NAME_CHAR_POSTURE).pName ); 2444 ChangeAttr.Value <<= awt::FontSlant_ITALIC; //char posture 2445 break; 2446 case SID_ATTR_CHAR_STRIKEOUT: 2447 ChangeAttr.Name = OUString::createFromAscii( GetPropName( UNO_NAME_CHAR_STRIKEOUT).pName ); 2448 ChangeAttr.Value <<= awt::FontStrikeout::SINGLE; //char strikeout 2449 break; 2450 case SID_ATTR_CHAR_UNDERLINE: 2451 ChangeAttr.Name = OUString::createFromAscii( GetPropName( UNO_NAME_CHAR_UNDERLINE).pName ); 2452 ChangeAttr.Value <<= aChangeAttr.nAttr; //underline line 2453 break; 2454 } 2455 if( aChangeAttr.nColor != COL_NONE ) 2456 { 2457 if( aChangeAttr.nItemId == SID_ATTR_BRUSH ) 2458 { 2459 ChangeAttrColor.Name = OUString::createFromAscii( GetPropName( UNO_NAME_CHAR_BACK_COLOR).pName ); 2460 if( aChangeAttr.nColor == COL_TRANSPARENT )//char backcolor 2461 ChangeAttrColor.Value <<= COL_BLUE; 2462 else 2463 ChangeAttrColor.Value <<= aChangeAttr.nColor; 2464 } 2465 else 2466 { 2467 ChangeAttrColor.Name = OUString::createFromAscii( GetPropName( UNO_NAME_CHAR_COLOR ).pName ); 2468 if( aChangeAttr.nColor == COL_TRANSPARENT )//char color 2469 ChangeAttrColor.Value <<= COL_BLUE; 2470 else 2471 ChangeAttrColor.Value <<= aChangeAttr.nColor; 2472 } 2473 } 2474 } 2475 2476 PropertyValue* pValues = rValues.getArray(); 2477 2478 const SwTxtNode* pTxtNode( GetTxtNode() ); 2479 2480 sal_Int32 nValues = rValues.getLength(); 2481 for (sal_Int32 i = 0; i < nValues; ++i) 2482 { 2483 PropertyValue& rValue = pValues[i]; 2484 2485 if (rValue.Name.compareTo( ChangeAttr.Name )==0) 2486 { 2487 rValue.Value = ChangeAttr.Value; 2488 continue; 2489 } 2490 2491 if (rValue.Name.compareTo( ChangeAttrColor.Name )==0) 2492 { 2493 rValue.Value = ChangeAttr.Value; 2494 continue; 2495 } 2496 2497 //back color 2498 if (rValue.Name.compareTo(::rtl::OUString::createFromAscii( GetPropName( UNO_NAME_CHAR_BACK_COLOR ).pName ) )==0) 2499 { 2500 uno::Any &anyChar = rValue.Value; 2501 sal_uInt32 crBack = static_cast<sal_uInt32>( reinterpret_cast<sal_uIntPtr>(anyChar.pReserved)); 2502 if (COL_AUTO == crBack) 2503 { 2504 uno::Reference<XAccessibleComponent> xComponent(this); 2505 if (xComponent.is()) 2506 { 2507 crBack = (sal_uInt32)xComponent->getBackground(); 2508 } 2509 rValue.Value <<= crBack; 2510 } 2511 continue; 2512 } 2513 2514 //char color 2515 if (rValue.Name.compareTo(::rtl::OUString::createFromAscii( GetPropName( UNO_NAME_CHAR_COLOR ).pName ) )==0) 2516 { 2517 if( GetPortionData().IsInGrayPortion( nIndex ) ) 2518 rValue.Value <<= SwViewOption::GetFieldShadingsColor().GetColor(); 2519 uno::Any &anyChar = rValue.Value; 2520 sal_uInt32 crChar = static_cast<sal_uInt32>( reinterpret_cast<sal_uIntPtr>(anyChar.pReserved)); 2521 2522 if( COL_AUTO == crChar ) 2523 { 2524 uno::Reference<XAccessibleComponent> xComponent(this); 2525 if (xComponent.is()) 2526 { 2527 Color cr(xComponent->getBackground()); 2528 crChar = cr.IsDark() ? COL_WHITE : COL_BLACK; 2529 rValue.Value <<= crChar; 2530 } 2531 } 2532 continue; 2533 } 2534 2535 // UnderLine 2536 if (rValue.Name.compareTo(::rtl::OUString::createFromAscii( GetPropName( UNO_NAME_CHAR_UNDERLINE ).pName ) )==0) 2537 { 2538 //misspelled word 2539 SwCrsrShell* pCrsrShell = GetCrsrShell(); 2540 if( pCrsrShell != NULL && pCrsrShell->GetViewOptions() && pCrsrShell->GetViewOptions()->IsOnlineSpell()) 2541 { 2542 const SwWrongList* pWrongList = pTxtNode->GetWrong(); 2543 if( NULL != pWrongList ) 2544 { 2545 xub_StrLen nBegin = nIndex; 2546 xub_StrLen nLen = 1; 2547 if( pWrongList->InWrongWord(nBegin,nLen) && !pTxtNode->IsSymbol(nBegin) ) 2548 { 2549 rValue.Value <<= (sal_uInt16)UNDERLINE_WAVE; 2550 } 2551 } 2552 } 2553 continue; 2554 } 2555 2556 // UnderLineColor 2557 if (rValue.Name.compareTo(::rtl::OUString::createFromAscii( GetPropName( UNO_NAME_CHAR_UNDERLINE_COLOR ).pName ) )==0) 2558 { 2559 //misspelled word 2560 SwCrsrShell* pCrsrShell = GetCrsrShell(); 2561 if( pCrsrShell != NULL && pCrsrShell->GetViewOptions() && pCrsrShell->GetViewOptions()->IsOnlineSpell()) 2562 { 2563 const SwWrongList* pWrongList = pTxtNode->GetWrong(); 2564 if( NULL != pWrongList ) 2565 { 2566 xub_StrLen nBegin = nIndex; 2567 xub_StrLen nLen = 1; 2568 if( pWrongList->InWrongWord(nBegin,nLen) && !pTxtNode->IsSymbol(nBegin) ) 2569 { 2570 rValue.Value <<= (sal_Int32)0x00ff0000; 2571 continue; 2572 } 2573 } 2574 } 2575 2576 uno::Any &anyChar = rValue.Value; 2577 sal_uInt32 crUnderline = static_cast<sal_uInt32>( reinterpret_cast<sal_uIntPtr>(anyChar.pReserved)); 2578 if ( COL_AUTO == crUnderline ) 2579 { 2580 uno::Reference<XAccessibleComponent> xComponent(this); 2581 if (xComponent.is()) 2582 { 2583 Color cr(xComponent->getBackground()); 2584 crUnderline = cr.IsDark() ? COL_WHITE : COL_BLACK; 2585 rValue.Value <<= crUnderline; 2586 } 2587 } 2588 2589 continue; 2590 } 2591 2592 //tab stop 2593 if (rValue.Name.compareTo(::rtl::OUString::createFromAscii( GetPropName( UNO_NAME_TABSTOPS ).pName ) )==0) 2594 { 2595 com::sun::star::uno::Sequence< ::com::sun::star::style::TabStop > tabs = GetCurrentTabStop( nIndex ); 2596 if( !tabs.hasElements() ) 2597 { 2598 tabs.realloc(1); 2599 ::com::sun::star::style::TabStop ts; 2600 com::sun::star::awt::Rectangle rc0 = getCharacterBounds(0); 2601 com::sun::star::awt::Rectangle rc1 = getCharacterBounds(nIndex); 2602 if( rc1.X - rc0.X >= 48 ) 2603 ts.Position = (rc1.X - rc0.X) - (rc1.X - rc0.X - 48)% 47 + 47; 2604 else 2605 ts.Position = 48; 2606 ts.DecimalChar = ' '; 2607 ts.FillChar = ' '; 2608 ts.Alignment = ::com::sun::star::style::TabAlign_LEFT; 2609 tabs[0] = ts; 2610 } 2611 rValue.Value <<= tabs; 2612 continue; 2613 } 2614 2615 //number bullet 2616 if (rValue.Name.compareTo(::rtl::OUString::createFromAscii( GetPropName( UNO_NAME_NUMBERING_RULES ).pName ) )==0) 2617 { 2618 if ( pTxtNode->HasBullet() || pTxtNode->HasNumber() ) 2619 { 2620 uno::Any aVal; 2621 SwNumRule* pNumRule = pTxtNode->GetNumRule(); 2622 if (pNumRule) 2623 { 2624 uno::Reference< container::XIndexReplace > xNum = new SwXNumberingRules(*pNumRule); 2625 aVal.setValue(&xNum, ::getCppuType((const uno::Reference< container::XIndexReplace >*)0)); 2626 } 2627 rValue.Value <<= aVal; 2628 } 2629 continue; 2630 } 2631 2632 //footnote & endnote 2633 if (rValue.Name.compareTo(::rtl::OUString::createFromAscii( GetPropName( UNO_NAME_CHAR_ESCAPEMENT ).pName ) )==0) 2634 { 2635 if ( GetPortionData().IsIndexInFootnode(nIndex) ) 2636 { 2637 const OUString sEscapmentName = OUString::createFromAscii( GetPropName( UNO_NAME_CHAR_ESCAPEMENT ).pName ); 2638 rValue.Value <<= (sal_Int32)101; 2639 } 2640 continue; 2641 } 2642 } 2643 } 2644 2645 awt::Rectangle SwAccessibleParagraph::getCharacterBounds( 2646 sal_Int32 nIndex ) 2647 throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 2648 { 2649 vos::OGuard aGuard(Application::GetSolarMutex()); 2650 2651 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); 2652 2653 2654 /* #i12332# The position after the string needs special treatment. 2655 IsValidChar -> IsValidPosition 2656 */ 2657 if( ! (IsValidPosition( nIndex, GetString().getLength() ) ) ) 2658 throw lang::IndexOutOfBoundsException(); 2659 2660 /* #i12332# */ 2661 sal_Bool bBehindText = sal_False; 2662 if ( nIndex == GetString().getLength() ) 2663 bBehindText = sal_True; 2664 2665 // get model position & prepare GetCharRect() arguments 2666 SwCrsrMoveState aMoveState; 2667 aMoveState.bRealHeight = sal_True; 2668 aMoveState.bRealWidth = sal_True; 2669 SwSpecialPos aSpecialPos; 2670 SwTxtNode* pNode = const_cast<SwTxtNode*>( GetTxtNode() ); 2671 2672 sal_uInt16 nPos = 0; 2673 2674 /* #i12332# FillSpecialPos does not accept nIndex == 2675 GetString().getLength(). In that case nPos is set to the 2676 length of the string in the core. This way GetCharRect 2677 returns the rectangle for a cursor at the end of the 2678 paragraph. */ 2679 if (bBehindText) 2680 { 2681 nPos = pNode->GetTxt().Len(); 2682 } 2683 else 2684 nPos = GetPortionData().FillSpecialPos 2685 (nIndex, aSpecialPos, aMoveState.pSpecialPos ); 2686 2687 // call GetCharRect 2688 SwRect aCoreRect; 2689 SwIndex aIndex( pNode, nPos ); 2690 SwPosition aPosition( *pNode, aIndex ); 2691 GetFrm()->GetCharRect( aCoreRect, aPosition, &aMoveState ); 2692 2693 // translate core coordinates into accessibility coordinates 2694 Window *pWin = GetWindow(); 2695 CHECK_FOR_WINDOW( XAccessibleComponent, pWin ); 2696 2697 Rectangle aScreenRect( GetMap()->CoreToPixel( aCoreRect.SVRect() )); 2698 SwRect aFrmLogBounds( GetBounds( *(GetMap()) ) ); // twip rel to doc root 2699 2700 Point aFrmPixPos( GetMap()->CoreToPixel( aFrmLogBounds.SVRect() ).TopLeft() ); 2701 aScreenRect.Move( -aFrmPixPos.X(), -aFrmPixPos.Y() ); 2702 2703 // convert into AWT Rectangle 2704 return awt::Rectangle( 2705 aScreenRect.Left(), aScreenRect.Top(), 2706 aScreenRect.GetWidth(), aScreenRect.GetHeight() ); 2707 } 2708 2709 sal_Int32 SwAccessibleParagraph::getCharacterCount() 2710 throw (uno::RuntimeException) 2711 { 2712 vos::OGuard aGuard(Application::GetSolarMutex()); 2713 2714 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); 2715 2716 return GetString().getLength(); 2717 } 2718 2719 sal_Int32 SwAccessibleParagraph::getIndexAtPoint( const awt::Point& rPoint ) 2720 throw (uno::RuntimeException) 2721 { 2722 vos::OGuard aGuard(Application::GetSolarMutex()); 2723 2724 2725 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); 2726 2727 // construct SwPosition (where GetCrsrOfst() will put the result into) 2728 SwTxtNode* pNode = const_cast<SwTxtNode*>( GetTxtNode() ); 2729 SwIndex aIndex( pNode, 0); 2730 SwPosition aPos( *pNode, aIndex ); 2731 2732 // construct Point (translate into layout coordinates) 2733 Window *pWin = GetWindow(); 2734 CHECK_FOR_WINDOW( XAccessibleComponent, pWin ); 2735 Point aPoint( rPoint.X, rPoint.Y ); 2736 SwRect aLogBounds( GetBounds( *(GetMap()), GetFrm() ) ); // twip rel to doc root 2737 Point aPixPos( GetMap()->CoreToPixel( aLogBounds.SVRect() ).TopLeft() ); 2738 aPoint.X() += aPixPos.X(); 2739 aPoint.Y() += aPixPos.Y(); 2740 MapMode aMapMode = pWin->GetMapMode(); 2741 Point aCorePoint( GetMap()->PixelToCore( aPoint ) ); 2742 if( !aLogBounds.IsInside( aCorePoint ) ) 2743 { 2744 /* #i12332# rPoint is may also be in rectangle returned by 2745 getCharacterBounds(getCharacterCount() */ 2746 2747 awt::Rectangle aRectEndPos = 2748 getCharacterBounds(getCharacterCount()); 2749 2750 if (rPoint.X - aRectEndPos.X >= 0 && 2751 rPoint.X - aRectEndPos.X < aRectEndPos.Width && 2752 rPoint.Y - aRectEndPos.Y >= 0 && 2753 rPoint.Y - aRectEndPos.Y < aRectEndPos.Height) 2754 return getCharacterCount(); 2755 2756 return -1; 2757 } 2758 2759 // ask core for position 2760 DBG_ASSERT( GetFrm() != NULL, "The text frame has vanished!" ); 2761 DBG_ASSERT( GetFrm()->IsTxtFrm(), "The text frame has mutated!" ); 2762 const SwTxtFrm* pFrm = static_cast<const SwTxtFrm*>( GetFrm() ); 2763 SwCrsrMoveState aMoveState; 2764 aMoveState.bPosMatchesBounds = sal_True; 2765 sal_Bool bSuccess = pFrm->GetCrsrOfst( &aPos, aCorePoint, &aMoveState ); 2766 2767 SwIndex aCntntIdx = aPos.nContent; 2768 const xub_StrLen nIndex = aCntntIdx.GetIndex(); 2769 if ( nIndex > 0 ) 2770 { 2771 SwRect aResultRect; 2772 pFrm->GetCharRect( aResultRect, aPos ); 2773 bool bVert = pFrm->IsVertical(); 2774 bool bR2L = pFrm->IsRightToLeft(); 2775 2776 if ( (!bVert && aResultRect.Pos().X() > aCorePoint.X()) || 2777 ( bVert && aResultRect.Pos().Y() > aCorePoint.Y()) || 2778 ( bR2L && aResultRect.Right() < aCorePoint.X()) ) 2779 { 2780 SwIndex aIdxPrev( pNode, nIndex - 1); 2781 SwPosition aPosPrev( *pNode, aIdxPrev ); 2782 SwRect aResultRectPrev; 2783 pFrm->GetCharRect( aResultRectPrev, aPosPrev ); 2784 if ( (!bVert && aResultRectPrev.Pos().X() < aCorePoint.X() && aResultRect.Pos().Y() == aResultRectPrev.Pos().Y()) || 2785 ( bVert && aResultRectPrev.Pos().Y() < aCorePoint.Y() && aResultRect.Pos().X() == aResultRectPrev.Pos().X()) || 2786 ( bR2L && aResultRectPrev.Right() > aCorePoint.X() && aResultRect.Pos().Y() == aResultRectPrev.Pos().Y()) ) 2787 aPos = aPosPrev; 2788 } 2789 } 2790 2791 return bSuccess ? 2792 GetPortionData().GetAccessiblePosition( aPos.nContent.GetIndex() ) 2793 : -1L; 2794 } 2795 2796 ::rtl::OUString SwAccessibleParagraph::getSelectedText() 2797 throw (uno::RuntimeException) 2798 { 2799 vos::OGuard aGuard(Application::GetSolarMutex()); 2800 2801 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); 2802 2803 sal_Int32 nStart, nEnd; 2804 sal_Bool bSelected = GetSelection( nStart, nEnd ); 2805 return bSelected 2806 ? GetString().copy( nStart, nEnd - nStart ) 2807 : ::rtl::OUString(); 2808 } 2809 2810 sal_Int32 SwAccessibleParagraph::getSelectionStart() 2811 throw (uno::RuntimeException) 2812 { 2813 vos::OGuard aGuard(Application::GetSolarMutex()); 2814 2815 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); 2816 2817 sal_Int32 nStart, nEnd; 2818 GetSelection( nStart, nEnd ); 2819 return nStart; 2820 } 2821 2822 sal_Int32 SwAccessibleParagraph::getSelectionEnd() 2823 throw (uno::RuntimeException) 2824 { 2825 vos::OGuard aGuard(Application::GetSolarMutex()); 2826 2827 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); 2828 2829 sal_Int32 nStart, nEnd; 2830 GetSelection( nStart, nEnd ); 2831 return nEnd; 2832 } 2833 2834 sal_Bool SwAccessibleParagraph::setSelection( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) 2835 throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 2836 { 2837 vos::OGuard aGuard(Application::GetSolarMutex()); 2838 2839 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); 2840 2841 // parameter checking 2842 sal_Int32 nLength = GetString().getLength(); 2843 if ( ! IsValidRange( nStartIndex, nEndIndex, nLength ) ) 2844 { 2845 throw lang::IndexOutOfBoundsException(); 2846 } 2847 2848 sal_Bool bRet = sal_False; 2849 2850 // get cursor shell 2851 SwCrsrShell* pCrsrShell = GetCrsrShell(); 2852 if( pCrsrShell != NULL ) 2853 { 2854 // create pam for selection 2855 SwTxtNode* pNode = const_cast<SwTxtNode*>( GetTxtNode() ); 2856 SwIndex aIndex( pNode, GetPortionData().GetModelPosition(nStartIndex)); 2857 SwPosition aStartPos( *pNode, aIndex ); 2858 SwPaM aPaM( aStartPos ); 2859 aPaM.SetMark(); 2860 aPaM.GetPoint()->nContent = 2861 GetPortionData().GetModelPosition(nEndIndex); 2862 2863 // set PaM at cursor shell 2864 bRet = Select( aPaM ); 2865 } 2866 2867 return bRet; 2868 } 2869 2870 ::rtl::OUString SwAccessibleParagraph::getText() 2871 throw (uno::RuntimeException) 2872 { 2873 vos::OGuard aGuard(Application::GetSolarMutex()); 2874 2875 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); 2876 2877 return GetString(); 2878 } 2879 2880 ::rtl::OUString SwAccessibleParagraph::getTextRange( 2881 sal_Int32 nStartIndex, sal_Int32 nEndIndex ) 2882 throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 2883 { 2884 vos::OGuard aGuard(Application::GetSolarMutex()); 2885 2886 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); 2887 2888 ::rtl::OUString sText( GetString() ); 2889 2890 if ( IsValidRange( nStartIndex, nEndIndex, sText.getLength() ) ) 2891 { 2892 OrderRange( nStartIndex, nEndIndex ); 2893 return sText.copy(nStartIndex, nEndIndex-nStartIndex ); 2894 } 2895 else 2896 throw lang::IndexOutOfBoundsException(); 2897 } 2898 2899 /*accessibility::*/TextSegment SwAccessibleParagraph::getTextAtIndex( sal_Int32 nIndex, sal_Int16 nTextType ) throw (lang::IndexOutOfBoundsException, lang::IllegalArgumentException, uno::RuntimeException) 2900 { 2901 vos::OGuard aGuard(Application::GetSolarMutex()); 2902 2903 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); 2904 2905 /*accessibility::*/TextSegment aResult; 2906 aResult.SegmentStart = -1; 2907 aResult.SegmentEnd = -1; 2908 2909 const ::rtl::OUString rText = GetString(); 2910 // implement the silly specification that first position after 2911 // text must return an empty string, rather than throwing an 2912 // IndexOutOfBoundsException, except for LINE, where the last 2913 // line is returned 2914 if( nIndex == rText.getLength() && AccessibleTextType::LINE != nTextType ) 2915 return aResult; 2916 2917 // with error checking 2918 i18n::Boundary aBound; 2919 sal_Bool bWord = GetTextBoundary( aBound, rText, nIndex, nTextType ); 2920 2921 DBG_ASSERT( aBound.startPos >= 0, "illegal boundary" ); 2922 DBG_ASSERT( aBound.startPos <= aBound.endPos, "illegal boundary" ); 2923 2924 // return word (if present) 2925 if ( bWord ) 2926 { 2927 aResult.SegmentText = rText.copy( aBound.startPos, aBound.endPos - aBound.startPos ); 2928 aResult.SegmentStart = aBound.startPos; 2929 aResult.SegmentEnd = aBound.endPos; 2930 } 2931 2932 return aResult; 2933 } 2934 2935 /*accessibility::*/TextSegment SwAccessibleParagraph::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 nTextType ) throw (lang::IndexOutOfBoundsException, lang::IllegalArgumentException, uno::RuntimeException) 2936 { 2937 vos::OGuard aGuard(Application::GetSolarMutex()); 2938 2939 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); 2940 2941 const ::rtl::OUString rText = GetString(); 2942 2943 /*accessibility::*/TextSegment aResult; 2944 aResult.SegmentStart = -1; 2945 aResult.SegmentEnd = -1; 2946 //If nIndex = 0, then nobefore text so return -1 directly. 2947 if( nIndex == 0 ) 2948 return aResult; 2949 //Tab will be return when call WORDTYPE 2950 2951 // get starting pos 2952 i18n::Boundary aBound; 2953 if (nIndex == rText.getLength()) 2954 aBound.startPos = aBound.endPos = nIndex; 2955 else 2956 { 2957 sal_Bool bTmp = GetTextBoundary( aBound, rText, nIndex, nTextType ); 2958 2959 if ( ! bTmp ) 2960 aBound.startPos = aBound.endPos = nIndex; 2961 } 2962 2963 // now skip to previous word 2964 if (nTextType==2 || nTextType == 3) 2965 { 2966 i18n::Boundary preBound = aBound; 2967 while(preBound.startPos==aBound.startPos && nIndex > 0) 2968 { 2969 nIndex = min( nIndex, preBound.startPos ) - 1; 2970 if( nIndex < 0 ) break; 2971 GetTextBoundary( preBound, rText, nIndex, nTextType ); 2972 } 2973 //if (nIndex>0) 2974 if (nIndex>=0) 2975 //Tab will be return when call WORDTYPE 2976 { 2977 aResult.SegmentText = rText.copy( preBound.startPos, preBound.endPos - preBound.startPos ); 2978 aResult.SegmentStart = preBound.startPos; 2979 aResult.SegmentEnd = preBound.endPos; 2980 } 2981 } 2982 else 2983 { 2984 sal_Bool bWord = sal_False; 2985 while( !bWord ) 2986 { 2987 nIndex = min( nIndex, aBound.startPos ) - 1; 2988 if( nIndex >= 0 ) 2989 { 2990 bWord = GetTextBoundary( aBound, rText, nIndex, nTextType ); 2991 } 2992 else 2993 break; // exit if beginning of string is reached 2994 } 2995 2996 if (bWord && nIndex<rText.getLength()) 2997 { 2998 aResult.SegmentText = rText.copy( aBound.startPos, aBound.endPos - aBound.startPos ); 2999 aResult.SegmentStart = aBound.startPos; 3000 aResult.SegmentEnd = aBound.endPos; 3001 } 3002 } 3003 return aResult; 3004 } 3005 3006 /*accessibility::*/TextSegment SwAccessibleParagraph::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 nTextType ) throw (lang::IndexOutOfBoundsException, lang::IllegalArgumentException, uno::RuntimeException) 3007 { 3008 vos::OGuard aGuard(Application::GetSolarMutex()); 3009 3010 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); 3011 3012 /*accessibility::*/TextSegment aResult; 3013 aResult.SegmentStart = -1; 3014 aResult.SegmentEnd = -1; 3015 const ::rtl::OUString rText = GetString(); 3016 3017 // implement the silly specification that first position after 3018 // text must return an empty string, rather than throwing an 3019 // IndexOutOfBoundsException 3020 if( nIndex == rText.getLength() ) 3021 return aResult; 3022 3023 3024 // get first word, then skip to next word 3025 i18n::Boundary aBound; 3026 GetTextBoundary( aBound, rText, nIndex, nTextType ); 3027 sal_Bool bWord = sal_False; 3028 while( !bWord ) 3029 { 3030 nIndex = max( sal_Int32(nIndex+1), aBound.endPos ); 3031 if( nIndex < rText.getLength() ) 3032 bWord = GetTextBoundary( aBound, rText, nIndex, nTextType ); 3033 else 3034 break; // exit if end of string is reached 3035 } 3036 3037 if ( bWord ) 3038 { 3039 aResult.SegmentText = rText.copy( aBound.startPos, aBound.endPos - aBound.startPos ); 3040 aResult.SegmentStart = aBound.startPos; 3041 aResult.SegmentEnd = aBound.endPos; 3042 } 3043 3044 /* 3045 sal_Bool bWord = sal_False; 3046 bWord = GetTextBoundary( aBound, rText, nIndex, nTextType ); 3047 3048 if (nTextType==2) 3049 { 3050 Boundary nexBound=aBound; 3051 3052 // real current word 3053 if( nIndex <= aBound.endPos && nIndex >= aBound.startPos ) 3054 { 3055 while(nexBound.endPos==aBound.endPos&&nIndex<rText.getLength()) 3056 { 3057 // nIndex = max( (sal_Int32)(nIndex), nexBound.endPos) + 1; 3058 nIndex = max( (sal_Int32)(nIndex), nexBound.endPos) ; 3059 const sal_Unicode* pStr = rText.getStr(); 3060 if (pStr) 3061 { 3062 if( pStr[nIndex] == sal_Unicode(' ') ) 3063 nIndex++; 3064 } 3065 if( nIndex < rText.getLength() ) 3066 { 3067 bWord = GetTextBoundary( nexBound, rText, nIndex, nTextType ); 3068 } 3069 } 3070 } 3071 3072 if (bWord && nIndex<rText.getLength()) 3073 { 3074 aResult.SegmentText = rText.copy( nexBound.startPos, nexBound.endPos - nexBound.startPos ); 3075 aResult.SegmentStart = nexBound.startPos; 3076 aResult.SegmentEnd = nexBound.endPos; 3077 } 3078 3079 } 3080 else 3081 { 3082 bWord = sal_False; 3083 while( !bWord ) 3084 { 3085 nIndex = max( (sal_Int32)(nIndex+1), aBound.endPos ); 3086 if( nIndex < rText.getLength() ) 3087 { 3088 bWord = GetTextBoundary( aBound, rText, nIndex, nTextType ); 3089 } 3090 else 3091 break; // exit if end of string is reached 3092 } 3093 if (bWord && nIndex<rText.getLength()) 3094 { 3095 aResult.SegmentText = rText.copy( aBound.startPos, aBound.endPos - aBound.startPos ); 3096 aResult.SegmentStart = aBound.startPos; 3097 aResult.SegmentEnd = aBound.endPos; 3098 } 3099 } 3100 */ 3101 return aResult; 3102 } 3103 3104 sal_Bool SwAccessibleParagraph::copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) 3105 throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 3106 { 3107 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); 3108 vos::OGuard aGuard(Application::GetSolarMutex()); 3109 3110 // select and copy (through dispatch mechanism) 3111 setSelection( nStartIndex, nEndIndex ); 3112 ExecuteAtViewShell( SID_COPY ); 3113 return sal_True; 3114 } 3115 3116 3117 // 3118 //===== XAccesibleEditableText ========================================== 3119 // 3120 3121 sal_Bool SwAccessibleParagraph::cutText( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) 3122 throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 3123 { 3124 CHECK_FOR_DEFUNC( XAccessibleEditableText ); 3125 vos::OGuard aGuard(Application::GetSolarMutex()); 3126 3127 if( !IsEditableState() ) 3128 return sal_False; 3129 3130 // select and cut (through dispatch mechanism) 3131 setSelection( nStartIndex, nEndIndex ); 3132 ExecuteAtViewShell( SID_CUT ); 3133 return sal_True; 3134 } 3135 3136 sal_Bool SwAccessibleParagraph::pasteText( sal_Int32 nIndex ) 3137 throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 3138 { 3139 CHECK_FOR_DEFUNC( XAccessibleEditableText ); 3140 vos::OGuard aGuard(Application::GetSolarMutex()); 3141 3142 if( !IsEditableState() ) 3143 return sal_False; 3144 3145 // select and paste (through dispatch mechanism) 3146 setSelection( nIndex, nIndex ); 3147 ExecuteAtViewShell( SID_PASTE ); 3148 return sal_True; 3149 } 3150 3151 sal_Bool SwAccessibleParagraph::deleteText( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) 3152 throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 3153 { 3154 return replaceText( nStartIndex, nEndIndex, ::rtl::OUString() ); 3155 } 3156 3157 sal_Bool SwAccessibleParagraph::insertText( const ::rtl::OUString& sText, sal_Int32 nIndex ) 3158 throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 3159 { 3160 return replaceText( nIndex, nIndex, sText ); 3161 } 3162 3163 sal_Bool SwAccessibleParagraph::replaceText( 3164 sal_Int32 nStartIndex, sal_Int32 nEndIndex, 3165 const ::rtl::OUString& sReplacement ) 3166 throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 3167 { 3168 vos::OGuard aGuard(Application::GetSolarMutex()); 3169 3170 CHECK_FOR_DEFUNC( XAccessibleEditableText ); 3171 3172 const ::rtl::OUString& rText = GetString(); 3173 3174 if( IsValidRange( nStartIndex, nEndIndex, rText.getLength() ) ) 3175 { 3176 if( !IsEditableState() ) 3177 return sal_False; 3178 3179 SwTxtNode* pNode = const_cast<SwTxtNode*>( GetTxtNode() ); 3180 3181 // translate positions 3182 sal_uInt16 nStart, nEnd; 3183 sal_Bool bSuccess = GetPortionData().GetEditableRange( 3184 nStartIndex, nEndIndex, nStart, nEnd ); 3185 3186 // edit only if the range is editable 3187 if( bSuccess ) 3188 { 3189 // create SwPosition for nStartIndex 3190 SwIndex aIndex( pNode, nStart ); 3191 SwPosition aStartPos( *pNode, aIndex ); 3192 3193 // create SwPosition for nEndIndex 3194 SwPosition aEndPos( aStartPos ); 3195 aEndPos.nContent = nEnd; 3196 3197 // now create XTextRange as helper and set string 3198 const uno::Reference<text::XTextRange> xRange( 3199 SwXTextRange::CreateXTextRange( 3200 *pNode->GetDoc(), aStartPos, &aEndPos)); 3201 xRange->setString(sReplacement); 3202 3203 // delete portion data 3204 ClearPortionData(); 3205 } 3206 3207 return bSuccess; 3208 } 3209 else 3210 throw lang::IndexOutOfBoundsException(); 3211 } 3212 3213 3214 sal_Bool SwAccessibleParagraph::setAttributes( 3215 sal_Int32 nStartIndex, 3216 sal_Int32 nEndIndex, 3217 const uno::Sequence<PropertyValue>& rAttributeSet ) 3218 throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 3219 { 3220 vos::OGuard aGuard(Application::GetSolarMutex()); 3221 CHECK_FOR_DEFUNC( XAccessibleEditableText ); 3222 3223 const ::rtl::OUString& rText = GetString(); 3224 3225 if( ! IsValidRange( nStartIndex, nEndIndex, rText.getLength() ) ) 3226 throw lang::IndexOutOfBoundsException(); 3227 3228 if( !IsEditableState() ) 3229 return sal_False; 3230 3231 3232 // create a (dummy) text portion for the sole purpose of calling 3233 // setPropertyValue on it 3234 uno::Reference<XMultiPropertySet> xPortion = CreateUnoPortion( nStartIndex, 3235 nEndIndex ); 3236 3237 // build sorted index array 3238 sal_Int32 nLength = rAttributeSet.getLength(); 3239 const PropertyValue* pPairs = rAttributeSet.getConstArray(); 3240 sal_Int32* pIndices = new sal_Int32[nLength]; 3241 sal_Int32 i; 3242 for( i = 0; i < nLength; i++ ) 3243 pIndices[i] = i; 3244 sort( &pIndices[0], &pIndices[nLength], IndexCompare(pPairs) ); 3245 3246 // create sorted sequences accoring to index array 3247 uno::Sequence< ::rtl::OUString > aNames( nLength ); 3248 ::rtl::OUString* pNames = aNames.getArray(); 3249 uno::Sequence< uno::Any > aValues( nLength ); 3250 uno::Any* pValues = aValues.getArray(); 3251 for( i = 0; i < nLength; i++ ) 3252 { 3253 const PropertyValue& rVal = pPairs[pIndices[i]]; 3254 pNames[i] = rVal.Name; 3255 pValues[i] = rVal.Value; 3256 } 3257 delete[] pIndices; 3258 3259 // now set the values 3260 sal_Bool bRet = sal_True; 3261 try 3262 { 3263 xPortion->setPropertyValues( aNames, aValues ); 3264 } 3265 catch( UnknownPropertyException e ) 3266 { 3267 // error handling through return code! 3268 bRet = sal_False; 3269 } 3270 3271 return bRet; 3272 } 3273 3274 sal_Bool SwAccessibleParagraph::setText( const ::rtl::OUString& sText ) 3275 throw (uno::RuntimeException) 3276 { 3277 return replaceText(0, GetString().getLength(), sText); 3278 } 3279 3280 //===== XAccessibleSelection ============================================ 3281 3282 void SwAccessibleParagraph::selectAccessibleChild( 3283 sal_Int32 nChildIndex ) 3284 throw ( lang::IndexOutOfBoundsException, 3285 uno::RuntimeException ) 3286 { 3287 CHECK_FOR_DEFUNC( XAccessibleSelection ); 3288 3289 aSelectionHelper.selectAccessibleChild(nChildIndex); 3290 } 3291 3292 sal_Bool SwAccessibleParagraph::isAccessibleChildSelected( 3293 sal_Int32 nChildIndex ) 3294 throw ( lang::IndexOutOfBoundsException, 3295 uno::RuntimeException ) 3296 { 3297 CHECK_FOR_DEFUNC( XAccessibleSelection ); 3298 3299 return aSelectionHelper.isAccessibleChildSelected(nChildIndex); 3300 } 3301 3302 void SwAccessibleParagraph::clearAccessibleSelection( ) 3303 throw ( uno::RuntimeException ) 3304 { 3305 CHECK_FOR_DEFUNC( XAccessibleSelection ); 3306 3307 aSelectionHelper.clearAccessibleSelection(); 3308 } 3309 3310 void SwAccessibleParagraph::selectAllAccessibleChildren( ) 3311 throw ( uno::RuntimeException ) 3312 { 3313 CHECK_FOR_DEFUNC( XAccessibleSelection ); 3314 3315 aSelectionHelper.selectAllAccessibleChildren(); 3316 } 3317 3318 sal_Int32 SwAccessibleParagraph::getSelectedAccessibleChildCount( ) 3319 throw ( uno::RuntimeException ) 3320 { 3321 CHECK_FOR_DEFUNC( XAccessibleSelection ); 3322 3323 return aSelectionHelper.getSelectedAccessibleChildCount(); 3324 } 3325 3326 uno::Reference<XAccessible> SwAccessibleParagraph::getSelectedAccessibleChild( 3327 sal_Int32 nSelectedChildIndex ) 3328 throw ( lang::IndexOutOfBoundsException, 3329 uno::RuntimeException) 3330 { 3331 CHECK_FOR_DEFUNC( XAccessibleSelection ); 3332 3333 return aSelectionHelper.getSelectedAccessibleChild(nSelectedChildIndex); 3334 } 3335 3336 // --> OD 2004-11-16 #111714# - index has to be treated as global child index. 3337 void SwAccessibleParagraph::deselectAccessibleChild( 3338 sal_Int32 nChildIndex ) 3339 throw ( lang::IndexOutOfBoundsException, 3340 uno::RuntimeException ) 3341 { 3342 CHECK_FOR_DEFUNC( XAccessibleSelection ); 3343 3344 aSelectionHelper.deselectAccessibleChild( nChildIndex ); 3345 } 3346 3347 //===== XAccessibleHypertext ============================================ 3348 3349 class SwHyperlinkIter_Impl 3350 { 3351 const SwpHints *pHints; 3352 xub_StrLen nStt; 3353 xub_StrLen nEnd; 3354 sal_uInt16 nPos; 3355 3356 public: 3357 SwHyperlinkIter_Impl( const SwTxtFrm *pTxtFrm ); 3358 const SwTxtAttr *next(); 3359 sal_uInt16 getCurrHintPos() const { return nPos-1; } 3360 3361 xub_StrLen startIdx() const { return nStt; } 3362 xub_StrLen endIdx() const { return nEnd; } 3363 }; 3364 3365 SwHyperlinkIter_Impl::SwHyperlinkIter_Impl( const SwTxtFrm *pTxtFrm ) : 3366 pHints( pTxtFrm->GetTxtNode()->GetpSwpHints() ), 3367 nStt( pTxtFrm->GetOfst() ), 3368 nPos( 0 ) 3369 { 3370 const SwTxtFrm *pFollFrm = pTxtFrm->GetFollow(); 3371 nEnd = pFollFrm ? pFollFrm->GetOfst() : pTxtFrm->GetTxtNode()->Len(); 3372 } 3373 3374 const SwTxtAttr *SwHyperlinkIter_Impl::next() 3375 { 3376 const SwTxtAttr *pAttr = 0; 3377 if( pHints ) 3378 { 3379 while( !pAttr && nPos < pHints->Count() ) 3380 { 3381 const SwTxtAttr *pHt = (*pHints)[nPos]; 3382 if( RES_TXTATR_INETFMT == pHt->Which() ) 3383 { 3384 xub_StrLen nHtStt = *pHt->GetStart(); 3385 xub_StrLen nHtEnd = *pHt->GetAnyEnd(); 3386 if( nHtEnd > nHtStt && 3387 ( (nHtStt >= nStt && nHtStt < nEnd) || 3388 (nHtEnd > nStt && nHtEnd <= nEnd) ) ) 3389 { 3390 pAttr = pHt; 3391 } 3392 } 3393 ++nPos; 3394 } 3395 } 3396 3397 return pAttr; 3398 }; 3399 3400 sal_Int32 SAL_CALL SwAccessibleParagraph::getHyperLinkCount() 3401 throw (uno::RuntimeException) 3402 { 3403 vos::OGuard aGuard(Application::GetSolarMutex()); 3404 3405 CHECK_FOR_DEFUNC( XAccessibleHypertext ); 3406 3407 sal_Int32 nCount = 0; 3408 // --> OD 2007-06-27 #i77108# - provide hyperlinks also in editable documents. 3409 // if( !IsEditableState() ) 3410 // <-- 3411 { 3412 const SwTxtFrm *pTxtFrm = static_cast<const SwTxtFrm*>( GetFrm() ); 3413 SwHyperlinkIter_Impl aIter( pTxtFrm ); 3414 while( aIter.next() ) 3415 nCount++; 3416 } 3417 3418 /* Can't fin the function "GetTOCFirstWordEndIndex" declaration in sym2.0 (Added by yanjun) 3419 if( GetTOXSortTabBase() ) 3420 { 3421 SwTxtNode* pNode = const_cast<SwTxtNode*>(GetTxtNode()); 3422 if(pNode && pNode->GetTOCFirstWordEndIndex() > 0) 3423 nCount++; 3424 } 3425 */ 3426 return nCount; 3427 } 3428 3429 uno::Reference< XAccessibleHyperlink > SAL_CALL 3430 SwAccessibleParagraph::getHyperLink( sal_Int32 nLinkIndex ) 3431 throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 3432 { 3433 vos::OGuard aGuard(Application::GetSolarMutex()); 3434 CHECK_FOR_DEFUNC( XAccessibleHypertext ); 3435 3436 uno::Reference< XAccessibleHyperlink > xRet; 3437 3438 // --> OD 2007-06-27 #i77108# - provide hyperlinks also in editable documents. 3439 // if( !IsEditableState() ) 3440 const SwTxtFrm *pTxtFrm = static_cast<const SwTxtFrm*>( GetFrm() ); 3441 SwHyperlinkIter_Impl aHIter( pTxtFrm ); 3442 //SwAccessibleAutoRecognizerHelper_Impl aARHelper( pTxtFrm ); 3443 sal_Int32 nARCount = 0; 3444 sal_Int32 nARIndex = 0; 3445 sal_Int32 nTIndex = -1; 3446 sal_Int32 nTOCEndIndex = -1; 3447 SwTxtNode* pNode = NULL; 3448 SwTOXSortTabBase* pTBase = GetTOXSortTabBase(); 3449 if( pTBase ) 3450 { 3451 pNode = const_cast<SwTxtNode*>(GetTxtNode()); 3452 } 3453 nTOCEndIndex = -1; 3454 //if(pNode) 3455 // nTOCEndIndex = pNode->GetTOCFirstWordEndIndex(); 3456 SwTxtAttr* pHt = (SwTxtAttr*)(aHIter.next()); 3457 while( (nLinkIndex < getHyperLinkCount()) && nTIndex < nLinkIndex) 3458 { 3459 // no candidates, exit 3460 //if( (!pHt) && (nARIndex >= nARCount) && nTOCEndIndex <= 0) 3461 // break; 3462 3463 sal_Int32 nHStt = -1; 3464 sal_Int32 nAStt = -1; 3465 sal_Bool bH = sal_False; 3466 sal_Bool bA = sal_False; 3467 3468 3469 if( pHt ) 3470 nHStt = *pHt->GetStart(); 3471 if( nARIndex < nARCount ) 3472 { 3473 /* 3474 sal_Int32 nAEnd; 3475 aARHelper.getPosition( nARIndex, nAStt, nAEnd ); 3476 */ 3477 } 3478 sal_Bool bTOC = sal_False; 3479 // Inside TOC & get the first link 3480 if( pTBase && nTIndex == -1 ) 3481 { 3482 nTIndex++; 3483 bTOC = sal_True; 3484 } 3485 else 3486 { 3487 if( nHStt >=0 && nAStt >=0 ) 3488 { // both hyperlink and smart tag available 3489 nTIndex++; 3490 if( nHStt <= nAStt ) 3491 bH = sal_True; 3492 else 3493 bA = sal_True; 3494 } 3495 else if( nHStt >= 0 ) 3496 { // only hyperlink available 3497 nTIndex++; 3498 bH = sal_True; 3499 } 3500 else if( nAStt >= 0 ) 3501 { // only smart tag available 3502 nTIndex++; 3503 bA = sal_True; 3504 } 3505 } 3506 3507 if( nTIndex == nLinkIndex ) 3508 { // found 3509 if( bH ) 3510 { // it's a hyperlink 3511 if( pHt ) 3512 { 3513 // const SwField* pFFld = pHt->GetFld().GetFld(); 3514 { 3515 if( !pHyperTextData ) 3516 pHyperTextData = new SwAccessibleHyperTextData; 3517 SwAccessibleHyperTextData::iterator aIter = 3518 pHyperTextData ->find( pHt ); 3519 if( aIter != pHyperTextData->end() ) 3520 { 3521 xRet = (*aIter).second; 3522 } 3523 if( !xRet.is() ) 3524 { 3525 { 3526 const sal_Int32 nTmpHStt= GetPortionData().GetAccessiblePosition( 3527 max( aHIter.startIdx(), *pHt->GetStart() ) ); 3528 const sal_Int32 nTmpHEnd= GetPortionData().GetAccessiblePosition( 3529 min( aHIter.endIdx(), *pHt->GetAnyEnd() ) ); 3530 xRet = new SwAccessibleHyperlink( aHIter.getCurrHintPos(), 3531 this, nTmpHStt, nTmpHEnd ); 3532 } 3533 if( aIter != pHyperTextData->end() ) 3534 { 3535 (*aIter).second = xRet; 3536 } 3537 else 3538 { 3539 SwAccessibleHyperTextData::value_type aEntry( pHt, xRet ); 3540 pHyperTextData->insert( aEntry ); 3541 } 3542 } 3543 } 3544 } 3545 } 3546 else if( bTOC ) 3547 { 3548 //xRet = new SwAccessibleTOCLink( this ); 3549 } 3550 else if( bA ) 3551 { 3552 /* 3553 // it's a smart tag 3554 if( !pAutoRecognizerData ) 3555 pAutoRecognizerData = new SwAccessibleAutoRecognizerData; 3556 SwAccessibleAutoRecognizerData::iterator aIter = 3557 pAutoRecognizerData ->find( nARIndex ); 3558 if( aIter != pAutoRecognizerData->end() ) 3559 { 3560 xRet = (*aIter).second; 3561 } 3562 if( !xRet.is() ) 3563 { 3564 sal_Int32 nAStt = 0; 3565 sal_Int32 nAEnd = 0; 3566 //aARHelper.getPosition( nARIndex, nAStt, nAEnd ); 3567 xRet = new SwAccessibleAutoRecognizer( this, nAStt, nAEnd ); 3568 if( aIter != pAutoRecognizerData->end() ) 3569 { 3570 (*aIter).second = xRet; 3571 } 3572 else 3573 { 3574 SwAccessibleAutoRecognizerData::value_type aEntry( nARIndex, xRet ); 3575 pAutoRecognizerData->insert( aEntry ); 3576 } 3577 } 3578 */ 3579 } 3580 break; 3581 } 3582 3583 // iterate next 3584 if( bH ) 3585 // iterate next hyperlink 3586 pHt = (SwTxtAttr*)(aHIter.next()); 3587 else if( bA ) 3588 // iterate next smart tag 3589 nARIndex++; 3590 else if(bTOC) 3591 continue; 3592 else 3593 // no candidate, exit 3594 break; 3595 } 3596 /* 3597 const SwTxtFrm *pTxtFrm = static_cast<const SwTxtFrm*>( GetFrm() ); 3598 SwHyperlinkIter_Impl aHIter( pTxtFrm ); 3599 while( nLinkIndex-- ) 3600 aHIter.next(); 3601 3602 const SwTxtAttr *pHt = aHIter.next(); 3603 if( pHt ) 3604 { 3605 if( !pHyperTextData ) 3606 pHyperTextData = new SwAccessibleHyperTextData; 3607 SwAccessibleHyperTextData::iterator aIter = 3608 pHyperTextData ->find( pHt ); 3609 if( aIter != pHyperTextData->end() ) 3610 { 3611 xRet = (*aIter).second; 3612 } 3613 if( !xRet.is() ) 3614 { 3615 sal_Int32 nHStt= GetPortionData().GetAccessiblePosition( 3616 max( aHIter.startIdx(), *pHt->GetStart() ) ); 3617 sal_Int32 nHEnd= GetPortionData().GetAccessiblePosition( 3618 min( aHIter.endIdx(), *pHt->GetAnyEnd() ) ); 3619 xRet = new SwAccessibleHyperlink( aHIter.getCurrHintPos(), 3620 this, nHStt, nHEnd ); 3621 if( aIter != pHyperTextData->end() ) 3622 { 3623 (*aIter).second = xRet; 3624 } 3625 else 3626 { 3627 SwAccessibleHyperTextData::value_type aEntry( pHt, xRet ); 3628 pHyperTextData->insert( aEntry ); 3629 } 3630 } 3631 } 3632 } 3633 */ 3634 if( !xRet.is() ) 3635 throw lang::IndexOutOfBoundsException(); 3636 3637 return xRet; 3638 } 3639 3640 sal_Int32 SAL_CALL SwAccessibleParagraph::getHyperLinkIndex( sal_Int32 nCharIndex ) 3641 throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 3642 { 3643 vos::OGuard aGuard(Application::GetSolarMutex()); 3644 CHECK_FOR_DEFUNC( XAccessibleHypertext ); 3645 3646 // parameter checking 3647 sal_Int32 nLength = GetString().getLength(); 3648 if ( ! IsValidPosition( nCharIndex, nLength ) ) 3649 { 3650 throw lang::IndexOutOfBoundsException(); 3651 } 3652 3653 sal_Int32 nRet = -1; 3654 // --> OD 2007-06-27 #i77108# - provide hyperlinks also in editable documents. 3655 // if( !IsEditableState() ) 3656 // <-- 3657 { 3658 const SwTxtFrm *pTxtFrm = static_cast<const SwTxtFrm*>( GetFrm() ); 3659 SwHyperlinkIter_Impl aHIter( pTxtFrm ); 3660 3661 xub_StrLen nIdx = GetPortionData().GetModelPosition( nCharIndex ); 3662 sal_Int32 nPos = 0; 3663 const SwTxtAttr *pHt = aHIter.next(); 3664 while( pHt && !(nIdx >= *pHt->GetStart() && nIdx < *pHt->GetAnyEnd()) ) 3665 { 3666 pHt = aHIter.next(); 3667 nPos++; 3668 } 3669 3670 if( pHt ) 3671 nRet = nPos; 3672 } 3673 /* Added by yanjun for acc miagration 3674 if( nRet == -1 && GetTOXSortTabBase() ) 3675 { 3676 SwTxtNode* pNode = const_cast<SwTxtNode*>(GetTxtNode()); 3677 if( nCharIndex >= 0 && nCharIndex < pNode->GetTOCFirstWordEndIndex()) 3678 nRet = 0; 3679 } 3680 */ 3681 3682 if (nRet == -1) 3683 throw lang::IndexOutOfBoundsException(); 3684 else 3685 return nRet; 3686 //return nRet; 3687 } 3688 3689 // --> OD 2008-05-26 #i71360# 3690 // --> OD 2010-02-22 #i108125# - adjustments for change tracking text markup 3691 sal_Int32 SAL_CALL SwAccessibleParagraph::getTextMarkupCount( sal_Int32 nTextMarkupType ) 3692 throw (lang::IllegalArgumentException, 3693 uno::RuntimeException) 3694 { 3695 std::auto_ptr<SwTextMarkupHelper> pTextMarkupHelper; 3696 switch ( nTextMarkupType ) 3697 { 3698 case text::TextMarkupType::TRACK_CHANGE_INSERTION: 3699 case text::TextMarkupType::TRACK_CHANGE_DELETION: 3700 case text::TextMarkupType::TRACK_CHANGE_FORMATCHANGE: 3701 { 3702 pTextMarkupHelper.reset( new SwTextMarkupHelper( 3703 GetPortionData(), 3704 *(mpParaChangeTrackInfo->getChangeTrackingTextMarkupList( nTextMarkupType ) )) ); 3705 } 3706 break; 3707 default: 3708 { 3709 pTextMarkupHelper.reset( new SwTextMarkupHelper( GetPortionData(), *GetTxtNode() ) ); 3710 } 3711 } 3712 3713 return pTextMarkupHelper->getTextMarkupCount( nTextMarkupType ); 3714 } 3715 //MSAA Extension Implementation in app module 3716 sal_Bool SAL_CALL SwAccessibleParagraph::scrollToPosition( const ::com::sun::star::awt::Point&, sal_Bool ) 3717 throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) 3718 { 3719 return sal_False; 3720 } 3721 3722 sal_Int32 SAL_CALL SwAccessibleParagraph::getSelectedPortionCount( ) 3723 throw (::com::sun::star::uno::RuntimeException) 3724 { 3725 sal_Int32 nSeleted = 0; 3726 SwPaM* pCrsr = GetCursor( true ); 3727 if( pCrsr != NULL ) 3728 { 3729 // get SwPosition for my node 3730 const SwTxtNode* pNode = GetTxtNode(); 3731 sal_uLong nHere = pNode->GetIndex(); 3732 3733 // iterate over ring 3734 SwPaM* pRingStart = pCrsr; 3735 do 3736 { 3737 // ignore, if no mark 3738 if( pCrsr->HasMark() ) 3739 { 3740 // check whether nHere is 'inside' pCrsr 3741 SwPosition* pStart = pCrsr->Start(); 3742 sal_uLong nStartIndex = pStart->nNode.GetIndex(); 3743 SwPosition* pEnd = pCrsr->End(); 3744 sal_uLong nEndIndex = pEnd->nNode.GetIndex(); 3745 if( ( nHere >= nStartIndex ) && 3746 ( nHere <= nEndIndex ) ) 3747 { 3748 nSeleted++; 3749 } 3750 // else: this PaM doesn't point to this paragraph 3751 } 3752 // else: this PaM is collapsed and doesn't select anything 3753 3754 // next PaM in ring 3755 pCrsr = static_cast<SwPaM*>( pCrsr->GetNext() ); 3756 } 3757 while( pCrsr != pRingStart ); 3758 } 3759 return nSeleted; 3760 3761 } 3762 3763 sal_Int32 SAL_CALL SwAccessibleParagraph::getSeletedPositionStart( sal_Int32 nSelectedPortionIndex ) 3764 throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException) 3765 { 3766 vos::OGuard aGuard(Application::GetSolarMutex()); 3767 3768 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); 3769 3770 sal_Int32 nStart, nEnd; 3771 /*sal_Bool bSelected = */GetSelectionAtIndex(nSelectedPortionIndex, nStart, nEnd ); 3772 return nStart; 3773 } 3774 3775 sal_Int32 SAL_CALL SwAccessibleParagraph::getSeletedPositionEnd( sal_Int32 nSelectedPortionIndex ) 3776 throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException) 3777 { 3778 vos::OGuard aGuard(Application::GetSolarMutex()); 3779 3780 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); 3781 3782 sal_Int32 nStart, nEnd; 3783 /*sal_Bool bSelected = */GetSelectionAtIndex(nSelectedPortionIndex, nStart, nEnd ); 3784 return nEnd; 3785 } 3786 3787 sal_Bool SAL_CALL SwAccessibleParagraph::removeSelection( sal_Int32 selectionIndex ) 3788 throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException) 3789 { 3790 if(selectionIndex < 0) return sal_False; 3791 3792 sal_Bool bRet = sal_False; 3793 sal_Int32 nSelected = selectionIndex; 3794 3795 // get the selection, and test whether it affects our text node 3796 SwPaM* pCrsr = GetCursor( true ); 3797 // SwPaM* pFirst = pCrsr; 3798 SwPaM* pPrev = pCrsr; 3799 3800 if( pCrsr != NULL ) 3801 { 3802 // get SwPosition for my node 3803 const SwTxtNode* pNode = GetTxtNode(); 3804 sal_uLong nHere = pNode->GetIndex(); 3805 3806 // iterate over ring 3807 SwPaM* pRingStart = pCrsr; 3808 do 3809 { 3810 // ignore, if no mark 3811 if( pCrsr->HasMark() ) 3812 { 3813 // check whether nHere is 'inside' pCrsr 3814 SwPosition* pStart = pCrsr->Start(); 3815 sal_uLong nStartIndex = pStart->nNode.GetIndex(); 3816 SwPosition* pEnd = pCrsr->End(); 3817 sal_uLong nEndIndex = pEnd->nNode.GetIndex(); 3818 if( ( nHere >= nStartIndex ) && 3819 ( nHere <= nEndIndex ) ) 3820 { 3821 if( nSelected == 0 ) 3822 { 3823 pCrsr->MoveTo((Ring*)0); 3824 delete pCrsr; 3825 bRet = sal_True; 3826 } 3827 else 3828 { 3829 nSelected--; 3830 } 3831 } 3832 } 3833 // else: this PaM is collapsed and doesn't select anything 3834 pPrev = pCrsr; 3835 pCrsr = static_cast<SwPaM*>( pCrsr->GetNext() ); 3836 } 3837 while( !bRet && (pCrsr != pRingStart) ); 3838 } 3839 return sal_True; 3840 } 3841 3842 sal_Int32 SAL_CALL SwAccessibleParagraph::addSelection( sal_Int32, sal_Int32 startOffset, sal_Int32 endOffset) 3843 throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException) 3844 { 3845 vos::OGuard aGuard(Application::GetSolarMutex()); 3846 3847 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); 3848 3849 // parameter checking 3850 sal_Int32 nLength = GetString().getLength(); 3851 if ( ! IsValidRange( startOffset, endOffset, nLength ) ) 3852 { 3853 throw lang::IndexOutOfBoundsException(); 3854 } 3855 3856 sal_Int32 nSelectedCount = getSelectedPortionCount(); 3857 for ( sal_Int32 i = nSelectedCount ; i >= 0 ; i--) 3858 { 3859 sal_Int32 nStart, nEnd; 3860 sal_Bool bSelected = GetSelectionAtIndex(i, nStart, nEnd ); 3861 if(bSelected) 3862 { 3863 if(nStart <= nEnd ) 3864 { 3865 if (( startOffset>=nStart && startOffset <=nEnd ) || //startOffset in a selection 3866 ( endOffset>=nStart && endOffset <=nEnd ) || //endOffset in a selection 3867 ( startOffset <= nStart && endOffset >=nEnd) || //start and end include the old selection 3868 ( startOffset >= nStart && endOffset <=nEnd) ) 3869 { 3870 removeSelection(i); 3871 } 3872 3873 } 3874 else 3875 { 3876 if (( startOffset>=nEnd && startOffset <=nStart ) || //startOffset in a selection 3877 ( endOffset>=nEnd && endOffset <=nStart ) || //endOffset in a selection 3878 ( startOffset <= nStart && endOffset >=nEnd) || //start and end include the old selection 3879 ( startOffset >= nStart && endOffset <=nEnd) ) 3880 3881 { 3882 removeSelection(i); 3883 } 3884 } 3885 } 3886 3887 } 3888 3889 sal_Bool bRet = sal_False; 3890 3891 // get cursor shell 3892 SwCrsrShell* pCrsrShell = GetCrsrShell(); 3893 if( pCrsrShell != NULL ) 3894 { 3895 // create pam for selection 3896 pCrsrShell->StartAction(); 3897 // SwTxtNode* pNode = const_cast<SwTxtNode*>( GetTxtNode() ); 3898 SwPaM* aPaM = pCrsrShell->CreateCrsr(); 3899 aPaM->SetMark(); 3900 aPaM->GetPoint()->nContent = GetPortionData().GetModelPosition(startOffset); 3901 aPaM->GetMark()->nContent = GetPortionData().GetModelPosition(endOffset); 3902 //pCrsrShell->ShowCrsr(); 3903 pCrsrShell->EndAction(); 3904 // set PaM at cursor shell 3905 //bRet = Select( aPaM ); 3906 } 3907 3908 return bRet; 3909 } 3910 3911 /*accessibility::*/TextSegment SAL_CALL 3912 SwAccessibleParagraph::getTextMarkup( sal_Int32 nTextMarkupIndex, 3913 sal_Int32 nTextMarkupType ) 3914 throw (lang::IndexOutOfBoundsException, 3915 lang::IllegalArgumentException, 3916 uno::RuntimeException) 3917 { 3918 std::auto_ptr<SwTextMarkupHelper> pTextMarkupHelper; 3919 switch ( nTextMarkupType ) 3920 { 3921 case text::TextMarkupType::TRACK_CHANGE_INSERTION: 3922 case text::TextMarkupType::TRACK_CHANGE_DELETION: 3923 case text::TextMarkupType::TRACK_CHANGE_FORMATCHANGE: 3924 { 3925 pTextMarkupHelper.reset( new SwTextMarkupHelper( 3926 GetPortionData(), 3927 *(mpParaChangeTrackInfo->getChangeTrackingTextMarkupList( nTextMarkupType ) )) ); 3928 } 3929 break; 3930 default: 3931 { 3932 pTextMarkupHelper.reset( new SwTextMarkupHelper( GetPortionData(), *GetTxtNode() ) ); 3933 } 3934 } 3935 3936 return pTextMarkupHelper->getTextMarkup( nTextMarkupIndex, nTextMarkupType ); 3937 } 3938 3939 uno::Sequence< /*accessibility::*/TextSegment > SAL_CALL 3940 SwAccessibleParagraph::getTextMarkupAtIndex( sal_Int32 nCharIndex, 3941 sal_Int32 nTextMarkupType ) 3942 throw (lang::IndexOutOfBoundsException, 3943 lang::IllegalArgumentException, 3944 uno::RuntimeException) 3945 { 3946 // parameter checking 3947 const sal_Int32 nLength = GetString().getLength(); 3948 if ( ! IsValidPosition( nCharIndex, nLength ) ) 3949 { 3950 throw lang::IndexOutOfBoundsException(); 3951 } 3952 3953 std::auto_ptr<SwTextMarkupHelper> pTextMarkupHelper; 3954 switch ( nTextMarkupType ) 3955 { 3956 case text::TextMarkupType::TRACK_CHANGE_INSERTION: 3957 case text::TextMarkupType::TRACK_CHANGE_DELETION: 3958 case text::TextMarkupType::TRACK_CHANGE_FORMATCHANGE: 3959 { 3960 pTextMarkupHelper.reset( new SwTextMarkupHelper( 3961 GetPortionData(), 3962 *(mpParaChangeTrackInfo->getChangeTrackingTextMarkupList( nTextMarkupType ) )) ); 3963 } 3964 break; 3965 default: 3966 { 3967 pTextMarkupHelper.reset( new SwTextMarkupHelper( GetPortionData(), *GetTxtNode() ) ); 3968 } 3969 } 3970 3971 return pTextMarkupHelper->getTextMarkupAtIndex( nCharIndex, nTextMarkupType ); 3972 } 3973 // <-- 3974 3975 // --> OD 2008-05-29 #i89175# 3976 sal_Int32 SAL_CALL SwAccessibleParagraph::getLineNumberAtIndex( sal_Int32 nIndex ) 3977 throw (lang::IndexOutOfBoundsException, 3978 uno::RuntimeException) 3979 { 3980 // parameter checking 3981 const sal_Int32 nLength = GetString().getLength(); 3982 if ( ! IsValidPosition( nIndex, nLength ) ) 3983 { 3984 throw lang::IndexOutOfBoundsException(); 3985 } 3986 3987 const sal_Int32 nLineNo = GetPortionData().GetLineNo( nIndex ); 3988 return nLineNo; 3989 } 3990 3991 /*accessibility::*/TextSegment SAL_CALL 3992 SwAccessibleParagraph::getTextAtLineNumber( sal_Int32 nLineNo ) 3993 throw (lang::IndexOutOfBoundsException, 3994 uno::RuntimeException) 3995 { 3996 // parameter checking 3997 if ( nLineNo < 0 || 3998 nLineNo >= GetPortionData().GetLineCount() ) 3999 { 4000 throw lang::IndexOutOfBoundsException(); 4001 } 4002 4003 i18n::Boundary aLineBound; 4004 GetPortionData().GetBoundaryOfLine( nLineNo, aLineBound ); 4005 4006 /*accessibility::*/TextSegment aTextAtLine; 4007 const ::rtl::OUString rText = GetString(); 4008 aTextAtLine.SegmentText = rText.copy( aLineBound.startPos, 4009 aLineBound.endPos - aLineBound.startPos ); 4010 aTextAtLine.SegmentStart = aLineBound.startPos; 4011 aTextAtLine.SegmentEnd = aLineBound.endPos; 4012 4013 return aTextAtLine; 4014 } 4015 4016 /*accessibility::*/TextSegment SAL_CALL SwAccessibleParagraph::getTextAtLineWithCaret() 4017 throw (uno::RuntimeException) 4018 { 4019 const sal_Int32 nLineNoOfCaret = getNumberOfLineWithCaret(); 4020 4021 if ( nLineNoOfCaret >= 0 && 4022 nLineNoOfCaret < GetPortionData().GetLineCount() ) 4023 { 4024 return getTextAtLineNumber( nLineNoOfCaret ); 4025 } 4026 4027 return /*accessibility::*/TextSegment(); 4028 } 4029 4030 sal_Int32 SAL_CALL SwAccessibleParagraph::getNumberOfLineWithCaret() 4031 throw (uno::RuntimeException) 4032 { 4033 const sal_Int32 nCaretPos = getCaretPosition(); 4034 const sal_Int32 nLength = GetString().getLength(); 4035 if ( !IsValidPosition( nCaretPos, nLength ) ) 4036 { 4037 return -1; 4038 } 4039 4040 sal_Int32 nLineNo = GetPortionData().GetLineNo( nCaretPos ); 4041 4042 // special handling for cursor positioned at end of text line via End key 4043 if ( nCaretPos != 0 ) 4044 { 4045 i18n::Boundary aLineBound; 4046 GetPortionData().GetBoundaryOfLine( nLineNo, aLineBound ); 4047 if ( nCaretPos == aLineBound.startPos ) 4048 { 4049 SwCrsrShell* pCrsrShell = SwAccessibleParagraph::GetCrsrShell(); 4050 if ( pCrsrShell != 0 ) 4051 { 4052 const awt::Rectangle aCharRect = getCharacterBounds( nCaretPos ); 4053 4054 const SwRect& aCursorCoreRect = pCrsrShell->GetCharRect(); 4055 // translate core coordinates into accessibility coordinates 4056 Window *pWin = GetWindow(); 4057 CHECK_FOR_WINDOW( XAccessibleComponent, pWin ); 4058 4059 Rectangle aScreenRect( GetMap()->CoreToPixel( aCursorCoreRect.SVRect() )); 4060 4061 SwRect aFrmLogBounds( GetBounds( *(GetMap()) ) ); // twip rel to doc root 4062 Point aFrmPixPos( GetMap()->CoreToPixel( aFrmLogBounds.SVRect() ).TopLeft() ); 4063 aScreenRect.Move( -aFrmPixPos.X(), -aFrmPixPos.Y() ); 4064 4065 // convert into AWT Rectangle 4066 const awt::Rectangle aCursorRect( aScreenRect.Left(), 4067 aScreenRect.Top(), 4068 aScreenRect.GetWidth(), 4069 aScreenRect.GetHeight() ); 4070 4071 if ( aCharRect.X != aCursorRect.X || 4072 aCharRect.Y != aCursorRect.Y ) 4073 { 4074 --nLineNo; 4075 } 4076 } 4077 } 4078 } 4079 4080 return nLineNo; 4081 } 4082 4083 // --> OD 2010-02-19 #i108125# 4084 void SwAccessibleParagraph::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew ) 4085 { 4086 mpParaChangeTrackInfo->reset(); 4087 4088 CheckRegistration( pOld, pNew ); 4089 } 4090 // <-- 4091 4092 sal_Bool SwAccessibleParagraph::GetSelectionAtIndex( 4093 sal_Int32& nIndex, sal_Int32& nStart, sal_Int32& nEnd) 4094 { 4095 if(nIndex < 0) return sal_False; 4096 4097 4098 sal_Bool bRet = sal_False; 4099 nStart = -1; 4100 nEnd = -1; 4101 sal_Int32 nSelected = nIndex; 4102 4103 // get the selection, and test whether it affects our text node 4104 SwPaM* pCrsr = GetCursor( true ); 4105 if( pCrsr != NULL ) 4106 { 4107 // get SwPosition for my node 4108 const SwTxtNode* pNode = GetTxtNode(); 4109 sal_uLong nHere = pNode->GetIndex(); 4110 4111 // iterate over ring 4112 SwPaM* pRingStart = pCrsr; 4113 do 4114 { 4115 // ignore, if no mark 4116 if( pCrsr->HasMark() ) 4117 { 4118 // check whether nHere is 'inside' pCrsr 4119 SwPosition* pStart = pCrsr->Start(); 4120 sal_uLong nStartIndex = pStart->nNode.GetIndex(); 4121 SwPosition* pEnd = pCrsr->End(); 4122 sal_uLong nEndIndex = pEnd->nNode.GetIndex(); 4123 if( ( nHere >= nStartIndex ) && 4124 ( nHere <= nEndIndex ) ) 4125 { 4126 if( nSelected == 0 ) 4127 { 4128 // translate start and end positions 4129 4130 // start position 4131 sal_Int32 nLocalStart = -1; 4132 if( nHere > nStartIndex ) 4133 { 4134 // selection starts in previous node: 4135 // then our local selection starts with the paragraph 4136 nLocalStart = 0; 4137 } 4138 else 4139 { 4140 DBG_ASSERT( nHere == nStartIndex, 4141 "miscalculated index" ); 4142 4143 // selection starts in this node: 4144 // then check whether it's before or inside our part of 4145 // the paragraph, and if so, get the proper position 4146 sal_uInt16 nCoreStart = pStart->nContent.GetIndex(); 4147 if( nCoreStart < 4148 GetPortionData().GetFirstValidCorePosition() ) 4149 { 4150 nLocalStart = 0; 4151 } 4152 else if( nCoreStart <= 4153 GetPortionData().GetLastValidCorePosition() ) 4154 { 4155 DBG_ASSERT( 4156 GetPortionData().IsValidCorePosition( 4157 nCoreStart ), 4158 "problem determining valid core position" ); 4159 4160 nLocalStart = 4161 GetPortionData().GetAccessiblePosition( 4162 nCoreStart ); 4163 } 4164 } 4165 4166 // end position 4167 sal_Int32 nLocalEnd = -1; 4168 if( nHere < nEndIndex ) 4169 { 4170 // selection ends in following node: 4171 // then our local selection extends to the end 4172 nLocalEnd = GetPortionData().GetAccessibleString(). 4173 getLength(); 4174 } 4175 else 4176 { 4177 DBG_ASSERT( nHere == nStartIndex, 4178 "miscalculated index" ); 4179 4180 // selection ends in this node: then select everything 4181 // before our part of the node 4182 sal_uInt16 nCoreEnd = pEnd->nContent.GetIndex(); 4183 if( nCoreEnd > 4184 GetPortionData().GetLastValidCorePosition() ) 4185 { 4186 // selection extends beyond out part of this para 4187 nLocalEnd = GetPortionData().GetAccessibleString(). 4188 getLength(); 4189 } 4190 else if( nCoreEnd >= 4191 GetPortionData().GetFirstValidCorePosition() ) 4192 { 4193 // selection is inside our part of this para 4194 DBG_ASSERT( 4195 GetPortionData().IsValidCorePosition( 4196 nCoreEnd ), 4197 "problem determining valid core position" ); 4198 4199 nLocalEnd = GetPortionData().GetAccessiblePosition( 4200 nCoreEnd ); 4201 } 4202 } 4203 4204 if( ( nLocalStart != -1 ) && ( nLocalEnd != -1 ) ) 4205 { 4206 nStart = nLocalStart; 4207 nEnd = nLocalEnd; 4208 bRet = sal_True; 4209 } 4210 } // if hit the index 4211 else 4212 { 4213 nSelected--; 4214 } 4215 } 4216 // else: this PaM doesn't point to this paragraph 4217 } 4218 // else: this PaM is collapsed and doesn't select anything 4219 4220 // next PaM in ring 4221 pCrsr = static_cast<SwPaM*>( pCrsr->GetNext() ); 4222 } 4223 while( !bRet && (pCrsr != pRingStart) ); 4224 } 4225 // else: nocursor -> no selection 4226 4227 if( bRet ) 4228 { 4229 sal_Int32 nCaretPos = GetCaretPos(); 4230 if( nStart == nCaretPos ) 4231 { 4232 sal_Int32 tmp = nStart; 4233 nStart = nEnd; 4234 nEnd = tmp; 4235 } 4236 } 4237 return bRet; 4238 } 4239 4240 sal_Int16 SAL_CALL SwAccessibleParagraph::getAccessibleRole (void) throw (::com::sun::star::uno::RuntimeException) 4241 { 4242 //Get the real heading level, Heading1 ~ Heading10 4243 if (nHeadingLevel > 0) 4244 { 4245 return AccessibleRole::HEADING; 4246 } 4247 else 4248 { 4249 return AccessibleRole::PARAGRAPH; 4250 } 4251 } 4252 4253 // End Add 4254 4255 4256 /* This funcion is already defined in accpara.cxx(Added by yanjun) 4257 sal_Int32 SAL_CALL SwAccessibleParagraph::getBackground() 4258 throw (::com::sun::star::uno::RuntimeException) 4259 { 4260 // Test Code 4261 // Sequence<OUString> seNames(1); 4262 // OUString* pStrings = seNames.getArray(); 4263 // pStrings[0] = OUString(RTL_CONSTASCII_USTRINGPARAM("ParaBackColor")); 4264 // 4265 // Sequence<Any> aAnys(1); 4266 // Reference<XMultiPropertySet> xPortion = CreateUnoPortion( 0, 0 ); 4267 // aAnys = xPortion->getPropertyValues( seNames ); 4268 // const Any* pAnys = aAnys.getConstArray(); 4269 // 4270 // sal_uInt32 crColorT=0; 4271 // pAnys[0] >>= crColorT; 4272 // End Test Code 4273 4274 const SvxBrushItem &rBack = GetFrm()->GetAttrSet()->GetBackground(); 4275 sal_uInt32 crBack = rBack.GetColor().GetColor(); 4276 4277 if (COL_AUTO == crBack) 4278 { 4279 Reference<XAccessible> xAccDoc = getAccessibleParent(); 4280 if (xAccDoc.is()) 4281 { 4282 Reference<XAccessibleComponent> xCompoentDoc(xAccDoc,UNO_QUERY); 4283 if (xCompoentDoc.is()) 4284 { 4285 crBack = (sal_uInt32)xCompoentDoc->getBackground(); 4286 } 4287 } 4288 } 4289 return crBack; 4290 } 4291 */ 4292 4293 //Get the real heading level, Heading1 ~ Heading10 4294 sal_Int32 SwAccessibleParagraph::GetRealHeadingLevel() 4295 { 4296 uno::Reference< ::com::sun::star::beans::XPropertySet > xPortion = CreateUnoPortion( 0, 0 ); 4297 ::rtl::OUString pString = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ParaStyleName")); 4298 uno::Any styleAny = xPortion->getPropertyValue( pString ); 4299 ::rtl::OUString sValue; 4300 if (styleAny >>= sValue) 4301 { 4302 //Modified by yanjun for acc migration 4303 sal_Int32 length = sValue.getLength/*GetCharCount*/(); 4304 if (length == 9 || length == 10) 4305 { 4306 ::rtl::OUString headStr = sValue.copy(0, 7); 4307 if (headStr.equals(::rtl::OUString::createFromAscii("Heading"))) 4308 { 4309 ::rtl::OUString intStr = sValue.copy(8); 4310 sal_Int32 headingLevel = intStr.toInt32(10); 4311 return headingLevel; 4312 } 4313 } 4314 } 4315 return -1; 4316 } 4317 4318 uno::Any SAL_CALL SwAccessibleParagraph::getExtendedAttributes() 4319 throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException) 4320 { 4321 uno::Any Ret; 4322 ::rtl::OUString strHeading(::rtl::OUString::createFromAscii("heading-level:")); 4323 if( nHeadingLevel >= 0 ) 4324 strHeading += OUString::valueOf(nHeadingLevel, 10); 4325 strHeading += OUString::createFromAscii(";"); 4326 4327 Ret <<= strHeading; 4328 4329 return Ret; 4330 } 4331 4332 //Tab will be return when call WORDTYPE 4333 sal_Bool SwAccessibleParagraph::tabCharInWord( sal_Int32 nIndex, i18n::Boundary& aBound) 4334 { 4335 sal_Bool bFind = sal_False; 4336 if( aBound.startPos != nIndex) 4337 { 4338 OUString tabStr; 4339 if(aBound.startPos>nIndex) 4340 tabStr = GetString().copy(nIndex,(aBound.startPos - nIndex) ); 4341 4342 sal_Unicode tabChar('\t'); 4343 sal_Int32 tabIndex = tabStr.indexOf(tabChar); 4344 if( tabIndex > -1 ) 4345 { 4346 aBound.startPos = nIndex + tabIndex ; 4347 aBound.endPos = aBound.startPos + 1; 4348 bFind = sal_True; 4349 } 4350 } 4351 return bFind; 4352 } 4353