xref: /aoo41x/main/sw/source/core/access/accpara.cxx (revision 5b989b89)
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 	//IAccessibility2 Implementation 2009-----
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 	//-----IAccessibility2 Implementation 2009
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->GetFmtFld()).GetField();
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 = static_cast<sal_uInt32>( reinterpret_cast<sal_uIntPtr>(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 = static_cast<sal_uInt32>( reinterpret_cast<sal_uIntPtr>(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 = static_cast<sal_uInt32>( reinterpret_cast<sal_uIntPtr>(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 	/* Can't fin the function "GetTOCFirstWordEndIndex" declaration in sym2.0 (Added by yanjun)
3462 	if( GetTOXSortTabBase()  )
3463 	{
3464 		SwTxtNode* pNode = const_cast<SwTxtNode*>(GetTxtNode());
3465 		if(pNode && pNode->GetTOCFirstWordEndIndex() > 0)
3466 			nCount++;
3467 	}
3468 	*/
3469 	//-----IAccessibility2 Implementation 2009
3470 	return nCount;
3471 }
3472 
3473 uno::Reference< XAccessibleHyperlink > SAL_CALL
3474 	SwAccessibleParagraph::getHyperLink( sal_Int32 nLinkIndex )
3475     throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
3476 {
3477 	vos::OGuard aGuard(Application::GetSolarMutex());
3478 	CHECK_FOR_DEFUNC( XAccessibleHypertext );
3479 
3480     uno::Reference< XAccessibleHyperlink > xRet;
3481 
3482     // --> OD 2007-06-27 #i77108# - provide hyperlinks also in editable documents.
3483 //    if( !IsEditableState() )
3484 	const SwTxtFrm *pTxtFrm = static_cast<const SwTxtFrm*>( GetFrm() );
3485 	SwHyperlinkIter_Impl aHIter( pTxtFrm );
3486 	//SwAccessibleAutoRecognizerHelper_Impl aARHelper( pTxtFrm );
3487 	sal_Int32 nARCount = 0;
3488 	sal_Int32 nARIndex = 0;
3489 	sal_Int32 nTIndex = -1;
3490 	sal_Int32 nTOCEndIndex = -1;
3491 	SwTxtNode* pNode = NULL;
3492 	SwTOXSortTabBase* pTBase = GetTOXSortTabBase();
3493 	if( pTBase )
3494 	{
3495 		pNode = const_cast<SwTxtNode*>(GetTxtNode());
3496 	}
3497 	nTOCEndIndex = -1;
3498 	//if(pNode)
3499 	//	nTOCEndIndex = pNode->GetTOCFirstWordEndIndex();
3500 	SwTxtAttr* pHt = (SwTxtAttr*)(aHIter.next());
3501 	while( (nLinkIndex < getHyperLinkCount()) && nTIndex < nLinkIndex)
3502 	{
3503 		// no candidates, exit
3504 		//if( (!pHt) && (nARIndex >= nARCount) && nTOCEndIndex <= 0)
3505 		//	break;
3506 
3507 		sal_Int32 nHStt = -1;
3508 		sal_Int32 nAStt = -1;
3509 		sal_Bool bH = sal_False;
3510 		sal_Bool bA = sal_False;
3511 
3512 
3513 		if( pHt )
3514 			nHStt = *pHt->GetStart();
3515 		if( nARIndex < nARCount )
3516 		{
3517 			/*
3518 			sal_Int32 nAEnd;
3519 			aARHelper.getPosition( nARIndex, nAStt, nAEnd );
3520 			*/
3521 		}
3522 		sal_Bool bTOC = sal_False;
3523 		// Inside TOC & get the first link
3524 		if( pTBase && nTIndex == -1 )
3525 		{
3526 			nTIndex++;
3527 			bTOC = sal_True;
3528 		}
3529 		else
3530 		{
3531 			if( nHStt >=0 && nAStt >=0 )
3532 			{	// both hyperlink and smart tag available
3533 				nTIndex++;
3534 				if( nHStt <= nAStt )
3535 					bH = sal_True;
3536 				else
3537 					bA = sal_True;
3538 			}
3539 			else if( nHStt >= 0 )
3540 			{	// only hyperlink available
3541 				nTIndex++;
3542 				bH = sal_True;
3543 			}
3544 			else if( nAStt >= 0 )
3545 			{	// only smart tag available
3546 				nTIndex++;
3547 				bA = sal_True;
3548 			}
3549 		}
3550 
3551 		if( nTIndex == nLinkIndex )
3552 		{	// found
3553 			if( bH )
3554 			{	// it's a hyperlink
3555 				if( pHt )
3556 				{
3557 //                    const SwField* pFFld = pHt->GetFld().GetFld();
3558                     {
3559 						if( !pHyperTextData )
3560 							pHyperTextData = new SwAccessibleHyperTextData;
3561 						SwAccessibleHyperTextData::iterator aIter =
3562 							pHyperTextData ->find( pHt );
3563 						if( aIter != pHyperTextData->end() )
3564 						{
3565 							xRet = (*aIter).second;
3566 						}
3567 						if( !xRet.is() )
3568 						{
3569                             {
3570                                 const sal_Int32 nTmpHStt= GetPortionData().GetAccessiblePosition(
3571                                     max( aHIter.startIdx(), *pHt->GetStart() ) );
3572                                 const sal_Int32 nTmpHEnd= GetPortionData().GetAccessiblePosition(
3573                                     min( aHIter.endIdx(), *pHt->GetAnyEnd() ) );
3574                                 xRet = new SwAccessibleHyperlink( aHIter.getCurrHintPos(),
3575                                     this, nTmpHStt, nTmpHEnd );
3576                             }
3577 							if( aIter != pHyperTextData->end() )
3578 							{
3579 								(*aIter).second = xRet;
3580 							}
3581 							else
3582 							{
3583 								SwAccessibleHyperTextData::value_type aEntry( pHt, xRet );
3584 								pHyperTextData->insert( aEntry );
3585 							}
3586 						}
3587 					}
3588 				}
3589 			}
3590 			else if( bTOC )
3591 			{
3592 				//xRet = new SwAccessibleTOCLink( this );
3593 			}
3594 			else if( bA )
3595 			{
3596 				/*
3597 				// it's a smart tag
3598 				if( !pAutoRecognizerData )
3599 					pAutoRecognizerData = new SwAccessibleAutoRecognizerData;
3600 				SwAccessibleAutoRecognizerData::iterator aIter =
3601 					pAutoRecognizerData ->find( nARIndex );
3602 				if( aIter != pAutoRecognizerData->end() )
3603 				{
3604 					xRet = (*aIter).second;
3605 				}
3606 				if( !xRet.is() )
3607 				{
3608 					sal_Int32 nAStt = 0;
3609 					sal_Int32 nAEnd = 0;
3610 					//aARHelper.getPosition( nARIndex, nAStt, nAEnd );
3611 					xRet = new SwAccessibleAutoRecognizer( this, nAStt, nAEnd );
3612 					if( aIter != pAutoRecognizerData->end() )
3613 					{
3614 						(*aIter).second = xRet;
3615 					}
3616 					else
3617 					{
3618 						SwAccessibleAutoRecognizerData::value_type aEntry( nARIndex, xRet );
3619 						pAutoRecognizerData->insert( aEntry );
3620 					}
3621 				}
3622 				*/
3623 			}
3624 			break;
3625 		}
3626 
3627 		// iterate next
3628 		if( bH )
3629 			// iterate next hyperlink
3630 			pHt = (SwTxtAttr*)(aHIter.next());
3631 		else if( bA )
3632 			// iterate next smart tag
3633 			nARIndex++;
3634 		else if(bTOC)
3635 			continue;
3636 		else
3637 			// no candidate, exit
3638 			break;
3639 	}
3640 	/*
3641 		const SwTxtFrm *pTxtFrm = static_cast<const SwTxtFrm*>( GetFrm() );
3642 		SwHyperlinkIter_Impl aHIter( pTxtFrm );
3643 		while( nLinkIndex-- )
3644 			aHIter.next();
3645 
3646 		const SwTxtAttr *pHt = aHIter.next();
3647 		if( pHt )
3648 		{
3649 			if( !pHyperTextData )
3650 				pHyperTextData = new SwAccessibleHyperTextData;
3651 			SwAccessibleHyperTextData::iterator aIter =
3652 				pHyperTextData ->find( pHt );
3653 			if( aIter != pHyperTextData->end() )
3654 			{
3655 				xRet = (*aIter).second;
3656 			}
3657 			if( !xRet.is() )
3658 			{
3659 				sal_Int32 nHStt= GetPortionData().GetAccessiblePosition(
3660 								max( aHIter.startIdx(), *pHt->GetStart() ) );
3661 				sal_Int32 nHEnd= GetPortionData().GetAccessiblePosition(
3662 								min( aHIter.endIdx(), *pHt->GetAnyEnd() ) );
3663 				xRet = new SwAccessibleHyperlink( aHIter.getCurrHintPos(),
3664 												  this, nHStt, nHEnd );
3665 				if( aIter != pHyperTextData->end() )
3666 				{
3667 					(*aIter).second = xRet;
3668 				}
3669 				else
3670 				{
3671 					SwAccessibleHyperTextData::value_type aEntry( pHt, xRet );
3672 					pHyperTextData->insert( aEntry );
3673 				}
3674 			}
3675 		}
3676 	}
3677 	*/
3678 	if( !xRet.is() )
3679         throw lang::IndexOutOfBoundsException();
3680 
3681 	return xRet;
3682 }
3683 
3684 sal_Int32 SAL_CALL SwAccessibleParagraph::getHyperLinkIndex( sal_Int32 nCharIndex )
3685     throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
3686 {
3687 	vos::OGuard aGuard(Application::GetSolarMutex());
3688 	CHECK_FOR_DEFUNC( XAccessibleHypertext );
3689 
3690     // parameter checking
3691     sal_Int32 nLength = GetString().getLength();
3692     if ( ! IsValidPosition( nCharIndex, nLength ) )
3693     {
3694         throw lang::IndexOutOfBoundsException();
3695     }
3696 
3697 	sal_Int32 nRet = -1;
3698     // --> OD 2007-06-27 #i77108# - provide hyperlinks also in editable documents.
3699 //    if( !IsEditableState() )
3700     // <--
3701 	{
3702 		const SwTxtFrm *pTxtFrm = static_cast<const SwTxtFrm*>( GetFrm() );
3703 		SwHyperlinkIter_Impl aHIter( pTxtFrm );
3704 
3705 		xub_StrLen nIdx = GetPortionData().GetModelPosition( nCharIndex );
3706 		sal_Int32 nPos = 0;
3707 		const SwTxtAttr *pHt = aHIter.next();
3708 		while( pHt && !(nIdx >= *pHt->GetStart() && nIdx < *pHt->GetAnyEnd()) )
3709 		{
3710 			pHt = aHIter.next();
3711 			nPos++;
3712 		}
3713 
3714 		if( pHt )
3715 			nRet = nPos;
3716 	}
3717 	//IAccessibility2 Implementation 2009-----
3718 	/* Added by yanjun for acc miagration
3719 	if( nRet == -1 && GetTOXSortTabBase() )
3720 	{
3721 		SwTxtNode* pNode = const_cast<SwTxtNode*>(GetTxtNode());
3722 		if( nCharIndex >= 0 && nCharIndex < pNode->GetTOCFirstWordEndIndex())
3723 			nRet = 0;
3724 	}
3725 	*/
3726 
3727 	if (nRet == -1)
3728 		throw lang::IndexOutOfBoundsException();
3729 	else
3730 		return nRet;
3731 	//return nRet;
3732 	//-----IAccessibility2 Implementation 2009
3733 }
3734 
3735 // --> OD 2008-05-26 #i71360#
3736 // --> OD 2010-02-22 #i108125# - adjustments for change tracking text markup
3737 sal_Int32 SAL_CALL SwAccessibleParagraph::getTextMarkupCount( sal_Int32 nTextMarkupType )
3738                                         throw (lang::IllegalArgumentException,
3739                                                uno::RuntimeException)
3740 {
3741     std::auto_ptr<SwTextMarkupHelper> pTextMarkupHelper;
3742     switch ( nTextMarkupType )
3743     {
3744         case text::TextMarkupType::TRACK_CHANGE_INSERTION:
3745         case text::TextMarkupType::TRACK_CHANGE_DELETION:
3746         case text::TextMarkupType::TRACK_CHANGE_FORMATCHANGE:
3747         {
3748             pTextMarkupHelper.reset( new SwTextMarkupHelper(
3749                 GetPortionData(),
3750                 *(mpParaChangeTrackInfo->getChangeTrackingTextMarkupList( nTextMarkupType ) )) );
3751         }
3752         break;
3753         default:
3754         {
3755             pTextMarkupHelper.reset( new SwTextMarkupHelper( GetPortionData(), *GetTxtNode() ) );
3756         }
3757     }
3758 
3759     return pTextMarkupHelper->getTextMarkupCount( nTextMarkupType );
3760 }
3761 //IAccessibility2 Implementation 2009-----
3762 //MSAA Extension Implementation in app  module
3763 sal_Bool SAL_CALL SwAccessibleParagraph::scrollToPosition( const ::com::sun::star::awt::Point&, sal_Bool )
3764 	throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException)
3765 {
3766 	return sal_False;
3767 }
3768 
3769 sal_Int32 SAL_CALL SwAccessibleParagraph::getSelectedPortionCount(  )
3770 	throw (::com::sun::star::uno::RuntimeException)
3771 {
3772 	sal_Int32 nSeleted = 0;
3773 	SwPaM* pCrsr = GetCursor( true );
3774     if( pCrsr != NULL )
3775     {
3776         // get SwPosition for my node
3777         const SwTxtNode* pNode = GetTxtNode();
3778         sal_uLong nHere = pNode->GetIndex();
3779 
3780         // iterate over ring
3781         SwPaM* pRingStart = pCrsr;
3782         do
3783         {
3784             // ignore, if no mark
3785             if( pCrsr->HasMark() )
3786             {
3787                 // check whether nHere is 'inside' pCrsr
3788                 SwPosition* pStart = pCrsr->Start();
3789                 sal_uLong nStartIndex = pStart->nNode.GetIndex();
3790                 SwPosition* pEnd = pCrsr->End();
3791                 sal_uLong nEndIndex = pEnd->nNode.GetIndex();
3792                 if( ( nHere >= nStartIndex ) &&
3793                     ( nHere <= nEndIndex )      )
3794                 {
3795 					nSeleted++;
3796                 }
3797                 // else: this PaM doesn't point to this paragraph
3798             }
3799             // else: this PaM is collapsed and doesn't select anything
3800 
3801             // next PaM in ring
3802             pCrsr = static_cast<SwPaM*>( pCrsr->GetNext() );
3803         }
3804         while( pCrsr != pRingStart );
3805     }
3806 	return nSeleted;
3807 
3808 }
3809 
3810 sal_Int32 SAL_CALL SwAccessibleParagraph::getSeletedPositionStart( sal_Int32 nSelectedPortionIndex )
3811 	throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException)
3812 {
3813 	vos::OGuard aGuard(Application::GetSolarMutex());
3814 
3815 	CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
3816 
3817 	sal_Int32 nStart, nEnd;
3818     /*sal_Bool bSelected = */GetSelectionAtIndex(nSelectedPortionIndex, nStart, nEnd );
3819 	return nStart;
3820 }
3821 
3822 sal_Int32 SAL_CALL SwAccessibleParagraph::getSeletedPositionEnd( sal_Int32 nSelectedPortionIndex )
3823 	throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException)
3824 {
3825 	vos::OGuard aGuard(Application::GetSolarMutex());
3826 
3827 	CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
3828 
3829 	sal_Int32 nStart, nEnd;
3830     /*sal_Bool bSelected = */GetSelectionAtIndex(nSelectedPortionIndex, nStart, nEnd );
3831 	return nEnd;
3832 }
3833 
3834 sal_Bool SAL_CALL SwAccessibleParagraph::removeSelection( sal_Int32 selectionIndex )
3835 	throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException)
3836 {
3837 	if(selectionIndex < 0) return sal_False;
3838 
3839     sal_Bool bRet = sal_False;
3840 	sal_Int32 nSelected = selectionIndex;
3841 
3842     // get the selection, and test whether it affects our text node
3843 	SwPaM* pCrsr = GetCursor( true );
3844 //  SwPaM* pFirst = pCrsr;
3845 	SwPaM* pPrev = pCrsr;
3846 
3847     if( pCrsr != NULL )
3848     {
3849         // get SwPosition for my node
3850         const SwTxtNode* pNode = GetTxtNode();
3851         sal_uLong nHere = pNode->GetIndex();
3852 
3853         // iterate over ring
3854         SwPaM* pRingStart = pCrsr;
3855         do
3856         {
3857             // ignore, if no mark
3858             if( pCrsr->HasMark() )
3859             {
3860                 // check whether nHere is 'inside' pCrsr
3861                 SwPosition* pStart = pCrsr->Start();
3862                 sal_uLong nStartIndex = pStart->nNode.GetIndex();
3863                 SwPosition* pEnd = pCrsr->End();
3864                 sal_uLong nEndIndex = pEnd->nNode.GetIndex();
3865                 if( ( nHere >= nStartIndex ) &&
3866                     ( nHere <= nEndIndex )      )
3867                 {
3868 					if( nSelected == 0 )
3869 					{
3870 						pCrsr->MoveTo((Ring*)0);
3871 						delete pCrsr;
3872 						bRet = sal_True;
3873 					}
3874 					else
3875 					{
3876 						nSelected--;
3877 					}
3878 				}
3879 			}
3880             // else: this PaM is collapsed and doesn't select anything
3881 		   pPrev = pCrsr;
3882            pCrsr = static_cast<SwPaM*>( pCrsr->GetNext() );
3883         }
3884         while( !bRet && (pCrsr != pRingStart) );
3885 	}
3886 	return sal_True;
3887 }
3888 
3889 sal_Int32 SAL_CALL SwAccessibleParagraph::addSelection( sal_Int32, sal_Int32 startOffset, sal_Int32 endOffset)
3890 	throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException)
3891 {
3892 	vos::OGuard aGuard(Application::GetSolarMutex());
3893 
3894 	CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
3895 
3896     // parameter checking
3897     sal_Int32 nLength = GetString().getLength();
3898     if ( ! IsValidRange( startOffset, endOffset, nLength ) )
3899     {
3900         throw lang::IndexOutOfBoundsException();
3901     }
3902 
3903 	sal_Int32 nSelectedCount = getSelectedPortionCount();
3904 	for ( sal_Int32 i = nSelectedCount ; i >= 0 ; i--)
3905 	{
3906 		sal_Int32 nStart, nEnd;
3907 		sal_Bool bSelected = GetSelectionAtIndex(i, nStart, nEnd );
3908 		if(bSelected)
3909 		{
3910 			if(nStart <= nEnd )
3911 			{
3912 				if (( startOffset>=nStart && startOffset <=nEnd ) ||     //startOffset in a selection
3913 			   		( endOffset>=nStart && endOffset <=nEnd )     ||  //endOffset in a selection
3914 					( startOffset <= nStart && endOffset >=nEnd)  ||       //start and  end include the old selection
3915 					( startOffset >= nStart && endOffset <=nEnd) )
3916 				{
3917 					removeSelection(i);
3918 				}
3919 
3920 			}
3921 			else
3922 			{
3923 				if (( startOffset>=nEnd && startOffset <=nStart ) ||     //startOffset in a selection
3924 			   		( endOffset>=nEnd && endOffset <=nStart )     || //endOffset in a selection
3925 					( startOffset <= nStart && endOffset >=nEnd)  ||       //start and  end include the old selection
3926 					( startOffset >= nStart && endOffset <=nEnd) )
3927 
3928 				{
3929 					removeSelection(i);
3930 				}
3931 			}
3932 		}
3933 
3934 	}
3935 
3936     sal_Bool bRet = sal_False;
3937 
3938     // get cursor shell
3939     SwCrsrShell* pCrsrShell = GetCrsrShell();
3940     if( pCrsrShell != NULL )
3941     {
3942         // create pam for selection
3943 		pCrsrShell->StartAction();
3944 //        SwTxtNode* pNode = const_cast<SwTxtNode*>( GetTxtNode() );
3945         SwPaM* aPaM = pCrsrShell->CreateCrsr();
3946         aPaM->SetMark();
3947 		aPaM->GetPoint()->nContent = GetPortionData().GetModelPosition(startOffset);
3948         aPaM->GetMark()->nContent =  GetPortionData().GetModelPosition(endOffset);
3949 		//pCrsrShell->ShowCrsr();
3950 		pCrsrShell->EndAction();
3951         // set PaM at cursor shell
3952         //bRet = Select( aPaM );
3953     }
3954 
3955     return bRet;
3956 }
3957 //-----IAccessibility2 Implementation 2009
3958 
3959 /*accessibility::*/TextSegment SAL_CALL
3960         SwAccessibleParagraph::getTextMarkup( sal_Int32 nTextMarkupIndex,
3961                                               sal_Int32 nTextMarkupType )
3962                                         throw (lang::IndexOutOfBoundsException,
3963                                                lang::IllegalArgumentException,
3964                                                uno::RuntimeException)
3965 {
3966     std::auto_ptr<SwTextMarkupHelper> pTextMarkupHelper;
3967     switch ( nTextMarkupType )
3968     {
3969         case text::TextMarkupType::TRACK_CHANGE_INSERTION:
3970         case text::TextMarkupType::TRACK_CHANGE_DELETION:
3971         case text::TextMarkupType::TRACK_CHANGE_FORMATCHANGE:
3972         {
3973             pTextMarkupHelper.reset( new SwTextMarkupHelper(
3974                 GetPortionData(),
3975                 *(mpParaChangeTrackInfo->getChangeTrackingTextMarkupList( nTextMarkupType ) )) );
3976         }
3977         break;
3978         default:
3979         {
3980             pTextMarkupHelper.reset( new SwTextMarkupHelper( GetPortionData(), *GetTxtNode() ) );
3981         }
3982     }
3983 
3984     return pTextMarkupHelper->getTextMarkup( nTextMarkupIndex, nTextMarkupType );
3985 }
3986 
3987 uno::Sequence< /*accessibility::*/TextSegment > SAL_CALL
3988         SwAccessibleParagraph::getTextMarkupAtIndex( sal_Int32 nCharIndex,
3989                                                      sal_Int32 nTextMarkupType )
3990                                         throw (lang::IndexOutOfBoundsException,
3991                                                lang::IllegalArgumentException,
3992                                                uno::RuntimeException)
3993 {
3994     // parameter checking
3995     const sal_Int32 nLength = GetString().getLength();
3996     if ( ! IsValidPosition( nCharIndex, nLength ) )
3997     {
3998         throw lang::IndexOutOfBoundsException();
3999     }
4000 
4001     std::auto_ptr<SwTextMarkupHelper> pTextMarkupHelper;
4002     switch ( nTextMarkupType )
4003     {
4004         case text::TextMarkupType::TRACK_CHANGE_INSERTION:
4005         case text::TextMarkupType::TRACK_CHANGE_DELETION:
4006         case text::TextMarkupType::TRACK_CHANGE_FORMATCHANGE:
4007         {
4008             pTextMarkupHelper.reset( new SwTextMarkupHelper(
4009                 GetPortionData(),
4010                 *(mpParaChangeTrackInfo->getChangeTrackingTextMarkupList( nTextMarkupType ) )) );
4011         }
4012         break;
4013         default:
4014         {
4015             pTextMarkupHelper.reset( new SwTextMarkupHelper( GetPortionData(), *GetTxtNode() ) );
4016         }
4017     }
4018 
4019     return pTextMarkupHelper->getTextMarkupAtIndex( nCharIndex, nTextMarkupType );
4020 }
4021 // <--
4022 
4023 // --> OD 2008-05-29 #i89175#
4024 sal_Int32 SAL_CALL SwAccessibleParagraph::getLineNumberAtIndex( sal_Int32 nIndex )
4025                                         throw (lang::IndexOutOfBoundsException,
4026                                                uno::RuntimeException)
4027 {
4028     // parameter checking
4029     const sal_Int32 nLength = GetString().getLength();
4030     if ( ! IsValidPosition( nIndex, nLength ) )
4031     {
4032         throw lang::IndexOutOfBoundsException();
4033     }
4034 
4035     const sal_Int32 nLineNo = GetPortionData().GetLineNo( nIndex );
4036     return nLineNo;
4037 }
4038 
4039 /*accessibility::*/TextSegment SAL_CALL
4040         SwAccessibleParagraph::getTextAtLineNumber( sal_Int32 nLineNo )
4041                                         throw (lang::IndexOutOfBoundsException,
4042                                                uno::RuntimeException)
4043 {
4044     // parameter checking
4045     if ( nLineNo < 0 ||
4046          nLineNo >= GetPortionData().GetLineCount() )
4047     {
4048         throw lang::IndexOutOfBoundsException();
4049     }
4050 
4051     i18n::Boundary aLineBound;
4052     GetPortionData().GetBoundaryOfLine( nLineNo, aLineBound );
4053 
4054     /*accessibility::*/TextSegment aTextAtLine;
4055     const ::rtl::OUString rText = GetString();
4056     aTextAtLine.SegmentText = rText.copy( aLineBound.startPos,
4057                                           aLineBound.endPos - aLineBound.startPos );
4058     aTextAtLine.SegmentStart = aLineBound.startPos;
4059     aTextAtLine.SegmentEnd = aLineBound.endPos;
4060 
4061     return aTextAtLine;
4062 }
4063 
4064 /*accessibility::*/TextSegment SAL_CALL SwAccessibleParagraph::getTextAtLineWithCaret()
4065                                         throw (uno::RuntimeException)
4066 {
4067     const sal_Int32 nLineNoOfCaret = getNumberOfLineWithCaret();
4068 
4069     if ( nLineNoOfCaret >= 0 &&
4070          nLineNoOfCaret < GetPortionData().GetLineCount() )
4071     {
4072         return getTextAtLineNumber( nLineNoOfCaret );
4073     }
4074 
4075     return /*accessibility::*/TextSegment();
4076 }
4077 
4078 sal_Int32 SAL_CALL SwAccessibleParagraph::getNumberOfLineWithCaret()
4079                                         throw (uno::RuntimeException)
4080 {
4081     const sal_Int32 nCaretPos = getCaretPosition();
4082     const sal_Int32 nLength = GetString().getLength();
4083     if ( !IsValidPosition( nCaretPos, nLength ) )
4084     {
4085         return -1;
4086     }
4087 
4088     sal_Int32 nLineNo = GetPortionData().GetLineNo( nCaretPos );
4089 
4090     // special handling for cursor positioned at end of text line via End key
4091     if ( nCaretPos != 0 )
4092     {
4093         i18n::Boundary aLineBound;
4094         GetPortionData().GetBoundaryOfLine( nLineNo, aLineBound );
4095         if ( nCaretPos == aLineBound.startPos )
4096         {
4097             SwCrsrShell* pCrsrShell = SwAccessibleParagraph::GetCrsrShell();
4098             if ( pCrsrShell != 0 )
4099             {
4100                 const awt::Rectangle aCharRect = getCharacterBounds( nCaretPos );
4101 
4102                 const SwRect& aCursorCoreRect = pCrsrShell->GetCharRect();
4103                 // translate core coordinates into accessibility coordinates
4104                 Window *pWin = GetWindow();
4105                 CHECK_FOR_WINDOW( XAccessibleComponent, pWin );
4106 
4107                 Rectangle aScreenRect( GetMap()->CoreToPixel( aCursorCoreRect.SVRect() ));
4108 
4109                 SwRect aFrmLogBounds( GetBounds( *(GetMap()) ) ); // twip rel to doc root
4110                 Point aFrmPixPos( GetMap()->CoreToPixel( aFrmLogBounds.SVRect() ).TopLeft() );
4111                 aScreenRect.Move( -aFrmPixPos.X(), -aFrmPixPos.Y() );
4112 
4113                 // convert into AWT Rectangle
4114                 const awt::Rectangle aCursorRect( aScreenRect.Left(),
4115                                                   aScreenRect.Top(),
4116                                                   aScreenRect.GetWidth(),
4117                                                   aScreenRect.GetHeight() );
4118 
4119                 if ( aCharRect.X != aCursorRect.X ||
4120                      aCharRect.Y != aCursorRect.Y )
4121                 {
4122                     --nLineNo;
4123                 }
4124             }
4125         }
4126     }
4127 
4128     return nLineNo;
4129 }
4130 
4131 // --> OD 2010-02-19 #i108125#
4132 void SwAccessibleParagraph::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
4133 {
4134     mpParaChangeTrackInfo->reset();
4135 
4136     CheckRegistration( pOld, pNew );
4137 }
4138 // <--
4139 
4140 //IAccessibility2 Implementation 2009-----
4141 sal_Bool SwAccessibleParagraph::GetSelectionAtIndex(
4142     sal_Int32& nIndex, sal_Int32& nStart, sal_Int32& nEnd)
4143 {
4144         if(nIndex < 0) return sal_False;
4145 
4146 
4147     sal_Bool bRet = sal_False;
4148     nStart = -1;
4149     nEnd = -1;
4150 	sal_Int32 nSelected = nIndex;
4151 
4152     // get the selection, and test whether it affects our text node
4153 	SwPaM* pCrsr = GetCursor( true );
4154     if( pCrsr != NULL )
4155     {
4156         // get SwPosition for my node
4157         const SwTxtNode* pNode = GetTxtNode();
4158         sal_uLong nHere = pNode->GetIndex();
4159 
4160         // iterate over ring
4161         SwPaM* pRingStart = pCrsr;
4162         do
4163         {
4164             // ignore, if no mark
4165             if( pCrsr->HasMark() )
4166             {
4167                 // check whether nHere is 'inside' pCrsr
4168                 SwPosition* pStart = pCrsr->Start();
4169                 sal_uLong nStartIndex = pStart->nNode.GetIndex();
4170                 SwPosition* pEnd = pCrsr->End();
4171                 sal_uLong nEndIndex = pEnd->nNode.GetIndex();
4172                 if( ( nHere >= nStartIndex ) &&
4173                     ( nHere <= nEndIndex )      )
4174                 {
4175 					if( nSelected == 0 )
4176 					{
4177 						// translate start and end positions
4178 
4179 						// start position
4180 						sal_Int32 nLocalStart = -1;
4181 						if( nHere > nStartIndex )
4182 						{
4183 							// selection starts in previous node:
4184 							// then our local selection starts with the paragraph
4185 							nLocalStart = 0;
4186 						}
4187 						else
4188 						{
4189 							DBG_ASSERT( nHere == nStartIndex,
4190 										"miscalculated index" );
4191 
4192 							// selection starts in this node:
4193 							// then check whether it's before or inside our part of
4194 							// the paragraph, and if so, get the proper position
4195 							sal_uInt16 nCoreStart = pStart->nContent.GetIndex();
4196 							if( nCoreStart <
4197 								GetPortionData().GetFirstValidCorePosition() )
4198 							{
4199 								nLocalStart = 0;
4200 							}
4201 							else if( nCoreStart <=
4202 									 GetPortionData().GetLastValidCorePosition() )
4203 							{
4204 								DBG_ASSERT(
4205 									GetPortionData().IsValidCorePosition(
4206 																	  nCoreStart ),
4207 									 "problem determining valid core position" );
4208 
4209 								nLocalStart =
4210 									GetPortionData().GetAccessiblePosition(
4211 																	  nCoreStart );
4212 							}
4213 						}
4214 
4215 						// end position
4216 						sal_Int32 nLocalEnd = -1;
4217 						if( nHere < nEndIndex )
4218 						{
4219 							// selection ends in following node:
4220 							// then our local selection extends to the end
4221 							nLocalEnd = GetPortionData().GetAccessibleString().
4222 																	   getLength();
4223 						}
4224 						else
4225 						{
4226 							DBG_ASSERT( nHere == nStartIndex,
4227 										"miscalculated index" );
4228 
4229 							// selection ends in this node: then select everything
4230 							// before our part of the node
4231 							sal_uInt16 nCoreEnd = pEnd->nContent.GetIndex();
4232 							if( nCoreEnd >
4233 									GetPortionData().GetLastValidCorePosition() )
4234 							{
4235 								// selection extends beyond out part of this para
4236 								nLocalEnd = GetPortionData().GetAccessibleString().
4237 																	   getLength();
4238 							}
4239 							else if( nCoreEnd >=
4240 									 GetPortionData().GetFirstValidCorePosition() )
4241 							{
4242 								// selection is inside our part of this para
4243 								DBG_ASSERT(
4244 									GetPortionData().IsValidCorePosition(
4245 																	  nCoreEnd ),
4246 									 "problem determining valid core position" );
4247 
4248 								nLocalEnd = GetPortionData().GetAccessiblePosition(
4249 																	   nCoreEnd );
4250 							}
4251 						}
4252 
4253 						if( ( nLocalStart != -1 ) && ( nLocalEnd != -1 ) )
4254 						{
4255 							nStart = nLocalStart;
4256 							nEnd = nLocalEnd;
4257 							bRet = sal_True;
4258 						}
4259 					} // if hit the index
4260 					else
4261 					{
4262 						nSelected--;
4263 					}
4264                 }
4265                 // else: this PaM doesn't point to this paragraph
4266             }
4267             // else: this PaM is collapsed and doesn't select anything
4268 
4269             // next PaM in ring
4270             pCrsr = static_cast<SwPaM*>( pCrsr->GetNext() );
4271         }
4272         while( !bRet && (pCrsr != pRingStart) );
4273     }
4274     // else: nocursor -> no selection
4275 
4276     if( bRet )
4277     {
4278 		sal_Int32 nCaretPos = GetCaretPos();
4279 		if( nStart == nCaretPos )
4280 		{
4281 			sal_Int32 tmp = nStart;
4282 			nStart = nEnd;
4283 			nEnd = tmp;
4284 		}
4285     }
4286     return bRet;
4287 }
4288 
4289 sal_Int16 SAL_CALL SwAccessibleParagraph::getAccessibleRole (void) throw (::com::sun::star::uno::RuntimeException)
4290 {
4291 	//Get the real heading level, Heading1 ~ Heading10
4292 	if (nHeadingLevel > 0)
4293 	{
4294 		return AccessibleRole::HEADING;
4295 	}
4296 	else
4297 	{
4298 		return AccessibleRole::PARAGRAPH;
4299 	}
4300 }
4301 
4302 // End Add
4303 
4304 
4305 /* This funcion is already defined in accpara.cxx(Added by yanjun)
4306 sal_Int32 SAL_CALL SwAccessibleParagraph::getBackground()
4307 		throw (::com::sun::star::uno::RuntimeException)
4308 {
4309 // Test Code
4310 //     Sequence<OUString> seNames(1);
4311 //     OUString* pStrings = seNames.getArray();
4312 // 	pStrings[0] = OUString(RTL_CONSTASCII_USTRINGPARAM("ParaBackColor"));
4313 //
4314 //     Sequence<Any> aAnys(1);
4315 // 	Reference<XMultiPropertySet> xPortion = CreateUnoPortion( 0, 0 );
4316 //     aAnys = xPortion->getPropertyValues( seNames );
4317 // 	const Any* pAnys = aAnys.getConstArray();
4318 //
4319 // 	sal_uInt32 crColorT=0;
4320 // 	pAnys[0] >>= crColorT;
4321 // End Test Code
4322 
4323 	const SvxBrushItem &rBack = GetFrm()->GetAttrSet()->GetBackground();
4324 	sal_uInt32 crBack = rBack.GetColor().GetColor();
4325 
4326 	if (COL_AUTO == crBack)
4327 	{
4328 		Reference<XAccessible> xAccDoc = getAccessibleParent();
4329 		if (xAccDoc.is())
4330 		{
4331 			Reference<XAccessibleComponent> xCompoentDoc(xAccDoc,UNO_QUERY);
4332 			if (xCompoentDoc.is())
4333 			{
4334 				crBack = (sal_uInt32)xCompoentDoc->getBackground();
4335 			}
4336 		}
4337 	}
4338 	return crBack;
4339 }
4340 */
4341 
4342 //Get the real heading level, Heading1 ~ Heading10
4343 sal_Int32 SwAccessibleParagraph::GetRealHeadingLevel()
4344 {
4345     uno::Reference< ::com::sun::star::beans::XPropertySet > xPortion = CreateUnoPortion( 0, 0 );
4346     ::rtl::OUString pString = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ParaStyleName"));
4347     uno::Any styleAny = xPortion->getPropertyValue( pString );
4348     ::rtl::OUString sValue;
4349 	if (styleAny >>= sValue)
4350 	{
4351 		//Modified by yanjun for acc migration
4352 		sal_Int32 length = sValue.getLength/*GetCharCount*/();
4353 		if (length == 9 || length == 10)
4354 		{
4355             ::rtl::OUString headStr = sValue.copy(0, 7);
4356             if (headStr.equals(::rtl::OUString::createFromAscii("Heading")))
4357 			{
4358                 ::rtl::OUString intStr = sValue.copy(8);
4359 				sal_Int32 headingLevel = intStr.toInt32(10);
4360 				return headingLevel;
4361 			}
4362 		}
4363 	}
4364 	return -1;
4365 }
4366 
4367 uno::Any SAL_CALL SwAccessibleParagraph::getExtendedAttributes()
4368 		throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException)
4369 {
4370     uno::Any Ret;
4371     ::rtl::OUString strHeading(::rtl::OUString::createFromAscii("heading-level:"));
4372 	if( nHeadingLevel >= 0 )
4373 		strHeading += OUString::valueOf(nHeadingLevel, 10);
4374 	strHeading += OUString::createFromAscii(";");
4375 
4376 	Ret <<= strHeading;
4377 
4378 	return Ret;
4379 }
4380 
4381 //Tab will be return when call WORDTYPE
4382 sal_Bool SwAccessibleParagraph::tabCharInWord( sal_Int32 nIndex, i18n::Boundary& aBound)
4383 {
4384 	sal_Bool bFind =  sal_False;
4385 	if( aBound.startPos != nIndex)
4386 	{
4387 		OUString tabStr;
4388 		if(aBound.startPos>nIndex)
4389 			tabStr = GetString().copy(nIndex,(aBound.startPos - nIndex) );
4390 
4391 		sal_Unicode tabChar('\t');
4392 		sal_Int32 tabIndex = tabStr.indexOf(tabChar);
4393 		if( tabIndex > -1 )
4394 		{
4395 			aBound.startPos = nIndex + tabIndex ;
4396 			aBound.endPos = aBound.startPos + 1;
4397 			bFind = sal_True;
4398 		}
4399 	}
4400 	return bFind;
4401 }
4402 //-----IAccessibility2 Implementation 2009
4403