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