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