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