| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_sw.hxx" |
| |
| #include <txtfrm.hxx> |
| #include <flyfrm.hxx> |
| #include <ndtxt.hxx> |
| #include <pam.hxx> |
| #include <unotextrange.hxx> |
| #include <unocrsrhelper.hxx> |
| #include <crstate.hxx> |
| #include <accmap.hxx> |
| #include <fesh.hxx> |
| #include <viewopt.hxx> |
| #include <vos/mutex.hxx> |
| #include <vcl/svapp.hxx> |
| #include <vcl/window.hxx> |
| #include <rtl/ustrbuf.hxx> |
| #include <com/sun/star/accessibility/AccessibleRole.hpp> |
| #include <com/sun/star/accessibility/AccessibleStateType.hpp> |
| #include <com/sun/star/accessibility/AccessibleTextType.hpp> |
| #include <com/sun/star/accessibility/AccessibleEventId.hpp> |
| #include <unotools/accessiblestatesethelper.hxx> |
| #include <com/sun/star/i18n/CharacterIteratorMode.hpp> |
| #include <com/sun/star/i18n/WordType.hpp> |
| #include <com/sun/star/i18n/XBreakIterator.hpp> |
| #include <com/sun/star/beans/UnknownPropertyException.hpp> |
| #include <breakit.hxx> |
| #include <accpara.hxx> |
| #include <access.hrc> |
| #include <accportions.hxx> |
| #include <sfx2/viewsh.hxx> // for ExecuteAtViewShell(...) |
| #include <sfx2/viewfrm.hxx> // for ExecuteAtViewShell(...) |
| #include <sfx2/dispatch.hxx> // for ExecuteAtViewShell(...) |
| #include <unotools/charclass.hxx> // for GetWordBoundary |
| // for get/setCharacterAttribute(...) |
| #include <unocrsr.hxx> |
| //#include <unoobj.hxx> |
| #include <unoport.hxx> |
| #include <doc.hxx> |
| #include <crsskip.hxx> |
| #include <txtatr.hxx> |
| #include <acchyperlink.hxx> |
| #include <acchypertextdata.hxx> |
| #include <unotools/accessiblerelationsethelper.hxx> |
| #include <com/sun/star/accessibility/AccessibleRelationType.hpp> |
| #include <comphelper/accessibletexthelper.hxx> |
| #include <unomap.hxx> |
| #include <unoprnms.hxx> |
| #include <com/sun/star/text/WritingMode2.hpp> |
| #include <editeng/brshitem.hxx> |
| #include <viewimp.hxx> |
| #include <boost/scoped_ptr.hpp> |
| #include <textmarkuphelper.hxx> |
| // --> OD 2010-02-22 #i10825# |
| #include <parachangetrackinginfo.hxx> |
| #include <com/sun/star/text/TextMarkupType.hpp> |
| // <-- |
| // --> OD 2010-03-08 #i92233# |
| #include <comphelper/stlunosequence.hxx> |
| // <-- |
| |
| #include <algorithm> |
| |
| using namespace ::com::sun::star; |
| using namespace ::com::sun::star::accessibility; |
| |
| using beans::PropertyValue; |
| using beans::XMultiPropertySet; |
| using beans::UnknownPropertyException; |
| using beans::PropertyState_DIRECT_VALUE; |
| |
| using std::max; |
| using std::min; |
| using std::sort; |
| |
| namespace com { namespace sun { namespace star { |
| namespace text { |
| class XText; |
| } |
| } } } |
| |
| |
| const sal_Char sServiceName[] = "com.sun.star.text.AccessibleParagraphView"; |
| const sal_Char sImplementationName[] = "com.sun.star.comp.Writer.SwAccessibleParagraphView"; |
| const xub_StrLen MAX_DESC_TEXT_LEN = 40; |
| const SwTxtNode* SwAccessibleParagraph::GetTxtNode() const |
| { |
| const SwFrm* pFrm = GetFrm(); |
| DBG_ASSERT( pFrm->IsTxtFrm(), "The text frame has mutated!" ); |
| |
| const SwTxtNode* pNode = static_cast<const SwTxtFrm*>(pFrm)->GetTxtNode(); |
| DBG_ASSERT( pNode != NULL, "A text frame without a text node." ); |
| |
| return pNode; |
| } |
| |
| ::rtl::OUString SwAccessibleParagraph::GetString() |
| { |
| return GetPortionData().GetAccessibleString(); |
| } |
| |
| ::rtl::OUString SwAccessibleParagraph::GetDescription() |
| { |
| // --> OD 2004-09-29 #117933# - provide empty description for paragraphs |
| return ::rtl::OUString(); |
| // <-- |
| } |
| |
| sal_Int32 SwAccessibleParagraph::GetCaretPos() |
| { |
| sal_Int32 nRet = -1; |
| |
| // get the selection's point, and test whether it's in our node |
| // --> OD 2005-12-20 #i27301# - consider adjusted method signature |
| SwPaM* pCaret = GetCursor( false ); // caret is first PaM in PaM-ring |
| // <-- |
| if( pCaret != NULL ) |
| { |
| const SwTxtNode* pNode = GetTxtNode(); |
| |
| // check whether the point points into 'our' node |
| SwPosition* pPoint = pCaret->GetPoint(); |
| if( pNode->GetIndex() == pPoint->nNode.GetIndex() ) |
| { |
| // same node? Then check whether it's also within 'our' part |
| // of the paragraph |
| sal_uInt16 nIndex = pPoint->nContent.GetIndex(); |
| if( GetPortionData().IsValidCorePosition( nIndex ) ) |
| { |
| // Yes, it's us! |
| // --> OD 2006-10-19 #70538# |
| // consider that cursor/caret is in front of the list label |
| if ( pCaret->IsInFrontOfLabel() ) |
| { |
| nRet = 0; |
| } |
| else |
| { |
| nRet = GetPortionData().GetAccessiblePosition( nIndex ); |
| } |
| // <-- |
| |
| DBG_ASSERT( nRet >= 0, "invalid cursor?" ); |
| DBG_ASSERT( nRet <= GetPortionData().GetAccessibleString(). |
| getLength(), "invalid cursor?" ); |
| } |
| // else: in this paragraph, but in different frame |
| } |
| // else: not in this paragraph |
| } |
| // else: no cursor -> no caret |
| |
| return nRet; |
| } |
| |
| sal_Bool SwAccessibleParagraph::GetSelection( |
| sal_Int32& nStart, sal_Int32& nEnd) |
| { |
| sal_Bool bRet = sal_False; |
| nStart = -1; |
| nEnd = -1; |
| |
| // get the selection, and test whether it affects our text node |
| // --> OD 2005-12-20 #i27301# - consider adjusted method signature |
| SwPaM* pCrsr = GetCursor( true ); |
| // <-- |
| if( pCrsr != NULL ) |
| { |
| // get SwPosition for my node |
| const SwTxtNode* pNode = GetTxtNode(); |
| sal_uLong nHere = pNode->GetIndex(); |
| |
| // iterate over ring |
| SwPaM* pRingStart = pCrsr; |
| do |
| { |
| // ignore, if no mark |
| if( pCrsr->HasMark() ) |
| { |
| // check whether nHere is 'inside' pCrsr |
| SwPosition* pStart = pCrsr->Start(); |
| sal_uLong nStartIndex = pStart->nNode.GetIndex(); |
| SwPosition* pEnd = pCrsr->End(); |
| sal_uLong nEndIndex = pEnd->nNode.GetIndex(); |
| if( ( nHere >= nStartIndex ) && |
| ( nHere <= nEndIndex ) ) |
| { |
| // translate start and end positions |
| |
| // start position |
| sal_Int32 nLocalStart = -1; |
| if( nHere > nStartIndex ) |
| { |
| // selection starts in previous node: |
| // then our local selection starts with the paragraph |
| nLocalStart = 0; |
| } |
| else |
| { |
| DBG_ASSERT( nHere == nStartIndex, |
| "miscalculated index" ); |
| |
| // selection starts in this node: |
| // then check whether it's before or inside our part of |
| // the paragraph, and if so, get the proper position |
| sal_uInt16 nCoreStart = pStart->nContent.GetIndex(); |
| if( nCoreStart < |
| GetPortionData().GetFirstValidCorePosition() ) |
| { |
| nLocalStart = 0; |
| } |
| else if( nCoreStart <= |
| GetPortionData().GetLastValidCorePosition() ) |
| { |
| DBG_ASSERT( |
| GetPortionData().IsValidCorePosition( |
| nCoreStart ), |
| "problem determining valid core position" ); |
| |
| nLocalStart = |
| GetPortionData().GetAccessiblePosition( |
| nCoreStart ); |
| } |
| } |
| |
| // end position |
| sal_Int32 nLocalEnd = -1; |
| if( nHere < nEndIndex ) |
| { |
| // selection ends in following node: |
| // then our local selection extends to the end |
| nLocalEnd = GetPortionData().GetAccessibleString(). |
| getLength(); |
| } |
| else |
| { |
| DBG_ASSERT( nHere == nEndIndex, |
| "miscalculated index" ); |
| |
| // selection ends in this node: then select everything |
| // before our part of the node |
| sal_uInt16 nCoreEnd = pEnd->nContent.GetIndex(); |
| if( nCoreEnd > |
| GetPortionData().GetLastValidCorePosition() ) |
| { |
| // selection extends beyond out part of this para |
| nLocalEnd = GetPortionData().GetAccessibleString(). |
| getLength(); |
| } |
| else if( nCoreEnd >= |
| GetPortionData().GetFirstValidCorePosition() ) |
| { |
| // selection is inside our part of this para |
| DBG_ASSERT( |
| GetPortionData().IsValidCorePosition( |
| nCoreEnd ), |
| "problem determining valid core position" ); |
| |
| nLocalEnd = GetPortionData().GetAccessiblePosition( |
| nCoreEnd ); |
| } |
| } |
| |
| if( ( nLocalStart != -1 ) && ( nLocalEnd != -1 ) ) |
| { |
| nStart = nLocalStart; |
| nEnd = nLocalEnd; |
| bRet = sal_True; |
| } |
| } |
| // else: this PaM doesn't point to this paragraph |
| } |
| // else: this PaM is collapsed and doesn't select anything |
| |
| // next PaM in ring |
| pCrsr = static_cast<SwPaM*>( pCrsr->GetNext() ); |
| } |
| while( !bRet && (pCrsr != pRingStart) ); |
| } |
| // else: nocursor -> no selection |
| |
| return bRet; |
| } |
| |
| // --> OD 2005-12-20 #i27301# - new parameter <_bForSelection> |
| SwPaM* SwAccessibleParagraph::GetCursor( const bool _bForSelection ) |
| { |
| // get the cursor shell; if we don't have any, we don't have a |
| // cursor/selection either |
| SwPaM* pCrsr = NULL; |
| SwCrsrShell* pCrsrShell = SwAccessibleParagraph::GetCrsrShell(); |
| // --> OD 2005-12-20 #i27301# |
| // - if cursor is retrieved for selection, the cursors for a table selection |
| // has to be returned. |
| if ( pCrsrShell != NULL && |
| ( _bForSelection || !pCrsrShell->IsTableMode() ) ) |
| // <-- |
| { |
| SwFEShell *pFESh = pCrsrShell->ISA( SwFEShell ) |
| ? static_cast< SwFEShell * >( pCrsrShell ) : 0; |
| if( !pFESh || |
| !(pFESh->IsFrmSelected() || pFESh->IsObjSelected() > 0) ) |
| { |
| // get the selection, and test whether it affects our text node |
| pCrsr = pCrsrShell->GetCrsr( sal_False /* ??? */ ); |
| } |
| } |
| |
| return pCrsr; |
| } |
| |
| sal_Bool SwAccessibleParagraph::IsHeading() const |
| { |
| const SwTxtNode *pTxtNd = GetTxtNode(); |
| return pTxtNd->IsOutline(); |
| } |
| |
| void SwAccessibleParagraph::GetStates( |
| ::utl::AccessibleStateSetHelper& rStateSet ) |
| { |
| SwAccessibleContext::GetStates( rStateSet ); |
| |
| // MULTILINE |
| rStateSet.AddState( AccessibleStateType::MULTI_LINE ); |
| |
| // MULTISELECTABLE |
| SwCrsrShell *pCrsrSh = GetCrsrShell(); |
| if( pCrsrSh ) |
| rStateSet.AddState( AccessibleStateType::MULTI_SELECTABLE ); |
| |
| // FOCUSABLE |
| if( pCrsrSh ) |
| rStateSet.AddState( AccessibleStateType::FOCUSABLE ); |
| |
| // FOCUSED (simulates node index of cursor) |
| // --> OD 2005-12-20 #i27301# - consider adjusted method signature |
| SwPaM* pCaret = GetCursor( false ); |
| // <-- |
| const SwTxtNode* pTxtNd = GetTxtNode(); |
| if( pCaret != 0 && pTxtNd != 0 && |
| pTxtNd->GetIndex() == pCaret->GetPoint()->nNode.GetIndex() && |
| nOldCaretPos != -1) |
| { |
| Window *pWin = GetWindow(); |
| if( pWin && pWin->HasFocus() ) |
| rStateSet.AddState( AccessibleStateType::FOCUSED ); |
| ::vos::ORef < SwAccessibleContext > xThis( this ); |
| GetMap()->SetCursorContext( xThis ); |
| } |
| } |
| |
| void SwAccessibleParagraph::_InvalidateContent( sal_Bool bVisibleDataFired ) |
| { |
| ::rtl::OUString sOldText( GetString() ); |
| |
| ClearPortionData(); |
| |
| const ::rtl::OUString& rText = GetString(); |
| |
| if( rText != sOldText ) |
| { |
| // The text is changed |
| AccessibleEventObject aEvent; |
| aEvent.EventId = AccessibleEventId::TEXT_CHANGED; |
| |
| // determine exact changes between sOldText and rText |
| comphelper::OCommonAccessibleText::implInitTextChangedEvent( |
| sOldText, rText, |
| aEvent.OldValue, aEvent.NewValue ); |
| |
| FireAccessibleEvent( aEvent ); |
| } |
| else if( !bVisibleDataFired ) |
| { |
| FireVisibleDataEvent(); |
| } |
| |
| sal_Bool bNewIsHeading = IsHeading(); |
| sal_Bool bOldIsHeading; |
| { |
| vos::OGuard aGuard( aMutex ); |
| bOldIsHeading = bIsHeading; |
| if( bIsHeading != bNewIsHeading ) |
| bIsHeading = bNewIsHeading; |
| } |
| |
| |
| if( bNewIsHeading != bOldIsHeading || rText != sOldText ) |
| { |
| ::rtl::OUString sNewDesc( GetDescription() ); |
| ::rtl::OUString sOldDesc; |
| { |
| vos::OGuard aGuard( aMutex ); |
| sOldDesc = sDesc; |
| if( sDesc != sNewDesc ) |
| sDesc = sNewDesc; |
| } |
| |
| if( sNewDesc != sOldDesc ) |
| { |
| // The text is changed |
| AccessibleEventObject aEvent; |
| aEvent.EventId = AccessibleEventId::DESCRIPTION_CHANGED; |
| aEvent.OldValue <<= sOldDesc; |
| aEvent.NewValue <<= sNewDesc; |
| |
| FireAccessibleEvent( aEvent ); |
| } |
| } |
| } |
| |
| void SwAccessibleParagraph::_InvalidateCursorPos() |
| { |
| // The text is changed |
| sal_Int32 nNew = GetCaretPos(); |
| sal_Int32 nOld; |
| { |
| vos::OGuard aGuard( aMutex ); |
| nOld = nOldCaretPos; |
| nOldCaretPos = nNew; |
| } |
| if( -1 != nNew ) |
| { |
| // remember that object as the one that has the caret. This is |
| // neccessary to notify that object if the cursor leaves it. |
| ::vos::ORef < SwAccessibleContext > xThis( this ); |
| GetMap()->SetCursorContext( xThis ); |
| } |
| |
| Window *pWin = GetWindow(); |
| if( nOld != nNew ) |
| { |
| // The cursor's node position is sumilated by the focus! |
| if( pWin && pWin->HasFocus() && -1 == nOld ) |
| FireStateChangedEvent( AccessibleStateType::FOCUSED, sal_True ); |
| |
| |
| AccessibleEventObject aEvent; |
| aEvent.EventId = AccessibleEventId::CARET_CHANGED; |
| aEvent.OldValue <<= nOld; |
| aEvent.NewValue <<= nNew; |
| |
| FireAccessibleEvent( aEvent ); |
| |
| if( pWin && pWin->HasFocus() && -1 == nNew ) |
| FireStateChangedEvent( AccessibleStateType::FOCUSED, sal_False ); |
| } |
| } |
| |
| void SwAccessibleParagraph::_InvalidateFocus() |
| { |
| Window *pWin = GetWindow(); |
| if( pWin ) |
| { |
| sal_Int32 nPos; |
| { |
| vos::OGuard aGuard( aMutex ); |
| nPos = nOldCaretPos; |
| } |
| ASSERT( nPos != -1, "focus object should be selected" ); |
| |
| FireStateChangedEvent( AccessibleStateType::FOCUSED, |
| pWin->HasFocus() && nPos != -1 ); |
| } |
| } |
| |
| SwAccessibleParagraph::SwAccessibleParagraph( |
| SwAccessibleMap& rInitMap, |
| const SwTxtFrm& rTxtFrm ) |
| // --> OD 2010-02-24 #i108125# |
| : SwClient( const_cast<SwTxtNode*>(rTxtFrm.GetTxtNode()) ) |
| // <-- |
| , SwAccessibleContext( &rInitMap, AccessibleRole::PARAGRAPH, &rTxtFrm ) |
| , sDesc() |
| , pPortionData( NULL ) |
| , pHyperTextData( NULL ) |
| , nOldCaretPos( -1 ) |
| , bIsHeading( sal_False ) |
| , aSelectionHelper( *this ) |
| // --> OD 2010-02-19 #i108125# |
| , mpParaChangeTrackInfo( new SwParaChangeTrackingInfo( rTxtFrm ) ) |
| // <-- |
| { |
| vos::OGuard aGuard(Application::GetSolarMutex()); |
| |
| bIsHeading = IsHeading(); |
| // --> OD 2004-09-27 #117970# - set an empty accessibility name for paragraphs |
| SetName( ::rtl::OUString() ); |
| // <-- |
| |
| // If this object has the focus, then it is remembered by the map itself. |
| nOldCaretPos = GetCaretPos(); |
| } |
| |
| SwAccessibleParagraph::~SwAccessibleParagraph() |
| { |
| vos::OGuard aGuard(Application::GetSolarMutex()); |
| |
| delete pPortionData; |
| delete pHyperTextData; |
| // --> OD 2010-02-22 #i108125# |
| delete mpParaChangeTrackInfo; |
| // <-- |
| } |
| |
| sal_Bool SwAccessibleParagraph::HasCursor() |
| { |
| vos::OGuard aGuard( aMutex ); |
| return nOldCaretPos != -1; |
| } |
| |
| void SwAccessibleParagraph::UpdatePortionData() |
| throw( uno::RuntimeException ) |
| { |
| // obtain the text frame |
| DBG_ASSERT( GetFrm() != NULL, "The text frame has vanished!" ); |
| DBG_ASSERT( GetFrm()->IsTxtFrm(), "The text frame has mutated!" ); |
| const SwTxtFrm* pFrm = static_cast<const SwTxtFrm*>( GetFrm() ); |
| |
| // build new portion data |
| delete pPortionData; |
| pPortionData = new SwAccessiblePortionData( |
| pFrm->GetTxtNode(), GetMap()->GetShell()->GetViewOptions() ); |
| pFrm->VisitPortions( *pPortionData ); |
| |
| DBG_ASSERT( pPortionData != NULL, "UpdatePortionData() failed" ); |
| } |
| |
| void SwAccessibleParagraph::ClearPortionData() |
| { |
| delete pPortionData; |
| pPortionData = NULL; |
| |
| delete pHyperTextData; |
| pHyperTextData = 0; |
| } |
| |
| |
| void SwAccessibleParagraph::ExecuteAtViewShell( sal_uInt16 nSlot ) |
| { |
| DBG_ASSERT( GetMap() != NULL, "no map?" ); |
| ViewShell* pViewShell = GetMap()->GetShell(); |
| |
| DBG_ASSERT( pViewShell != NULL, "View shell exptected!" ); |
| SfxViewShell* pSfxShell = pViewShell->GetSfxViewShell(); |
| |
| DBG_ASSERT( pSfxShell != NULL, "SfxViewShell shell exptected!" ); |
| if( !pSfxShell ) |
| return; |
| |
| SfxViewFrame *pFrame = pSfxShell->GetViewFrame(); |
| DBG_ASSERT( pFrame != NULL, "View frame exptected!" ); |
| if( !pFrame ) |
| return; |
| |
| SfxDispatcher *pDispatcher = pFrame->GetDispatcher(); |
| DBG_ASSERT( pDispatcher != NULL, "Dispatcher exptected!" ); |
| if( !pDispatcher ) |
| return; |
| |
| pDispatcher->Execute( nSlot ); |
| } |
| |
| SwXTextPortion* SwAccessibleParagraph::CreateUnoPortion( |
| sal_Int32 nStartIndex, |
| sal_Int32 nEndIndex ) |
| { |
| DBG_ASSERT( (IsValidChar(nStartIndex, GetString().getLength()) && |
| (nEndIndex == -1)) || |
| IsValidRange(nStartIndex, nEndIndex, GetString().getLength()), |
| "please check parameters before calling this method" ); |
| |
| sal_uInt16 nStart = GetPortionData().GetModelPosition( nStartIndex ); |
| sal_uInt16 nEnd = (nEndIndex == -1) ? (nStart + 1) : |
| GetPortionData().GetModelPosition( nEndIndex ); |
| |
| // create UNO cursor |
| SwTxtNode* pTxtNode = const_cast<SwTxtNode*>( GetTxtNode() ); |
| SwIndex aIndex( pTxtNode, nStart ); |
| SwPosition aStartPos( *pTxtNode, aIndex ); |
| SwUnoCrsr* pUnoCursor = pTxtNode->GetDoc()->CreateUnoCrsr( aStartPos ); |
| pUnoCursor->SetMark(); |
| pUnoCursor->GetMark()->nContent = nEnd; |
| |
| // create a (dummy) text portion to be returned |
| uno::Reference<text::XText> aEmpty; |
| SwXTextPortion* pPortion = |
| new SwXTextPortion ( pUnoCursor, aEmpty, PORTION_TEXT); |
| delete pUnoCursor; |
| |
| return pPortion; |
| } |
| |
| |
| // |
| // range checking for parameter |
| // |
| |
| sal_Bool SwAccessibleParagraph::IsValidChar( |
| sal_Int32 nPos, sal_Int32 nLength) |
| { |
| return (nPos >= 0) && (nPos < nLength); |
| } |
| |
| sal_Bool SwAccessibleParagraph::IsValidPosition( |
| sal_Int32 nPos, sal_Int32 nLength) |
| { |
| return (nPos >= 0) && (nPos <= nLength); |
| } |
| |
| sal_Bool SwAccessibleParagraph::IsValidRange( |
| sal_Int32 nBegin, sal_Int32 nEnd, sal_Int32 nLength) |
| { |
| return IsValidPosition(nBegin, nLength) && IsValidPosition(nEnd, nLength); |
| } |
| |
| |
| // |
| // text boundaries |
| // |
| |
| |
| sal_Bool SwAccessibleParagraph::GetCharBoundary( |
| i18n::Boundary& rBound, |
| const ::rtl::OUString&, |
| sal_Int32 nPos ) |
| { |
| rBound.startPos = nPos; |
| rBound.endPos = nPos+1; |
| return sal_True; |
| } |
| |
| sal_Bool SwAccessibleParagraph::GetWordBoundary( |
| i18n::Boundary& rBound, |
| const ::rtl::OUString& rText, |
| sal_Int32 nPos ) |
| { |
| sal_Bool bRet = sal_False; |
| |
| // now ask the Break-Iterator for the word |
| DBG_ASSERT( pBreakIt != NULL, "We always need a break." ); |
| DBG_ASSERT( pBreakIt->GetBreakIter().is(), "No break-iterator." ); |
| if( pBreakIt->GetBreakIter().is() ) |
| { |
| // get locale for this position |
| sal_uInt16 nModelPos = GetPortionData().GetModelPosition( nPos ); |
| lang::Locale aLocale = pBreakIt->GetLocale( |
| GetTxtNode()->GetLang( nModelPos ) ); |
| |
| // which type of word are we interested in? |
| // (DICTIONARY_WORD includes punctuation, ANY_WORD doesn't.) |
| const sal_uInt16 nWordType = i18n::WordType::ANY_WORD; |
| |
| // get word boundary, as the Break-Iterator sees fit. |
| rBound = pBreakIt->GetBreakIter()->getWordBoundary( |
| rText, nPos, aLocale, nWordType, sal_True ); |
| |
| // It's a word if the first character is an alpha-numeric character. |
| bRet = GetAppCharClass().isLetterNumeric( |
| rText.getStr()[ rBound.startPos ] ); |
| } |
| else |
| { |
| // no break Iterator -> no word |
| rBound.startPos = nPos; |
| rBound.endPos = nPos; |
| } |
| |
| return bRet; |
| } |
| |
| sal_Bool SwAccessibleParagraph::GetSentenceBoundary( |
| i18n::Boundary& rBound, |
| const ::rtl::OUString&, |
| sal_Int32 nPos ) |
| { |
| GetPortionData().GetSentenceBoundary( rBound, nPos ); |
| return sal_True; |
| } |
| |
| sal_Bool SwAccessibleParagraph::GetLineBoundary( |
| i18n::Boundary& rBound, |
| const ::rtl::OUString& rText, |
| sal_Int32 nPos ) |
| { |
| if( rText.getLength() == nPos ) |
| GetPortionData().GetLastLineBoundary( rBound ); |
| else |
| GetPortionData().GetLineBoundary( rBound, nPos ); |
| return sal_True; |
| } |
| |
| sal_Bool SwAccessibleParagraph::GetParagraphBoundary( |
| i18n::Boundary& rBound, |
| const ::rtl::OUString& rText, |
| sal_Int32 ) |
| { |
| rBound.startPos = 0; |
| rBound.endPos = rText.getLength(); |
| return sal_True; |
| } |
| |
| sal_Bool SwAccessibleParagraph::GetAttributeBoundary( |
| i18n::Boundary& rBound, |
| const ::rtl::OUString&, |
| sal_Int32 nPos ) |
| { |
| GetPortionData().GetAttributeBoundary( rBound, nPos ); |
| return sal_True; |
| } |
| |
| sal_Bool SwAccessibleParagraph::GetGlyphBoundary( |
| i18n::Boundary& rBound, |
| const ::rtl::OUString& rText, |
| sal_Int32 nPos ) |
| { |
| sal_Bool bRet = sal_False; |
| |
| // ask the Break-Iterator for the glyph by moving one cell |
| // forward, and then one cell back |
| DBG_ASSERT( pBreakIt != NULL, "We always need a break." ); |
| DBG_ASSERT( pBreakIt->GetBreakIter().is(), "No break-iterator." ); |
| if( pBreakIt->GetBreakIter().is() ) |
| { |
| // get locale for this position |
| sal_uInt16 nModelPos = GetPortionData().GetModelPosition( nPos ); |
| lang::Locale aLocale = pBreakIt->GetLocale( |
| GetTxtNode()->GetLang( nModelPos ) ); |
| |
| // get word boundary, as the Break-Iterator sees fit. |
| const sal_uInt16 nIterMode = i18n::CharacterIteratorMode::SKIPCELL; |
| sal_Int32 nDone = 0; |
| rBound.endPos = pBreakIt->GetBreakIter()->nextCharacters( |
| rText, nPos, aLocale, nIterMode, 1, nDone ); |
| rBound.startPos = pBreakIt->GetBreakIter()->previousCharacters( |
| rText, rBound.endPos, aLocale, nIterMode, 1, nDone ); |
| |
| DBG_ASSERT( rBound.startPos <= nPos, "start pos too high" ); |
| DBG_ASSERT( rBound.endPos >= nPos, "end pos too low" ); |
| } |
| else |
| { |
| // no break Iterator -> no glyph |
| rBound.startPos = nPos; |
| rBound.endPos = nPos; |
| } |
| |
| return bRet; |
| } |
| |
| |
| sal_Bool SwAccessibleParagraph::GetTextBoundary( |
| i18n::Boundary& rBound, |
| const ::rtl::OUString& rText, |
| sal_Int32 nPos, |
| sal_Int16 nTextType ) |
| throw ( |
| lang::IndexOutOfBoundsException, |
| lang::IllegalArgumentException, |
| uno::RuntimeException) |
| { |
| // error checking |
| if( !( AccessibleTextType::LINE == nTextType |
| ? IsValidPosition( nPos, rText.getLength() ) |
| : IsValidChar( nPos, rText.getLength() ) ) ) |
| throw lang::IndexOutOfBoundsException(); |
| |
| sal_Bool bRet; |
| |
| switch( nTextType ) |
| { |
| case AccessibleTextType::WORD: |
| bRet = GetWordBoundary( rBound, rText, nPos ); |
| break; |
| |
| case AccessibleTextType::SENTENCE: |
| bRet = GetSentenceBoundary( rBound, rText, nPos ); |
| break; |
| |
| case AccessibleTextType::PARAGRAPH: |
| bRet = GetParagraphBoundary( rBound, rText, nPos ); |
| break; |
| |
| case AccessibleTextType::CHARACTER: |
| bRet = GetCharBoundary( rBound, rText, nPos ); |
| break; |
| |
| case AccessibleTextType::LINE: |
| bRet = GetLineBoundary( rBound, rText, nPos ); |
| break; |
| |
| case AccessibleTextType::ATTRIBUTE_RUN: |
| bRet = GetAttributeBoundary( rBound, rText, nPos ); |
| break; |
| |
| case AccessibleTextType::GLYPH: |
| bRet = GetGlyphBoundary( rBound, rText, nPos ); |
| break; |
| |
| default: |
| throw lang::IllegalArgumentException( ); |
| } |
| |
| return bRet; |
| } |
| |
| ::rtl::OUString SAL_CALL SwAccessibleParagraph::getAccessibleDescription (void) |
| throw (uno::RuntimeException) |
| { |
| vos::OGuard aGuard(Application::GetSolarMutex()); |
| |
| CHECK_FOR_DEFUNC( XAccessibleContext ); |
| |
| vos::OGuard aGuard2( aMutex ); |
| if( !sDesc.getLength() ) |
| sDesc = GetDescription(); |
| |
| return sDesc; |
| } |
| |
| lang::Locale SAL_CALL SwAccessibleParagraph::getLocale (void) |
| throw (IllegalAccessibleComponentStateException, uno::RuntimeException) |
| { |
| vos::OGuard aGuard(Application::GetSolarMutex()); |
| |
| SwTxtFrm *pTxtFrm = PTR_CAST( SwTxtFrm, GetFrm() ); |
| if( !pTxtFrm ) |
| { |
| THROW_RUNTIME_EXCEPTION( XAccessibleContext, "internal error (no text frame)" ); |
| } |
| |
| const SwTxtNode *pTxtNd = pTxtFrm->GetTxtNode(); |
| lang::Locale aLoc( pBreakIt->GetLocale( pTxtNd->GetLang( 0 ) ) ); |
| |
| return aLoc; |
| } |
| |
| /** paragraphs are in relation CONTENT_FLOWS_FROM and/or CONTENT_FLOWS_TO |
| |
| OD 2005-12-02 #i27138# |
| |
| @author OD |
| */ |
| uno::Reference<XAccessibleRelationSet> SAL_CALL SwAccessibleParagraph::getAccessibleRelationSet() |
| throw ( uno::RuntimeException ) |
| { |
| vos::OGuard aGuard(Application::GetSolarMutex()); |
| CHECK_FOR_DEFUNC( XAccessibleContext ); |
| |
| utl::AccessibleRelationSetHelper* pHelper = new utl::AccessibleRelationSetHelper(); |
| |
| const SwTxtFrm* pTxtFrm = dynamic_cast<const SwTxtFrm*>(GetFrm()); |
| ASSERT( pTxtFrm, |
| "<SwAccessibleParagraph::getAccessibleRelationSet()> - missing text frame"); |
| if ( pTxtFrm ) |
| { |
| const SwCntntFrm* pPrevCntFrm( pTxtFrm->FindPrevCnt( true ) ); |
| if ( pPrevCntFrm ) |
| { |
| uno::Sequence< uno::Reference<XInterface> > aSequence(1); |
| aSequence[0] = GetMap()->GetContext( pPrevCntFrm ); |
| AccessibleRelation aAccRel( AccessibleRelationType::CONTENT_FLOWS_FROM, |
| aSequence ); |
| pHelper->AddRelation( aAccRel ); |
| } |
| |
| const SwCntntFrm* pNextCntFrm( pTxtFrm->FindNextCnt( true ) ); |
| if ( pNextCntFrm ) |
| { |
| uno::Sequence< uno::Reference<XInterface> > aSequence(1); |
| aSequence[0] = GetMap()->GetContext( pNextCntFrm ); |
| AccessibleRelation aAccRel( AccessibleRelationType::CONTENT_FLOWS_TO, |
| aSequence ); |
| pHelper->AddRelation( aAccRel ); |
| } |
| } |
| |
| return pHelper; |
| } |
| |
| void SAL_CALL SwAccessibleParagraph::grabFocus() |
| throw (uno::RuntimeException) |
| { |
| vos::OGuard aGuard(Application::GetSolarMutex()); |
| |
| CHECK_FOR_DEFUNC( XAccessibleContext ); |
| |
| // get cursor shell |
| SwCrsrShell *pCrsrSh = GetCrsrShell(); |
| // --> OD 2005-12-20 #i27301# - consider new method signature |
| SwPaM *pCrsr = GetCursor( false ); |
| // <-- |
| const SwTxtFrm *pTxtFrm = static_cast<const SwTxtFrm*>( GetFrm() ); |
| const SwTxtNode* pTxtNd = pTxtFrm->GetTxtNode(); |
| |
| if( pCrsrSh != 0 && pTxtNd != 0 && |
| ( pCrsr == 0 || |
| pCrsr->GetPoint()->nNode.GetIndex() != pTxtNd->GetIndex() || |
| !pTxtFrm->IsInside( pCrsr->GetPoint()->nContent.GetIndex()) ) ) |
| { |
| // create pam for selection |
| SwIndex aIndex( const_cast< SwTxtNode * >( pTxtNd ), |
| pTxtFrm->GetOfst() ); |
| SwPosition aStartPos( *pTxtNd, aIndex ); |
| SwPaM aPaM( aStartPos ); |
| |
| // set PaM at cursor shell |
| Select( aPaM ); |
| |
| |
| } |
| |
| /* ->#i13955# */ |
| Window * pWindow = GetWindow(); |
| |
| if (pWindow != NULL) |
| pWindow->GrabFocus(); |
| /* <-#i13955# */ |
| } |
| |
| // --> OD 2007-01-17 #i71385# |
| bool lcl_GetBackgroundColor( Color & rColor, |
| const SwFrm* pFrm, |
| SwCrsrShell* pCrsrSh ) |
| { |
| const SvxBrushItem* pBackgrdBrush = 0; |
| const Color* pSectionTOXColor = 0; |
| SwRect aDummyRect; |
| if ( pFrm && |
| pFrm->GetBackgroundBrush( pBackgrdBrush, pSectionTOXColor, aDummyRect, false ) ) |
| { |
| if ( pSectionTOXColor ) |
| { |
| rColor = *pSectionTOXColor; |
| return true; |
| } |
| else |
| { |
| rColor = pBackgrdBrush->GetColor(); |
| return true; |
| } |
| } |
| else if ( pCrsrSh ) |
| { |
| rColor = pCrsrSh->Imp()->GetRetoucheColor(); |
| return true; |
| } |
| |
| return false; |
| } |
| |
| sal_Int32 SAL_CALL SwAccessibleParagraph::getForeground() |
| throw (uno::RuntimeException) |
| { |
| Color aBackgroundCol; |
| |
| if ( lcl_GetBackgroundColor( aBackgroundCol, GetFrm(), GetCrsrShell() ) ) |
| { |
| if ( aBackgroundCol.IsDark() ) |
| { |
| return COL_WHITE; |
| } |
| else |
| { |
| return COL_BLACK; |
| } |
| } |
| |
| return SwAccessibleContext::getForeground(); |
| } |
| |
| sal_Int32 SAL_CALL SwAccessibleParagraph::getBackground() |
| throw (uno::RuntimeException) |
| { |
| Color aBackgroundCol; |
| |
| if ( lcl_GetBackgroundColor( aBackgroundCol, GetFrm(), GetCrsrShell() ) ) |
| { |
| return aBackgroundCol.GetColor(); |
| } |
| |
| return SwAccessibleContext::getBackground(); |
| } |
| // <-- |
| |
| ::rtl::OUString SAL_CALL SwAccessibleParagraph::getImplementationName() |
| throw( uno::RuntimeException ) |
| { |
| return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(sImplementationName)); |
| } |
| |
| sal_Bool SAL_CALL SwAccessibleParagraph::supportsService( |
| const ::rtl::OUString& sTestServiceName) |
| throw (uno::RuntimeException) |
| { |
| return sTestServiceName.equalsAsciiL( sServiceName, |
| sizeof(sServiceName)-1 ) || |
| sTestServiceName.equalsAsciiL( sAccessibleServiceName, |
| sizeof(sAccessibleServiceName)-1 ); |
| } |
| |
| uno::Sequence< ::rtl::OUString > SAL_CALL SwAccessibleParagraph::getSupportedServiceNames() |
| throw( uno::RuntimeException ) |
| { |
| uno::Sequence< ::rtl::OUString > aRet(2); |
| ::rtl::OUString* pArray = aRet.getArray(); |
| pArray[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(sServiceName) ); |
| pArray[1] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(sAccessibleServiceName) ); |
| return aRet; |
| } |
| |
| // |
| //===== XInterface ======================================================= |
| // |
| |
| uno::Any SwAccessibleParagraph::queryInterface( const uno::Type& rType ) |
| throw (uno::RuntimeException) |
| { |
| uno::Any aRet; |
| if ( rType == ::getCppuType((uno::Reference<XAccessibleText> *)0) ) |
| { |
| uno::Reference<XAccessibleText> aAccText = (XAccessibleText *) *this; // resolve ambiguity |
| aRet <<= aAccText; |
| } |
| else if ( rType == ::getCppuType((uno::Reference<XAccessibleEditableText> *)0) ) |
| { |
| uno::Reference<XAccessibleEditableText> aAccEditText = this; |
| aRet <<= aAccEditText; |
| } |
| else if ( rType == ::getCppuType((uno::Reference<XAccessibleSelection> *)0) ) |
| { |
| uno::Reference<XAccessibleSelection> aAccSel = this; |
| aRet <<= aAccSel; |
| } |
| else if ( rType == ::getCppuType((uno::Reference<XAccessibleHypertext> *)0) ) |
| { |
| uno::Reference<XAccessibleHypertext> aAccHyp = this; |
| aRet <<= aAccHyp; |
| } |
| // --> OD 2006-07-13 #i63870# |
| // add interface com::sun:star:accessibility::XAccessibleTextAttributes |
| else if ( rType == ::getCppuType((uno::Reference<XAccessibleTextAttributes> *)0) ) |
| { |
| uno::Reference<XAccessibleTextAttributes> aAccTextAttr = this; |
| aRet <<= aAccTextAttr; |
| } |
| // <-- |
| // --> OD 2008-06-10 #i89175# |
| // add interface com::sun:star:accessibility::XAccessibleTextMarkup |
| else if ( rType == ::getCppuType((uno::Reference<XAccessibleTextMarkup> *)0) ) |
| { |
| uno::Reference<XAccessibleTextMarkup> aAccTextMarkup = this; |
| aRet <<= aAccTextMarkup; |
| } |
| // add interface com::sun:star:accessibility::XAccessibleMultiLineText |
| else if ( rType == ::getCppuType((uno::Reference<XAccessibleMultiLineText> *)0) ) |
| { |
| uno::Reference<XAccessibleMultiLineText> aAccMultiLineText = this; |
| aRet <<= aAccMultiLineText; |
| } |
| // <-- |
| else |
| { |
| aRet = SwAccessibleContext::queryInterface(rType); |
| } |
| |
| return aRet; |
| } |
| |
| //====== XTypeProvider ==================================================== |
| uno::Sequence< uno::Type > SAL_CALL SwAccessibleParagraph::getTypes() throw(uno::RuntimeException) |
| { |
| uno::Sequence< uno::Type > aTypes( SwAccessibleContext::getTypes() ); |
| |
| sal_Int32 nIndex = aTypes.getLength(); |
| // --> OD 2006-07-13 #i63870# |
| // add type accessibility::XAccessibleTextAttributes |
| // --> OD 2008-06-10 #i89175# |
| // add type accessibility::XAccessibleTextMarkup and accessibility::XAccessibleMultiLineText |
| aTypes.realloc( nIndex + 6 ); |
| |
| uno::Type* pTypes = aTypes.getArray(); |
| pTypes[nIndex++] = ::getCppuType( static_cast< uno::Reference< XAccessibleEditableText > * >( 0 ) ); |
| pTypes[nIndex++] = ::getCppuType( static_cast< uno::Reference< XAccessibleTextAttributes > * >( 0 ) ); |
| pTypes[nIndex++] = ::getCppuType( static_cast< uno::Reference< XAccessibleSelection > * >( 0 ) ); |
| pTypes[nIndex++] = ::getCppuType( static_cast< uno::Reference< XAccessibleTextMarkup > * >( 0 ) ); |
| pTypes[nIndex++] = ::getCppuType( static_cast< uno::Reference< XAccessibleMultiLineText > * >( 0 ) ); |
| pTypes[nIndex] = ::getCppuType( static_cast< uno::Reference< XAccessibleHypertext > * >( 0 ) ); |
| // <-- |
| |
| return aTypes; |
| } |
| |
| uno::Sequence< sal_Int8 > SAL_CALL SwAccessibleParagraph::getImplementationId() |
| throw(uno::RuntimeException) |
| { |
| vos::OGuard aGuard(Application::GetSolarMutex()); |
| static uno::Sequence< sal_Int8 > aId( 16 ); |
| static sal_Bool bInit = sal_False; |
| if(!bInit) |
| { |
| rtl_createUuid( (sal_uInt8 *)(aId.getArray() ), 0, sal_True ); |
| bInit = sal_True; |
| } |
| return aId; |
| } |
| |
| |
| // |
| //===== XAccesibleText =================================================== |
| // |
| |
| sal_Int32 SwAccessibleParagraph::getCaretPosition() |
| throw (uno::RuntimeException) |
| { |
| vos::OGuard aGuard(Application::GetSolarMutex()); |
| |
| CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); |
| |
| sal_Int32 nRet = GetCaretPos(); |
| { |
| vos::OGuard aOldCaretPosGuard( aMutex ); |
| ASSERT( nRet == nOldCaretPos, "caret pos out of sync" ); |
| nOldCaretPos = nRet; |
| } |
| if( -1 != nRet ) |
| { |
| ::vos::ORef < SwAccessibleContext > xThis( this ); |
| GetMap()->SetCursorContext( xThis ); |
| } |
| |
| return nRet; |
| } |
| |
| sal_Bool SAL_CALL SwAccessibleParagraph::setCaretPosition( sal_Int32 nIndex ) |
| throw (lang::IndexOutOfBoundsException, uno::RuntimeException) |
| { |
| vos::OGuard aGuard(Application::GetSolarMutex()); |
| |
| CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); |
| |
| // parameter checking |
| sal_Int32 nLength = GetString().getLength(); |
| if ( ! IsValidPosition( nIndex, nLength ) ) |
| { |
| throw lang::IndexOutOfBoundsException(); |
| } |
| |
| sal_Bool bRet = sal_False; |
| |
| // get cursor shell |
| SwCrsrShell* pCrsrShell = GetCrsrShell(); |
| if( pCrsrShell != NULL ) |
| { |
| // create pam for selection |
| SwTxtNode* pNode = const_cast<SwTxtNode*>( GetTxtNode() ); |
| SwIndex aIndex( pNode, GetPortionData().GetModelPosition(nIndex)); |
| SwPosition aStartPos( *pNode, aIndex ); |
| SwPaM aPaM( aStartPos ); |
| |
| // set PaM at cursor shell |
| bRet = Select( aPaM ); |
| } |
| |
| return bRet; |
| } |
| |
| sal_Unicode SwAccessibleParagraph::getCharacter( sal_Int32 nIndex ) |
| throw (lang::IndexOutOfBoundsException, uno::RuntimeException) |
| { |
| vos::OGuard aGuard(Application::GetSolarMutex()); |
| |
| CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); |
| |
| ::rtl::OUString sText( GetString() ); |
| |
| // return character (if valid) |
| if( IsValidChar(nIndex, sText.getLength() ) ) |
| { |
| return sText.getStr()[nIndex]; |
| } |
| else |
| throw lang::IndexOutOfBoundsException(); |
| } |
| |
| // --> OD 2006-07-20 #i63870# |
| // re-implement method on behalf of methods <_getDefaultAttributesImpl(..)> and |
| // <_getRunAttributesImpl(..)> |
| uno::Sequence<PropertyValue> SwAccessibleParagraph::getCharacterAttributes( |
| sal_Int32 nIndex, |
| const uno::Sequence< ::rtl::OUString >& aRequestedAttributes ) |
| throw (lang::IndexOutOfBoundsException, uno::RuntimeException) |
| { |
| |
| vos::OGuard aGuard(Application::GetSolarMutex()); |
| CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); |
| |
| const ::rtl::OUString& rText = GetString(); |
| |
| if( ! IsValidChar( nIndex, rText.getLength() ) ) |
| throw lang::IndexOutOfBoundsException(); |
| |
| // retrieve default character attributes |
| tAccParaPropValMap aDefAttrSeq; |
| _getDefaultAttributesImpl( aRequestedAttributes, aDefAttrSeq, true ); |
| |
| // retrieved run character attributes |
| tAccParaPropValMap aRunAttrSeq; |
| _getRunAttributesImpl( nIndex, aRequestedAttributes, aRunAttrSeq ); |
| |
| // merge default and run attributes |
| uno::Sequence< PropertyValue > aValues( aDefAttrSeq.size() ); |
| PropertyValue* pValues = aValues.getArray(); |
| sal_Int32 i = 0; |
| for ( tAccParaPropValMap::const_iterator aDefIter = aDefAttrSeq.begin(); |
| aDefIter != aDefAttrSeq.end(); |
| ++aDefIter ) |
| { |
| tAccParaPropValMap::const_iterator aRunIter = |
| aRunAttrSeq.find( aDefIter->first ); |
| if ( aRunIter != aRunAttrSeq.end() ) |
| { |
| pValues[i] = aRunIter->second; |
| } |
| else |
| { |
| pValues[i] = aDefIter->second; |
| } |
| ++i; |
| } |
| |
| // // create a (dummy) text portion for the sole purpose of calling |
| // // getPropertyValues on it |
| // Reference<XMultiPropertySet> xPortion = CreateUnoPortion( nIndex, nIndex + 1 ); |
| |
| // // get values |
| // Sequence<OUString> aNames = getAttributeNames(); |
| // sal_Int32 nLength = aNames.getLength(); |
| // Sequence<Any> aAnys( nLength ); |
| // aAnys = xPortion->getPropertyValues( aNames ); |
| |
| // // copy names + anys into return sequence |
| // Sequence<PropertyValue> aValues( aNames.getLength() ); |
| // const OUString* pNames = aNames.getConstArray(); |
| // const Any* pAnys = aAnys.getConstArray(); |
| // PropertyValue* pValues = aValues.getArray(); |
| // for( sal_Int32 i = 0; i < nLength; i++ ) |
| // { |
| // PropertyValue& rValue = pValues[i]; |
| // rValue.Name = pNames[i]; |
| // rValue.Value = pAnys[i]; |
| // rValue.Handle = -1; // handle not supported |
| // rValue.State = PropertyState_DIRECT_VALUE; // states not supported |
| // } |
| |
| // // adjust background color if we're in a gray portion |
| // DBG_ASSERT( pValues[CHAR_BACK_COLOR_POS].Name. |
| // equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("CharBackColor")), |
| // "Please adjust CHAR_BACK_COLOR_POS constant." ); |
| // if( GetPortionData().IsInGrayPortion( nIndex ) ) |
| // pValues[CHAR_BACK_COLOR_POS].Value <<= SwViewOption::GetFieldShadingsColor().GetColor(); |
| |
| return aValues; |
| } |
| |
| // --> OD 2006-07-11 #i63870# |
| void SwAccessibleParagraph::_getDefaultAttributesImpl( |
| const uno::Sequence< ::rtl::OUString >& aRequestedAttributes, |
| tAccParaPropValMap& rDefAttrSeq, |
| const bool bOnlyCharAttrs ) |
| { |
| // retrieve default attributes |
| const SwTxtNode* pTxtNode( GetTxtNode() ); |
| ::boost::scoped_ptr<SfxItemSet> pSet; |
| if ( !bOnlyCharAttrs ) |
| { |
| pSet.reset( new SfxItemSet( const_cast<SwAttrPool&>(pTxtNode->GetDoc()->GetAttrPool()), |
| RES_CHRATR_BEGIN, RES_CHRATR_END - 1, |
| RES_PARATR_BEGIN, RES_PARATR_END - 1, |
| RES_FRMATR_BEGIN, RES_FRMATR_END - 1, |
| 0 ) ); |
| } |
| else |
| { |
| pSet.reset( new SfxItemSet( const_cast<SwAttrPool&>(pTxtNode->GetDoc()->GetAttrPool()), |
| RES_CHRATR_BEGIN, RES_CHRATR_END - 1, |
| 0 ) ); |
| } |
| // --> OD 2007-11-12 #i82637# |
| // From the perspective of the a11y API the default character attributes |
| // are the character attributes, which are set at the paragraph style |
| // of the paragraph. The character attributes set at the automatic paragraph |
| // style of the paragraph are treated as run attributes. |
| // pTxtNode->SwCntntNode::GetAttr( *pSet ); |
| // get default paragraph attributes, if needed, and merge these into <pSet> |
| if ( !bOnlyCharAttrs ) |
| { |
| SfxItemSet aParaSet( const_cast<SwAttrPool&>(pTxtNode->GetDoc()->GetAttrPool()), |
| RES_PARATR_BEGIN, RES_PARATR_END - 1, |
| RES_FRMATR_BEGIN, RES_FRMATR_END - 1, |
| 0 ); |
| pTxtNode->SwCntntNode::GetAttr( aParaSet ); |
| pSet->Put( aParaSet ); |
| } |
| // get default character attributes and merge these into <pSet> |
| ASSERT( pTxtNode->GetTxtColl(), |
| "<SwAccessibleParagraph::_getDefaultAttributesImpl(..)> - missing paragraph style. Serious defect, please inform OD!" ); |
| if ( pTxtNode->GetTxtColl() ) |
| { |
| SfxItemSet aCharSet( const_cast<SwAttrPool&>(pTxtNode->GetDoc()->GetAttrPool()), |
| RES_CHRATR_BEGIN, RES_CHRATR_END - 1, |
| 0 ); |
| aCharSet.Put( pTxtNode->GetTxtColl()->GetAttrSet() ); |
| pSet->Put( aCharSet ); |
| } |
| // <-- |
| |
| // build-up sequence containing the run attributes <rDefAttrSeq> |
| tAccParaPropValMap aDefAttrSeq; |
| { |
| const SfxItemPropertyMap* pPropMap = |
| aSwMapProvider.GetPropertySet( PROPERTY_MAP_TEXT_CURSOR )->getPropertyMap(); |
| PropertyEntryVector_t aPropertyEntries = pPropMap->getPropertyEntries(); |
| PropertyEntryVector_t::const_iterator aPropIt = aPropertyEntries.begin(); |
| while ( aPropIt != aPropertyEntries.end() ) |
| { |
| const SfxPoolItem* pItem = pSet->GetItem( aPropIt->nWID ); |
| if ( pItem ) |
| { |
| uno::Any aVal; |
| pItem->QueryValue( aVal, aPropIt->nMemberId ); |
| |
| PropertyValue rPropVal; |
| rPropVal.Name = aPropIt->sName; |
| rPropVal.Value = aVal; |
| rPropVal.Handle = -1; |
| rPropVal.State = beans::PropertyState_DEFAULT_VALUE; |
| |
| aDefAttrSeq[rPropVal.Name] = rPropVal; |
| } |
| ++aPropIt; |
| } |
| |
| // --> OD 2007-01-15 #i72800# |
| // add property value entry for the paragraph style |
| if ( !bOnlyCharAttrs && pTxtNode->GetTxtColl() ) |
| { |
| const ::rtl::OUString sParaStyleName = |
| ::rtl::OUString::createFromAscii( |
| GetPropName( UNO_NAME_PARA_STYLE_NAME ).pName ); |
| if ( aDefAttrSeq.find( sParaStyleName ) == aDefAttrSeq.end() ) |
| { |
| PropertyValue rPropVal; |
| rPropVal.Name = sParaStyleName; |
| uno::Any aVal( uno::makeAny( ::rtl::OUString( pTxtNode->GetTxtColl()->GetName() ) ) ); |
| rPropVal.Value = aVal; |
| rPropVal.Handle = -1; |
| rPropVal.State = beans::PropertyState_DEFAULT_VALUE; |
| |
| aDefAttrSeq[rPropVal.Name] = rPropVal; |
| } |
| } |
| // <-- |
| |
| // --> OD 2007-01-15 #i73371# |
| // resolve value text::WritingMode2::PAGE of property value entry WritingMode |
| if ( !bOnlyCharAttrs && GetFrm() ) |
| { |
| const ::rtl::OUString sWritingMode = |
| ::rtl::OUString::createFromAscii( |
| GetPropName( UNO_NAME_WRITING_MODE ).pName ); |
| tAccParaPropValMap::iterator aIter = aDefAttrSeq.find( sWritingMode ); |
| if ( aIter != aDefAttrSeq.end() ) |
| { |
| PropertyValue rPropVal( aIter->second ); |
| sal_Int16 nVal = rPropVal.Value.get<sal_Int16>(); |
| if ( nVal == text::WritingMode2::PAGE ) |
| { |
| const SwFrm* pUpperFrm( GetFrm()->GetUpper() ); |
| while ( pUpperFrm ) |
| { |
| if ( pUpperFrm->GetType() & |
| ( FRM_PAGE | FRM_FLY | FRM_SECTION | FRM_TAB | FRM_CELL ) ) |
| { |
| if ( pUpperFrm->IsVertical() ) |
| { |
| nVal = text::WritingMode2::TB_RL; |
| } |
| else if ( pUpperFrm->IsRightToLeft() ) |
| { |
| nVal = text::WritingMode2::RL_TB; |
| } |
| else |
| { |
| nVal = text::WritingMode2::LR_TB; |
| } |
| rPropVal.Value <<= nVal; |
| aDefAttrSeq[rPropVal.Name] = rPropVal; |
| break; |
| } |
| |
| if ( dynamic_cast<const SwFlyFrm*>(pUpperFrm) ) |
| { |
| pUpperFrm = dynamic_cast<const SwFlyFrm*>(pUpperFrm)->GetAnchorFrm(); |
| } |
| else |
| { |
| pUpperFrm = pUpperFrm->GetUpper(); |
| } |
| } |
| } |
| } |
| } |
| // <-- |
| } |
| |
| if ( aRequestedAttributes.getLength() == 0 ) |
| { |
| rDefAttrSeq = aDefAttrSeq; |
| } |
| else |
| { |
| const ::rtl::OUString* pReqAttrs = aRequestedAttributes.getConstArray(); |
| const sal_Int32 nLength = aRequestedAttributes.getLength(); |
| for( sal_Int32 i = 0; i < nLength; ++i ) |
| { |
| tAccParaPropValMap::const_iterator const aIter = aDefAttrSeq.find( pReqAttrs[i] ); |
| if ( aIter != aDefAttrSeq.end() ) |
| { |
| rDefAttrSeq[ aIter->first ] = aIter->second; |
| } |
| } |
| } |
| } |
| |
| uno::Sequence< PropertyValue > SwAccessibleParagraph::getDefaultAttributes( |
| const uno::Sequence< ::rtl::OUString >& aRequestedAttributes ) |
| throw ( uno::RuntimeException ) |
| { |
| vos::OGuard aGuard(Application::GetSolarMutex()); |
| CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); |
| |
| tAccParaPropValMap aDefAttrSeq; |
| _getDefaultAttributesImpl( aRequestedAttributes, aDefAttrSeq ); |
| |
| // --> OD 2010-03-08 #i92233# |
| static rtl::OUString sMMToPixelRatio( rtl::OUString::createFromAscii( "MMToPixelRatio" ) ); |
| bool bProvideMMToPixelRatio( false ); |
| { |
| if ( aRequestedAttributes.getLength() == 0 ) |
| { |
| bProvideMMToPixelRatio = true; |
| } |
| else |
| { |
| const rtl::OUString* aRequestedAttrIter = |
| ::std::find( ::comphelper::stl_begin( aRequestedAttributes ), |
| ::comphelper::stl_end( aRequestedAttributes ), |
| sMMToPixelRatio ); |
| if ( aRequestedAttrIter != ::comphelper::stl_end( aRequestedAttributes ) ) |
| { |
| bProvideMMToPixelRatio = true; |
| } |
| } |
| } |
| // <-- |
| |
| uno::Sequence< PropertyValue > aValues( aDefAttrSeq.size() + |
| ( bProvideMMToPixelRatio ? 1 : 0 ) ); |
| PropertyValue* pValues = aValues.getArray(); |
| sal_Int32 i = 0; |
| for ( tAccParaPropValMap::const_iterator aIter = aDefAttrSeq.begin(); |
| aIter != aDefAttrSeq.end(); |
| ++aIter ) |
| { |
| pValues[i] = aIter->second; |
| ++i; |
| } |
| |
| // --> OD 2010-03-08 #i92233# |
| if ( bProvideMMToPixelRatio ) |
| { |
| PropertyValue rPropVal; |
| rPropVal.Name = sMMToPixelRatio; |
| const Size a100thMMSize( 1000, 1000 ); |
| const Size aPixelSize = GetMap()->LogicToPixel( a100thMMSize ); |
| const float fRatio = ((float)a100thMMSize.Width()/100)/aPixelSize.Width(); |
| rPropVal.Value = uno::makeAny( fRatio ); |
| rPropVal.Handle = -1; |
| rPropVal.State = beans::PropertyState_DEFAULT_VALUE; |
| pValues[ aValues.getLength() - 1 ] = rPropVal; |
| } |
| // <-- |
| |
| return aValues; |
| } |
| |
| void SwAccessibleParagraph::_getRunAttributesImpl( |
| const sal_Int32 nIndex, |
| const uno::Sequence< ::rtl::OUString >& aRequestedAttributes, |
| tAccParaPropValMap& rRunAttrSeq ) |
| { |
| // create PaM for character at position <nIndex> |
| SwPaM* pPaM( 0 ); |
| { |
| const SwTxtNode* pTxtNode( GetTxtNode() ); |
| SwPosition* pStartPos = new SwPosition( *pTxtNode ); |
| pStartPos->nContent.Assign( const_cast<SwTxtNode*>(pTxtNode), static_cast<sal_uInt16>(nIndex) ); |
| SwPosition* pEndPos = new SwPosition( *pTxtNode ); |
| pEndPos->nContent.Assign( const_cast<SwTxtNode*>(pTxtNode), static_cast<sal_uInt16>(nIndex+1) ); |
| |
| pPaM = new SwPaM( *pStartPos, *pEndPos ); |
| |
| delete pStartPos; |
| delete pEndPos; |
| } |
| |
| // retrieve character attributes for the created PaM <pPaM> |
| SfxItemSet aSet( pPaM->GetDoc()->GetAttrPool(), |
| RES_CHRATR_BEGIN, RES_CHRATR_END -1, |
| 0 ); |
| // --> OD 2007-11-12 #i82637# |
| // From the perspective of the a11y API the character attributes, which |
| // are set at the automatic paragraph style of the paragraph are treated |
| // as run attributes. |
| // SwXTextCursor::GetCrsrAttr( *pPaM, aSet, sal_True, sal_True ); |
| // get character attributes from automatic paragraph style and merge these into <aSet> |
| { |
| const SwTxtNode* pTxtNode( GetTxtNode() ); |
| if ( pTxtNode->HasSwAttrSet() ) |
| { |
| SfxItemSet aAutomaticParaStyleCharAttrs( pPaM->GetDoc()->GetAttrPool(), |
| RES_CHRATR_BEGIN, RES_CHRATR_END -1, |
| 0 ); |
| aAutomaticParaStyleCharAttrs.Put( *(pTxtNode->GetpSwAttrSet()), sal_False ); |
| aSet.Put( aAutomaticParaStyleCharAttrs ); |
| } |
| } |
| // get character attributes at <pPaM> and merge these into <aSet> |
| { |
| SfxItemSet aCharAttrsAtPaM( pPaM->GetDoc()->GetAttrPool(), |
| RES_CHRATR_BEGIN, RES_CHRATR_END -1, |
| 0 ); |
| SwUnoCursorHelper::GetCrsrAttr(*pPaM, aCharAttrsAtPaM, sal_True, sal_True); |
| aSet.Put( aCharAttrsAtPaM ); |
| } |
| // <-- |
| |
| // build-up sequence containing the run attributes <rRunAttrSeq> |
| { |
| tAccParaPropValMap aRunAttrSeq; |
| { |
| // --> OD 2007-11-12 #i82637# |
| tAccParaPropValMap aDefAttrSeq; |
| uno::Sequence< ::rtl::OUString > aDummy; |
| _getDefaultAttributesImpl( aDummy, aDefAttrSeq, true ); |
| // <-- |
| |
| const SfxItemPropertyMap* pPropMap = |
| aSwMapProvider.GetPropertySet( PROPERTY_MAP_TEXT_CURSOR )->getPropertyMap(); |
| PropertyEntryVector_t aPropertyEntries = pPropMap->getPropertyEntries(); |
| PropertyEntryVector_t::const_iterator aPropIt = aPropertyEntries.begin(); |
| while ( aPropIt != aPropertyEntries.end() ) |
| { |
| const SfxPoolItem* pItem( 0 ); |
| // --> OD 2007-11-12 #i82637# |
| // Found character attributes, whose value equals the value of |
| // the corresponding default character attributes, are excluded. |
| if ( aSet.GetItemState( aPropIt->nWID, sal_True, &pItem ) == SFX_ITEM_SET ) |
| { |
| uno::Any aVal; |
| pItem->QueryValue( aVal, aPropIt->nMemberId ); |
| |
| PropertyValue rPropVal; |
| rPropVal.Name = aPropIt->sName; |
| rPropVal.Value = aVal; |
| rPropVal.Handle = -1; |
| rPropVal.State = PropertyState_DIRECT_VALUE; |
| |
| tAccParaPropValMap::const_iterator aDefIter = |
| aDefAttrSeq.find( rPropVal.Name ); |
| if ( aDefIter == aDefAttrSeq.end() || |
| rPropVal.Value != aDefIter->second.Value ) |
| { |
| aRunAttrSeq[rPropVal.Name] = rPropVal; |
| } |
| } |
| |
| ++aPropIt; |
| } |
| } |
| |
| if ( aRequestedAttributes.getLength() == 0 ) |
| { |
| rRunAttrSeq = aRunAttrSeq; |
| } |
| else |
| { |
| const ::rtl::OUString* pReqAttrs = aRequestedAttributes.getConstArray(); |
| const sal_Int32 nLength = aRequestedAttributes.getLength(); |
| for( sal_Int32 i = 0; i < nLength; ++i ) |
| { |
| tAccParaPropValMap::iterator aIter = aRunAttrSeq.find( pReqAttrs[i] ); |
| if ( aIter != aRunAttrSeq.end() ) |
| { |
| rRunAttrSeq[ (*aIter).first ] = (*aIter).second; |
| } |
| } |
| } |
| } |
| |
| delete pPaM; |
| } |
| |
| uno::Sequence< PropertyValue > SwAccessibleParagraph::getRunAttributes( |
| sal_Int32 nIndex, |
| const uno::Sequence< ::rtl::OUString >& aRequestedAttributes ) |
| throw ( lang::IndexOutOfBoundsException, |
| uno::RuntimeException ) |
| { |
| vos::OGuard aGuard(Application::GetSolarMutex()); |
| CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); |
| |
| { |
| const ::rtl::OUString& rText = GetString(); |
| if ( !IsValidChar( nIndex, rText.getLength() ) ) |
| { |
| throw lang::IndexOutOfBoundsException(); |
| } |
| } |
| |
| tAccParaPropValMap aRunAttrSeq; |
| _getRunAttributesImpl( nIndex, aRequestedAttributes, aRunAttrSeq ); |
| |
| uno::Sequence< PropertyValue > aValues( aRunAttrSeq.size() ); |
| PropertyValue* pValues = aValues.getArray(); |
| sal_Int32 i = 0; |
| for ( tAccParaPropValMap::const_iterator aIter = aRunAttrSeq.begin(); |
| aIter != aRunAttrSeq.end(); |
| ++aIter ) |
| { |
| pValues[i] = aIter->second; |
| ++i; |
| } |
| |
| return aValues; |
| } |
| // <-- |
| |
| awt::Rectangle SwAccessibleParagraph::getCharacterBounds( |
| sal_Int32 nIndex ) |
| throw (lang::IndexOutOfBoundsException, uno::RuntimeException) |
| { |
| vos::OGuard aGuard(Application::GetSolarMutex()); |
| |
| CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); |
| |
| |
| /* #i12332# The position after the string needs special treatment. |
| IsValidChar -> IsValidPosition |
| */ |
| if( ! (IsValidPosition( nIndex, GetString().getLength() ) ) ) |
| throw lang::IndexOutOfBoundsException(); |
| |
| /* #i12332# */ |
| sal_Bool bBehindText = sal_False; |
| if ( nIndex == GetString().getLength() ) |
| bBehindText = sal_True; |
| |
| // get model position & prepare GetCharRect() arguments |
| SwCrsrMoveState aMoveState; |
| aMoveState.bRealHeight = sal_True; |
| aMoveState.bRealWidth = sal_True; |
| SwSpecialPos aSpecialPos; |
| SwTxtNode* pNode = const_cast<SwTxtNode*>( GetTxtNode() ); |
| |
| sal_uInt16 nPos = 0; |
| |
| /* #i12332# FillSpecialPos does not accept nIndex == |
| GetString().getLength(). In that case nPos is set to the |
| length of the string in the core. This way GetCharRect |
| returns the rectangle for a cursor at the end of the |
| paragraph. */ |
| if (bBehindText) |
| { |
| nPos = pNode->GetTxt().Len(); |
| } |
| else |
| nPos = GetPortionData().FillSpecialPos |
| (nIndex, aSpecialPos, aMoveState.pSpecialPos ); |
| |
| // call GetCharRect |
| SwRect aCoreRect; |
| SwIndex aIndex( pNode, nPos ); |
| SwPosition aPosition( *pNode, aIndex ); |
| GetFrm()->GetCharRect( aCoreRect, aPosition, &aMoveState ); |
| |
| // translate core coordinates into accessibility coordinates |
| Window *pWin = GetWindow(); |
| CHECK_FOR_WINDOW( XAccessibleComponent, pWin ); |
| |
| Rectangle aScreenRect( GetMap()->CoreToPixel( aCoreRect.SVRect() )); |
| SwRect aFrmLogBounds( GetBounds( *(GetMap()) ) ); // twip rel to doc root |
| |
| Point aFrmPixPos( GetMap()->CoreToPixel( aFrmLogBounds.SVRect() ).TopLeft() ); |
| aScreenRect.Move( -aFrmPixPos.X(), -aFrmPixPos.Y() ); |
| |
| // convert into AWT Rectangle |
| return awt::Rectangle( |
| aScreenRect.Left(), aScreenRect.Top(), |
| aScreenRect.GetWidth(), aScreenRect.GetHeight() ); |
| } |
| |
| sal_Int32 SwAccessibleParagraph::getCharacterCount() |
| throw (uno::RuntimeException) |
| { |
| vos::OGuard aGuard(Application::GetSolarMutex()); |
| |
| CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); |
| |
| return GetString().getLength(); |
| } |
| |
| sal_Int32 SwAccessibleParagraph::getIndexAtPoint( const awt::Point& rPoint ) |
| throw (uno::RuntimeException) |
| { |
| vos::OGuard aGuard(Application::GetSolarMutex()); |
| |
| |
| CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); |
| |
| // construct SwPosition (where GetCrsrOfst() will put the result into) |
| SwTxtNode* pNode = const_cast<SwTxtNode*>( GetTxtNode() ); |
| SwIndex aIndex( pNode, 0); |
| SwPosition aPos( *pNode, aIndex ); |
| |
| // construct Point (translate into layout coordinates) |
| Window *pWin = GetWindow(); |
| CHECK_FOR_WINDOW( XAccessibleComponent, pWin ); |
| Point aPoint( rPoint.X, rPoint.Y ); |
| SwRect aLogBounds( GetBounds( *(GetMap()), GetFrm() ) ); // twip rel to doc root |
| Point aPixPos( GetMap()->CoreToPixel( aLogBounds.SVRect() ).TopLeft() ); |
| aPoint.X() += aPixPos.X(); |
| aPoint.Y() += aPixPos.Y(); |
| MapMode aMapMode = pWin->GetMapMode(); |
| Point aCorePoint( GetMap()->PixelToCore( aPoint ) ); |
| if( !aLogBounds.IsInside( aCorePoint ) ) |
| { |
| /* #i12332# rPoint is may also be in rectangle returned by |
| getCharacterBounds(getCharacterCount() */ |
| |
| awt::Rectangle aRectEndPos = |
| getCharacterBounds(getCharacterCount()); |
| |
| if (rPoint.X - aRectEndPos.X >= 0 && |
| rPoint.X - aRectEndPos.X < aRectEndPos.Width && |
| rPoint.Y - aRectEndPos.Y >= 0 && |
| rPoint.Y - aRectEndPos.Y < aRectEndPos.Height) |
| return getCharacterCount(); |
| |
| return -1; |
| } |
| |
| // ask core for position |
| DBG_ASSERT( GetFrm() != NULL, "The text frame has vanished!" ); |
| DBG_ASSERT( GetFrm()->IsTxtFrm(), "The text frame has mutated!" ); |
| const SwTxtFrm* pFrm = static_cast<const SwTxtFrm*>( GetFrm() ); |
| SwCrsrMoveState aMoveState; |
| aMoveState.bPosMatchesBounds = sal_True; |
| sal_Bool bSuccess = pFrm->GetCrsrOfst( &aPos, aCorePoint, &aMoveState ); |
| |
| SwIndex aCntntIdx = aPos.nContent; |
| const xub_StrLen nIndex = aCntntIdx.GetIndex(); |
| if ( nIndex > 0 ) |
| { |
| SwRect aResultRect; |
| pFrm->GetCharRect( aResultRect, aPos ); |
| bool bVert = pFrm->IsVertical(); |
| bool bR2L = pFrm->IsRightToLeft(); |
| |
| if ( (!bVert && aResultRect.Pos().X() > aCorePoint.X()) || |
| ( bVert && aResultRect.Pos().Y() > aCorePoint.Y()) || |
| ( bR2L && aResultRect.Right() < aCorePoint.X()) ) |
| { |
| SwIndex aIdxPrev( pNode, nIndex - 1); |
| SwPosition aPosPrev( *pNode, aIdxPrev ); |
| SwRect aResultRectPrev; |
| pFrm->GetCharRect( aResultRectPrev, aPosPrev ); |
| if ( (!bVert && aResultRectPrev.Pos().X() < aCorePoint.X() && aResultRect.Pos().Y() == aResultRectPrev.Pos().Y()) || |
| ( bVert && aResultRectPrev.Pos().Y() < aCorePoint.Y() && aResultRect.Pos().X() == aResultRectPrev.Pos().X()) || |
| ( bR2L && aResultRectPrev.Right() > aCorePoint.X() && aResultRect.Pos().Y() == aResultRectPrev.Pos().Y()) ) |
| aPos = aPosPrev; |
| } |
| } |
| |
| return bSuccess ? |
| GetPortionData().GetAccessiblePosition( aPos.nContent.GetIndex() ) |
| : -1L; |
| } |
| |
| ::rtl::OUString SwAccessibleParagraph::getSelectedText() |
| throw (uno::RuntimeException) |
| { |
| vos::OGuard aGuard(Application::GetSolarMutex()); |
| |
| CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); |
| |
| sal_Int32 nStart, nEnd; |
| sal_Bool bSelected = GetSelection( nStart, nEnd ); |
| return bSelected |
| ? GetString().copy( nStart, nEnd - nStart ) |
| : ::rtl::OUString(); |
| } |
| |
| sal_Int32 SwAccessibleParagraph::getSelectionStart() |
| throw (uno::RuntimeException) |
| { |
| vos::OGuard aGuard(Application::GetSolarMutex()); |
| |
| CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); |
| |
| sal_Int32 nStart, nEnd; |
| GetSelection( nStart, nEnd ); |
| return nStart; |
| } |
| |
| sal_Int32 SwAccessibleParagraph::getSelectionEnd() |
| throw (uno::RuntimeException) |
| { |
| vos::OGuard aGuard(Application::GetSolarMutex()); |
| |
| CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); |
| |
| sal_Int32 nStart, nEnd; |
| GetSelection( nStart, nEnd ); |
| return nEnd; |
| } |
| |
| sal_Bool SwAccessibleParagraph::setSelection( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) |
| throw (lang::IndexOutOfBoundsException, uno::RuntimeException) |
| { |
| vos::OGuard aGuard(Application::GetSolarMutex()); |
| |
| CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); |
| |
| // parameter checking |
| sal_Int32 nLength = GetString().getLength(); |
| if ( ! IsValidRange( nStartIndex, nEndIndex, nLength ) ) |
| { |
| throw lang::IndexOutOfBoundsException(); |
| } |
| |
| sal_Bool bRet = sal_False; |
| |
| // get cursor shell |
| SwCrsrShell* pCrsrShell = GetCrsrShell(); |
| if( pCrsrShell != NULL ) |
| { |
| // create pam for selection |
| SwTxtNode* pNode = const_cast<SwTxtNode*>( GetTxtNode() ); |
| SwIndex aIndex( pNode, GetPortionData().GetModelPosition(nStartIndex)); |
| SwPosition aStartPos( *pNode, aIndex ); |
| SwPaM aPaM( aStartPos ); |
| aPaM.SetMark(); |
| aPaM.GetPoint()->nContent = |
| GetPortionData().GetModelPosition(nEndIndex); |
| |
| // set PaM at cursor shell |
| bRet = Select( aPaM ); |
| } |
| |
| return bRet; |
| } |
| |
| ::rtl::OUString SwAccessibleParagraph::getText() |
| throw (uno::RuntimeException) |
| { |
| vos::OGuard aGuard(Application::GetSolarMutex()); |
| |
| CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); |
| |
| return GetString(); |
| } |
| |
| ::rtl::OUString SwAccessibleParagraph::getTextRange( |
| sal_Int32 nStartIndex, sal_Int32 nEndIndex ) |
| throw (lang::IndexOutOfBoundsException, uno::RuntimeException) |
| { |
| vos::OGuard aGuard(Application::GetSolarMutex()); |
| |
| CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); |
| |
| ::rtl::OUString sText( GetString() ); |
| |
| if ( IsValidRange( nStartIndex, nEndIndex, sText.getLength() ) ) |
| { |
| OrderRange( nStartIndex, nEndIndex ); |
| return sText.copy(nStartIndex, nEndIndex-nStartIndex ); |
| } |
| else |
| throw lang::IndexOutOfBoundsException(); |
| } |
| |
| /*accessibility::*/TextSegment SwAccessibleParagraph::getTextAtIndex( sal_Int32 nIndex, sal_Int16 nTextType ) throw (lang::IndexOutOfBoundsException, lang::IllegalArgumentException, uno::RuntimeException) |
| { |
| vos::OGuard aGuard(Application::GetSolarMutex()); |
| |
| CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); |
| |
| /*accessibility::*/TextSegment aResult; |
| aResult.SegmentStart = -1; |
| aResult.SegmentEnd = -1; |
| |
| const ::rtl::OUString rText = GetString(); |
| // implement the silly specification that first position after |
| // text must return an empty string, rather than throwing an |
| // IndexOutOfBoundsException, except for LINE, where the last |
| // line is returned |
| if( nIndex == rText.getLength() && AccessibleTextType::LINE != nTextType ) |
| return aResult; |
| |
| // with error checking |
| i18n::Boundary aBound; |
| sal_Bool bWord = GetTextBoundary( aBound, rText, nIndex, nTextType ); |
| |
| DBG_ASSERT( aBound.startPos >= 0, "illegal boundary" ); |
| DBG_ASSERT( aBound.startPos <= aBound.endPos, "illegal boundary" ); |
| |
| // return word (if present) |
| if ( bWord ) |
| { |
| aResult.SegmentText = rText.copy( aBound.startPos, aBound.endPos - aBound.startPos ); |
| aResult.SegmentStart = aBound.startPos; |
| aResult.SegmentEnd = aBound.endPos; |
| } |
| |
| return aResult; |
| } |
| |
| /*accessibility::*/TextSegment SwAccessibleParagraph::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 nTextType ) throw (lang::IndexOutOfBoundsException, lang::IllegalArgumentException, uno::RuntimeException) |
| { |
| vos::OGuard aGuard(Application::GetSolarMutex()); |
| |
| CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); |
| |
| const ::rtl::OUString rText = GetString(); |
| |
| /*accessibility::*/TextSegment aResult; |
| aResult.SegmentStart = -1; |
| aResult.SegmentEnd = -1; |
| |
| // get starting pos |
| i18n::Boundary aBound; |
| if (nIndex == rText.getLength()) |
| aBound.startPos = aBound.endPos = nIndex; |
| else |
| { |
| sal_Bool bTmp = GetTextBoundary( aBound, rText, nIndex, nTextType ); |
| |
| if ( ! bTmp ) |
| aBound.startPos = aBound.endPos = nIndex; |
| } |
| |
| // now skip to previous word |
| sal_Bool bWord = sal_False; |
| while( !bWord ) |
| { |
| nIndex = min( nIndex, aBound.startPos ) - 1; |
| if( nIndex >= 0 ) |
| bWord = GetTextBoundary( aBound, rText, nIndex, nTextType ); |
| else |
| break; // exit if beginning of string is reached |
| } |
| |
| if ( bWord ) |
| { |
| aResult.SegmentText = rText.copy( aBound.startPos, aBound.endPos - aBound.startPos ); |
| aResult.SegmentStart = aBound.startPos; |
| aResult.SegmentEnd = aBound.endPos; |
| }; |
| return aResult; |
| } |
| |
| /*accessibility::*/TextSegment SwAccessibleParagraph::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 nTextType ) throw (lang::IndexOutOfBoundsException, lang::IllegalArgumentException, uno::RuntimeException) |
| { |
| vos::OGuard aGuard(Application::GetSolarMutex()); |
| |
| CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); |
| |
| /*accessibility::*/TextSegment aResult; |
| aResult.SegmentStart = -1; |
| aResult.SegmentEnd = -1; |
| const ::rtl::OUString rText = GetString(); |
| |
| // implement the silly specification that first position after |
| // text must return an empty string, rather than throwing an |
| // IndexOutOfBoundsException |
| if( nIndex == rText.getLength() ) |
| return aResult; |
| |
| |
| // get first word, then skip to next word |
| i18n::Boundary aBound; |
| GetTextBoundary( aBound, rText, nIndex, nTextType ); |
| sal_Bool bWord = sal_False; |
| while( !bWord ) |
| { |
| nIndex = max( sal_Int32(nIndex+1), aBound.endPos ); |
| if( nIndex < rText.getLength() ) |
| bWord = GetTextBoundary( aBound, rText, nIndex, nTextType ); |
| else |
| break; // exit if end of string is reached |
| } |
| |
| if ( bWord ) |
| { |
| aResult.SegmentText = rText.copy( aBound.startPos, aBound.endPos - aBound.startPos ); |
| aResult.SegmentStart = aBound.startPos; |
| aResult.SegmentEnd = aBound.endPos; |
| } |
| return aResult; |
| } |
| |
| sal_Bool SwAccessibleParagraph::copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) |
| throw (lang::IndexOutOfBoundsException, uno::RuntimeException) |
| { |
| CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this ); |
| vos::OGuard aGuard(Application::GetSolarMutex()); |
| |
| // select and copy (through dispatch mechanism) |
| setSelection( nStartIndex, nEndIndex ); |
| ExecuteAtViewShell( SID_COPY ); |
| return sal_True; |
| } |
| |
| |
| // |
| //===== XAccesibleEditableText ========================================== |
| // |
| |
| sal_Bool SwAccessibleParagraph::cutText( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) |
| throw (lang::IndexOutOfBoundsException, uno::RuntimeException) |
| { |
| CHECK_FOR_DEFUNC( XAccessibleEditableText ); |
| vos::OGuard aGuard(Application::GetSolarMutex()); |
| |
| if( !IsEditableState() ) |
| return sal_False; |
| |
| // select and cut (through dispatch mechanism) |
| setSelection( nStartIndex, nEndIndex ); |
| ExecuteAtViewShell( SID_CUT ); |
| return sal_True; |
| } |
| |
| sal_Bool SwAccessibleParagraph::pasteText( sal_Int32 nIndex ) |
| throw (lang::IndexOutOfBoundsException, uno::RuntimeException) |
| { |
| CHECK_FOR_DEFUNC( XAccessibleEditableText ); |
| vos::OGuard aGuard(Application::GetSolarMutex()); |
| |
| if( !IsEditableState() ) |
| return sal_False; |
| |
| // select and paste (through dispatch mechanism) |
| setSelection( nIndex, nIndex ); |
| ExecuteAtViewShell( SID_PASTE ); |
| return sal_True; |
| } |
| |
| sal_Bool SwAccessibleParagraph::deleteText( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) |
| throw (lang::IndexOutOfBoundsException, uno::RuntimeException) |
| { |
| return replaceText( nStartIndex, nEndIndex, ::rtl::OUString() ); |
| } |
| |
| sal_Bool SwAccessibleParagraph::insertText( const ::rtl::OUString& sText, sal_Int32 nIndex ) |
| throw (lang::IndexOutOfBoundsException, uno::RuntimeException) |
| { |
| return replaceText( nIndex, nIndex, sText ); |
| } |
| |
| sal_Bool SwAccessibleParagraph::replaceText( |
| sal_Int32 nStartIndex, sal_Int32 nEndIndex, |
| const ::rtl::OUString& sReplacement ) |
| throw (lang::IndexOutOfBoundsException, uno::RuntimeException) |
| { |
| vos::OGuard aGuard(Application::GetSolarMutex()); |
| |
| CHECK_FOR_DEFUNC( XAccessibleEditableText ); |
| |
| const ::rtl::OUString& rText = GetString(); |
| |
| if( IsValidRange( nStartIndex, nEndIndex, rText.getLength() ) ) |
| { |
| if( !IsEditableState() ) |
| return sal_False; |
| |
| SwTxtNode* pNode = const_cast<SwTxtNode*>( GetTxtNode() ); |
| |
| // translate positions |
| sal_uInt16 nStart, nEnd; |
| sal_Bool bSuccess = GetPortionData().GetEditableRange( |
| nStartIndex, nEndIndex, nStart, nEnd ); |
| |
| // edit only if the range is editable |
| if( bSuccess ) |
| { |
| // create SwPosition for nStartIndex |
| SwIndex aIndex( pNode, nStart ); |
| SwPosition aStartPos( *pNode, aIndex ); |
| |
| // create SwPosition for nEndIndex |
| SwPosition aEndPos( aStartPos ); |
| aEndPos.nContent = nEnd; |
| |
| // now create XTextRange as helper and set string |
| const uno::Reference<text::XTextRange> xRange( |
| SwXTextRange::CreateXTextRange( |
| *pNode->GetDoc(), aStartPos, &aEndPos)); |
| xRange->setString(sReplacement); |
| |
| // delete portion data |
| ClearPortionData(); |
| } |
| |
| return bSuccess; |
| } |
| else |
| throw lang::IndexOutOfBoundsException(); |
| } |
| |
| struct IndexCompare |
| { |
| const PropertyValue* pValues; |
| IndexCompare( const PropertyValue* pVals ) : pValues(pVals) {} |
| bool operator() ( const sal_Int32& a, const sal_Int32& b ) const |
| { |
| return (pValues[a].Name < pValues[b].Name) ? true : false; |
| } |
| }; |
| |
| |
| sal_Bool SwAccessibleParagraph::setAttributes( |
| sal_Int32 nStartIndex, |
| sal_Int32 nEndIndex, |
| const uno::Sequence<PropertyValue>& rAttributeSet ) |
| throw (lang::IndexOutOfBoundsException, uno::RuntimeException) |
| { |
| vos::OGuard aGuard(Application::GetSolarMutex()); |
| CHECK_FOR_DEFUNC( XAccessibleEditableText ); |
| |
| const ::rtl::OUString& rText = GetString(); |
| |
| if( ! IsValidRange( nStartIndex, nEndIndex, rText.getLength() ) ) |
| throw lang::IndexOutOfBoundsException(); |
| |
| if( !IsEditableState() ) |
| return sal_False; |
| |
| |
| // create a (dummy) text portion for the sole purpose of calling |
| // setPropertyValue on it |
| uno::Reference<XMultiPropertySet> xPortion = CreateUnoPortion( nStartIndex, |
| nEndIndex ); |
| |
| // build sorted index array |
| sal_Int32 nLength = rAttributeSet.getLength(); |
| const PropertyValue* pPairs = rAttributeSet.getConstArray(); |
| sal_Int32* pIndices = new sal_Int32[nLength]; |
| sal_Int32 i; |
| for( i = 0; i < nLength; i++ ) |
| pIndices[i] = i; |
| sort( &pIndices[0], &pIndices[nLength], IndexCompare(pPairs) ); |
| |
| // create sorted sequences accoring to index array |
| uno::Sequence< ::rtl::OUString > aNames( nLength ); |
| ::rtl::OUString* pNames = aNames.getArray(); |
| uno::Sequence< uno::Any > aValues( nLength ); |
| uno::Any* pValues = aValues.getArray(); |
| for( i = 0; i < nLength; i++ ) |
| { |
| const PropertyValue& rVal = pPairs[pIndices[i]]; |
| pNames[i] = rVal.Name; |
| pValues[i] = rVal.Value; |
| } |
| delete[] pIndices; |
| |
| // now set the values |
| sal_Bool bRet = sal_True; |
| try |
| { |
| xPortion->setPropertyValues( aNames, aValues ); |
| } |
| catch( UnknownPropertyException e ) |
| { |
| // error handling through return code! |
| bRet = sal_False; |
| } |
| |
| return bRet; |
| } |
| |
| sal_Bool SwAccessibleParagraph::setText( const ::rtl::OUString& sText ) |
| throw (uno::RuntimeException) |
| { |
| return replaceText(0, GetString().getLength(), sText); |
| } |
| |
| //===== XAccessibleSelection ============================================ |
| |
| void SwAccessibleParagraph::selectAccessibleChild( |
| sal_Int32 nChildIndex ) |
| throw ( lang::IndexOutOfBoundsException, |
| uno::RuntimeException ) |
| { |
| CHECK_FOR_DEFUNC( XAccessibleSelection ); |
| |
| aSelectionHelper.selectAccessibleChild(nChildIndex); |
| } |
| |
| sal_Bool SwAccessibleParagraph::isAccessibleChildSelected( |
| sal_Int32 nChildIndex ) |
| throw ( lang::IndexOutOfBoundsException, |
| uno::RuntimeException ) |
| { |
| CHECK_FOR_DEFUNC( XAccessibleSelection ); |
| |
| return aSelectionHelper.isAccessibleChildSelected(nChildIndex); |
| } |
| |
| void SwAccessibleParagraph::clearAccessibleSelection( ) |
| throw ( uno::RuntimeException ) |
| { |
| CHECK_FOR_DEFUNC( XAccessibleSelection ); |
| |
| aSelectionHelper.clearAccessibleSelection(); |
| } |
| |
| void SwAccessibleParagraph::selectAllAccessibleChildren( ) |
| throw ( uno::RuntimeException ) |
| { |
| CHECK_FOR_DEFUNC( XAccessibleSelection ); |
| |
| aSelectionHelper.selectAllAccessibleChildren(); |
| } |
| |
| sal_Int32 SwAccessibleParagraph::getSelectedAccessibleChildCount( ) |
| throw ( uno::RuntimeException ) |
| { |
| CHECK_FOR_DEFUNC( XAccessibleSelection ); |
| |
| return aSelectionHelper.getSelectedAccessibleChildCount(); |
| } |
| |
| uno::Reference<XAccessible> SwAccessibleParagraph::getSelectedAccessibleChild( |
| sal_Int32 nSelectedChildIndex ) |
| throw ( lang::IndexOutOfBoundsException, |
| uno::RuntimeException) |
| { |
| CHECK_FOR_DEFUNC( XAccessibleSelection ); |
| |
| return aSelectionHelper.getSelectedAccessibleChild(nSelectedChildIndex); |
| } |
| |
| // --> OD 2004-11-16 #111714# - index has to be treated as global child index. |
| void SwAccessibleParagraph::deselectAccessibleChild( |
| sal_Int32 nChildIndex ) |
| throw ( lang::IndexOutOfBoundsException, |
| uno::RuntimeException ) |
| { |
| CHECK_FOR_DEFUNC( XAccessibleSelection ); |
| |
| aSelectionHelper.deselectAccessibleChild( nChildIndex ); |
| } |
| |
| //===== XAccessibleHypertext ============================================ |
| |
| class SwHyperlinkIter_Impl |
| { |
| const SwpHints *pHints; |
| xub_StrLen nStt; |
| xub_StrLen nEnd; |
| sal_uInt16 nPos; |
| |
| public: |
| SwHyperlinkIter_Impl( const SwTxtFrm *pTxtFrm ); |
| const SwTxtAttr *next(); |
| sal_uInt16 getCurrHintPos() const { return nPos-1; } |
| |
| xub_StrLen startIdx() const { return nStt; } |
| xub_StrLen endIdx() const { return nEnd; } |
| }; |
| |
| SwHyperlinkIter_Impl::SwHyperlinkIter_Impl( const SwTxtFrm *pTxtFrm ) : |
| pHints( pTxtFrm->GetTxtNode()->GetpSwpHints() ), |
| nStt( pTxtFrm->GetOfst() ), |
| nPos( 0 ) |
| { |
| const SwTxtFrm *pFollFrm = pTxtFrm->GetFollow(); |
| nEnd = pFollFrm ? pFollFrm->GetOfst() : pTxtFrm->GetTxtNode()->Len(); |
| } |
| |
| const SwTxtAttr *SwHyperlinkIter_Impl::next() |
| { |
| const SwTxtAttr *pAttr = 0; |
| if( pHints ) |
| { |
| while( !pAttr && nPos < pHints->Count() ) |
| { |
| const SwTxtAttr *pHt = (*pHints)[nPos]; |
| if( RES_TXTATR_INETFMT == pHt->Which() ) |
| { |
| xub_StrLen nHtStt = *pHt->GetStart(); |
| xub_StrLen nHtEnd = *pHt->GetAnyEnd(); |
| if( nHtEnd > nHtStt && |
| ( (nHtStt >= nStt && nHtStt < nEnd) || |
| (nHtEnd > nStt && nHtEnd <= nEnd) ) ) |
| { |
| pAttr = pHt; |
| } |
| } |
| ++nPos; |
| } |
| } |
| |
| return pAttr; |
| }; |
| |
| sal_Int32 SAL_CALL SwAccessibleParagraph::getHyperLinkCount() |
| throw (uno::RuntimeException) |
| { |
| vos::OGuard aGuard(Application::GetSolarMutex()); |
| |
| CHECK_FOR_DEFUNC( XAccessibleHypertext ); |
| |
| sal_Int32 nCount = 0; |
| // --> OD 2007-06-27 #i77108# - provide hyperlinks also in editable documents. |
| // if( !IsEditableState() ) |
| // <-- |
| { |
| const SwTxtFrm *pTxtFrm = static_cast<const SwTxtFrm*>( GetFrm() ); |
| SwHyperlinkIter_Impl aIter( pTxtFrm ); |
| while( aIter.next() ) |
| nCount++; |
| } |
| |
| return nCount; |
| } |
| |
| uno::Reference< XAccessibleHyperlink > SAL_CALL |
| SwAccessibleParagraph::getHyperLink( sal_Int32 nLinkIndex ) |
| throw (lang::IndexOutOfBoundsException, uno::RuntimeException) |
| { |
| vos::OGuard aGuard(Application::GetSolarMutex()); |
| CHECK_FOR_DEFUNC( XAccessibleHypertext ); |
| |
| uno::Reference< XAccessibleHyperlink > xRet; |
| |
| // --> OD 2007-06-27 #i77108# - provide hyperlinks also in editable documents. |
| // if( !IsEditableState() ) |
| // <-- |
| { |
| const SwTxtFrm *pTxtFrm = static_cast<const SwTxtFrm*>( GetFrm() ); |
| SwHyperlinkIter_Impl aHIter( pTxtFrm ); |
| while( nLinkIndex-- ) |
| aHIter.next(); |
| |
| const SwTxtAttr *pHt = aHIter.next(); |
| if( pHt ) |
| { |
| if( !pHyperTextData ) |
| pHyperTextData = new SwAccessibleHyperTextData; |
| SwAccessibleHyperTextData::iterator aIter = |
| pHyperTextData ->find( pHt ); |
| if( aIter != pHyperTextData->end() ) |
| { |
| xRet = (*aIter).second; |
| } |
| if( !xRet.is() ) |
| { |
| sal_Int32 nHStt= GetPortionData().GetAccessiblePosition( |
| max( aHIter.startIdx(), *pHt->GetStart() ) ); |
| sal_Int32 nHEnd= GetPortionData().GetAccessiblePosition( |
| min( aHIter.endIdx(), *pHt->GetAnyEnd() ) ); |
| xRet = new SwAccessibleHyperlink( aHIter.getCurrHintPos(), |
| this, nHStt, nHEnd ); |
| if( aIter != pHyperTextData->end() ) |
| { |
| (*aIter).second = xRet; |
| } |
| else |
| { |
| SwAccessibleHyperTextData::value_type aEntry( pHt, xRet ); |
| pHyperTextData->insert( aEntry ); |
| } |
| } |
| } |
| } |
| |
| if( !xRet.is() ) |
| throw lang::IndexOutOfBoundsException(); |
| |
| return xRet; |
| } |
| |
| sal_Int32 SAL_CALL SwAccessibleParagraph::getHyperLinkIndex( sal_Int32 nCharIndex ) |
| throw (lang::IndexOutOfBoundsException, uno::RuntimeException) |
| { |
| vos::OGuard aGuard(Application::GetSolarMutex()); |
| CHECK_FOR_DEFUNC( XAccessibleHypertext ); |
| |
| // parameter checking |
| sal_Int32 nLength = GetString().getLength(); |
| if ( ! IsValidPosition( nCharIndex, nLength ) ) |
| { |
| throw lang::IndexOutOfBoundsException(); |
| } |
| |
| sal_Int32 nRet = -1; |
| // --> OD 2007-06-27 #i77108# - provide hyperlinks also in editable documents. |
| // if( !IsEditableState() ) |
| // <-- |
| { |
| const SwTxtFrm *pTxtFrm = static_cast<const SwTxtFrm*>( GetFrm() ); |
| SwHyperlinkIter_Impl aHIter( pTxtFrm ); |
| |
| xub_StrLen nIdx = GetPortionData().GetModelPosition( nCharIndex ); |
| sal_Int32 nPos = 0; |
| const SwTxtAttr *pHt = aHIter.next(); |
| while( pHt && !(nIdx >= *pHt->GetStart() && nIdx < *pHt->GetAnyEnd()) ) |
| { |
| pHt = aHIter.next(); |
| nPos++; |
| } |
| |
| if( pHt ) |
| nRet = nPos; |
| |
| } |
| |
| return nRet; |
| } |
| |
| // --> OD 2008-05-26 #i71360# |
| // --> OD 2010-02-22 #i108125# - adjustments for change tracking text markup |
| sal_Int32 SAL_CALL SwAccessibleParagraph::getTextMarkupCount( sal_Int32 nTextMarkupType ) |
| throw (lang::IllegalArgumentException, |
| uno::RuntimeException) |
| { |
| std::auto_ptr<SwTextMarkupHelper> pTextMarkupHelper; |
| switch ( nTextMarkupType ) |
| { |
| case text::TextMarkupType::TRACK_CHANGE_INSERTION: |
| case text::TextMarkupType::TRACK_CHANGE_DELETION: |
| case text::TextMarkupType::TRACK_CHANGE_FORMATCHANGE: |
| { |
| pTextMarkupHelper.reset( new SwTextMarkupHelper( |
| GetPortionData(), |
| *(mpParaChangeTrackInfo->getChangeTrackingTextMarkupList( nTextMarkupType ) )) ); |
| } |
| break; |
| default: |
| { |
| pTextMarkupHelper.reset( new SwTextMarkupHelper( GetPortionData(), *GetTxtNode() ) ); |
| } |
| } |
| |
| return pTextMarkupHelper->getTextMarkupCount( nTextMarkupType ); |
| } |
| |
| /*accessibility::*/TextSegment SAL_CALL |
| SwAccessibleParagraph::getTextMarkup( sal_Int32 nTextMarkupIndex, |
| sal_Int32 nTextMarkupType ) |
| throw (lang::IndexOutOfBoundsException, |
| lang::IllegalArgumentException, |
| uno::RuntimeException) |
| { |
| std::auto_ptr<SwTextMarkupHelper> pTextMarkupHelper; |
| switch ( nTextMarkupType ) |
| { |
| case text::TextMarkupType::TRACK_CHANGE_INSERTION: |
| case text::TextMarkupType::TRACK_CHANGE_DELETION: |
| case text::TextMarkupType::TRACK_CHANGE_FORMATCHANGE: |
| { |
| pTextMarkupHelper.reset( new SwTextMarkupHelper( |
| GetPortionData(), |
| *(mpParaChangeTrackInfo->getChangeTrackingTextMarkupList( nTextMarkupType ) )) ); |
| } |
| break; |
| default: |
| { |
| pTextMarkupHelper.reset( new SwTextMarkupHelper( GetPortionData(), *GetTxtNode() ) ); |
| } |
| } |
| |
| return pTextMarkupHelper->getTextMarkup( nTextMarkupIndex, nTextMarkupType ); |
| } |
| |
| uno::Sequence< /*accessibility::*/TextSegment > SAL_CALL |
| SwAccessibleParagraph::getTextMarkupAtIndex( sal_Int32 nCharIndex, |
| sal_Int32 nTextMarkupType ) |
| throw (lang::IndexOutOfBoundsException, |
| lang::IllegalArgumentException, |
| uno::RuntimeException) |
| { |
| // parameter checking |
| const sal_Int32 nLength = GetString().getLength(); |
| if ( ! IsValidPosition( nCharIndex, nLength ) ) |
| { |
| throw lang::IndexOutOfBoundsException(); |
| } |
| |
| std::auto_ptr<SwTextMarkupHelper> pTextMarkupHelper; |
| switch ( nTextMarkupType ) |
| { |
| case text::TextMarkupType::TRACK_CHANGE_INSERTION: |
| case text::TextMarkupType::TRACK_CHANGE_DELETION: |
| case text::TextMarkupType::TRACK_CHANGE_FORMATCHANGE: |
| { |
| pTextMarkupHelper.reset( new SwTextMarkupHelper( |
| GetPortionData(), |
| *(mpParaChangeTrackInfo->getChangeTrackingTextMarkupList( nTextMarkupType ) )) ); |
| } |
| break; |
| default: |
| { |
| pTextMarkupHelper.reset( new SwTextMarkupHelper( GetPortionData(), *GetTxtNode() ) ); |
| } |
| } |
| |
| return pTextMarkupHelper->getTextMarkupAtIndex( nCharIndex, nTextMarkupType ); |
| } |
| // <-- |
| |
| // --> OD 2008-05-29 #i89175# |
| sal_Int32 SAL_CALL SwAccessibleParagraph::getLineNumberAtIndex( sal_Int32 nIndex ) |
| throw (lang::IndexOutOfBoundsException, |
| uno::RuntimeException) |
| { |
| // parameter checking |
| const sal_Int32 nLength = GetString().getLength(); |
| if ( ! IsValidPosition( nIndex, nLength ) ) |
| { |
| throw lang::IndexOutOfBoundsException(); |
| } |
| |
| const sal_Int32 nLineNo = GetPortionData().GetLineNo( nIndex ); |
| return nLineNo; |
| } |
| |
| /*accessibility::*/TextSegment SAL_CALL |
| SwAccessibleParagraph::getTextAtLineNumber( sal_Int32 nLineNo ) |
| throw (lang::IndexOutOfBoundsException, |
| uno::RuntimeException) |
| { |
| // parameter checking |
| if ( nLineNo < 0 || |
| nLineNo >= GetPortionData().GetLineCount() ) |
| { |
| throw lang::IndexOutOfBoundsException(); |
| } |
| |
| i18n::Boundary aLineBound; |
| GetPortionData().GetBoundaryOfLine( nLineNo, aLineBound ); |
| |
| /*accessibility::*/TextSegment aTextAtLine; |
| const ::rtl::OUString rText = GetString(); |
| aTextAtLine.SegmentText = rText.copy( aLineBound.startPos, |
| aLineBound.endPos - aLineBound.startPos ); |
| aTextAtLine.SegmentStart = aLineBound.startPos; |
| aTextAtLine.SegmentEnd = aLineBound.endPos; |
| |
| return aTextAtLine; |
| } |
| |
| /*accessibility::*/TextSegment SAL_CALL SwAccessibleParagraph::getTextAtLineWithCaret() |
| throw (uno::RuntimeException) |
| { |
| const sal_Int32 nLineNoOfCaret = getNumberOfLineWithCaret(); |
| |
| if ( nLineNoOfCaret >= 0 && |
| nLineNoOfCaret < GetPortionData().GetLineCount() ) |
| { |
| return getTextAtLineNumber( nLineNoOfCaret ); |
| } |
| |
| return /*accessibility::*/TextSegment(); |
| } |
| |
| sal_Int32 SAL_CALL SwAccessibleParagraph::getNumberOfLineWithCaret() |
| throw (uno::RuntimeException) |
| { |
| const sal_Int32 nCaretPos = getCaretPosition(); |
| const sal_Int32 nLength = GetString().getLength(); |
| if ( !IsValidPosition( nCaretPos, nLength ) ) |
| { |
| return -1; |
| } |
| |
| sal_Int32 nLineNo = GetPortionData().GetLineNo( nCaretPos ); |
| |
| // special handling for cursor positioned at end of text line via End key |
| if ( nCaretPos != 0 ) |
| { |
| i18n::Boundary aLineBound; |
| GetPortionData().GetBoundaryOfLine( nLineNo, aLineBound ); |
| if ( nCaretPos == aLineBound.startPos ) |
| { |
| SwCrsrShell* pCrsrShell = SwAccessibleParagraph::GetCrsrShell(); |
| if ( pCrsrShell != 0 ) |
| { |
| const awt::Rectangle aCharRect = getCharacterBounds( nCaretPos ); |
| |
| const SwRect& aCursorCoreRect = pCrsrShell->GetCharRect(); |
| // translate core coordinates into accessibility coordinates |
| Window *pWin = GetWindow(); |
| CHECK_FOR_WINDOW( XAccessibleComponent, pWin ); |
| |
| Rectangle aScreenRect( GetMap()->CoreToPixel( aCursorCoreRect.SVRect() )); |
| |
| SwRect aFrmLogBounds( GetBounds( *(GetMap()) ) ); // twip rel to doc root |
| Point aFrmPixPos( GetMap()->CoreToPixel( aFrmLogBounds.SVRect() ).TopLeft() ); |
| aScreenRect.Move( -aFrmPixPos.X(), -aFrmPixPos.Y() ); |
| |
| // convert into AWT Rectangle |
| const awt::Rectangle aCursorRect( aScreenRect.Left(), |
| aScreenRect.Top(), |
| aScreenRect.GetWidth(), |
| aScreenRect.GetHeight() ); |
| |
| if ( aCharRect.X != aCursorRect.X || |
| aCharRect.Y != aCursorRect.Y ) |
| { |
| --nLineNo; |
| } |
| } |
| } |
| } |
| |
| return nLineNo; |
| } |
| |
| // --> OD 2010-02-19 #i108125# |
| void SwAccessibleParagraph::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew ) |
| { |
| mpParaChangeTrackInfo->reset(); |
| |
| CheckRegistration( pOld, pNew ); |
| } |
| // <-- |