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