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