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