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