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_editeng.hxx"
26 
27 //------------------------------------------------------------------------
28 //
29 // Global header
30 //
31 //------------------------------------------------------------------------
32 
33 #include <limits.h>
34 #include <vector>
35 #include <algorithm>
36 #include <boost/bind.hpp>
37 #include <vos/mutex.hxx>
38 #include <vcl/window.hxx>
39 #include <vcl/svapp.hxx>
40 #include <comphelper/sequenceasvector.hxx>
41 #include <com/sun/star/uno/Any.hxx>
42 #include <com/sun/star/uno/Reference.hxx>
43 #include <com/sun/star/awt/Point.hpp>
44 #include <com/sun/star/awt/Rectangle.hpp>
45 #include <com/sun/star/accessibility/AccessibleTextType.hpp>
46 
47 //------------------------------------------------------------------------
48 //
49 // Project-local header
50 //
51 //------------------------------------------------------------------------
52 
53 #include <editeng/editdata.hxx>
54 #include <editeng/unopracc.hxx>
55 #include "editeng/unoedprx.hxx"
56 #include <editeng/AccessibleStaticTextBase.hxx>
57 #include "editeng/AccessibleEditableTextPara.hxx"
58 
59 
60 using namespace ::com::sun::star;
61 using namespace ::com::sun::star::accessibility;
62 
63 /* TODO:
64    =====
65 
66    - separate adapter functionality from AccessibleStaticText class
67 
68    - refactor common loops into templates, using mem_fun
69 
70  */
71 
72 namespace accessibility
73 {
74     typedef ::comphelper::SequenceAsVector< beans::PropertyValue > PropertyValueVector;
75 
76     class PropertyValueEqualFunctor : public ::std::binary_function< beans::PropertyValue, beans::PropertyValue, bool >
77     {
78     public:
79         PropertyValueEqualFunctor()
80         {}
81         bool operator() ( const beans::PropertyValue& lhs, const beans::PropertyValue& rhs ) const
82         {
83             return ( lhs.Name == rhs.Name && lhs.Value == rhs.Value );
84         }
85     };
86 //IAccessibility2 Implementation 2009-----
87 sal_Unicode cNewLine(0x0a);
88 //-----IAccessibility2 Implementation 2009
89 	//------------------------------------------------------------------------
90 	//
91 	// Static Helper
92 	//
93 	//------------------------------------------------------------------------
94     ESelection MakeSelection( sal_Int32 nStartPara, sal_Int32 nStartIndex,
95                               sal_Int32 nEndPara, sal_Int32 nEndIndex )
96     {
97         DBG_ASSERT(nStartPara >= 0 && nStartPara <= USHRT_MAX &&
98                    nStartIndex >= 0 && nStartIndex <= USHRT_MAX &&
99                    nEndPara >= 0 && nEndPara <= USHRT_MAX &&
100                    nEndIndex >= 0 && nEndIndex <= USHRT_MAX ,
101                    "AccessibleStaticTextBase_Impl::MakeSelection: index value overflow");
102 
103         return ESelection( static_cast< sal_uInt16 >(nStartPara), static_cast< sal_uInt16 >(nStartIndex),
104                            static_cast< sal_uInt16 >(nEndPara), static_cast< sal_uInt16 >(nEndIndex) );
105     }
106 
107 	//------------------------------------------------------------------------
108 	//
109 	// AccessibleStaticTextBase_Impl declaration
110 	//
111 	//------------------------------------------------------------------------
112 
113     DBG_NAME( AccessibleStaticTextBase_Impl );
114 
115     /** AccessibleStaticTextBase_Impl
116 
117     	This class implements the AccessibleStaticTextBase
118     	functionality, mainly by forwarding the calls to an aggregated
119     	AccessibleEditableTextPara. As this is a therefore non-trivial
120     	adapter, factoring out the common functionality from
121     	AccessibleEditableTextPara might be a profitable future task.
122      */
123     class AccessibleStaticTextBase_Impl
124     {
125 	//IAccessibility2 Implementation 2009-----
126 		friend class AccessibleStaticTextBase;
127 	//-----IAccessibility2 Implementation 2009
128     public:
129 
130         // receive pointer to our frontend class and view window
131         AccessibleStaticTextBase_Impl();
132         ~AccessibleStaticTextBase_Impl();
133 
134         SvxEditSourceAdapter& GetEditSource() const SAL_THROW((uno::RuntimeException))
135         {
136             DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL );
137 
138             return maEditSource;
139         }
140         void SetEditSource( ::std::auto_ptr< SvxEditSource > pEditSource ) SAL_THROW((uno::RuntimeException));
141 
142         void SetEventSource( const uno::Reference< XAccessible >& rInterface )
143         {
144             DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL );
145 
146             mxThis = rInterface;
147         }
148         uno::Reference< XAccessible > GetEventSource() const
149         {
150             DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL );
151 
152             return mxThis;
153         }
154 
155         void SetOffset( const Point& );
156         Point GetOffset() const
157         {
158             DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL );
159 
160             ::osl::MutexGuard aGuard( maMutex ); Point aPoint( maOffset );
161             return aPoint;
162         }
163 
164         void UpdateChildren();
165         void Dispose();
166 
167 #ifdef DBG_UTIL
168         void CheckInvariants() const;
169 #endif
170 
171         AccessibleEditableTextPara& GetParagraph( sal_Int32 nPara ) const;
172         sal_Int32 					GetParagraphCount() const;
173         sal_Int32                   GetParagraphIndex() const;
174         sal_Int32                   GetLineCount( sal_Int32 nParagraph ) const;
175 
176         EPosition                   Index2Internal( sal_Int32 nFlatIndex ) const
177         {
178             DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL );
179 
180             return ImpCalcInternal( nFlatIndex, false );
181         }
182 
183         EPosition                   Range2Internal( sal_Int32 nFlatIndex ) const
184         {
185             DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL );
186 
187             return ImpCalcInternal( nFlatIndex, true );
188         }
189 
190         sal_Int32					Internal2Index( EPosition nEEIndex ) const;
191 
192         void						CorrectTextSegment( TextSegment&	aTextSegment,
193                                                         int				nPara	) const;
194 
195         sal_Bool					SetSelection( sal_Int32 nStartPara, sal_Int32 nStartIndex,
196                                                   sal_Int32 nEndPara, sal_Int32 nEndIndex );
197         sal_Bool					CopyText( sal_Int32 nStartPara, sal_Int32 nStartIndex,
198                                               sal_Int32 nEndPara, sal_Int32 nEndIndex );
199 
200         Rectangle                   GetParagraphBoundingBox() const;
201 	//IAccessibility2 Implementation 2009-----
202 		sal_Bool					RemoveLineBreakCount( sal_Int32& rIndex );
203 	//-----IAccessibility2 Implementation 2009
204 
205     private:
206 
207         EPosition 					ImpCalcInternal( sal_Int32 nFlatIndex, bool bExclusive ) const;
208 
209         // our frontend class (the one implementing the actual
210         // interface). That's not necessarily the one containing the impl
211         // pointer
212         uno::Reference< XAccessible > mxThis;
213 
214         // implements our functionality, we're just an adapter (guarded by solar mutex)
215         mutable AccessibleEditableTextPara* mpTextParagraph;
216 
217         uno::Reference< XAccessible > mxParagraph;
218 
219         // a wrapper for the text forwarders (guarded by solar mutex)
220         mutable SvxEditSourceAdapter maEditSource;
221 
222         // guard for maOffset
223         mutable ::osl::Mutex maMutex;
224 
225         /// our current offset to the containing shape/cell (guarded by maMutex)
226         Point maOffset;
227 
228     };
229 
230 	//------------------------------------------------------------------------
231 	//
232 	// AccessibleStaticTextBase_Impl implementation
233 	//
234 	//------------------------------------------------------------------------
235 
236     AccessibleStaticTextBase_Impl::AccessibleStaticTextBase_Impl() :
237         mxThis( NULL ),
238         mpTextParagraph( new AccessibleEditableTextPara(NULL) ),
239         mxParagraph( mpTextParagraph ),
240         maEditSource(),
241         maMutex(),
242         maOffset(0,0)
243     {
244         DBG_CTOR( AccessibleStaticTextBase_Impl, NULL );
245 
246         // TODO: this is still somewhat of a hack, all the more since
247         // now the maTextParagraph has an empty parent reference set
248     }
249 
250     AccessibleStaticTextBase_Impl::~AccessibleStaticTextBase_Impl()
251     {
252         DBG_DTOR( AccessibleStaticTextBase_Impl, NULL );
253     }
254 
255     void AccessibleStaticTextBase_Impl::SetEditSource( ::std::auto_ptr< SvxEditSource > pEditSource ) SAL_THROW((uno::RuntimeException))
256     {
257         DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL );
258 
259         maEditSource.SetEditSource( pEditSource );
260         if( mpTextParagraph )
261             mpTextParagraph->SetEditSource( &maEditSource );
262     }
263 
264     void AccessibleStaticTextBase_Impl::SetOffset( const Point& rPoint )
265     {
266         DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL );
267 
268         // guard against non-atomic access to maOffset data structure
269         {
270             ::osl::MutexGuard aGuard( maMutex );
271             maOffset = rPoint;
272         }
273 
274         if( mpTextParagraph )
275             mpTextParagraph->SetEEOffset( rPoint );
276 
277         // in all cases, check visibility afterwards.
278         UpdateChildren();
279     }
280 
281     void AccessibleStaticTextBase_Impl::UpdateChildren()
282     {
283         DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL );
284 
285         // currently no children
286     }
287 
288     void AccessibleStaticTextBase_Impl::Dispose()
289     {
290         DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL );
291 
292         // we're the owner of the paragraph, so destroy it, too
293         if( mpTextParagraph )
294             mpTextParagraph->Dispose();
295 
296         // drop references
297         mxParagraph = NULL;
298         mxThis = NULL;
299         mpTextParagraph = NULL;
300     }
301 
302 #ifdef DBG_UTIL
303     void AccessibleStaticTextBase_Impl::CheckInvariants() const
304     {
305         // TODO
306     }
307 #endif
308 
309     AccessibleEditableTextPara& AccessibleStaticTextBase_Impl::GetParagraph( sal_Int32 nPara ) const
310     {
311         DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL );
312 
313         if( !mpTextParagraph )
314             throw lang::DisposedException (
315                 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("object has been already disposed")), mxThis );
316 
317         // TODO: Have a differnt method on AccessibleEditableTextPara
318         // that does not care about state changes
319         mpTextParagraph->SetParagraphIndex( nPara );
320 
321         return *mpTextParagraph;
322     }
323 
324     sal_Int32 AccessibleStaticTextBase_Impl::GetParagraphCount() const
325     {
326         DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL );
327 
328         if( !mpTextParagraph )
329             return 0;
330         else
331             return mpTextParagraph->GetTextForwarder().GetParagraphCount();
332     }
333 
334     sal_Int32 AccessibleStaticTextBase_Impl::GetParagraphIndex() const
335     {
336         DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL );
337 
338         sal_Int32 nIndex = -1;
339         if( mpTextParagraph )
340             nIndex = mpTextParagraph->GetParagraphIndex();
341         return nIndex;
342     }
343 
344     sal_Int32 AccessibleStaticTextBase_Impl::GetLineCount( sal_Int32 nParagraph ) const
345     {
346         DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL );
347 
348         sal_Int32 nIndex = 0;
349         if( mpTextParagraph )
350             nIndex = mpTextParagraph->GetTextForwarder().GetLineCount( static_cast< sal_uInt16 >(nParagraph) );
351         return nIndex;
352     }
353 
354     sal_Int32 AccessibleStaticTextBase_Impl::Internal2Index( EPosition nEEIndex ) const
355     {
356         sal_Int32 aRes(0);
357         int i;
358         for(i=0; i<nEEIndex.nPara; ++i)
359             aRes += GetParagraph(i).getCharacterCount();
360 
361         return aRes + nEEIndex.nIndex;
362     }
363 
364     void AccessibleStaticTextBase_Impl::CorrectTextSegment( TextSegment&	aTextSegment,
365                                                             int				nPara	) const
366     {
367         // Keep 'invalid' values at the TextSegment
368         if( aTextSegment.SegmentStart != -1 &&
369             aTextSegment.SegmentStart != -1 )
370         {
371             // #112814# Correct TextSegment by paragraph offset
372             sal_Int32 nOffset(0);
373             int i;
374             for(i=0; i<nPara; ++i)
375                 nOffset += GetParagraph(i).getCharacterCount();
376 
377             aTextSegment.SegmentStart += nOffset;
378             aTextSegment.SegmentEnd += nOffset;
379         }
380     }
381 
382     EPosition AccessibleStaticTextBase_Impl::ImpCalcInternal( sal_Int32 nFlatIndex, bool bExclusive ) const
383     {
384         DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL );
385 
386         if( nFlatIndex < 0 )
387             throw lang::IndexOutOfBoundsException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AccessibleStaticTextBase_Impl::Index2Internal: character index out of bounds")),
388                                                   mxThis);
389         // gratuitously accepting larger indices here, AccessibleEditableTextPara will throw eventually
390 
391         sal_Int32 nCurrPara, nCurrIndex, nParas, nCurrCount;
392         for( nCurrPara=0, nParas=GetParagraphCount(), nCurrCount=0, nCurrIndex=0; nCurrPara<nParas; ++nCurrPara )
393         {
394             nCurrCount = GetParagraph( nCurrPara ).getCharacterCount();
395             nCurrIndex += nCurrCount;
396 	//IAccessibility2 Implementation 2009-----
397             if( nCurrIndex >= nFlatIndex )
398 	//-----IAccessibility2 Implementation 2009
399             {
400                 // check overflow
401                 DBG_ASSERT(nCurrPara >= 0 && nCurrPara <= USHRT_MAX &&
402                            nFlatIndex - nCurrIndex + nCurrCount >= 0 && nFlatIndex - nCurrIndex + nCurrCount <= USHRT_MAX ,
403                            "AccessibleStaticTextBase_Impl::Index2Internal: index value overflow");
404 
405                 return EPosition( static_cast< sal_uInt16 >(nCurrPara), static_cast< sal_uInt16 >(nFlatIndex - nCurrIndex + nCurrCount) );
406             }
407         }
408 
409         // #102170# Allow one-past the end for ranges
410         if( bExclusive && nCurrIndex == nFlatIndex )
411         {
412             // check overflow
413             DBG_ASSERT(nCurrPara >= 0 && nCurrPara <= USHRT_MAX &&
414                        nFlatIndex - nCurrIndex + nCurrCount >= 0 && nFlatIndex - nCurrIndex + nCurrCount <= USHRT_MAX ,
415                        "AccessibleStaticTextBase_Impl::Index2Internal: index value overflow");
416 
417             return EPosition( static_cast< sal_uInt16 >(nCurrPara-1), static_cast< sal_uInt16 >(nFlatIndex - nCurrIndex + nCurrCount) );
418         }
419 
420         // not found? Out of bounds
421         throw lang::IndexOutOfBoundsException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AccessibleStaticTextBase_Impl::Index2Internal: character index out of bounds")),
422                                               mxThis);
423     }
424 
425     sal_Bool AccessibleStaticTextBase_Impl::SetSelection( sal_Int32 nStartPara, sal_Int32 nStartIndex,
426                                                           sal_Int32 nEndPara, sal_Int32 nEndIndex )
427     {
428         DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL );
429 
430         if( !mpTextParagraph )
431             return sal_False;
432 
433         try
434         {
435             SvxEditViewForwarder& rCacheVF = mpTextParagraph->GetEditViewForwarder( sal_True );
436             return rCacheVF.SetSelection( MakeSelection(nStartPara, nStartIndex, nEndPara, nEndIndex) );
437         }
438         catch( const uno::RuntimeException& )
439         {
440             return sal_False;
441         }
442     }
443 
444     sal_Bool AccessibleStaticTextBase_Impl::CopyText( sal_Int32 nStartPara, sal_Int32 nStartIndex,
445                                                       sal_Int32 nEndPara, sal_Int32 nEndIndex )
446     {
447         DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL );
448 
449         if( !mpTextParagraph )
450             return sal_False;
451 
452         try
453         {
454             SvxEditViewForwarder& rCacheVF = mpTextParagraph->GetEditViewForwarder( sal_True );
455             mpTextParagraph->GetTextForwarder();	// MUST be after GetEditViewForwarder(), see method docs
456             sal_Bool aRetVal;
457 
458             // save current selection
459             ESelection aOldSelection;
460 
461             rCacheVF.GetSelection( aOldSelection );
462             rCacheVF.SetSelection( MakeSelection(nStartPara, nStartIndex, nEndPara, nEndIndex) );
463             aRetVal = rCacheVF.Copy();
464             rCacheVF.SetSelection( aOldSelection ); // restore
465 
466             return aRetVal;
467         }
468         catch( const uno::RuntimeException& )
469         {
470             return sal_False;
471         }
472     }
473 
474     Rectangle AccessibleStaticTextBase_Impl::GetParagraphBoundingBox() const
475     {
476         Rectangle aRect;
477         if( mpTextParagraph )
478         {
479             awt::Rectangle aAwtRect = mpTextParagraph->getBounds();
480             aRect = Rectangle( Point( aAwtRect.X, aAwtRect.Y ), Size( aAwtRect.Width, aAwtRect.Height ) );
481         }
482         else
483         {
484             aRect.SetEmpty();
485         }
486         return aRect;
487     }
488     	//IAccessibility2 Implementation 2009-----
489 	//the input argument is the index(including "\n" ) in the string.
490 	//the function will calculate the actual index(not including "\n") in the string.
491 	//and return true if the index is just at a "\n"
492 	sal_Bool AccessibleStaticTextBase_Impl::RemoveLineBreakCount( sal_Int32& rIndex )
493 	{
494 		// get the total char number inside the cell.
495 		sal_Int32 i, nCount, nParas;
496         for( i=0, nCount=0, nParas=GetParagraphCount(); i<nParas; ++i )
497             nCount += GetParagraph(i).getCharacterCount();
498 		nCount = nCount + (nParas-1);
499 		if( nCount == 0 &&  rIndex == 0) return sal_False;
500 
501 
502 		sal_Int32 nCurrPara, nCurrCount;
503 		sal_Int32 nLineBreakPos = 0, nLineBreakCount = 0;
504 		sal_Int32 nParaCount = GetParagraphCount();
505 		for ( nCurrCount = 0, nCurrPara = 0; nCurrPara < nParaCount; nCurrPara++ )
506 		{
507 			nCurrCount += GetParagraph( nCurrPara ).getCharacterCount();
508 			nLineBreakPos = nCurrCount++;
509 			if ( rIndex == nLineBreakPos )
510 			{
511 				rIndex -= (++nLineBreakCount);//(++nLineBreakCount);
512 				if ( rIndex < 0)
513 				{
514 					rIndex = 0;
515 				}
516 				//if the index is at the last position of the last paragraph
517 				//there is no "\n" , so we should increase rIndex by 1 and return false.
518 				if ( (nCurrPara+1) == nParaCount )
519 				{
520 					rIndex++;
521 					return sal_False;
522 				}
523 				else
524 				{
525 					return sal_True;
526 				}
527 			}
528 			else if ( rIndex < nLineBreakPos )
529 			{
530 				rIndex -= nLineBreakCount;
531 				return sal_False;
532 			}
533 			else
534 			{
535 				nLineBreakCount++;
536 			}
537 		}
538 		return sal_False;
539 	}
540 	//-----IAccessibility2 Implementation 2009
541 	//------------------------------------------------------------------------
542 	//
543 	// AccessibleStaticTextBase implementation
544 	//
545 	//------------------------------------------------------------------------
546 
547     AccessibleStaticTextBase::AccessibleStaticTextBase( ::std::auto_ptr< SvxEditSource > 		pEditSource ) :
548         mpImpl( new AccessibleStaticTextBase_Impl() )
549     {
550         ::vos::OGuard aGuard( Application::GetSolarMutex() );
551 
552         SetEditSource( pEditSource );
553     }
554 
555     AccessibleStaticTextBase::~AccessibleStaticTextBase()
556     {
557     }
558 
559     const SvxEditSource& AccessibleStaticTextBase::GetEditSource() const SAL_THROW((::com::sun::star::uno::RuntimeException))
560     {
561 #ifdef DBG_UTIL
562         mpImpl->CheckInvariants();
563 
564         const SvxEditSource& aEditSource = mpImpl->GetEditSource();
565 
566         mpImpl->CheckInvariants();
567 
568         return aEditSource;
569 #else
570         return mpImpl->GetEditSource();
571 #endif
572     }
573 
574     void AccessibleStaticTextBase::SetEditSource( ::std::auto_ptr< SvxEditSource > pEditSource ) SAL_THROW((::com::sun::star::uno::RuntimeException))
575     {
576 #ifdef DBG_UTIL
577         // precondition: solar mutex locked
578         DBG_TESTSOLARMUTEX();
579 
580         mpImpl->CheckInvariants();
581 
582         mpImpl->SetEditSource( pEditSource );
583 
584         mpImpl->CheckInvariants();
585 #else
586         mpImpl->SetEditSource( pEditSource );
587 #endif
588     }
589 
590     void AccessibleStaticTextBase::SetEventSource( const uno::Reference< XAccessible >& rInterface )
591     {
592 #ifdef DBG_UTIL
593         mpImpl->CheckInvariants();
594 #endif
595 
596         mpImpl->SetEventSource( rInterface );
597 
598 #ifdef DBG_UTIL
599         mpImpl->CheckInvariants();
600 #endif
601     }
602 
603     uno::Reference< XAccessible > AccessibleStaticTextBase::GetEventSource() const
604     {
605 #ifdef DBG_UTIL
606         mpImpl->CheckInvariants();
607 
608         uno::Reference< XAccessible > xRet( mpImpl->GetEventSource() );
609 
610         mpImpl->CheckInvariants();
611 
612         return xRet;
613 #else
614         return mpImpl->GetEventSource();
615 #endif
616     }
617 
618     void AccessibleStaticTextBase::SetOffset( const Point& rPoint )
619     {
620 #ifdef DBG_UTIL
621         // precondition: solar mutex locked
622         DBG_TESTSOLARMUTEX();
623 
624         mpImpl->CheckInvariants();
625 
626         mpImpl->SetOffset( rPoint );
627 
628         mpImpl->CheckInvariants();
629 #else
630         mpImpl->SetOffset( rPoint );
631 #endif
632     }
633 
634     Point AccessibleStaticTextBase::GetOffset() const
635     {
636 #ifdef DBG_UTIL
637         mpImpl->CheckInvariants();
638 
639         Point aPoint( mpImpl->GetOffset() );
640 
641         mpImpl->CheckInvariants();
642 
643         return aPoint;
644 #else
645         return mpImpl->GetOffset();
646 #endif
647     }
648 
649     void AccessibleStaticTextBase::UpdateChildren() SAL_THROW((::com::sun::star::uno::RuntimeException))
650     {
651 #ifdef DBG_UTIL
652         // precondition: solar mutex locked
653         DBG_TESTSOLARMUTEX();
654 
655         mpImpl->CheckInvariants();
656 
657         mpImpl->UpdateChildren();
658 
659         mpImpl->CheckInvariants();
660 #else
661         mpImpl->UpdateChildren();
662 #endif
663     }
664 
665     void AccessibleStaticTextBase::Dispose()
666     {
667 #ifdef DBG_UTIL
668         mpImpl->CheckInvariants();
669 #endif
670 
671         mpImpl->Dispose();
672 
673 #ifdef DBG_UTIL
674         mpImpl->CheckInvariants();
675 #endif
676     }
677 
678 	// XAccessibleContext
679     sal_Int32 SAL_CALL AccessibleStaticTextBase::getAccessibleChildCount() throw (uno::RuntimeException)
680     {
681         // no children at all
682         return 0;
683     }
684 
685     uno::Reference< XAccessible > SAL_CALL AccessibleStaticTextBase::getAccessibleChild( sal_Int32 /*i*/ ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
686     {
687         // no children at all
688         return uno::Reference< XAccessible >();
689     }
690 
691     uno::Reference< XAccessible > SAL_CALL AccessibleStaticTextBase::getAccessibleAtPoint( const awt::Point& /*_aPoint*/ ) throw (uno::RuntimeException)
692     {
693         // no children at all
694         return uno::Reference< XAccessible >();
695     }
696 
697 	// XAccessibleText
698     sal_Int32 SAL_CALL AccessibleStaticTextBase::getCaretPosition() throw (uno::RuntimeException)
699     {
700         ::vos::OGuard aGuard( Application::GetSolarMutex() );
701 
702         sal_Int32 i, nPos, nParas;
703         for( i=0, nPos=-1, nParas=mpImpl->GetParagraphCount(); i<nParas; ++i )
704         {
705             if( (nPos=mpImpl->GetParagraph(i).getCaretPosition()) != -1 )
706                 return nPos;
707         }
708 
709         return nPos;
710     }
711 
712     sal_Bool SAL_CALL AccessibleStaticTextBase::setCaretPosition( sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
713     {
714         return setSelection(nIndex, nIndex);
715     }
716 
717     sal_Unicode SAL_CALL AccessibleStaticTextBase::getCharacter( sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
718     {
719         ::vos::OGuard aGuard( Application::GetSolarMutex() );
720 
721         EPosition aPos( mpImpl->Index2Internal(nIndex) );
722 
723         return mpImpl->GetParagraph( aPos.nPara ).getCharacter( aPos.nIndex );
724     }
725 
726     uno::Sequence< beans::PropertyValue > SAL_CALL AccessibleStaticTextBase::getCharacterAttributes( sal_Int32 nIndex, const ::com::sun::star::uno::Sequence< ::rtl::OUString >& aRequestedAttributes ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
727     {
728         ::vos::OGuard aGuard( Application::GetSolarMutex() );
729 	//IAccessibility2 Implementation 2009-----
730 		//get the actual index without "\n"
731 		mpImpl->RemoveLineBreakCount( nIndex );
732 	//IAccessibility2 Implementation 2009-----
733 
734         EPosition aPos( mpImpl->Index2Internal(nIndex) );
735 
736         return mpImpl->GetParagraph( aPos.nPara ).getCharacterAttributes( aPos.nIndex, aRequestedAttributes );
737     }
738 
739     awt::Rectangle SAL_CALL AccessibleStaticTextBase::getCharacterBounds( sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
740     {
741         ::vos::OGuard aGuard( Application::GetSolarMutex() );
742 
743         // #108900# Allow ranges for nIndex, as one-past-the-end
744         // values are now legal, too.
745         EPosition aPos( mpImpl->Range2Internal(nIndex) );
746 
747         // #i70916# Text in spread sheet cells return the wrong extents
748         AccessibleEditableTextPara& rPara = mpImpl->GetParagraph( aPos.nPara );
749         awt::Rectangle aParaBounds( rPara.getBounds() );
750         awt::Rectangle aBounds( rPara.getCharacterBounds( aPos.nIndex ) );
751         aBounds.X += aParaBounds.X;
752         aBounds.Y += aParaBounds.Y;
753 
754         return aBounds;
755     }
756 
757     sal_Int32 SAL_CALL AccessibleStaticTextBase::getCharacterCount() throw (uno::RuntimeException)
758     {
759         ::vos::OGuard aGuard( Application::GetSolarMutex() );
760 
761         sal_Int32 i, nCount, nParas;
762         for( i=0, nCount=0, nParas=mpImpl->GetParagraphCount(); i<nParas; ++i )
763             nCount += mpImpl->GetParagraph(i).getCharacterCount();
764 	//IAccessibility2 Implementation 2009-----
765 		//count on the number of "\n" which equals number of paragraphs decrease 1.
766 		nCount = nCount + (nParas-1);
767 	//IAccessibility2 Implementation 2009-----
768         return nCount;
769     }
770 
771     sal_Int32 SAL_CALL AccessibleStaticTextBase::getIndexAtPoint( const awt::Point& rPoint ) throw (uno::RuntimeException)
772     {
773         ::vos::OGuard aGuard( Application::GetSolarMutex() );
774 
775         const sal_Int32 nParas( mpImpl->GetParagraphCount() );
776         sal_Int32 nIndex;
777         int i;
778         for( i=0; i<nParas; ++i )
779         {
780             // TODO: maybe exploit the fact that paragraphs are
781             // ordered vertically for early exit
782 
783             // #i70916# Text in spread sheet cells return the wrong extents
784             AccessibleEditableTextPara& rPara = mpImpl->GetParagraph( i );
785             awt::Rectangle aParaBounds( rPara.getBounds() );
786             awt::Point aPoint( rPoint );
787             aPoint.X -= aParaBounds.X;
788             aPoint.Y -= aParaBounds.Y;
789 
790             // #112814# Use correct index offset
791             if ( ( nIndex = rPara.getIndexAtPoint( aPoint ) ) != -1 )
792                 return mpImpl->Internal2Index( EPosition(sal::static_int_cast<sal_uInt16>(i),
793                                                          sal::static_int_cast<sal_uInt16>(nIndex)) );
794         }
795 
796         return -1;
797     }
798 
799     ::rtl::OUString SAL_CALL AccessibleStaticTextBase::getSelectedText() throw (uno::RuntimeException)
800     {
801         ::vos::OGuard aGuard( Application::GetSolarMutex() );
802 
803         sal_Int32 nStart( getSelectionStart() );
804         sal_Int32 nEnd( getSelectionEnd() );
805 
806         // #104481# Return the empty string for 'no selection'
807         if( nStart < 0 || nEnd < 0 )
808             return ::rtl::OUString();
809 
810         return getTextRange( nStart, nEnd );
811     }
812 
813     sal_Int32 SAL_CALL AccessibleStaticTextBase::getSelectionStart() throw (uno::RuntimeException)
814     {
815         ::vos::OGuard aGuard( Application::GetSolarMutex() );
816 
817         sal_Int32 i, nPos, nParas;
818         for( i=0, nPos=-1, nParas=mpImpl->GetParagraphCount(); i<nParas; ++i )
819         {
820             if( (nPos=mpImpl->GetParagraph(i).getSelectionStart()) != -1 )
821                 return nPos;
822         }
823 
824         return nPos;
825     }
826 
827     sal_Int32 SAL_CALL AccessibleStaticTextBase::getSelectionEnd() throw (uno::RuntimeException)
828     {
829         ::vos::OGuard aGuard( Application::GetSolarMutex() );
830 
831         sal_Int32 i, nPos, nParas;
832         for( i=0, nPos=-1, nParas=mpImpl->GetParagraphCount(); i<nParas; ++i )
833         {
834             if( (nPos=mpImpl->GetParagraph(i).getSelectionEnd()) != -1 )
835                 return nPos;
836         }
837 
838         return nPos;
839     }
840 
841     sal_Bool SAL_CALL AccessibleStaticTextBase::setSelection( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
842     {
843         ::vos::OGuard aGuard( Application::GetSolarMutex() );
844 
845         EPosition aStartIndex( mpImpl->Range2Internal(nStartIndex) );
846         EPosition aEndIndex( mpImpl->Range2Internal(nEndIndex) );
847 
848         return mpImpl->SetSelection( aStartIndex.nPara, aStartIndex.nIndex,
849                                      aEndIndex.nPara, aEndIndex.nIndex );
850     }
851 
852     ::rtl::OUString SAL_CALL AccessibleStaticTextBase::getText() throw (uno::RuntimeException)
853     {
854         ::vos::OGuard aGuard( Application::GetSolarMutex() );
855 
856         sal_Int32 i, nParas;
857         ::rtl::OUString aRes;
858         for( i=0, nParas=mpImpl->GetParagraphCount(); i<nParas; ++i )
859             aRes += mpImpl->GetParagraph(i).getText();
860 
861         return aRes;
862     }
863 
864     ::rtl::OUString SAL_CALL AccessibleStaticTextBase::getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
865     {
866         ::vos::OGuard aGuard( Application::GetSolarMutex() );
867 
868         if( nStartIndex > nEndIndex )
869             ::std::swap(nStartIndex, nEndIndex);
870 		//IAccessibility2 Implementation 2009-----
871 		//if startindex equals endindex we will get nothing. So return an empty string directly.
872 		if ( nStartIndex == nEndIndex )
873 		{
874 			::rtl::OUString sEmptyStr;
875 			return sEmptyStr;
876 		}
877 		sal_Bool bStart = mpImpl->RemoveLineBreakCount( nStartIndex );
878 		//if the start index is just at a "\n", we need to begin from the next char
879 		if ( bStart )
880 		{
881 			nStartIndex++;
882 		}
883 		//we need to find out whether the previous position of the current endindex is at "\n" or not
884 		//if yes we need to mark it and add "\n" at the end of the result
885 		sal_Int32 nTemp = nEndIndex - 1;
886 		sal_Bool bEnd = mpImpl->RemoveLineBreakCount( nTemp );
887 		sal_Bool bTemp = mpImpl->RemoveLineBreakCount( nEndIndex );
888 		//if the below condition is true it indicates an empty paragraph with just a "\n"
889 		//so we need to set one "\n" flag to avoid duplication.
890 		if ( bStart && bEnd && ( nStartIndex == nEndIndex) )
891 		{
892 			bEnd = sal_False;
893 		}
894 		//if the current endindex is at a "\n", we need to increase endindex by 1 to make sure
895 		//the char before "\n" is included. Because string returned by this function will not include
896 		//the char at the endindex.
897 		if ( bTemp )
898 		{
899 			nEndIndex++;
900 		}
901 		::rtl::OUString aRes;
902         EPosition aStartIndex( mpImpl->Range2Internal(nStartIndex) );
903         EPosition aEndIndex( mpImpl->Range2Internal(nEndIndex) );
904 
905         // #102170# Special case: start and end paragraph are identical
906         if( aStartIndex.nPara == aEndIndex.nPara )
907         {
908 			//we don't return the string directly now for that we have to do some further process for "\n"
909 			aRes = mpImpl->GetParagraph( aStartIndex.nPara ).getTextRange( aStartIndex.nIndex, aEndIndex.nIndex );
910             //return mpImpl->GetParagraph( aStartIndex.nPara ).getTextRange( aStartIndex.nIndex, aEndIndex.nIndex );
911 			//-----IAccessibility2 Implementation 2009
912         }
913         else
914         {
915             sal_Int32 i( aStartIndex.nPara );
916 	    		//IAccessibility2 Implementation 2009-----
917 	            aRes = mpImpl->GetParagraph(i).getTextRange( aStartIndex.nIndex,
918                                                                         mpImpl->GetParagraph(i).getCharacterCount()/*-1*/);
919 			//-----IAccessibility2 Implementation 2009
920             ++i;
921 
922             // paragraphs inbetween are fully included
923             for( ; i<aEndIndex.nPara; ++i )
924 	    //IAccessibility2 Implementation 2009-----
925 			{
926 				aRes += rtl::OUString(cNewLine);
927                 aRes += mpImpl->GetParagraph(i).getText();
928 			}
929 
930             if( i<=aEndIndex.nPara )
931 			{
932 				//if the below condition is mathed it means the endindex is at mid of the last paragraph
933 				//we need to add a "\n" before we add the last part of the string.
934 				if ( !bEnd && aEndIndex.nIndex )
935 				{
936 					aRes += rtl::OUString(cNewLine);
937 				}
938                 aRes += mpImpl->GetParagraph(i).getTextRange( 0, aEndIndex.nIndex );
939 			}
940             //return aRes;
941         }
942 		//According the the flag we marked before, we have to add "\n" at the beginning
943 		//or at the end of the result string.
944 		if ( bStart )
945 		{
946 			aRes = rtl::OUString(cNewLine) + aRes;
947 		}
948 		if ( bEnd )
949 		{
950 			aRes += rtl::OUString(cNewLine);
951 		}
952 		return aRes;
953 		//-----IAccessibility2 Implementation 2009
954     }
955 
956     ::com::sun::star::accessibility::TextSegment SAL_CALL AccessibleStaticTextBase::getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException)
957     {
958     	//IAccessibility2 Implementation 2009-----
959         ::vos::OGuard aGuard( Application::GetSolarMutex() );
960 
961 		sal_Bool bLineBreak = mpImpl->RemoveLineBreakCount( nIndex );
962 	//-----IAccessibility2 Implementation 2009
963         EPosition aPos( mpImpl->Range2Internal(nIndex) );
964 
965         ::com::sun::star::accessibility::TextSegment aResult;
966 
967         if( AccessibleTextType::PARAGRAPH == aTextType )
968         {
969             // #106393# Special casing one behind last paragraph is
970             // not necessary, since then, we return the content and
971             // boundary of that last paragraph. Range2Internal is
972             // tolerant against that, and returns the last paragraph
973             // in aPos.nPara.
974 
975             // retrieve full text of the paragraph
976             aResult.SegmentText = mpImpl->GetParagraph( aPos.nPara ).getText();
977 
978             // #112814# Adapt the start index with the paragraph offset
979             aResult.SegmentStart = mpImpl->Internal2Index( EPosition( aPos.nPara, 0 ) );
980             aResult.SegmentEnd = aResult.SegmentStart + aResult.SegmentText.getLength();
981         }
982 	//IAccessibility2 Implementation 2009-----
983         else if ( AccessibleTextType::ATTRIBUTE_RUN == aTextType )
984         {
985               SvxAccessibleTextAdapter& rTextForwarder = mpImpl->GetParagraph( aPos.nIndex ).GetTextForwarder();
986               sal_uInt16 nStartIndex, nEndIndex;
987               if ( rTextForwarder.GetAttributeRun( nStartIndex, nEndIndex, aPos.nPara, aPos.nIndex, sal_True ) )
988               {
989                      aResult.SegmentText = getTextRange( nStartIndex, nEndIndex );
990                      aResult.SegmentStart = nStartIndex;
991                      aResult.SegmentEnd = nEndIndex;
992               }
993         }
994 	//-----IAccessibility2 Implementation 2009
995         else
996         {
997             // No special handling required, forward to wrapped class
998             aResult = mpImpl->GetParagraph( aPos.nPara ).getTextAtIndex( aPos.nIndex, aTextType );
999 
1000             // #112814# Adapt the start index with the paragraph offset
1001             mpImpl->CorrectTextSegment( aResult, aPos.nPara );
1002 	    //IAccessibility2 Implementation 2009-----
1003 			if ( bLineBreak )
1004 			{
1005 				aResult.SegmentText = rtl::OUString(cNewLine);
1006 			}
1007 	    //-----IAccessibility2 Implementation 2009
1008         }
1009 
1010         return aResult;
1011     }
1012 
1013     ::com::sun::star::accessibility::TextSegment SAL_CALL AccessibleStaticTextBase::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException)
1014     {
1015         ::vos::OGuard aGuard( Application::GetSolarMutex() );
1016 		//IAccessibility2 Implementation 2009-----
1017 		sal_Int32 nOldIdx = nIndex;
1018 		sal_Bool bLineBreak =  mpImpl->RemoveLineBreakCount( nIndex );
1019 		//-----IAccessibility2 Implementation 2009
1020         EPosition aPos( mpImpl->Range2Internal(nIndex) );
1021 
1022         ::com::sun::star::accessibility::TextSegment aResult;
1023 
1024         if( AccessibleTextType::PARAGRAPH == aTextType )
1025         {
1026             if( aPos.nIndex == mpImpl->GetParagraph( aPos.nPara ).getCharacterCount() )
1027             {
1028                 // #103589# Special casing one behind the last paragraph
1029                 aResult.SegmentText = mpImpl->GetParagraph( aPos.nPara ).getText();
1030 
1031                 // #112814# Adapt the start index with the paragraph offset
1032                 aResult.SegmentStart = mpImpl->Internal2Index( EPosition( aPos.nPara, 0 ) );
1033             }
1034             else if( aPos.nPara > 0 )
1035             {
1036                 aResult.SegmentText = mpImpl->GetParagraph( aPos.nPara - 1 ).getText();
1037 
1038                 // #112814# Adapt the start index with the paragraph offset
1039                 aResult.SegmentStart = mpImpl->Internal2Index( EPosition( aPos.nPara - 1, 0 ) );
1040             }
1041 
1042             aResult.SegmentEnd = aResult.SegmentStart + aResult.SegmentText.getLength();
1043         }
1044         else
1045         {
1046             // No special handling required, forward to wrapped class
1047             aResult = mpImpl->GetParagraph( aPos.nPara ).getTextBeforeIndex( aPos.nIndex, aTextType );
1048 
1049             // #112814# Adapt the start index with the paragraph offset
1050             mpImpl->CorrectTextSegment( aResult, aPos.nPara );
1051 			//IAccessibility2 Implementation 2009-----
1052 			if ( bLineBreak && (nOldIdx-1) >= 0)
1053 			{
1054 				aResult = getTextAtIndex( nOldIdx-1, aTextType );
1055 			}
1056 			//-----IAccessibility2 Implementation 2009
1057         }
1058 
1059         return aResult;
1060     }
1061 
1062     ::com::sun::star::accessibility::TextSegment SAL_CALL AccessibleStaticTextBase::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException)
1063     {
1064         ::vos::OGuard aGuard( Application::GetSolarMutex() );
1065 	//IAccessibility2 Implementation 2009-----
1066 		sal_Int32 nTemp = nIndex+1;
1067 		sal_Bool bLineBreak = mpImpl->RemoveLineBreakCount( nTemp );
1068 		mpImpl->RemoveLineBreakCount( nIndex );
1069 	//-----IAccessibility2 Implementation 2009
1070         EPosition aPos( mpImpl->Range2Internal(nIndex) );
1071 
1072         ::com::sun::star::accessibility::TextSegment aResult;
1073 
1074         if( AccessibleTextType::PARAGRAPH == aTextType )
1075         {
1076             // Special casing one behind the last paragraph is not
1077             // necessary, this case is invalid here for
1078             // getTextBehindIndex
1079             if( aPos.nPara + 1 < mpImpl->GetParagraphCount() )
1080             {
1081                 aResult.SegmentText = mpImpl->GetParagraph( aPos.nPara + 1 ).getText();
1082 
1083                 // #112814# Adapt the start index with the paragraph offset
1084                 aResult.SegmentStart = mpImpl->Internal2Index( EPosition( aPos.nPara + 1, 0 ) );
1085                 aResult.SegmentEnd = aResult.SegmentStart + aResult.SegmentText.getLength();
1086             }
1087         }
1088         else
1089         {
1090             // No special handling required, forward to wrapped class
1091             aResult = mpImpl->GetParagraph( aPos.nPara ).getTextBehindIndex( aPos.nIndex, aTextType );
1092 
1093             // #112814# Adapt the start index with the paragraph offset
1094             mpImpl->CorrectTextSegment( aResult, aPos.nPara );
1095 			//IAccessibility2 Implementation 2009-----
1096 			if ( bLineBreak )
1097 			{
1098 				aResult.SegmentText = rtl::OUString(cNewLine) + aResult.SegmentText;
1099 			}
1100 			//-----IAccessibility2 Implementation 2009
1101        }
1102 
1103         return aResult;
1104     }
1105 
1106     sal_Bool SAL_CALL AccessibleStaticTextBase::copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
1107     {
1108         ::vos::OGuard aGuard( Application::GetSolarMutex() );
1109 
1110         if( nStartIndex > nEndIndex )
1111             ::std::swap(nStartIndex, nEndIndex);
1112 
1113         EPosition aStartIndex( mpImpl->Range2Internal(nStartIndex) );
1114         EPosition aEndIndex( mpImpl->Range2Internal(nEndIndex) );
1115 
1116         return mpImpl->CopyText( aStartIndex.nPara, aStartIndex.nIndex,
1117                                  aEndIndex.nPara, aEndIndex.nIndex );
1118     }
1119 
1120     // XAccessibleTextAttributes
1121     uno::Sequence< beans::PropertyValue > AccessibleStaticTextBase::getDefaultAttributes( const uno::Sequence< ::rtl::OUString >& RequestedAttributes ) throw (uno::RuntimeException)
1122     {
1123         // get the intersection of the default attributes of all paragraphs
1124 
1125         ::vos::OGuard aGuard( Application::GetSolarMutex() );
1126 
1127         PropertyValueVector aDefAttrVec( mpImpl->GetParagraph( 0 ).getDefaultAttributes( RequestedAttributes ) );
1128 
1129         const sal_Int32 nParaCount = mpImpl->GetParagraphCount();
1130         for ( sal_Int32 nPara = 1; nPara < nParaCount; ++nPara )
1131         {
1132             uno::Sequence< beans::PropertyValue > aSeq = mpImpl->GetParagraph( nPara ).getDefaultAttributes( RequestedAttributes );
1133             PropertyValueVector aIntersectionVec;
1134 
1135             PropertyValueVector::const_iterator aEnd = aDefAttrVec.end();
1136             for ( PropertyValueVector::const_iterator aItr = aDefAttrVec.begin(); aItr != aEnd; ++aItr )
1137             {
1138                 const beans::PropertyValue* pItr = aSeq.getConstArray();
1139                 const beans::PropertyValue* pEnd  = pItr + aSeq.getLength();
1140                 const beans::PropertyValue* pFind = ::std::find_if( pItr, pEnd, ::std::bind2nd( PropertyValueEqualFunctor(), boost::cref( *aItr ) ) );
1141                 if ( pFind != pEnd )
1142                 {
1143                     aIntersectionVec.push_back( *pFind );
1144                 }
1145             }
1146 
1147             aDefAttrVec.swap( aIntersectionVec );
1148 
1149             if ( aDefAttrVec.empty() )
1150             {
1151                 break;
1152             }
1153         }
1154 
1155         return aDefAttrVec.getAsConstList();
1156     }
1157 
1158     uno::Sequence< beans::PropertyValue > SAL_CALL AccessibleStaticTextBase::getRunAttributes( sal_Int32 nIndex, const uno::Sequence< ::rtl::OUString >& RequestedAttributes ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
1159     {
1160         // get those default attributes of the paragraph, which are not part
1161         // of the intersection of all paragraphs and add them to the run attributes
1162 
1163         ::vos::OGuard aGuard( Application::GetSolarMutex() );
1164 
1165         EPosition aPos( mpImpl->Index2Internal( nIndex ) );
1166         AccessibleEditableTextPara& rPara = mpImpl->GetParagraph( aPos.nPara );
1167         uno::Sequence< beans::PropertyValue > aDefAttrSeq = rPara.getDefaultAttributes( RequestedAttributes );
1168         uno::Sequence< beans::PropertyValue > aRunAttrSeq = rPara.getRunAttributes( aPos.nIndex, RequestedAttributes );
1169         uno::Sequence< beans::PropertyValue > aIntersectionSeq = getDefaultAttributes( RequestedAttributes );
1170         PropertyValueVector aDiffVec;
1171 
1172         const beans::PropertyValue* pDefAttr = aDefAttrSeq.getConstArray();
1173         const sal_Int32 nLength = aDefAttrSeq.getLength();
1174         for ( sal_Int32 i = 0; i < nLength; ++i )
1175         {
1176             const beans::PropertyValue* pItr = aIntersectionSeq.getConstArray();
1177             const beans::PropertyValue* pEnd  = pItr + aIntersectionSeq.getLength();
1178             const beans::PropertyValue* pFind = ::std::find_if( pItr, pEnd, ::std::bind2nd( PropertyValueEqualFunctor(), boost::cref( pDefAttr[i] ) ) );
1179             if ( pFind == pEnd && pDefAttr[i].Handle != 0)
1180             {
1181                 aDiffVec.push_back( pDefAttr[i] );
1182             }
1183         }
1184 
1185         return ::comphelper::concatSequences( aRunAttrSeq, aDiffVec.getAsConstList() );
1186     }
1187 
1188     Rectangle AccessibleStaticTextBase::GetParagraphBoundingBox() const
1189     {
1190         return mpImpl->GetParagraphBoundingBox();
1191     }
1192 
1193     sal_Int32 AccessibleStaticTextBase::GetParagraphIndex() const
1194     {
1195         return mpImpl->GetParagraphIndex();
1196     }
1197 
1198     sal_Int32 AccessibleStaticTextBase::GetParagraphCount() const
1199     {
1200         return mpImpl->GetParagraphCount();
1201     }
1202 
1203     sal_Int32 AccessibleStaticTextBase::GetLineCount( sal_Int32 nParagraph ) const
1204     {
1205         return mpImpl->GetLineCount( nParagraph );
1206     }
1207 
1208 }  // end of namespace accessibility
1209 
1210 //------------------------------------------------------------------------
1211