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