1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: accpara.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
37 #include <crstate.hxx>
40 #include <viewopt.hxx>
41 #include <vos/mutex.hxx>
42 #include <vcl/svapp.hxx>
43 #include <vcl/window.hxx>
44 #include <rtl/ustrbuf.hxx>
45 #include <com/sun/star/accessibility/AccessibleRole.hpp>
46 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
47 #include <com/sun/star/accessibility/AccessibleTextType.hpp>
48 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
49 #include <unotools/accessiblestatesethelper.hxx>
50 #include <com/sun/star/i18n/CharacterIteratorMode.hpp>
51 #include <com/sun/star/i18n/WordType.hpp>
52 #include <com/sun/star/i18n/XBreakIterator.hpp>
53 #include <com/sun/star/beans/UnknownPropertyException.hpp>
54 #include <breakit.hxx>
55 #include "accpara.hxx"
59 #include "accportions.hxx"
60 #include <sfx2/viewsh.hxx> // for ExecuteAtViewShell(...)
61 #include <sfx2/viewfrm.hxx> // for ExecuteAtViewShell(...)
62 #include <sfx2/dispatch.hxx> // for ExecuteAtViewShell(...)
63 #include <unotools/charclass.hxx> // for GetWordBoundary
64 // for get/setCharacterAttribute(...)
65 #include "unocrsr.hxx"
67 #include "unoport.hxx"
69 #include "crsskip.hxx"
71 #include <acchyperlink.hxx>
72 #include <acchypertextdata.hxx>
73 // --> OD 2005-12-02 #i27138#
74 #include <unotools/accessiblerelationsethelper.hxx>
75 #include <com/sun/star/accessibility/AccessibleRelationType.hpp>
77 #include <comphelper/accessibletexthelper.hxx>
78 // --> OD 2006-07-12 #i63870#
81 // --> OD 2007-01-15 #i72800#
82 #include <unoprnms.hxx>
84 // --> OD 2007-01-15 #i73371#
85 #include <com/sun/star/text/WritingMode2.hpp>
87 // --> OD 2007-01-17 #i71385#
88 #include <svx/brshitem.hxx>
89 #include <viewimp.hxx>
91 // --> OD 2007-11-12 #i82637#
92 #include <boost/scoped_ptr.hpp>
94 // --> OD 2008-05-26 #i71360#
95 #include <textmarkuphelper.hxx>
100 using namespace ::com::sun::star
;
101 using namespace ::com::sun::star::i18n
;
102 using namespace ::com::sun::star::lang
;
103 using namespace ::com::sun::star::uno
;
104 using namespace ::com::sun::star::accessibility
;
105 using ::rtl::OUString
;
107 using beans::PropertyValue
;
108 using beans::XMultiPropertySet
;
109 using beans::UnknownPropertyException
;
110 using beans::PropertyState_DIRECT_VALUE
;
116 namespace com
{ namespace sun
{ namespace star
{
123 const sal_Char sServiceName
[] = "com.sun.star.text.AccessibleParagraphView";
124 const sal_Char sImplementationName
[] = "com.sun.star.comp.Writer.SwAccessibleParagraphView";
125 const xub_StrLen MAX_DESC_TEXT_LEN
= 40;
126 const SwTxtNode
* SwAccessibleParagraph::GetTxtNode() const
128 const SwFrm
* pFrm
= GetFrm();
129 DBG_ASSERT( pFrm
->IsTxtFrm(), "The text frame has mutated!" );
131 const SwTxtNode
* pNode
= static_cast<const SwTxtFrm
*>(pFrm
)->GetTxtNode();
132 DBG_ASSERT( pNode
!= NULL
, "A text frame without a text node." );
137 OUString
SwAccessibleParagraph::GetString()
139 return GetPortionData().GetAccessibleString();
142 OUString
SwAccessibleParagraph::GetDescription()
144 // --> OD 2004-09-29 #117933# - provide empty description for paragraphs
149 sal_Int32
SwAccessibleParagraph::GetCaretPos()
153 // get the selection's point, and test whether it's in our node
154 // --> OD 2005-12-20 #i27301# - consider adjusted method signature
155 SwPaM
* pCaret
= GetCursor( false ); // caret is first PaM in PaM-ring
159 const SwTxtNode
* pNode
= GetTxtNode();
161 // check whether the point points into 'our' node
162 SwPosition
* pPoint
= pCaret
->GetPoint();
163 if( pNode
->GetIndex() == pPoint
->nNode
.GetIndex() )
165 // same node? Then check whether it's also within 'our' part
167 USHORT nIndex
= pPoint
->nContent
.GetIndex();
168 if( GetPortionData().IsValidCorePosition( nIndex
) )
171 // --> OD 2006-10-19 #70538#
172 // consider that cursor/caret is in front of the list label
173 if ( pCaret
->IsInFrontOfLabel() )
179 nRet
= GetPortionData().GetAccessiblePosition( nIndex
);
183 DBG_ASSERT( nRet
>= 0, "invalid cursor?" );
184 DBG_ASSERT( nRet
<= GetPortionData().GetAccessibleString().
185 getLength(), "invalid cursor?" );
187 // else: in this paragraph, but in different frame
189 // else: not in this paragraph
191 // else: no cursor -> no caret
196 sal_Bool
SwAccessibleParagraph::GetSelection(
197 sal_Int32
& nStart
, sal_Int32
& nEnd
)
199 sal_Bool bRet
= sal_False
;
203 // get the selection, and test whether it affects our text node
204 // --> OD 2005-12-20 #i27301# - consider adjusted method signature
205 SwPaM
* pCrsr
= GetCursor( true );
209 // get SwPosition for my node
210 const SwTxtNode
* pNode
= GetTxtNode();
211 ULONG nHere
= pNode
->GetIndex();
214 SwPaM
* pRingStart
= pCrsr
;
217 // ignore, if no mark
218 if( pCrsr
->HasMark() )
220 // check whether nHere is 'inside' pCrsr
221 SwPosition
* pStart
= pCrsr
->Start();
222 ULONG nStartIndex
= pStart
->nNode
.GetIndex();
223 SwPosition
* pEnd
= pCrsr
->End();
224 ULONG nEndIndex
= pEnd
->nNode
.GetIndex();
225 if( ( nHere
>= nStartIndex
) &&
226 ( nHere
<= nEndIndex
) )
228 // translate start and end positions
231 sal_Int32 nLocalStart
= -1;
232 if( nHere
> nStartIndex
)
234 // selection starts in previous node:
235 // then our local selection starts with the paragraph
240 DBG_ASSERT( nHere
== nStartIndex
,
241 "miscalculated index" );
243 // selection starts in this node:
244 // then check whether it's before or inside our part of
245 // the paragraph, and if so, get the proper position
246 USHORT nCoreStart
= pStart
->nContent
.GetIndex();
248 GetPortionData().GetFirstValidCorePosition() )
252 else if( nCoreStart
<=
253 GetPortionData().GetLastValidCorePosition() )
256 GetPortionData().IsValidCorePosition(
258 "problem determining valid core position" );
261 GetPortionData().GetAccessiblePosition(
267 sal_Int32 nLocalEnd
= -1;
268 if( nHere
< nEndIndex
)
270 // selection ends in following node:
271 // then our local selection extends to the end
272 nLocalEnd
= GetPortionData().GetAccessibleString().
277 DBG_ASSERT( nHere
== nEndIndex
,
278 "miscalculated index" );
280 // selection ends in this node: then select everything
281 // before our part of the node
282 USHORT nCoreEnd
= pEnd
->nContent
.GetIndex();
284 GetPortionData().GetLastValidCorePosition() )
286 // selection extends beyond out part of this para
287 nLocalEnd
= GetPortionData().GetAccessibleString().
291 GetPortionData().GetFirstValidCorePosition() )
293 // selection is inside our part of this para
295 GetPortionData().IsValidCorePosition(
297 "problem determining valid core position" );
299 nLocalEnd
= GetPortionData().GetAccessiblePosition(
304 if( ( nLocalStart
!= -1 ) && ( nLocalEnd
!= -1 ) )
306 nStart
= nLocalStart
;
311 // else: this PaM doesn't point to this paragraph
313 // else: this PaM is collapsed and doesn't select anything
316 pCrsr
= static_cast<SwPaM
*>( pCrsr
->GetNext() );
318 while( !bRet
&& (pCrsr
!= pRingStart
) );
320 // else: nocursor -> no selection
325 // --> OD 2005-12-20 #i27301# - new parameter <_bForSelection>
326 SwPaM
* SwAccessibleParagraph::GetCursor( const bool _bForSelection
)
328 // get the cursor shell; if we don't have any, we don't have a
329 // cursor/selection either
331 SwCrsrShell
* pCrsrShell
= SwAccessibleParagraph::GetCrsrShell();
332 // --> OD 2005-12-20 #i27301#
333 // - if cursor is retrieved for selection, the cursors for a table selection
334 // has to be returned.
335 if ( pCrsrShell
!= NULL
&&
336 ( _bForSelection
|| !pCrsrShell
->IsTableMode() ) )
339 SwFEShell
*pFESh
= pCrsrShell
->ISA( SwFEShell
)
340 ? static_cast< SwFEShell
* >( pCrsrShell
) : 0;
342 !(pFESh
->IsFrmSelected() || pFESh
->IsObjSelected() > 0) )
344 // get the selection, and test whether it affects our text node
345 pCrsr
= pCrsrShell
->GetCrsr( FALSE
/* ??? */ );
352 sal_Bool
SwAccessibleParagraph::IsHeading() const
354 const SwTxtNode
*pTxtNd
= GetTxtNode();
355 return pTxtNd
->IsOutline();
358 void SwAccessibleParagraph::GetStates(
359 ::utl::AccessibleStateSetHelper
& rStateSet
)
361 SwAccessibleContext::GetStates( rStateSet
);
364 rStateSet
.AddState( AccessibleStateType::MULTI_LINE
);
367 SwCrsrShell
*pCrsrSh
= GetCrsrShell();
369 rStateSet
.AddState( AccessibleStateType::MULTI_SELECTABLE
);
373 rStateSet
.AddState( AccessibleStateType::FOCUSABLE
);
375 // FOCUSED (simulates node index of cursor)
376 // --> OD 2005-12-20 #i27301# - consider adjusted method signature
377 SwPaM
* pCaret
= GetCursor( false );
379 const SwTxtNode
* pTxtNd
= GetTxtNode();
380 if( pCaret
!= 0 && pTxtNd
!= 0 &&
381 pTxtNd
->GetIndex() == pCaret
->GetPoint()->nNode
.GetIndex() &&
384 Window
*pWin
= GetWindow();
385 if( pWin
&& pWin
->HasFocus() )
386 rStateSet
.AddState( AccessibleStateType::FOCUSED
);
387 ::vos::ORef
< SwAccessibleContext
> xThis( this );
388 GetMap()->SetCursorContext( xThis
);
392 void SwAccessibleParagraph::_InvalidateContent( sal_Bool bVisibleDataFired
)
394 OUString
sOldText( GetString() );
398 const OUString
& rText
= GetString();
400 if( rText
!= sOldText
)
402 // The text is changed
403 AccessibleEventObject aEvent
;
404 aEvent
.EventId
= AccessibleEventId::TEXT_CHANGED
;
406 // determine exact changes between sOldText and rText
407 comphelper::OCommonAccessibleText::implInitTextChangedEvent(
409 aEvent
.OldValue
, aEvent
.NewValue
);
411 FireAccessibleEvent( aEvent
);
413 else if( !bVisibleDataFired
)
415 FireVisibleDataEvent();
418 sal_Bool bNewIsHeading
= IsHeading();
419 sal_Bool bOldIsHeading
;
421 vos::OGuard
aGuard( aMutex
);
422 bOldIsHeading
= bIsHeading
;
423 if( bIsHeading
!= bNewIsHeading
)
424 bIsHeading
= bNewIsHeading
;
428 if( bNewIsHeading
!= bOldIsHeading
|| rText
!= sOldText
)
430 OUString
sNewDesc( GetDescription() );
433 vos::OGuard
aGuard( aMutex
);
435 if( sDesc
!= sNewDesc
)
439 if( sNewDesc
!= sOldDesc
)
441 // The text is changed
442 AccessibleEventObject aEvent
;
443 aEvent
.EventId
= AccessibleEventId::DESCRIPTION_CHANGED
;
444 aEvent
.OldValue
<<= sOldDesc
;
445 aEvent
.NewValue
<<= sNewDesc
;
447 FireAccessibleEvent( aEvent
);
452 void SwAccessibleParagraph::_InvalidateCursorPos()
454 // The text is changed
455 sal_Int32 nNew
= GetCaretPos();
458 vos::OGuard
aGuard( aMutex
);
464 // remember that object as the one that has the caret. This is
465 // neccessary to notify that object if the cursor leaves it.
466 ::vos::ORef
< SwAccessibleContext
> xThis( this );
467 GetMap()->SetCursorContext( xThis
);
470 Window
*pWin
= GetWindow();
473 // The cursor's node position is sumilated by the focus!
474 if( pWin
&& pWin
->HasFocus() && -1 == nOld
)
475 FireStateChangedEvent( AccessibleStateType::FOCUSED
, sal_True
);
478 AccessibleEventObject aEvent
;
479 aEvent
.EventId
= AccessibleEventId::CARET_CHANGED
;
480 aEvent
.OldValue
<<= nOld
;
481 aEvent
.NewValue
<<= nNew
;
483 FireAccessibleEvent( aEvent
);
485 if( pWin
&& pWin
->HasFocus() && -1 == nNew
)
486 FireStateChangedEvent( AccessibleStateType::FOCUSED
, sal_False
);
490 void SwAccessibleParagraph::_InvalidateFocus()
492 Window
*pWin
= GetWindow();
497 vos::OGuard
aGuard( aMutex
);
500 ASSERT( nPos
!= -1, "focus object should be selected" );
502 FireStateChangedEvent( AccessibleStateType::FOCUSED
,
503 pWin
->HasFocus() && nPos
!= -1 );
507 SwAccessibleParagraph::SwAccessibleParagraph(
508 SwAccessibleMap
* pInitMap
,
509 const SwTxtFrm
*pTxtFrm
) :
510 SwAccessibleContext( pInitMap
, AccessibleRole::PARAGRAPH
, pTxtFrm
),
511 pPortionData( NULL
),
512 pHyperTextData( NULL
),
514 aSelectionHelper( *this )
516 vos::OGuard
aGuard(Application::GetSolarMutex());
518 bIsHeading
= IsHeading();
519 // --> OD 2004-09-27 #117970# - set an empty accessibility name for paragraphs
520 SetName( OUString() );
523 // If this object has the focus, then it is remembered by the map itself.
524 nOldCaretPos
= GetCaretPos();
527 SwAccessibleParagraph::~SwAccessibleParagraph()
529 vos::OGuard
aGuard(Application::GetSolarMutex());
532 delete pHyperTextData
;
535 sal_Bool
SwAccessibleParagraph::HasCursor()
537 vos::OGuard
aGuard( aMutex
);
538 return nOldCaretPos
!= -1;
541 void SwAccessibleParagraph::UpdatePortionData()
542 throw( uno::RuntimeException
)
544 // obtain the text frame
545 DBG_ASSERT( GetFrm() != NULL
, "The text frame has vanished!" );
546 DBG_ASSERT( GetFrm()->IsTxtFrm(), "The text frame has mutated!" );
547 const SwTxtFrm
* pFrm
= static_cast<const SwTxtFrm
*>( GetFrm() );
549 // build new portion data
551 pPortionData
= new SwAccessiblePortionData(
552 pFrm
->GetTxtNode(), GetMap()->GetShell()->GetViewOptions() );
553 pFrm
->VisitPortions( *pPortionData
);
555 DBG_ASSERT( pPortionData
!= NULL
, "UpdatePortionData() failed" );
558 void SwAccessibleParagraph::ClearPortionData()
563 delete pHyperTextData
;
568 void SwAccessibleParagraph::ExecuteAtViewShell( UINT16 nSlot
)
570 DBG_ASSERT( GetMap() != NULL
, "no map?" );
571 ViewShell
* pViewShell
= GetMap()->GetShell();
573 DBG_ASSERT( pViewShell
!= NULL
, "View shell exptected!" );
574 SfxViewShell
* pSfxShell
= pViewShell
->GetSfxViewShell();
576 DBG_ASSERT( pSfxShell
!= NULL
, "SfxViewShell shell exptected!" );
580 SfxViewFrame
*pFrame
= pSfxShell
->GetViewFrame();
581 DBG_ASSERT( pFrame
!= NULL
, "View frame exptected!" );
585 SfxDispatcher
*pDispatcher
= pFrame
->GetDispatcher();
586 DBG_ASSERT( pDispatcher
!= NULL
, "Dispatcher exptected!" );
590 pDispatcher
->Execute( nSlot
);
593 SwXTextPortion
* SwAccessibleParagraph::CreateUnoPortion(
594 sal_Int32 nStartIndex
,
595 sal_Int32 nEndIndex
)
597 DBG_ASSERT( (IsValidChar(nStartIndex
, GetString().getLength()) &&
598 (nEndIndex
== -1)) ||
599 IsValidRange(nStartIndex
, nEndIndex
, GetString().getLength()),
600 "please check parameters before calling this method" );
602 USHORT nStart
= GetPortionData().GetModelPosition( nStartIndex
);
603 USHORT nEnd
= (nEndIndex
== -1) ? (nStart
+ 1) :
604 GetPortionData().GetModelPosition( nEndIndex
);
607 SwTxtNode
* pTxtNode
= const_cast<SwTxtNode
*>( GetTxtNode() );
608 SwIndex
aIndex( pTxtNode
, nStart
);
609 SwPosition
aStartPos( *pTxtNode
, aIndex
);
610 SwUnoCrsr
* pUnoCursor
= pTxtNode
->GetDoc()->CreateUnoCrsr( aStartPos
);
611 pUnoCursor
->SetMark();
612 pUnoCursor
->GetMark()->nContent
= nEnd
;
614 // create a (dummy) text portion to be returned
615 uno::Reference
<text::XText
> aEmpty
;
616 SwXTextPortion
* pPortion
=
617 new SwXTextPortion ( pUnoCursor
, aEmpty
, PORTION_TEXT
);
625 // range checking for parameter
628 sal_Bool
SwAccessibleParagraph::IsValidChar(
629 sal_Int32 nPos
, sal_Int32 nLength
)
631 return (nPos
>= 0) && (nPos
< nLength
);
634 sal_Bool
SwAccessibleParagraph::IsValidPosition(
635 sal_Int32 nPos
, sal_Int32 nLength
)
637 return (nPos
>= 0) && (nPos
<= nLength
);
640 sal_Bool
SwAccessibleParagraph::IsValidRange(
641 sal_Int32 nBegin
, sal_Int32 nEnd
, sal_Int32 nLength
)
643 return IsValidPosition(nBegin
, nLength
) && IsValidPosition(nEnd
, nLength
);
652 sal_Bool
SwAccessibleParagraph::GetCharBoundary(
657 rBound
.startPos
= nPos
;
658 rBound
.endPos
= nPos
+1;
662 sal_Bool
SwAccessibleParagraph::GetWordBoundary(
664 const OUString
& rText
,
667 sal_Bool bRet
= sal_False
;
669 // now ask the Break-Iterator for the word
670 DBG_ASSERT( pBreakIt
!= NULL
, "We always need a break." );
671 DBG_ASSERT( pBreakIt
->GetBreakIter().is(), "No break-iterator." );
672 if( pBreakIt
->GetBreakIter().is() )
674 // get locale for this position
675 USHORT nModelPos
= GetPortionData().GetModelPosition( nPos
);
676 Locale aLocale
= pBreakIt
->GetLocale(
677 GetTxtNode()->GetLang( nModelPos
) );
679 // which type of word are we interested in?
680 // (DICTIONARY_WORD includes punctuation, ANY_WORD doesn't.)
681 const USHORT nWordType
= WordType::ANY_WORD
;
683 // get word boundary, as the Break-Iterator sees fit.
684 rBound
= pBreakIt
->GetBreakIter()->getWordBoundary(
685 rText
, nPos
, aLocale
, nWordType
, sal_True
);
687 // It's a word if the first character is an alpha-numeric character.
688 bRet
= GetAppCharClass().isLetterNumeric(
689 rText
.getStr()[ rBound
.startPos
] );
693 // no break Iterator -> no word
694 rBound
.startPos
= nPos
;
695 rBound
.endPos
= nPos
;
701 sal_Bool
SwAccessibleParagraph::GetSentenceBoundary(
706 GetPortionData().GetSentenceBoundary( rBound
, nPos
);
710 sal_Bool
SwAccessibleParagraph::GetLineBoundary(
712 const OUString
& rText
,
715 if( rText
.getLength() == nPos
)
716 GetPortionData().GetLastLineBoundary( rBound
);
718 GetPortionData().GetLineBoundary( rBound
, nPos
);
722 sal_Bool
SwAccessibleParagraph::GetParagraphBoundary(
724 const OUString
& rText
,
728 rBound
.endPos
= rText
.getLength();
732 sal_Bool
SwAccessibleParagraph::GetAttributeBoundary(
737 GetPortionData().GetAttributeBoundary( rBound
, nPos
);
741 sal_Bool
SwAccessibleParagraph::GetGlyphBoundary(
743 const OUString
& rText
,
746 sal_Bool bRet
= sal_False
;
748 // ask the Break-Iterator for the glyph by moving one cell
749 // forward, and then one cell back
750 DBG_ASSERT( pBreakIt
!= NULL
, "We always need a break." );
751 DBG_ASSERT( pBreakIt
->GetBreakIter().is(), "No break-iterator." );
752 if( pBreakIt
->GetBreakIter().is() )
754 // get locale for this position
755 USHORT nModelPos
= GetPortionData().GetModelPosition( nPos
);
756 Locale aLocale
= pBreakIt
->GetLocale(
757 GetTxtNode()->GetLang( nModelPos
) );
759 // get word boundary, as the Break-Iterator sees fit.
760 const USHORT nIterMode
= CharacterIteratorMode::SKIPCELL
;
762 rBound
.endPos
= pBreakIt
->GetBreakIter()->nextCharacters(
763 rText
, nPos
, aLocale
, nIterMode
, 1, nDone
);
764 rBound
.startPos
= pBreakIt
->GetBreakIter()->previousCharacters(
765 rText
, rBound
.endPos
, aLocale
, nIterMode
, 1, nDone
);
767 DBG_ASSERT( rBound
.startPos
<= nPos
, "start pos too high" );
768 DBG_ASSERT( rBound
.endPos
>= nPos
, "end pos too low" );
772 // no break Iterator -> no glyph
773 rBound
.startPos
= nPos
;
774 rBound
.endPos
= nPos
;
781 sal_Bool
SwAccessibleParagraph::GetTextBoundary(
783 const OUString
& rText
,
785 sal_Int16 nTextType
)
787 IndexOutOfBoundsException
,
788 IllegalArgumentException
,
789 uno::RuntimeException
)
792 if( !( AccessibleTextType::LINE
== nTextType
793 ? IsValidPosition( nPos
, rText
.getLength() )
794 : IsValidChar( nPos
, rText
.getLength() ) ) )
795 throw IndexOutOfBoundsException();
801 case AccessibleTextType::WORD
:
802 bRet
= GetWordBoundary( rBound
, rText
, nPos
);
805 case AccessibleTextType::SENTENCE
:
806 bRet
= GetSentenceBoundary( rBound
, rText
, nPos
);
809 case AccessibleTextType::PARAGRAPH
:
810 bRet
= GetParagraphBoundary( rBound
, rText
, nPos
);
813 case AccessibleTextType::CHARACTER
:
814 bRet
= GetCharBoundary( rBound
, rText
, nPos
);
817 case AccessibleTextType::LINE
:
818 bRet
= GetLineBoundary( rBound
, rText
, nPos
);
821 case AccessibleTextType::ATTRIBUTE_RUN
:
822 bRet
= GetAttributeBoundary( rBound
, rText
, nPos
);
825 case AccessibleTextType::GLYPH
:
826 bRet
= GetGlyphBoundary( rBound
, rText
, nPos
);
830 throw IllegalArgumentException( );
836 OUString SAL_CALL
SwAccessibleParagraph::getAccessibleDescription (void)
837 throw (uno::RuntimeException
)
839 vos::OGuard
aGuard(Application::GetSolarMutex());
841 CHECK_FOR_DEFUNC( XAccessibleContext
);
843 vos::OGuard
aGuard2( aMutex
);
844 if( !sDesc
.getLength() )
845 sDesc
= GetDescription();
850 Locale SAL_CALL
SwAccessibleParagraph::getLocale (void)
851 throw (IllegalAccessibleComponentStateException
, uno::RuntimeException
)
853 vos::OGuard
aGuard(Application::GetSolarMutex());
855 SwTxtFrm
*pTxtFrm
= PTR_CAST( SwTxtFrm
, GetFrm() );
858 THROW_RUNTIME_EXCEPTION( XAccessibleContext
, "internal error (no text frame)" );
861 const SwTxtNode
*pTxtNd
= pTxtFrm
->GetTxtNode();
862 Locale
aLoc( pBreakIt
->GetLocale( pTxtNd
->GetLang( 0 ) ) );
867 /** paragraphs are in relation CONTENT_FLOWS_FROM and/or CONTENT_FLOWS_TO
869 OD 2005-12-02 #i27138#
873 uno::Reference
<XAccessibleRelationSet
> SAL_CALL
SwAccessibleParagraph::getAccessibleRelationSet()
874 throw ( uno::RuntimeException
)
876 vos::OGuard
aGuard(Application::GetSolarMutex());
877 CHECK_FOR_DEFUNC( XAccessibleContext
);
879 utl::AccessibleRelationSetHelper
* pHelper
= new utl::AccessibleRelationSetHelper();
881 const SwTxtFrm
* pTxtFrm
= dynamic_cast<const SwTxtFrm
*>(GetFrm());
883 "<SwAccessibleParagraph::getAccessibleRelationSet()> - missing text frame");
886 const SwCntntFrm
* pPrevCntFrm( pTxtFrm
->FindPrevCnt( true ) );
889 uno::Sequence
< uno::Reference
<XInterface
> > aSequence(1);
890 aSequence
[0] = GetMap()->GetContext( pPrevCntFrm
);
891 AccessibleRelation
aAccRel( AccessibleRelationType::CONTENT_FLOWS_FROM
,
893 pHelper
->AddRelation( aAccRel
);
896 const SwCntntFrm
* pNextCntFrm( pTxtFrm
->FindNextCnt( true ) );
899 uno::Sequence
< uno::Reference
<XInterface
> > aSequence(1);
900 aSequence
[0] = GetMap()->GetContext( pNextCntFrm
);
901 AccessibleRelation
aAccRel( AccessibleRelationType::CONTENT_FLOWS_TO
,
903 pHelper
->AddRelation( aAccRel
);
910 void SAL_CALL
SwAccessibleParagraph::grabFocus()
911 throw (uno::RuntimeException
)
913 vos::OGuard
aGuard(Application::GetSolarMutex());
915 CHECK_FOR_DEFUNC( XAccessibleContext
);
918 SwCrsrShell
*pCrsrSh
= GetCrsrShell();
919 // --> OD 2005-12-20 #i27301# - consider new method signature
920 SwPaM
*pCrsr
= GetCursor( false );
922 const SwTxtFrm
*pTxtFrm
= static_cast<const SwTxtFrm
*>( GetFrm() );
923 const SwTxtNode
* pTxtNd
= pTxtFrm
->GetTxtNode();
925 if( pCrsrSh
!= 0 && pTxtNd
!= 0 &&
927 pCrsr
->GetPoint()->nNode
.GetIndex() != pTxtNd
->GetIndex() ||
928 !pTxtFrm
->IsInside( pCrsr
->GetPoint()->nContent
.GetIndex()) ) )
930 // create pam for selection
931 SwIndex
aIndex( const_cast< SwTxtNode
* >( pTxtNd
),
932 pTxtFrm
->GetOfst() );
933 SwPosition
aStartPos( *pTxtNd
, aIndex
);
934 SwPaM
aPaM( aStartPos
);
936 // set PaM at cursor shell
943 Window
* pWindow
= GetWindow();
946 pWindow
->GrabFocus();
950 // --> OD 2007-01-17 #i71385#
951 bool lcl_GetBackgroundColor( Color
& rColor
,
953 SwCrsrShell
* pCrsrSh
)
955 const SvxBrushItem
* pBackgrdBrush
= 0;
956 const Color
* pSectionTOXColor
= 0;
959 pFrm
->GetBackgroundBrush( pBackgrdBrush
, pSectionTOXColor
, aDummyRect
, false ) )
961 if ( pSectionTOXColor
)
963 rColor
= *pSectionTOXColor
;
968 rColor
= pBackgrdBrush
->GetColor();
974 rColor
= pCrsrSh
->Imp()->GetRetoucheColor();
981 sal_Int32 SAL_CALL
SwAccessibleParagraph::getForeground()
982 throw (uno::RuntimeException
)
984 Color aBackgroundCol
;
986 if ( lcl_GetBackgroundColor( aBackgroundCol
, GetFrm(), GetCrsrShell() ) )
988 if ( aBackgroundCol
.IsDark() )
998 return SwAccessibleContext::getForeground();
1001 sal_Int32 SAL_CALL
SwAccessibleParagraph::getBackground()
1002 throw (uno::RuntimeException
)
1004 Color aBackgroundCol
;
1006 if ( lcl_GetBackgroundColor( aBackgroundCol
, GetFrm(), GetCrsrShell() ) )
1008 return aBackgroundCol
.GetColor();
1011 return SwAccessibleContext::getBackground();
1015 OUString SAL_CALL
SwAccessibleParagraph::getImplementationName()
1016 throw( uno::RuntimeException
)
1018 return OUString(RTL_CONSTASCII_USTRINGPARAM(sImplementationName
));
1021 sal_Bool SAL_CALL
SwAccessibleParagraph::supportsService(
1022 const ::rtl::OUString
& sTestServiceName
)
1023 throw (uno::RuntimeException
)
1025 return sTestServiceName
.equalsAsciiL( sServiceName
,
1026 sizeof(sServiceName
)-1 ) ||
1027 sTestServiceName
.equalsAsciiL( sAccessibleServiceName
,
1028 sizeof(sAccessibleServiceName
)-1 );
1031 Sequence
< OUString
> SAL_CALL
SwAccessibleParagraph::getSupportedServiceNames()
1032 throw( uno::RuntimeException
)
1034 Sequence
< OUString
> aRet(2);
1035 OUString
* pArray
= aRet
.getArray();
1036 pArray
[0] = OUString( RTL_CONSTASCII_USTRINGPARAM(sServiceName
) );
1037 pArray
[1] = OUString( RTL_CONSTASCII_USTRINGPARAM(sAccessibleServiceName
) );
1042 //===== XInterface =======================================================
1045 Any
SwAccessibleParagraph::queryInterface( const Type
& rType
)
1046 throw (RuntimeException
)
1049 if ( rType
== ::getCppuType((uno::Reference
<XAccessibleText
> *)0) )
1051 uno::Reference
<XAccessibleText
> aAccText
= (XAccessibleText
*) *this; // resolve ambiguity
1054 else if ( rType
== ::getCppuType((uno::Reference
<XAccessibleEditableText
> *)0) )
1056 uno::Reference
<XAccessibleEditableText
> aAccEditText
= this;
1057 aRet
<<= aAccEditText
;
1059 else if ( rType
== ::getCppuType((uno::Reference
<XAccessibleSelection
> *)0) )
1061 uno::Reference
<XAccessibleSelection
> aAccSel
= this;
1064 else if ( rType
== ::getCppuType((uno::Reference
<XAccessibleHypertext
> *)0) )
1066 uno::Reference
<XAccessibleHypertext
> aAccHyp
= this;
1069 // --> OD 2006-07-13 #i63870#
1070 // add interface com::sun:star:accessibility::XAccessibleTextAttributes
1071 else if ( rType
== ::getCppuType((uno::Reference
<XAccessibleTextAttributes
> *)0) )
1073 uno::Reference
<XAccessibleTextAttributes
> aAccTextAttr
= this;
1074 aRet
<<= aAccTextAttr
;
1077 // --> OD 2008-06-10 #i89175#
1078 // add interface com::sun:star:accessibility::XAccessibleTextMarkup
1079 else if ( rType
== ::getCppuType((uno::Reference
<XAccessibleTextMarkup
> *)0) )
1081 uno::Reference
<XAccessibleTextMarkup
> aAccTextMarkup
= this;
1082 aRet
<<= aAccTextMarkup
;
1084 // add interface com::sun:star:accessibility::XAccessibleMultiLineText
1085 else if ( rType
== ::getCppuType((uno::Reference
<XAccessibleMultiLineText
> *)0) )
1087 uno::Reference
<XAccessibleMultiLineText
> aAccMultiLineText
= this;
1088 aRet
<<= aAccMultiLineText
;
1093 aRet
= SwAccessibleContext::queryInterface(rType
);
1099 //====== XTypeProvider ====================================================
1100 Sequence
< Type
> SAL_CALL
SwAccessibleParagraph::getTypes() throw(RuntimeException
)
1102 Sequence
< Type
> aTypes( SwAccessibleContext::getTypes() );
1104 sal_Int32 nIndex
= aTypes
.getLength();
1105 // --> OD 2006-07-13 #i63870#
1106 // add type accessibility::XAccessibleTextAttributes
1107 // --> OD 2008-06-10 #i89175#
1108 // add type accessibility::XAccessibleTextMarkup and accessibility::XAccessibleMultiLineText
1109 aTypes
.realloc( nIndex
+ 6 );
1111 Type
* pTypes
= aTypes
.getArray();
1112 pTypes
[nIndex
++] = ::getCppuType( static_cast< uno::Reference
< XAccessibleEditableText
> * >( 0 ) );
1113 pTypes
[nIndex
++] = ::getCppuType( static_cast< uno::Reference
< XAccessibleTextAttributes
> * >( 0 ) );
1114 pTypes
[nIndex
++] = ::getCppuType( static_cast< uno::Reference
< XAccessibleSelection
> * >( 0 ) );
1115 pTypes
[nIndex
++] = ::getCppuType( static_cast< uno::Reference
< XAccessibleTextMarkup
> * >( 0 ) );
1116 pTypes
[nIndex
++] = ::getCppuType( static_cast< uno::Reference
< XAccessibleMultiLineText
> * >( 0 ) );
1117 pTypes
[nIndex
] = ::getCppuType( static_cast< uno::Reference
< XAccessibleHypertext
> * >( 0 ) );
1123 Sequence
< sal_Int8
> SAL_CALL
SwAccessibleParagraph::getImplementationId()
1124 throw(RuntimeException
)
1126 vos::OGuard
aGuard(Application::GetSolarMutex());
1127 static Sequence
< sal_Int8
> aId( 16 );
1128 static sal_Bool bInit
= sal_False
;
1131 rtl_createUuid( (sal_uInt8
*)(aId
.getArray() ), 0, sal_True
);
1139 //===== XAccesibleText ===================================================
1142 sal_Int32
SwAccessibleParagraph::getCaretPosition()
1143 throw (RuntimeException
)
1145 vos::OGuard
aGuard(Application::GetSolarMutex());
1147 CHECK_FOR_DEFUNC_THIS( XAccessibleText
, *this );
1149 sal_Int32 nRet
= GetCaretPos();
1151 vos::OGuard
aOldCaretPosGuard( aMutex
);
1152 ASSERT( nRet
== nOldCaretPos
, "caret pos out of sync" );
1153 nOldCaretPos
= nRet
;
1157 ::vos::ORef
< SwAccessibleContext
> xThis( this );
1158 GetMap()->SetCursorContext( xThis
);
1164 sal_Bool SAL_CALL
SwAccessibleParagraph::setCaretPosition( sal_Int32 nIndex
)
1165 throw (IndexOutOfBoundsException
, uno::RuntimeException
)
1167 vos::OGuard
aGuard(Application::GetSolarMutex());
1169 CHECK_FOR_DEFUNC_THIS( XAccessibleText
, *this );
1171 // parameter checking
1172 sal_Int32 nLength
= GetString().getLength();
1173 if ( ! IsValidPosition( nIndex
, nLength
) )
1175 throw IndexOutOfBoundsException();
1178 sal_Bool bRet
= sal_False
;
1181 SwCrsrShell
* pCrsrShell
= GetCrsrShell();
1182 if( pCrsrShell
!= NULL
)
1184 // create pam for selection
1185 SwTxtNode
* pNode
= const_cast<SwTxtNode
*>( GetTxtNode() );
1186 SwIndex
aIndex( pNode
, GetPortionData().GetModelPosition(nIndex
));
1187 SwPosition
aStartPos( *pNode
, aIndex
);
1188 SwPaM
aPaM( aStartPos
);
1190 // set PaM at cursor shell
1191 bRet
= Select( aPaM
);
1197 sal_Unicode
SwAccessibleParagraph::getCharacter( sal_Int32 nIndex
)
1198 throw (IndexOutOfBoundsException
, uno::RuntimeException
)
1200 vos::OGuard
aGuard(Application::GetSolarMutex());
1202 CHECK_FOR_DEFUNC_THIS( XAccessibleText
, *this );
1204 OUString
sText( GetString() );
1206 // return character (if valid)
1207 if( IsValidChar(nIndex
, sText
.getLength() ) )
1209 return sText
.getStr()[nIndex
];
1212 throw IndexOutOfBoundsException();
1215 // --> OD 2006-07-20 #i63870#
1216 // re-implement method on behalf of methods <_getDefaultAttributesImpl(..)> and
1217 // <_getRunAttributesImpl(..)>
1218 Sequence
<PropertyValue
> SwAccessibleParagraph::getCharacterAttributes(
1220 const uno::Sequence
< ::rtl::OUString
>& aRequestedAttributes
)
1221 throw (IndexOutOfBoundsException
, uno::RuntimeException
)
1224 vos::OGuard
aGuard(Application::GetSolarMutex());
1225 CHECK_FOR_DEFUNC_THIS( XAccessibleText
, *this );
1227 const OUString
& rText
= GetString();
1229 if( ! IsValidChar( nIndex
, rText
.getLength() ) )
1230 throw IndexOutOfBoundsException();
1232 // retrieve default character attributes
1233 tAccParaPropValMap aDefAttrSeq
;
1234 _getDefaultAttributesImpl( aRequestedAttributes
, aDefAttrSeq
, true );
1236 // retrieved run character attributes
1237 tAccParaPropValMap aRunAttrSeq
;
1238 _getRunAttributesImpl( nIndex
, aRequestedAttributes
, aRunAttrSeq
);
1240 // merge default and run attributes
1241 Sequence
< PropertyValue
> aValues( aDefAttrSeq
.size() );
1242 PropertyValue
* pValues
= aValues
.getArray();
1244 for ( tAccParaPropValMap::const_iterator aDefIter
= aDefAttrSeq
.begin();
1245 aDefIter
!= aDefAttrSeq
.end();
1248 tAccParaPropValMap::const_iterator aRunIter
=
1249 aRunAttrSeq
.find( aDefIter
->first
);
1250 if ( aRunIter
!= aRunAttrSeq
.end() )
1252 pValues
[i
] = aRunIter
->second
;
1256 pValues
[i
] = aDefIter
->second
;
1261 // // create a (dummy) text portion for the sole purpose of calling
1262 // // getPropertyValues on it
1263 // Reference<XMultiPropertySet> xPortion = CreateUnoPortion( nIndex, nIndex + 1 );
1266 // Sequence<OUString> aNames = getAttributeNames();
1267 // sal_Int32 nLength = aNames.getLength();
1268 // Sequence<Any> aAnys( nLength );
1269 // aAnys = xPortion->getPropertyValues( aNames );
1271 // // copy names + anys into return sequence
1272 // Sequence<PropertyValue> aValues( aNames.getLength() );
1273 // const OUString* pNames = aNames.getConstArray();
1274 // const Any* pAnys = aAnys.getConstArray();
1275 // PropertyValue* pValues = aValues.getArray();
1276 // for( sal_Int32 i = 0; i < nLength; i++ )
1278 // PropertyValue& rValue = pValues[i];
1279 // rValue.Name = pNames[i];
1280 // rValue.Value = pAnys[i];
1281 // rValue.Handle = -1; // handle not supported
1282 // rValue.State = PropertyState_DIRECT_VALUE; // states not supported
1285 // // adjust background color if we're in a gray portion
1286 // DBG_ASSERT( pValues[CHAR_BACK_COLOR_POS].Name.
1287 // equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("CharBackColor")),
1288 // "Please adjust CHAR_BACK_COLOR_POS constant." );
1289 // if( GetPortionData().IsInGrayPortion( nIndex ) )
1290 // pValues[CHAR_BACK_COLOR_POS].Value <<= SwViewOption::GetFieldShadingsColor().GetColor();
1295 // --> OD 2006-07-11 #i63870#
1296 void SwAccessibleParagraph::_getDefaultAttributesImpl(
1297 const uno::Sequence
< ::rtl::OUString
>& aRequestedAttributes
,
1298 tAccParaPropValMap
& rDefAttrSeq
,
1299 const bool bOnlyCharAttrs
)
1301 // retrieve default attributes
1302 const SwTxtNode
* pTxtNode( GetTxtNode() );
1303 ::boost::scoped_ptr
<SfxItemSet
> pSet
;
1304 if ( !bOnlyCharAttrs
)
1306 pSet
.reset( new SfxItemSet( const_cast<SwAttrPool
&>(pTxtNode
->GetDoc()->GetAttrPool()),
1307 RES_CHRATR_BEGIN
, RES_CHRATR_END
- 1,
1308 RES_PARATR_BEGIN
, RES_PARATR_END
- 1,
1309 RES_FRMATR_BEGIN
, RES_FRMATR_END
- 1,
1314 pSet
.reset( new SfxItemSet( const_cast<SwAttrPool
&>(pTxtNode
->GetDoc()->GetAttrPool()),
1315 RES_CHRATR_BEGIN
, RES_CHRATR_END
- 1,
1318 // --> OD 2007-11-12 #i82637#
1319 // From the perspective of the a11y API the default character attributes
1320 // are the character attributes, which are set at the paragraph style
1321 // of the paragraph. The character attributes set at the automatic paragraph
1322 // style of the paragraph are treated as run attributes.
1323 // pTxtNode->SwCntntNode::GetAttr( *pSet );
1324 // get default paragraph attributes, if needed, and merge these into <pSet>
1325 if ( !bOnlyCharAttrs
)
1327 SfxItemSet
aParaSet( const_cast<SwAttrPool
&>(pTxtNode
->GetDoc()->GetAttrPool()),
1328 RES_PARATR_BEGIN
, RES_PARATR_END
- 1,
1329 RES_FRMATR_BEGIN
, RES_FRMATR_END
- 1,
1331 pTxtNode
->SwCntntNode::GetAttr( aParaSet
);
1332 pSet
->Put( aParaSet
);
1334 // get default character attributes and merge these into <pSet>
1335 ASSERT( pTxtNode
->GetTxtColl(),
1336 "<SwAccessibleParagraph::_getDefaultAttributesImpl(..)> - missing paragraph style. Serious defect, please inform OD!" );
1337 if ( pTxtNode
->GetTxtColl() )
1339 SfxItemSet
aCharSet( const_cast<SwAttrPool
&>(pTxtNode
->GetDoc()->GetAttrPool()),
1340 RES_CHRATR_BEGIN
, RES_CHRATR_END
- 1,
1342 aCharSet
.Put( pTxtNode
->GetTxtColl()->GetAttrSet() );
1343 pSet
->Put( aCharSet
);
1347 // build-up sequence containing the run attributes <rDefAttrSeq>
1348 tAccParaPropValMap aDefAttrSeq
;
1350 const SfxItemPropertyMap
* pPropMap
=
1351 aSwMapProvider
.GetPropertySet( PROPERTY_MAP_TEXT_CURSOR
)->getPropertyMap();
1352 PropertyEntryVector_t aPropertyEntries
= pPropMap
->getPropertyEntries();
1353 PropertyEntryVector_t::const_iterator aPropIt
= aPropertyEntries
.begin();
1354 while ( aPropIt
!= aPropertyEntries
.end() )
1356 const SfxPoolItem
* pItem
= pSet
->GetItem( aPropIt
->nWID
);
1360 pItem
->QueryValue( aVal
, aPropIt
->nMemberId
);
1362 PropertyValue rPropVal
;
1363 rPropVal
.Name
= aPropIt
->sName
;
1364 rPropVal
.Value
= aVal
;
1365 rPropVal
.Handle
= -1;
1366 rPropVal
.State
= beans::PropertyState_DEFAULT_VALUE
;
1368 aDefAttrSeq
[rPropVal
.Name
] = rPropVal
;
1373 // --> OD 2007-01-15 #i72800#
1374 // add property value entry for the paragraph style
1375 if ( !bOnlyCharAttrs
&& pTxtNode
->GetTxtColl() )
1377 const OUString sParaStyleName
=
1378 OUString::createFromAscii(
1379 GetPropName( UNO_NAME_PARA_STYLE_NAME
).pName
);
1380 if ( aDefAttrSeq
.find( sParaStyleName
) == aDefAttrSeq
.end() )
1382 PropertyValue rPropVal
;
1383 rPropVal
.Name
= sParaStyleName
;
1384 Any
aVal( makeAny( OUString( pTxtNode
->GetTxtColl()->GetName() ) ) );
1385 rPropVal
.Value
= aVal
;
1386 rPropVal
.Handle
= -1;
1387 rPropVal
.State
= beans::PropertyState_DEFAULT_VALUE
;
1389 aDefAttrSeq
[rPropVal
.Name
] = rPropVal
;
1394 // --> OD 2007-01-15 #i73371#
1395 // resolve value text::WritingMode2::PAGE of property value entry WritingMode
1396 if ( !bOnlyCharAttrs
&& GetFrm() )
1398 const OUString sWritingMode
=
1399 OUString::createFromAscii(
1400 GetPropName( UNO_NAME_WRITING_MODE
).pName
);
1401 tAccParaPropValMap::iterator aIter
= aDefAttrSeq
.find( sWritingMode
);
1402 if ( aIter
!= aDefAttrSeq
.end() )
1404 PropertyValue
rPropVal( aIter
->second
);
1405 sal_Int16 nVal
= rPropVal
.Value
.get
<sal_Int16
>();
1406 if ( nVal
== text::WritingMode2::PAGE
)
1408 const SwFrm
* pUpperFrm( GetFrm()->GetUpper() );
1411 if ( pUpperFrm
->GetType() &
1412 ( FRM_PAGE
| FRM_FLY
| FRM_SECTION
| FRM_TAB
| FRM_CELL
) )
1414 if ( pUpperFrm
->IsVertical() )
1416 nVal
= text::WritingMode2::TB_RL
;
1418 else if ( pUpperFrm
->IsRightToLeft() )
1420 nVal
= text::WritingMode2::RL_TB
;
1424 nVal
= text::WritingMode2::LR_TB
;
1426 rPropVal
.Value
<<= nVal
;
1427 aDefAttrSeq
[rPropVal
.Name
] = rPropVal
;
1431 if ( dynamic_cast<const SwFlyFrm
*>(pUpperFrm
) )
1433 pUpperFrm
= dynamic_cast<const SwFlyFrm
*>(pUpperFrm
)->GetAnchorFrm();
1437 pUpperFrm
= pUpperFrm
->GetUpper();
1446 if ( aRequestedAttributes
.getLength() == 0 )
1448 rDefAttrSeq
= aDefAttrSeq
;
1452 const OUString
* pReqAttrs
= aRequestedAttributes
.getConstArray();
1453 const sal_Int32 nLength
= aRequestedAttributes
.getLength();
1454 for( sal_Int32 i
= 0; i
< nLength
; ++i
)
1456 tAccParaPropValMap::const_iterator
const aIter
= aDefAttrSeq
.find( pReqAttrs
[i
] );
1457 if ( aIter
!= aDefAttrSeq
.end() )
1459 rDefAttrSeq
[ aIter
->first
] = aIter
->second
;
1465 Sequence
< PropertyValue
> SwAccessibleParagraph::getDefaultAttributes(
1466 const Sequence
< ::rtl::OUString
>& aRequestedAttributes
)
1467 throw ( uno::RuntimeException
)
1469 vos::OGuard
aGuard(Application::GetSolarMutex());
1470 CHECK_FOR_DEFUNC_THIS( XAccessibleText
, *this );
1472 tAccParaPropValMap aDefAttrSeq
;
1473 _getDefaultAttributesImpl( aRequestedAttributes
, aDefAttrSeq
);
1475 Sequence
< PropertyValue
> aValues( aDefAttrSeq
.size() );
1476 PropertyValue
* pValues
= aValues
.getArray();
1478 for ( tAccParaPropValMap::const_iterator aIter
= aDefAttrSeq
.begin();
1479 aIter
!= aDefAttrSeq
.end();
1482 pValues
[i
] = aIter
->second
;
1489 void SwAccessibleParagraph::_getRunAttributesImpl(
1490 const sal_Int32 nIndex
,
1491 const uno::Sequence
< ::rtl::OUString
>& aRequestedAttributes
,
1492 tAccParaPropValMap
& rRunAttrSeq
)
1494 // create PaM for character at position <nIndex>
1497 const SwTxtNode
* pTxtNode( GetTxtNode() );
1498 SwPosition
* pStartPos
= new SwPosition( *pTxtNode
);
1499 pStartPos
->nContent
.Assign( const_cast<SwTxtNode
*>(pTxtNode
), static_cast<USHORT
>(nIndex
) );
1500 SwPosition
* pEndPos
= new SwPosition( *pTxtNode
);
1501 pEndPos
->nContent
.Assign( const_cast<SwTxtNode
*>(pTxtNode
), static_cast<USHORT
>(nIndex
+1) );
1503 pPaM
= new SwPaM( *pStartPos
, *pEndPos
);
1509 // retrieve character attributes for the created PaM <pPaM>
1510 SfxItemSet
aSet( pPaM
->GetDoc()->GetAttrPool(),
1511 RES_CHRATR_BEGIN
, RES_CHRATR_END
-1,
1513 // --> OD 2007-11-12 #i82637#
1514 // From the perspective of the a11y API the character attributes, which
1515 // are set at the automatic paragraph style of the paragraph are treated
1516 // as run attributes.
1517 // SwXTextCursor::GetCrsrAttr( *pPaM, aSet, TRUE, TRUE );
1518 // get character attributes from automatic paragraph style and merge these into <aSet>
1520 const SwTxtNode
* pTxtNode( GetTxtNode() );
1521 if ( pTxtNode
->HasSwAttrSet() )
1523 SfxItemSet
aAutomaticParaStyleCharAttrs( pPaM
->GetDoc()->GetAttrPool(),
1524 RES_CHRATR_BEGIN
, RES_CHRATR_END
-1,
1526 aAutomaticParaStyleCharAttrs
.Put( *(pTxtNode
->GetpSwAttrSet()), FALSE
);
1527 aSet
.Put( aAutomaticParaStyleCharAttrs
);
1530 // get character attributes at <pPaM> and merge these into <aSet>
1532 SfxItemSet
aCharAttrsAtPaM( pPaM
->GetDoc()->GetAttrPool(),
1533 RES_CHRATR_BEGIN
, RES_CHRATR_END
-1,
1535 SwXTextCursor::GetCrsrAttr( *pPaM
, aCharAttrsAtPaM
, TRUE
, TRUE
);
1536 aSet
.Put( aCharAttrsAtPaM
);
1540 // build-up sequence containing the run attributes <rRunAttrSeq>
1542 tAccParaPropValMap aRunAttrSeq
;
1544 // --> OD 2007-11-12 #i82637#
1545 tAccParaPropValMap aDefAttrSeq
;
1546 uno::Sequence
< ::rtl::OUString
> aDummy
;
1547 _getDefaultAttributesImpl( aDummy
, aDefAttrSeq
, true );
1550 const SfxItemPropertyMap
* pPropMap
=
1551 aSwMapProvider
.GetPropertySet( PROPERTY_MAP_TEXT_CURSOR
)->getPropertyMap();
1552 PropertyEntryVector_t aPropertyEntries
= pPropMap
->getPropertyEntries();
1553 PropertyEntryVector_t::const_iterator aPropIt
= aPropertyEntries
.begin();
1554 while ( aPropIt
!= aPropertyEntries
.end() )
1556 const SfxPoolItem
* pItem( 0 );
1557 // --> OD 2007-11-12 #i82637#
1558 // Found character attributes, whose value equals the value of
1559 // the corresponding default character attributes, are excluded.
1560 if ( aSet
.GetItemState( aPropIt
->nWID
, TRUE
, &pItem
) == SFX_ITEM_SET
)
1563 pItem
->QueryValue( aVal
, aPropIt
->nMemberId
);
1565 PropertyValue rPropVal
;
1566 rPropVal
.Name
= aPropIt
->sName
;
1567 rPropVal
.Value
= aVal
;
1568 rPropVal
.Handle
= -1;
1569 rPropVal
.State
= PropertyState_DIRECT_VALUE
;
1571 tAccParaPropValMap::const_iterator aDefIter
=
1572 aDefAttrSeq
.find( rPropVal
.Name
);
1573 if ( aDefIter
== aDefAttrSeq
.end() ||
1574 rPropVal
.Value
!= aDefIter
->second
.Value
)
1576 aRunAttrSeq
[rPropVal
.Name
] = rPropVal
;
1584 if ( aRequestedAttributes
.getLength() == 0 )
1586 rRunAttrSeq
= aRunAttrSeq
;
1590 const OUString
* pReqAttrs
= aRequestedAttributes
.getConstArray();
1591 const sal_Int32 nLength
= aRequestedAttributes
.getLength();
1592 for( sal_Int32 i
= 0; i
< nLength
; ++i
)
1594 tAccParaPropValMap::iterator aIter
= aRunAttrSeq
.find( pReqAttrs
[i
] );
1595 if ( aIter
!= aRunAttrSeq
.end() )
1597 rRunAttrSeq
[ (*aIter
).first
] = (*aIter
).second
;
1606 Sequence
< PropertyValue
> SwAccessibleParagraph::getRunAttributes(
1608 const Sequence
< ::rtl::OUString
>& aRequestedAttributes
)
1609 throw ( IndexOutOfBoundsException
,
1610 uno::RuntimeException
)
1612 vos::OGuard
aGuard(Application::GetSolarMutex());
1613 CHECK_FOR_DEFUNC_THIS( XAccessibleText
, *this );
1616 const OUString
& rText
= GetString();
1617 if ( !IsValidChar( nIndex
, rText
.getLength() ) )
1619 throw IndexOutOfBoundsException();
1623 tAccParaPropValMap aRunAttrSeq
;
1624 _getRunAttributesImpl( nIndex
, aRequestedAttributes
, aRunAttrSeq
);
1626 Sequence
< PropertyValue
> aValues( aRunAttrSeq
.size() );
1627 PropertyValue
* pValues
= aValues
.getArray();
1629 for ( tAccParaPropValMap::const_iterator aIter
= aRunAttrSeq
.begin();
1630 aIter
!= aRunAttrSeq
.end();
1633 pValues
[i
] = aIter
->second
;
1641 awt::Rectangle
SwAccessibleParagraph::getCharacterBounds(
1643 throw (IndexOutOfBoundsException
, uno::RuntimeException
)
1645 vos::OGuard
aGuard(Application::GetSolarMutex());
1647 CHECK_FOR_DEFUNC_THIS( XAccessibleText
, *this );
1650 /* #i12332# The position after the string needs special treatment.
1651 IsValidChar -> IsValidPosition
1653 if( ! (IsValidPosition( nIndex
, GetString().getLength() ) ) )
1654 throw IndexOutOfBoundsException();
1657 sal_Bool bBehindText
= sal_False
;
1658 if ( nIndex
== GetString().getLength() )
1659 bBehindText
= sal_True
;
1661 // get model position & prepare GetCharRect() arguments
1662 SwCrsrMoveState aMoveState
;
1663 aMoveState
.bRealHeight
= TRUE
;
1664 aMoveState
.bRealWidth
= TRUE
;
1665 SwSpecialPos aSpecialPos
;
1666 SwTxtNode
* pNode
= const_cast<SwTxtNode
*>( GetTxtNode() );
1670 /* #i12332# FillSpecialPos does not accept nIndex ==
1671 GetString().getLength(). In that case nPos is set to the
1672 length of the string in the core. This way GetCharRect
1673 returns the rectangle for a cursor at the end of the
1677 nPos
= pNode
->GetTxt().Len();
1680 nPos
= GetPortionData().FillSpecialPos
1681 (nIndex
, aSpecialPos
, aMoveState
.pSpecialPos
);
1685 SwIndex
aIndex( pNode
, nPos
);
1686 SwPosition
aPosition( *pNode
, aIndex
);
1687 GetFrm()->GetCharRect( aCoreRect
, aPosition
, &aMoveState
);
1689 // translate core coordinates into accessibility coordinates
1690 Window
*pWin
= GetWindow();
1691 CHECK_FOR_WINDOW( XAccessibleComponent
, pWin
);
1693 Rectangle
aScreenRect( GetMap()->CoreToPixel( aCoreRect
.SVRect() ));
1694 SwRect
aFrmLogBounds( GetBounds() ); // twip rel to doc root
1696 Point
aFrmPixPos( GetMap()->CoreToPixel( aFrmLogBounds
.SVRect() ).TopLeft() );
1697 aScreenRect
.Move( -aFrmPixPos
.X(), -aFrmPixPos
.Y() );
1699 // convert into AWT Rectangle
1700 return awt::Rectangle(
1701 aScreenRect
.Left(), aScreenRect
.Top(),
1702 aScreenRect
.GetWidth(), aScreenRect
.GetHeight() );
1705 sal_Int32
SwAccessibleParagraph::getCharacterCount()
1706 throw (RuntimeException
)
1708 vos::OGuard
aGuard(Application::GetSolarMutex());
1710 CHECK_FOR_DEFUNC_THIS( XAccessibleText
, *this );
1712 return GetString().getLength();
1715 sal_Int32
SwAccessibleParagraph::getIndexAtPoint( const awt::Point
& rPoint
)
1716 throw (RuntimeException
)
1718 vos::OGuard
aGuard(Application::GetSolarMutex());
1721 CHECK_FOR_DEFUNC_THIS( XAccessibleText
, *this );
1723 // construct SwPosition (where GetCrsrOfst() will put the result into)
1724 SwTxtNode
* pNode
= const_cast<SwTxtNode
*>( GetTxtNode() );
1725 SwIndex
aIndex( pNode
, 0);
1726 SwPosition
aPos( *pNode
, aIndex
);
1728 // construct Point (translate into layout coordinates)
1729 Window
*pWin
= GetWindow();
1730 CHECK_FOR_WINDOW( XAccessibleComponent
, pWin
);
1731 Point
aPoint( rPoint
.X
, rPoint
.Y
);
1732 SwRect
aLogBounds( GetBounds( GetFrm() ) ); // twip rel to doc root
1733 Point
aPixPos( GetMap()->CoreToPixel( aLogBounds
.SVRect() ).TopLeft() );
1734 aPoint
.X() += aPixPos
.X();
1735 aPoint
.Y() += aPixPos
.Y();
1736 MapMode aMapMode
= pWin
->GetMapMode();
1737 Point
aCorePoint( GetMap()->PixelToCore( aPoint
) );
1738 if( !aLogBounds
.IsInside( aCorePoint
) )
1740 /* #i12332# rPoint is may also be in rectangle returned by
1741 getCharacterBounds(getCharacterCount() */
1743 awt::Rectangle aRectEndPos
=
1744 getCharacterBounds(getCharacterCount());
1746 if (rPoint
.X
- aRectEndPos
.X
>= 0 &&
1747 rPoint
.X
- aRectEndPos
.X
< aRectEndPos
.Width
&&
1748 rPoint
.Y
- aRectEndPos
.Y
>= 0 &&
1749 rPoint
.Y
- aRectEndPos
.Y
< aRectEndPos
.Height
)
1750 return getCharacterCount();
1755 // ask core for position
1756 DBG_ASSERT( GetFrm() != NULL
, "The text frame has vanished!" );
1757 DBG_ASSERT( GetFrm()->IsTxtFrm(), "The text frame has mutated!" );
1758 const SwTxtFrm
* pFrm
= static_cast<const SwTxtFrm
*>( GetFrm() );
1759 SwCrsrMoveState aMoveState
;
1760 aMoveState
.bPosMatchesBounds
= TRUE
;
1761 sal_Bool bSuccess
= pFrm
->GetCrsrOfst( &aPos
, aCorePoint
, &aMoveState
);
1763 SwIndex aCntntIdx
= aPos
.nContent
;
1764 const xub_StrLen nIndex
= aCntntIdx
.GetIndex();
1768 pFrm
->GetCharRect( aResultRect
, aPos
);
1769 bool bVert
= pFrm
->IsVertical();
1770 bool bR2L
= pFrm
->IsRightToLeft();
1772 if ( (!bVert
&& aResultRect
.Pos().X() > aCorePoint
.X()) ||
1773 ( bVert
&& aResultRect
.Pos().Y() > aCorePoint
.Y()) ||
1774 ( bR2L
&& aResultRect
.Right() < aCorePoint
.X()) )
1776 SwIndex
aIdxPrev( pNode
, nIndex
- 1);
1777 SwPosition
aPosPrev( *pNode
, aIdxPrev
);
1778 SwRect aResultRectPrev
;
1779 pFrm
->GetCharRect( aResultRectPrev
, aPosPrev
);
1780 if ( (!bVert
&& aResultRectPrev
.Pos().X() < aCorePoint
.X() && aResultRect
.Pos().Y() == aResultRectPrev
.Pos().Y()) ||
1781 ( bVert
&& aResultRectPrev
.Pos().Y() < aCorePoint
.Y() && aResultRect
.Pos().X() == aResultRectPrev
.Pos().X()) ||
1782 ( bR2L
&& aResultRectPrev
.Right() > aCorePoint
.X() && aResultRect
.Pos().Y() == aResultRectPrev
.Pos().Y()) )
1788 GetPortionData().GetAccessiblePosition( aPos
.nContent
.GetIndex() )
1792 OUString
SwAccessibleParagraph::getSelectedText()
1793 throw (RuntimeException
)
1795 vos::OGuard
aGuard(Application::GetSolarMutex());
1797 CHECK_FOR_DEFUNC_THIS( XAccessibleText
, *this );
1799 sal_Int32 nStart
, nEnd
;
1800 sal_Bool bSelected
= GetSelection( nStart
, nEnd
);
1801 return bSelected
? GetString().copy( nStart
, nEnd
- nStart
) : OUString();
1804 sal_Int32
SwAccessibleParagraph::getSelectionStart()
1805 throw (RuntimeException
)
1807 vos::OGuard
aGuard(Application::GetSolarMutex());
1809 CHECK_FOR_DEFUNC_THIS( XAccessibleText
, *this );
1811 sal_Int32 nStart
, nEnd
;
1812 GetSelection( nStart
, nEnd
);
1816 sal_Int32
SwAccessibleParagraph::getSelectionEnd()
1817 throw (RuntimeException
)
1819 vos::OGuard
aGuard(Application::GetSolarMutex());
1821 CHECK_FOR_DEFUNC_THIS( XAccessibleText
, *this );
1823 sal_Int32 nStart
, nEnd
;
1824 GetSelection( nStart
, nEnd
);
1828 sal_Bool
SwAccessibleParagraph::setSelection( sal_Int32 nStartIndex
, sal_Int32 nEndIndex
)
1829 throw (IndexOutOfBoundsException
, uno::RuntimeException
)
1831 vos::OGuard
aGuard(Application::GetSolarMutex());
1833 CHECK_FOR_DEFUNC_THIS( XAccessibleText
, *this );
1835 // parameter checking
1836 sal_Int32 nLength
= GetString().getLength();
1837 if ( ! IsValidRange( nStartIndex
, nEndIndex
, nLength
) )
1839 throw IndexOutOfBoundsException();
1842 sal_Bool bRet
= sal_False
;
1845 SwCrsrShell
* pCrsrShell
= GetCrsrShell();
1846 if( pCrsrShell
!= NULL
)
1848 // create pam for selection
1849 SwTxtNode
* pNode
= const_cast<SwTxtNode
*>( GetTxtNode() );
1850 SwIndex
aIndex( pNode
, GetPortionData().GetModelPosition(nStartIndex
));
1851 SwPosition
aStartPos( *pNode
, aIndex
);
1852 SwPaM
aPaM( aStartPos
);
1854 aPaM
.GetPoint()->nContent
=
1855 GetPortionData().GetModelPosition(nEndIndex
);
1857 // set PaM at cursor shell
1858 bRet
= Select( aPaM
);
1864 OUString
SwAccessibleParagraph::getText()
1865 throw (RuntimeException
)
1867 vos::OGuard
aGuard(Application::GetSolarMutex());
1869 CHECK_FOR_DEFUNC_THIS( XAccessibleText
, *this );
1874 OUString
SwAccessibleParagraph::getTextRange(
1875 sal_Int32 nStartIndex
, sal_Int32 nEndIndex
)
1876 throw (IndexOutOfBoundsException
, uno::RuntimeException
)
1878 vos::OGuard
aGuard(Application::GetSolarMutex());
1880 CHECK_FOR_DEFUNC_THIS( XAccessibleText
, *this );
1882 OUString
sText( GetString() );
1884 if ( IsValidRange( nStartIndex
, nEndIndex
, sText
.getLength() ) )
1886 OrderRange( nStartIndex
, nEndIndex
);
1887 return sText
.copy(nStartIndex
, nEndIndex
-nStartIndex
);
1890 throw IndexOutOfBoundsException();
1893 /*accessibility::*/TextSegment
SwAccessibleParagraph::getTextAtIndex( sal_Int32 nIndex
, sal_Int16 nTextType
) throw (lang::IndexOutOfBoundsException
, lang::IllegalArgumentException
, uno::RuntimeException
)
1895 vos::OGuard
aGuard(Application::GetSolarMutex());
1897 CHECK_FOR_DEFUNC_THIS( XAccessibleText
, *this );
1899 /*accessibility::*/TextSegment aResult
;
1900 aResult
.SegmentStart
= -1;
1901 aResult
.SegmentEnd
= -1;
1903 const OUString rText
= GetString();
1904 // implement the silly specification that first position after
1905 // text must return an empty string, rather than throwing an
1906 // IndexOutOfBoundsException, except for LINE, where the last
1908 if( nIndex
== rText
.getLength() && AccessibleTextType::LINE
!= nTextType
)
1911 // with error checking
1913 sal_Bool bWord
= GetTextBoundary( aBound
, rText
, nIndex
, nTextType
);
1915 DBG_ASSERT( aBound
.startPos
>= 0, "illegal boundary" );
1916 DBG_ASSERT( aBound
.startPos
<= aBound
.endPos
, "illegal boundary" );
1918 // return word (if present)
1921 aResult
.SegmentText
= rText
.copy( aBound
.startPos
, aBound
.endPos
- aBound
.startPos
);
1922 aResult
.SegmentStart
= aBound
.startPos
;
1923 aResult
.SegmentEnd
= aBound
.endPos
;
1929 /*accessibility::*/TextSegment
SwAccessibleParagraph::getTextBeforeIndex( sal_Int32 nIndex
, sal_Int16 nTextType
) throw (lang::IndexOutOfBoundsException
, lang::IllegalArgumentException
, uno::RuntimeException
)
1931 vos::OGuard
aGuard(Application::GetSolarMutex());
1933 CHECK_FOR_DEFUNC_THIS( XAccessibleText
, *this );
1935 const OUString rText
= GetString();
1937 /*accessibility::*/TextSegment aResult
;
1938 aResult
.SegmentStart
= -1;
1939 aResult
.SegmentEnd
= -1;
1943 if (nIndex
== rText
.getLength())
1944 aBound
.startPos
= aBound
.endPos
= nIndex
;
1947 sal_Bool bTmp
= GetTextBoundary( aBound
, rText
, nIndex
, nTextType
);
1950 aBound
.startPos
= aBound
.endPos
= nIndex
;
1953 // now skip to previous word
1954 sal_Bool bWord
= sal_False
;
1957 nIndex
= min( nIndex
, aBound
.startPos
) - 1;
1959 bWord
= GetTextBoundary( aBound
, rText
, nIndex
, nTextType
);
1961 break; // exit if beginning of string is reached
1966 aResult
.SegmentText
= rText
.copy( aBound
.startPos
, aBound
.endPos
- aBound
.startPos
);
1967 aResult
.SegmentStart
= aBound
.startPos
;
1968 aResult
.SegmentEnd
= aBound
.endPos
;
1973 /*accessibility::*/TextSegment
SwAccessibleParagraph::getTextBehindIndex( sal_Int32 nIndex
, sal_Int16 nTextType
) throw (lang::IndexOutOfBoundsException
, lang::IllegalArgumentException
, uno::RuntimeException
)
1975 vos::OGuard
aGuard(Application::GetSolarMutex());
1977 CHECK_FOR_DEFUNC_THIS( XAccessibleText
, *this );
1979 /*accessibility::*/TextSegment aResult
;
1980 aResult
.SegmentStart
= -1;
1981 aResult
.SegmentEnd
= -1;
1982 const OUString rText
= GetString();
1984 // implement the silly specification that first position after
1985 // text must return an empty string, rather than throwing an
1986 // IndexOutOfBoundsException
1987 if( nIndex
== rText
.getLength() )
1991 // get first word, then skip to next word
1993 GetTextBoundary( aBound
, rText
, nIndex
, nTextType
);
1994 sal_Bool bWord
= sal_False
;
1997 nIndex
= max( sal_Int32(nIndex
+1), aBound
.endPos
);
1998 if( nIndex
< rText
.getLength() )
1999 bWord
= GetTextBoundary( aBound
, rText
, nIndex
, nTextType
);
2001 break; // exit if end of string is reached
2006 aResult
.SegmentText
= rText
.copy( aBound
.startPos
, aBound
.endPos
- aBound
.startPos
);
2007 aResult
.SegmentStart
= aBound
.startPos
;
2008 aResult
.SegmentEnd
= aBound
.endPos
;
2013 sal_Bool
SwAccessibleParagraph::copyText( sal_Int32 nStartIndex
, sal_Int32 nEndIndex
)
2014 throw (IndexOutOfBoundsException
, uno::RuntimeException
)
2016 CHECK_FOR_DEFUNC_THIS( XAccessibleText
, *this );
2017 vos::OGuard
aGuard(Application::GetSolarMutex());
2019 // select and copy (through dispatch mechanism)
2020 setSelection( nStartIndex
, nEndIndex
);
2021 ExecuteAtViewShell( SID_COPY
);
2027 //===== XAccesibleEditableText ==========================================
2030 sal_Bool
SwAccessibleParagraph::cutText( sal_Int32 nStartIndex
, sal_Int32 nEndIndex
)
2031 throw (IndexOutOfBoundsException
, uno::RuntimeException
)
2033 CHECK_FOR_DEFUNC( XAccessibleEditableText
);
2034 vos::OGuard
aGuard(Application::GetSolarMutex());
2036 if( !IsEditableState() )
2039 // select and cut (through dispatch mechanism)
2040 setSelection( nStartIndex
, nEndIndex
);
2041 ExecuteAtViewShell( SID_CUT
);
2045 sal_Bool
SwAccessibleParagraph::pasteText( sal_Int32 nIndex
)
2046 throw (IndexOutOfBoundsException
, uno::RuntimeException
)
2048 CHECK_FOR_DEFUNC( XAccessibleEditableText
);
2049 vos::OGuard
aGuard(Application::GetSolarMutex());
2051 if( !IsEditableState() )
2054 // select and paste (through dispatch mechanism)
2055 setSelection( nIndex
, nIndex
);
2056 ExecuteAtViewShell( SID_PASTE
);
2060 sal_Bool
SwAccessibleParagraph::deleteText( sal_Int32 nStartIndex
, sal_Int32 nEndIndex
)
2061 throw (IndexOutOfBoundsException
, uno::RuntimeException
)
2063 return replaceText( nStartIndex
, nEndIndex
, OUString() );
2066 sal_Bool
SwAccessibleParagraph::insertText( const OUString
& sText
, sal_Int32 nIndex
)
2067 throw (IndexOutOfBoundsException
, uno::RuntimeException
)
2069 return replaceText( nIndex
, nIndex
, sText
);
2072 sal_Bool
SwAccessibleParagraph::replaceText(
2073 sal_Int32 nStartIndex
, sal_Int32 nEndIndex
,
2074 const OUString
& sReplacement
)
2075 throw (IndexOutOfBoundsException
, uno::RuntimeException
)
2077 vos::OGuard
aGuard(Application::GetSolarMutex());
2079 CHECK_FOR_DEFUNC( XAccessibleEditableText
);
2081 const OUString
& rText
= GetString();
2083 if( IsValidRange( nStartIndex
, nEndIndex
, rText
.getLength() ) )
2085 if( !IsEditableState() )
2088 SwTxtNode
* pNode
= const_cast<SwTxtNode
*>( GetTxtNode() );
2090 // translate positions
2091 USHORT nStart
, nEnd
;
2092 sal_Bool bSuccess
= GetPortionData().GetEditableRange(
2093 nStartIndex
, nEndIndex
, nStart
, nEnd
);
2095 // edit only if the range is editable
2098 // create SwPosition for nStartIndex
2099 SwIndex
aIndex( pNode
, nStart
);
2100 SwPosition
aStartPos( *pNode
, aIndex
);
2102 // create SwPosition for nEndIndex
2103 SwPosition
aEndPos( aStartPos
);
2104 aEndPos
.nContent
= nEnd
;
2106 // now create XTextRange as helper and set string
2107 SwXTextRange::CreateTextRangeFromPosition(
2108 pNode
->GetDoc(), aStartPos
, &aEndPos
)->setString(sReplacement
);
2110 // delete portion data
2117 throw IndexOutOfBoundsException();
2122 const PropertyValue
* pValues
;
2123 IndexCompare( const PropertyValue
* pVals
) : pValues(pVals
) {}
2124 bool operator() ( const sal_Int32
& a
, const sal_Int32
& b
) const
2126 return (pValues
[a
].Name
< pValues
[b
].Name
) ? true : false;
2131 sal_Bool
SwAccessibleParagraph::setAttributes(
2132 sal_Int32 nStartIndex
,
2133 sal_Int32 nEndIndex
,
2134 const Sequence
<PropertyValue
>& rAttributeSet
)
2135 throw (IndexOutOfBoundsException
, uno::RuntimeException
)
2137 vos::OGuard
aGuard(Application::GetSolarMutex());
2138 CHECK_FOR_DEFUNC( XAccessibleEditableText
);
2140 const OUString
& rText
= GetString();
2142 if( ! IsValidRange( nStartIndex
, nEndIndex
, rText
.getLength() ) )
2143 throw IndexOutOfBoundsException();
2145 if( !IsEditableState() )
2149 // create a (dummy) text portion for the sole purpose of calling
2150 // setPropertyValue on it
2151 uno::Reference
<XMultiPropertySet
> xPortion
= CreateUnoPortion( nStartIndex
,
2154 // build sorted index array
2155 sal_Int32 nLength
= rAttributeSet
.getLength();
2156 const PropertyValue
* pPairs
= rAttributeSet
.getConstArray();
2157 sal_Int32
* pIndices
= new sal_Int32
[nLength
];
2159 for( i
= 0; i
< nLength
; i
++ )
2161 sort( &pIndices
[0], &pIndices
[nLength
], IndexCompare(pPairs
) );
2163 // create sorted sequences accoring to index array
2164 Sequence
<OUString
> aNames( nLength
);
2165 OUString
* pNames
= aNames
.getArray();
2166 Sequence
<Any
> aValues( nLength
);
2167 Any
* pValues
= aValues
.getArray();
2168 for( i
= 0; i
< nLength
; i
++ )
2170 const PropertyValue
& rVal
= pPairs
[pIndices
[i
]];
2171 pNames
[i
] = rVal
.Name
;
2172 pValues
[i
] = rVal
.Value
;
2176 // now set the values
2177 sal_Bool bRet
= sal_True
;
2180 xPortion
->setPropertyValues( aNames
, aValues
);
2182 catch( UnknownPropertyException e
)
2184 // error handling through return code!
2191 sal_Bool
SwAccessibleParagraph::setText( const OUString
& sText
)
2192 throw (RuntimeException
)
2194 return replaceText(0, GetString().getLength(), sText
);
2197 //===== XAccessibleSelection ============================================
2199 void SwAccessibleParagraph::selectAccessibleChild(
2200 sal_Int32 nChildIndex
)
2201 throw ( IndexOutOfBoundsException
,
2202 uno::RuntimeException
)
2204 CHECK_FOR_DEFUNC( XAccessibleSelection
);
2206 aSelectionHelper
.selectAccessibleChild(nChildIndex
);
2209 sal_Bool
SwAccessibleParagraph::isAccessibleChildSelected(
2210 sal_Int32 nChildIndex
)
2211 throw ( IndexOutOfBoundsException
,
2212 uno::RuntimeException
)
2214 CHECK_FOR_DEFUNC( XAccessibleSelection
);
2216 return aSelectionHelper
.isAccessibleChildSelected(nChildIndex
);
2219 void SwAccessibleParagraph::clearAccessibleSelection( )
2220 throw ( uno::RuntimeException
)
2222 CHECK_FOR_DEFUNC( XAccessibleSelection
);
2224 aSelectionHelper
.clearAccessibleSelection();
2227 void SwAccessibleParagraph::selectAllAccessibleChildren( )
2228 throw ( uno::RuntimeException
)
2230 CHECK_FOR_DEFUNC( XAccessibleSelection
);
2232 aSelectionHelper
.selectAllAccessibleChildren();
2235 sal_Int32
SwAccessibleParagraph::getSelectedAccessibleChildCount( )
2236 throw ( uno::RuntimeException
)
2238 CHECK_FOR_DEFUNC( XAccessibleSelection
);
2240 return aSelectionHelper
.getSelectedAccessibleChildCount();
2243 uno::Reference
<XAccessible
> SwAccessibleParagraph::getSelectedAccessibleChild(
2244 sal_Int32 nSelectedChildIndex
)
2245 throw ( IndexOutOfBoundsException
,
2246 uno::RuntimeException
)
2248 CHECK_FOR_DEFUNC( XAccessibleSelection
);
2250 return aSelectionHelper
.getSelectedAccessibleChild(nSelectedChildIndex
);
2253 // --> OD 2004-11-16 #111714# - index has to be treated as global child index.
2254 void SwAccessibleParagraph::deselectAccessibleChild(
2255 sal_Int32 nChildIndex
)
2256 throw ( IndexOutOfBoundsException
,
2257 uno::RuntimeException
)
2259 CHECK_FOR_DEFUNC( XAccessibleSelection
);
2261 aSelectionHelper
.deselectAccessibleChild( nChildIndex
);
2264 //===== XAccessibleHypertext ============================================
2266 class SwHyperlinkIter_Impl
2268 const SwpHints
*pHints
;
2274 SwHyperlinkIter_Impl( const SwTxtFrm
*pTxtFrm
);
2275 const SwTxtAttr
*next();
2276 sal_uInt16
getCurrHintPos() const { return nPos
-1; }
2278 xub_StrLen
startIdx() const { return nStt
; }
2279 xub_StrLen
endIdx() const { return nEnd
; }
2282 SwHyperlinkIter_Impl::SwHyperlinkIter_Impl( const SwTxtFrm
*pTxtFrm
) :
2283 pHints( pTxtFrm
->GetTxtNode()->GetpSwpHints() ),
2284 nStt( pTxtFrm
->GetOfst() ),
2287 const SwTxtFrm
*pFollFrm
= pTxtFrm
->GetFollow();
2288 nEnd
= pFollFrm
? pFollFrm
->GetOfst() : pTxtFrm
->GetTxtNode()->Len();
2291 const SwTxtAttr
*SwHyperlinkIter_Impl::next()
2293 const SwTxtAttr
*pAttr
= 0;
2296 while( !pAttr
&& nPos
< pHints
->Count() )
2298 const SwTxtAttr
*pHt
= (*pHints
)[nPos
];
2299 if( RES_TXTATR_INETFMT
== pHt
->Which() )
2301 xub_StrLen nHtStt
= *pHt
->GetStart();
2302 xub_StrLen nHtEnd
= *pHt
->GetAnyEnd();
2303 if( nHtEnd
> nHtStt
&&
2304 ( (nHtStt
>= nStt
&& nHtStt
< nEnd
) ||
2305 (nHtEnd
> nStt
&& nHtEnd
<= nEnd
) ) )
2317 sal_Int32 SAL_CALL
SwAccessibleParagraph::getHyperLinkCount()
2318 throw (RuntimeException
)
2320 vos::OGuard
aGuard(Application::GetSolarMutex());
2322 CHECK_FOR_DEFUNC( XAccessibleHypertext
);
2324 sal_Int32 nCount
= 0;
2325 // --> OD 2007-06-27 #i77108# - provide hyperlinks also in editable documents.
2326 // if( !IsEditableState() )
2329 const SwTxtFrm
*pTxtFrm
= static_cast<const SwTxtFrm
*>( GetFrm() );
2330 SwHyperlinkIter_Impl
aIter( pTxtFrm
);
2331 while( aIter
.next() )
2338 uno::Reference
< XAccessibleHyperlink
> SAL_CALL
2339 SwAccessibleParagraph::getHyperLink( sal_Int32 nLinkIndex
)
2340 throw (IndexOutOfBoundsException
, uno::RuntimeException
)
2342 vos::OGuard
aGuard(Application::GetSolarMutex());
2343 CHECK_FOR_DEFUNC( XAccessibleHypertext
);
2345 uno::Reference
< XAccessibleHyperlink
> xRet
;
2347 // --> OD 2007-06-27 #i77108# - provide hyperlinks also in editable documents.
2348 // if( !IsEditableState() )
2351 const SwTxtFrm
*pTxtFrm
= static_cast<const SwTxtFrm
*>( GetFrm() );
2352 SwHyperlinkIter_Impl
aHIter( pTxtFrm
);
2353 while( nLinkIndex
-- )
2356 const SwTxtAttr
*pHt
= aHIter
.next();
2359 if( !pHyperTextData
)
2360 pHyperTextData
= new SwAccessibleHyperTextData
;
2361 SwAccessibleHyperTextData::iterator aIter
=
2362 pHyperTextData
->find( pHt
);
2363 if( aIter
!= pHyperTextData
->end() )
2365 xRet
= (*aIter
).second
;
2369 sal_Int32 nHStt
= GetPortionData().GetAccessiblePosition(
2370 max( aHIter
.startIdx(), *pHt
->GetStart() ) );
2371 sal_Int32 nHEnd
= GetPortionData().GetAccessiblePosition(
2372 min( aHIter
.endIdx(), *pHt
->GetAnyEnd() ) );
2373 xRet
= new SwAccessibleHyperlink( aHIter
.getCurrHintPos(),
2374 this, nHStt
, nHEnd
);
2375 if( aIter
!= pHyperTextData
->end() )
2377 (*aIter
).second
= xRet
;
2381 SwAccessibleHyperTextData::value_type
aEntry( pHt
, xRet
);
2382 pHyperTextData
->insert( aEntry
);
2389 throw IndexOutOfBoundsException();
2394 sal_Int32 SAL_CALL
SwAccessibleParagraph::getHyperLinkIndex( sal_Int32 nCharIndex
)
2395 throw (IndexOutOfBoundsException
, uno::RuntimeException
)
2397 vos::OGuard
aGuard(Application::GetSolarMutex());
2398 CHECK_FOR_DEFUNC( XAccessibleHypertext
);
2400 // parameter checking
2401 sal_Int32 nLength
= GetString().getLength();
2402 if ( ! IsValidPosition( nCharIndex
, nLength
) )
2404 throw IndexOutOfBoundsException();
2407 sal_Int32 nRet
= -1;
2408 // --> OD 2007-06-27 #i77108# - provide hyperlinks also in editable documents.
2409 // if( !IsEditableState() )
2412 const SwTxtFrm
*pTxtFrm
= static_cast<const SwTxtFrm
*>( GetFrm() );
2413 SwHyperlinkIter_Impl
aHIter( pTxtFrm
);
2415 xub_StrLen nIdx
= GetPortionData().GetModelPosition( nCharIndex
);
2417 const SwTxtAttr
*pHt
= aHIter
.next();
2418 while( pHt
&& !(nIdx
>= *pHt
->GetStart() && nIdx
< *pHt
->GetAnyEnd()) )
2420 pHt
= aHIter
.next();
2432 // --> OD 2008-05-26 #i71360#
2433 sal_Int32 SAL_CALL
SwAccessibleParagraph::getTextMarkupCount( sal_Int32 nTextMarkupType
)
2434 throw (lang::IllegalArgumentException
,
2435 uno::RuntimeException
)
2437 SwTextMarkupHelper
aTextMarkupHelper( *GetTxtNode(), GetPortionData() );
2439 return aTextMarkupHelper
.getTextMarkupCount( nTextMarkupType
);
2442 /*accessibility::*/TextSegment SAL_CALL
2443 SwAccessibleParagraph::getTextMarkup( sal_Int32 nTextMarkupIndex
,
2444 sal_Int32 nTextMarkupType
)
2445 throw (lang::IndexOutOfBoundsException
,
2446 lang::IllegalArgumentException
,
2447 uno::RuntimeException
)
2449 SwTextMarkupHelper
aTextMarkupHelper( *GetTxtNode(), GetPortionData() );
2451 return aTextMarkupHelper
.getTextMarkup( nTextMarkupIndex
, nTextMarkupType
);
2454 uno::Sequence
< /*accessibility::*/TextSegment
> SAL_CALL
2455 SwAccessibleParagraph::getTextMarkupAtIndex( sal_Int32 nCharIndex
,
2456 sal_Int32 nTextMarkupType
)
2457 throw (lang::IndexOutOfBoundsException
,
2458 lang::IllegalArgumentException
,
2459 uno::RuntimeException
)
2461 // parameter checking
2462 const sal_Int32 nLength
= GetString().getLength();
2463 if ( ! IsValidPosition( nCharIndex
, nLength
) )
2465 throw lang::IndexOutOfBoundsException();
2468 SwTextMarkupHelper
aTextMarkupHelper( *GetTxtNode(), GetPortionData() );
2470 return aTextMarkupHelper
.getTextMarkupAtIndex( nCharIndex
, nTextMarkupType
);
2474 // --> OD 2008-05-29 #i89175#
2475 sal_Int32 SAL_CALL
SwAccessibleParagraph::getLineNumberAtIndex( sal_Int32 nIndex
)
2476 throw (lang::IndexOutOfBoundsException
,
2477 uno::RuntimeException
)
2479 // parameter checking
2480 const sal_Int32 nLength
= GetString().getLength();
2481 if ( ! IsValidPosition( nIndex
, nLength
) )
2483 throw lang::IndexOutOfBoundsException();
2486 const sal_Int32 nLineNo
= GetPortionData().GetLineNo( nIndex
);
2490 /*accessibility::*/TextSegment SAL_CALL
2491 SwAccessibleParagraph::getTextAtLineNumber( sal_Int32 nLineNo
)
2492 throw (lang::IndexOutOfBoundsException
,
2493 uno::RuntimeException
)
2495 // parameter checking
2497 nLineNo
>= GetPortionData().GetLineCount() )
2499 throw lang::IndexOutOfBoundsException();
2502 Boundary aLineBound
;
2503 GetPortionData().GetBoundaryOfLine( nLineNo
, aLineBound
);
2505 /*accessibility::*/TextSegment aTextAtLine
;
2506 const ::rtl::OUString rText
= GetString();
2507 aTextAtLine
.SegmentText
= rText
.copy( aLineBound
.startPos
,
2508 aLineBound
.endPos
- aLineBound
.startPos
);
2509 aTextAtLine
.SegmentStart
= aLineBound
.startPos
;
2510 aTextAtLine
.SegmentEnd
= aLineBound
.endPos
;
2515 /*accessibility::*/TextSegment SAL_CALL
SwAccessibleParagraph::getTextAtLineWithCaret()
2516 throw (uno::RuntimeException
)
2518 const sal_Int32 nLineNoOfCaret
= getNumberOfLineWithCaret();
2520 if ( nLineNoOfCaret
>= 0 &&
2521 nLineNoOfCaret
< GetPortionData().GetLineCount() )
2523 return getTextAtLineNumber( nLineNoOfCaret
);
2526 return /*accessibility::*/TextSegment();
2529 sal_Int32 SAL_CALL
SwAccessibleParagraph::getNumberOfLineWithCaret()
2530 throw (uno::RuntimeException
)
2532 const sal_Int32 nCaretPos
= getCaretPosition();
2533 const sal_Int32 nLength
= GetString().getLength();
2534 if ( !IsValidPosition( nCaretPos
, nLength
) )
2539 sal_Int32 nLineNo
= GetPortionData().GetLineNo( nCaretPos
);
2541 // special handling for cursor positioned at end of text line via End key
2542 if ( nCaretPos
!= 0 )
2544 Boundary aLineBound
;
2545 GetPortionData().GetBoundaryOfLine( nLineNo
, aLineBound
);
2546 if ( nCaretPos
== aLineBound
.startPos
)
2548 SwCrsrShell
* pCrsrShell
= SwAccessibleParagraph::GetCrsrShell();
2549 if ( pCrsrShell
!= 0 )
2551 const awt::Rectangle aCharRect
= getCharacterBounds( nCaretPos
);
2553 const SwRect
& aCursorCoreRect
= pCrsrShell
->GetCharRect();
2554 // translate core coordinates into accessibility coordinates
2555 Window
*pWin
= GetWindow();
2556 CHECK_FOR_WINDOW( XAccessibleComponent
, pWin
);
2558 Rectangle
aScreenRect( GetMap()->CoreToPixel( aCursorCoreRect
.SVRect() ));
2560 SwRect
aFrmLogBounds( GetBounds() ); // twip rel to doc root
2561 Point
aFrmPixPos( GetMap()->CoreToPixel( aFrmLogBounds
.SVRect() ).TopLeft() );
2562 aScreenRect
.Move( -aFrmPixPos
.X(), -aFrmPixPos
.Y() );
2564 // convert into AWT Rectangle
2565 const awt::Rectangle
aCursorRect( aScreenRect
.Left(),
2567 aScreenRect
.GetWidth(),
2568 aScreenRect
.GetHeight() );
2570 if ( aCharRect
.X
!= aCursorRect
.X
||
2571 aCharRect
.Y
!= aCursorRect
.Y
)