xref: /AOO41X/main/svx/source/accessibility/AccessibleTextHelper.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
29*cdf0e10cSrcweir #include "precompiled_svx.hxx"
30*cdf0e10cSrcweir 
31*cdf0e10cSrcweir //------------------------------------------------------------------------
32*cdf0e10cSrcweir //
33*cdf0e10cSrcweir // Global header
34*cdf0e10cSrcweir //
35*cdf0e10cSrcweir //------------------------------------------------------------------------
36*cdf0e10cSrcweir 
37*cdf0e10cSrcweir #include <limits.h>
38*cdf0e10cSrcweir #include <memory>
39*cdf0e10cSrcweir #include <algorithm>
40*cdf0e10cSrcweir #include <deque>
41*cdf0e10cSrcweir #include <vos/mutex.hxx>
42*cdf0e10cSrcweir #include <com/sun/star/uno/Any.hxx>
43*cdf0e10cSrcweir #include <com/sun/star/uno/Reference.hxx>
44*cdf0e10cSrcweir #include <cppuhelper/weakref.hxx>
45*cdf0e10cSrcweir #include <com/sun/star/awt/Point.hpp>
46*cdf0e10cSrcweir #include <com/sun/star/awt/Rectangle.hpp>
47*cdf0e10cSrcweir #include <com/sun/star/lang/DisposedException.hpp>
48*cdf0e10cSrcweir #include <com/sun/star/accessibility/AccessibleEventId.hpp>
49*cdf0e10cSrcweir #include <com/sun/star/accessibility/XAccessible.hpp>
50*cdf0e10cSrcweir #include <com/sun/star/accessibility/XAccessibleContext.hpp>
51*cdf0e10cSrcweir #include <com/sun/star/accessibility/XAccessibleComponent.hpp>
52*cdf0e10cSrcweir #include <com/sun/star/accessibility/AccessibleStateType.hpp>
53*cdf0e10cSrcweir #include <comphelper/accessibleeventnotifier.hxx>
54*cdf0e10cSrcweir #include <unotools/accessiblestatesethelper.hxx>
55*cdf0e10cSrcweir #include <vcl/unohelp.hxx>
56*cdf0e10cSrcweir #include <vcl/svapp.hxx>
57*cdf0e10cSrcweir 
58*cdf0e10cSrcweir //------------------------------------------------------------------------
59*cdf0e10cSrcweir //
60*cdf0e10cSrcweir // Project-local header
61*cdf0e10cSrcweir //
62*cdf0e10cSrcweir //------------------------------------------------------------------------
63*cdf0e10cSrcweir #include "AccessibleTextEventQueue.hxx"
64*cdf0e10cSrcweir #include <svx/AccessibleTextHelper.hxx>
65*cdf0e10cSrcweir #include <svx/unoshape.hxx>
66*cdf0e10cSrcweir #include "editeng/unolingu.hxx"
67*cdf0e10cSrcweir #include <editeng/unotext.hxx>
68*cdf0e10cSrcweir 
69*cdf0e10cSrcweir #include "editeng/unoedhlp.hxx"
70*cdf0e10cSrcweir #include "editeng/unopracc.hxx"
71*cdf0e10cSrcweir #include "editeng/AccessibleParaManager.hxx"
72*cdf0e10cSrcweir #include "editeng/AccessibleEditableTextPara.hxx"
73*cdf0e10cSrcweir #include <svx/svdmodel.hxx>
74*cdf0e10cSrcweir #include <svx/svdpntv.hxx>
75*cdf0e10cSrcweir #include <editeng/editdata.hxx>
76*cdf0e10cSrcweir #include <editeng/editeng.hxx>
77*cdf0e10cSrcweir #include <editeng/editview.hxx>
78*cdf0e10cSrcweir 
79*cdf0e10cSrcweir using namespace ::com::sun::star;
80*cdf0e10cSrcweir using namespace ::com::sun::star::accessibility;
81*cdf0e10cSrcweir 
82*cdf0e10cSrcweir namespace accessibility
83*cdf0e10cSrcweir {
84*cdf0e10cSrcweir 
85*cdf0e10cSrcweir //------------------------------------------------------------------------
86*cdf0e10cSrcweir //
87*cdf0e10cSrcweir // AccessibleTextHelper_Impl declaration
88*cdf0e10cSrcweir //
89*cdf0e10cSrcweir //------------------------------------------------------------------------
90*cdf0e10cSrcweir 
91*cdf0e10cSrcweir     DBG_NAME( AccessibleTextHelper_Impl )
92*cdf0e10cSrcweir 
93*cdf0e10cSrcweir     template < typename first_type, typename second_type >
94*cdf0e10cSrcweir 	    ::std::pair< first_type, second_type > makeSortedPair( first_type 	first,
95*cdf0e10cSrcweir                                                                                  second_type 	second	)
96*cdf0e10cSrcweir     {
97*cdf0e10cSrcweir         if( first > second )
98*cdf0e10cSrcweir             return ::std::make_pair( second, first );
99*cdf0e10cSrcweir         else
100*cdf0e10cSrcweir             return ::std::make_pair( first, second );
101*cdf0e10cSrcweir     }
102*cdf0e10cSrcweir 
103*cdf0e10cSrcweir     class AccessibleTextHelper_Impl : public SfxListener
104*cdf0e10cSrcweir     {
105*cdf0e10cSrcweir 
106*cdf0e10cSrcweir     public:
107*cdf0e10cSrcweir         typedef ::std::vector< sal_Int16 > VectorOfStates;
108*cdf0e10cSrcweir 
109*cdf0e10cSrcweir         // receive pointer to our frontend class and view window
110*cdf0e10cSrcweir         AccessibleTextHelper_Impl();
111*cdf0e10cSrcweir         ~AccessibleTextHelper_Impl();
112*cdf0e10cSrcweir 
113*cdf0e10cSrcweir         // XAccessibleContext child handling methods
114*cdf0e10cSrcweir         sal_Int32 SAL_CALL getAccessibleChildCount() SAL_THROW((uno::RuntimeException));
115*cdf0e10cSrcweir         uno::Reference< XAccessible > SAL_CALL getAccessibleChild( sal_Int32 i ) SAL_THROW((lang::IndexOutOfBoundsException, uno::RuntimeException));
116*cdf0e10cSrcweir 
117*cdf0e10cSrcweir         // XAccessibleEventBroadcaster child related methods
118*cdf0e10cSrcweir         void SAL_CALL addEventListener( const uno::Reference< XAccessibleEventListener >& xListener ) SAL_THROW((uno::RuntimeException));
119*cdf0e10cSrcweir         void SAL_CALL removeEventListener( const uno::Reference< XAccessibleEventListener >& xListener ) SAL_THROW((uno::RuntimeException));
120*cdf0e10cSrcweir 
121*cdf0e10cSrcweir         // XAccessibleComponent child related methods
122*cdf0e10cSrcweir         uno::Reference< XAccessible > SAL_CALL getAccessibleAtPoint( const awt::Point& aPoint ) SAL_THROW((uno::RuntimeException));
123*cdf0e10cSrcweir 
124*cdf0e10cSrcweir         SvxEditSourceAdapter& GetEditSource() const SAL_THROW((uno::RuntimeException));
125*cdf0e10cSrcweir         void SetEditSource( ::std::auto_ptr< SvxEditSource > pEditSource ) SAL_THROW((uno::RuntimeException));
126*cdf0e10cSrcweir 
127*cdf0e10cSrcweir         void SetEventSource( const uno::Reference< XAccessible >& rInterface )
128*cdf0e10cSrcweir         {
129*cdf0e10cSrcweir             DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
130*cdf0e10cSrcweir             mxFrontEnd = rInterface;
131*cdf0e10cSrcweir         }
132*cdf0e10cSrcweir         uno::Reference< XAccessible > GetEventSource() const
133*cdf0e10cSrcweir         {
134*cdf0e10cSrcweir             DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
135*cdf0e10cSrcweir             return mxFrontEnd;
136*cdf0e10cSrcweir         }
137*cdf0e10cSrcweir 
138*cdf0e10cSrcweir         void SetOffset( const Point& );
139*cdf0e10cSrcweir         Point GetOffset() const
140*cdf0e10cSrcweir         {
141*cdf0e10cSrcweir             DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
142*cdf0e10cSrcweir             ::osl::MutexGuard aGuard( maMutex ); Point aPoint( maOffset );
143*cdf0e10cSrcweir             return aPoint;
144*cdf0e10cSrcweir         }
145*cdf0e10cSrcweir 
146*cdf0e10cSrcweir         void SetStartIndex( sal_Int32 nOffset );
147*cdf0e10cSrcweir         sal_Int32 GetStartIndex() const
148*cdf0e10cSrcweir         {
149*cdf0e10cSrcweir             DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
150*cdf0e10cSrcweir 			// Strictly correct only with locked solar mutex, // but
151*cdf0e10cSrcweir 			// here we rely on the fact that sal_Int32 access is
152*cdf0e10cSrcweir 			// atomic
153*cdf0e10cSrcweir             return mnStartIndex;
154*cdf0e10cSrcweir         }
155*cdf0e10cSrcweir 
156*cdf0e10cSrcweir         void SetAdditionalChildStates( const VectorOfStates& rChildStates );
157*cdf0e10cSrcweir         const VectorOfStates& GetAdditionalChildStates() const;
158*cdf0e10cSrcweir 
159*cdf0e10cSrcweir         sal_Bool IsSelected() const;
160*cdf0e10cSrcweir 
161*cdf0e10cSrcweir         void Dispose();
162*cdf0e10cSrcweir 
163*cdf0e10cSrcweir         // do NOT hold object mutex when calling this! Danger of deadlock
164*cdf0e10cSrcweir         void FireEvent( const sal_Int16 nEventId, const uno::Any& rNewValue = uno::Any(), const uno::Any& rOldValue = uno::Any() ) const;
165*cdf0e10cSrcweir         void FireEvent( const AccessibleEventObject& rEvent ) const;
166*cdf0e10cSrcweir 
167*cdf0e10cSrcweir         void SetFocus( sal_Bool bHaveFocus ) SAL_THROW((::com::sun::star::uno::RuntimeException));
168*cdf0e10cSrcweir         sal_Bool HaveFocus() SAL_THROW((::com::sun::star::uno::RuntimeException));
169*cdf0e10cSrcweir         void SetChildFocus( sal_Int32 nChild, sal_Bool bHaveFocus ) SAL_THROW((::com::sun::star::uno::RuntimeException));
170*cdf0e10cSrcweir         void SetShapeFocus( sal_Bool bHaveFocus ) SAL_THROW((::com::sun::star::uno::RuntimeException));
171*cdf0e10cSrcweir         void ChangeChildFocus( sal_Int32 nNewChild ) SAL_THROW((::com::sun::star::uno::RuntimeException));
172*cdf0e10cSrcweir 
173*cdf0e10cSrcweir #ifdef DBG_UTIL
174*cdf0e10cSrcweir         void CheckInvariants() const;
175*cdf0e10cSrcweir #endif
176*cdf0e10cSrcweir 
177*cdf0e10cSrcweir         // checks all children for visibility, throws away invisible ones
178*cdf0e10cSrcweir         void UpdateVisibleChildren( bool bBroadcastEvents=true );
179*cdf0e10cSrcweir 
180*cdf0e10cSrcweir         // check all children for changes in posit�on and size
181*cdf0e10cSrcweir         void UpdateBoundRect();
182*cdf0e10cSrcweir 
183*cdf0e10cSrcweir         // calls SetSelection on the forwarder and updates maLastSelection
184*cdf0e10cSrcweir         // cache.
185*cdf0e10cSrcweir         void UpdateSelection();
186*cdf0e10cSrcweir 
187*cdf0e10cSrcweir     private:
188*cdf0e10cSrcweir 
189*cdf0e10cSrcweir         // Process event queue
190*cdf0e10cSrcweir         void ProcessQueue();
191*cdf0e10cSrcweir 
192*cdf0e10cSrcweir         // syntactic sugar for FireEvent
193*cdf0e10cSrcweir         void GotPropertyEvent( const uno::Any& rNewValue, const sal_Int16 nEventId ) const { FireEvent( nEventId, rNewValue ); }
194*cdf0e10cSrcweir         void LostPropertyEvent( const uno::Any& rOldValue, const sal_Int16 nEventId ) const { FireEvent( nEventId, uno::Any(), rOldValue ); }
195*cdf0e10cSrcweir 
196*cdf0e10cSrcweir         // shutdown usage of current edit source on myself and the children.
197*cdf0e10cSrcweir         void ShutdownEditSource() SAL_THROW((uno::RuntimeException));
198*cdf0e10cSrcweir 
199*cdf0e10cSrcweir         void ParagraphsMoved( sal_Int32 nFirst, sal_Int32 nMiddle, sal_Int32 nLast );
200*cdf0e10cSrcweir 
201*cdf0e10cSrcweir         virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint );
202*cdf0e10cSrcweir 
203*cdf0e10cSrcweir         int getNotifierClientId() const { return mnNotifierClientId; }
204*cdf0e10cSrcweir 
205*cdf0e10cSrcweir         // lock solar mutex before
206*cdf0e10cSrcweir         SvxTextForwarder& GetTextForwarder() const SAL_THROW((uno::RuntimeException));
207*cdf0e10cSrcweir         // lock solar mutex before
208*cdf0e10cSrcweir         SvxViewForwarder& GetViewForwarder() const SAL_THROW((uno::RuntimeException));
209*cdf0e10cSrcweir         // lock solar mutex before
210*cdf0e10cSrcweir         SvxEditViewForwarder& GetEditViewForwarder( sal_Bool bCreate = sal_False ) const SAL_THROW((uno::RuntimeException));
211*cdf0e10cSrcweir 
212*cdf0e10cSrcweir         // are we in edit mode?
213*cdf0e10cSrcweir         sal_Bool IsActive() const SAL_THROW((uno::RuntimeException));
214*cdf0e10cSrcweir 
215*cdf0e10cSrcweir         // our frontend class (the one implementing the actual
216*cdf0e10cSrcweir         // interface). That's not necessarily the one containing the impl
217*cdf0e10cSrcweir         // pointer!
218*cdf0e10cSrcweir         uno::Reference< XAccessible > mxFrontEnd;
219*cdf0e10cSrcweir 
220*cdf0e10cSrcweir         // a wrapper for the text forwarders (guarded by solar mutex)
221*cdf0e10cSrcweir         mutable SvxEditSourceAdapter maEditSource;
222*cdf0e10cSrcweir 
223*cdf0e10cSrcweir         // store last selection (to correctly report selection changes, guarded by solar mutex)
224*cdf0e10cSrcweir         ESelection maLastSelection;
225*cdf0e10cSrcweir 
226*cdf0e10cSrcweir         // cache range of visible children (guarded by solar mutex)
227*cdf0e10cSrcweir         sal_Int32 mnFirstVisibleChild;
228*cdf0e10cSrcweir         sal_Int32 mnLastVisibleChild;
229*cdf0e10cSrcweir 
230*cdf0e10cSrcweir         // offset to add to all our children (unguarded, relying on
231*cdf0e10cSrcweir         // the fact that sal_Int32 access is atomic)
232*cdf0e10cSrcweir         sal_Int32 mnStartIndex;
233*cdf0e10cSrcweir 
234*cdf0e10cSrcweir         // the object handling our children (guarded by solar mutex)
235*cdf0e10cSrcweir         ::accessibility::AccessibleParaManager maParaManager;
236*cdf0e10cSrcweir 
237*cdf0e10cSrcweir         // number of not-yet-closed event frames (BEGIN/END sequences) (guarded by solar mutex)
238*cdf0e10cSrcweir         sal_Int32 maEventOpenFrames;
239*cdf0e10cSrcweir 
240*cdf0e10cSrcweir         // Queued events from Notify() (guarded by solar mutex)
241*cdf0e10cSrcweir         AccessibleTextEventQueue maEventQueue;
242*cdf0e10cSrcweir 
243*cdf0e10cSrcweir         // spin lock to prevent notify in notify (guarded by solar mutex)
244*cdf0e10cSrcweir         sal_Bool mbInNotify;
245*cdf0e10cSrcweir 
246*cdf0e10cSrcweir         // whether the object or it's children has the focus set (guarded by solar mutex)
247*cdf0e10cSrcweir         sal_Bool mbGroupHasFocus;
248*cdf0e10cSrcweir 
249*cdf0e10cSrcweir         // whether we (this object) has the focus set (guarded by solar mutex)
250*cdf0e10cSrcweir         sal_Bool mbThisHasFocus;
251*cdf0e10cSrcweir 
252*cdf0e10cSrcweir         mutable ::osl::Mutex maMutex;
253*cdf0e10cSrcweir 
254*cdf0e10cSrcweir         /// our current offset to the containing shape/cell (guarded by maMutex)
255*cdf0e10cSrcweir         Point maOffset;
256*cdf0e10cSrcweir 
257*cdf0e10cSrcweir         /// client Id from AccessibleEventNotifier
258*cdf0e10cSrcweir         int mnNotifierClientId;
259*cdf0e10cSrcweir     };
260*cdf0e10cSrcweir 
261*cdf0e10cSrcweir 	//------------------------------------------------------------------------
262*cdf0e10cSrcweir 	//
263*cdf0e10cSrcweir 	// AccessibleTextHelper_Impl implementation
264*cdf0e10cSrcweir 	//
265*cdf0e10cSrcweir 	//------------------------------------------------------------------------
266*cdf0e10cSrcweir 
267*cdf0e10cSrcweir     AccessibleTextHelper_Impl::AccessibleTextHelper_Impl() :
268*cdf0e10cSrcweir         mxFrontEnd( NULL ),
269*cdf0e10cSrcweir         maLastSelection( EE_PARA_NOT_FOUND,EE_PARA_NOT_FOUND,EE_PARA_NOT_FOUND,EE_PARA_NOT_FOUND ),
270*cdf0e10cSrcweir         mnFirstVisibleChild( -1 ),
271*cdf0e10cSrcweir         mnLastVisibleChild( -2 ),
272*cdf0e10cSrcweir         mnStartIndex( 0 ),
273*cdf0e10cSrcweir         maEventOpenFrames( 0 ),
274*cdf0e10cSrcweir         mbInNotify( sal_False ),
275*cdf0e10cSrcweir         mbGroupHasFocus( sal_False ),
276*cdf0e10cSrcweir         mbThisHasFocus( sal_False ),
277*cdf0e10cSrcweir         maOffset(0,0),
278*cdf0e10cSrcweir         // well, that's strictly exception safe, though not really
279*cdf0e10cSrcweir         // robust. We rely on the fact that this member is constructed
280*cdf0e10cSrcweir         // last, and that the constructor body is empty, thus no
281*cdf0e10cSrcweir         // chance for exceptions once the Id is fetched. Nevertheless,
282*cdf0e10cSrcweir         // normally should employ RAII here...
283*cdf0e10cSrcweir         mnNotifierClientId(::comphelper::AccessibleEventNotifier::registerClient())
284*cdf0e10cSrcweir     {
285*cdf0e10cSrcweir         DBG_CTOR( AccessibleTextHelper_Impl, NULL );
286*cdf0e10cSrcweir 
287*cdf0e10cSrcweir #ifdef DBG_UTIL
288*cdf0e10cSrcweir         OSL_TRACE( "AccessibleTextHelper_Impl received ID: %d", mnNotifierClientId );
289*cdf0e10cSrcweir #endif
290*cdf0e10cSrcweir     }
291*cdf0e10cSrcweir 
292*cdf0e10cSrcweir     AccessibleTextHelper_Impl::~AccessibleTextHelper_Impl()
293*cdf0e10cSrcweir     {
294*cdf0e10cSrcweir         DBG_DTOR( AccessibleTextHelper_Impl, NULL );
295*cdf0e10cSrcweir 
296*cdf0e10cSrcweir         ::vos::OGuard aGuard( Application::GetSolarMutex() );
297*cdf0e10cSrcweir 
298*cdf0e10cSrcweir         try
299*cdf0e10cSrcweir         {
300*cdf0e10cSrcweir             // call Dispose here, too, since we've some resources not
301*cdf0e10cSrcweir             // automatically freed otherwise
302*cdf0e10cSrcweir             Dispose();
303*cdf0e10cSrcweir         }
304*cdf0e10cSrcweir         catch( const uno::Exception& ) {}
305*cdf0e10cSrcweir     }
306*cdf0e10cSrcweir 
307*cdf0e10cSrcweir     SvxTextForwarder& AccessibleTextHelper_Impl::GetTextForwarder() const SAL_THROW((uno::RuntimeException))
308*cdf0e10cSrcweir     {
309*cdf0e10cSrcweir         DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
310*cdf0e10cSrcweir 
311*cdf0e10cSrcweir         if( !maEditSource.IsValid() )
312*cdf0e10cSrcweir             throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Unknown edit source")), mxFrontEnd);
313*cdf0e10cSrcweir 
314*cdf0e10cSrcweir         SvxTextForwarder* pTextForwarder = maEditSource.GetTextForwarder();
315*cdf0e10cSrcweir 
316*cdf0e10cSrcweir         if( !pTextForwarder )
317*cdf0e10cSrcweir             throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Unable to fetch text forwarder, model might be dead")), mxFrontEnd);
318*cdf0e10cSrcweir 
319*cdf0e10cSrcweir         if( pTextForwarder->IsValid() )
320*cdf0e10cSrcweir             return *pTextForwarder;
321*cdf0e10cSrcweir         else
322*cdf0e10cSrcweir             throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Text forwarder is invalid, model might be dead")), mxFrontEnd);
323*cdf0e10cSrcweir     }
324*cdf0e10cSrcweir 
325*cdf0e10cSrcweir     SvxViewForwarder& AccessibleTextHelper_Impl::GetViewForwarder() const SAL_THROW((uno::RuntimeException))
326*cdf0e10cSrcweir     {
327*cdf0e10cSrcweir         DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
328*cdf0e10cSrcweir 
329*cdf0e10cSrcweir         if( !maEditSource.IsValid() )
330*cdf0e10cSrcweir             throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Unknown edit source")), mxFrontEnd);
331*cdf0e10cSrcweir 
332*cdf0e10cSrcweir         SvxViewForwarder* pViewForwarder = maEditSource.GetViewForwarder();
333*cdf0e10cSrcweir 
334*cdf0e10cSrcweir         if( !pViewForwarder )
335*cdf0e10cSrcweir             throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Unable to fetch view forwarder, model might be dead")), mxFrontEnd);
336*cdf0e10cSrcweir 
337*cdf0e10cSrcweir         if( pViewForwarder->IsValid() )
338*cdf0e10cSrcweir             return *pViewForwarder;
339*cdf0e10cSrcweir         else
340*cdf0e10cSrcweir             throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("View forwarder is invalid, model might be dead")), mxFrontEnd);
341*cdf0e10cSrcweir     }
342*cdf0e10cSrcweir 
343*cdf0e10cSrcweir     SvxEditViewForwarder& AccessibleTextHelper_Impl::GetEditViewForwarder( sal_Bool bCreate ) const SAL_THROW((uno::RuntimeException))
344*cdf0e10cSrcweir     {
345*cdf0e10cSrcweir         DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
346*cdf0e10cSrcweir 
347*cdf0e10cSrcweir         if( !maEditSource.IsValid() )
348*cdf0e10cSrcweir             throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Unknown edit source")), mxFrontEnd);
349*cdf0e10cSrcweir 
350*cdf0e10cSrcweir         SvxEditViewForwarder* pViewForwarder = maEditSource.GetEditViewForwarder( bCreate );
351*cdf0e10cSrcweir 
352*cdf0e10cSrcweir         if( !pViewForwarder )
353*cdf0e10cSrcweir         {
354*cdf0e10cSrcweir             if( bCreate )
355*cdf0e10cSrcweir                 throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Unable to fetch edit view forwarder, model might be dead")), mxFrontEnd);
356*cdf0e10cSrcweir             else
357*cdf0e10cSrcweir                 throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("No edit view forwarder, object not in edit mode")), mxFrontEnd);
358*cdf0e10cSrcweir         }
359*cdf0e10cSrcweir 
360*cdf0e10cSrcweir         if( pViewForwarder->IsValid() )
361*cdf0e10cSrcweir             return *pViewForwarder;
362*cdf0e10cSrcweir         else
363*cdf0e10cSrcweir         {
364*cdf0e10cSrcweir             if( bCreate )
365*cdf0e10cSrcweir                 throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("View forwarder is invalid, model might be dead")), mxFrontEnd);
366*cdf0e10cSrcweir             else
367*cdf0e10cSrcweir                 throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("View forwarder is invalid, object not in edit mode")), mxFrontEnd);
368*cdf0e10cSrcweir         }
369*cdf0e10cSrcweir     }
370*cdf0e10cSrcweir 
371*cdf0e10cSrcweir     SvxEditSourceAdapter& AccessibleTextHelper_Impl::GetEditSource() const SAL_THROW((uno::RuntimeException))
372*cdf0e10cSrcweir     {
373*cdf0e10cSrcweir         DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
374*cdf0e10cSrcweir 
375*cdf0e10cSrcweir         if( maEditSource.IsValid() )
376*cdf0e10cSrcweir             return maEditSource;
377*cdf0e10cSrcweir         else
378*cdf0e10cSrcweir             throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AccessibleTextHelper_Impl::GetEditSource: no edit source")), mxFrontEnd );
379*cdf0e10cSrcweir     }
380*cdf0e10cSrcweir 
381*cdf0e10cSrcweir     sal_Bool AccessibleTextHelper_Impl::IsSelected() const
382*cdf0e10cSrcweir     {
383*cdf0e10cSrcweir         DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
384*cdf0e10cSrcweir 
385*cdf0e10cSrcweir         sal_Bool bRet = sal_False;
386*cdf0e10cSrcweir 
387*cdf0e10cSrcweir         try
388*cdf0e10cSrcweir         {
389*cdf0e10cSrcweir             ESelection aSelection;
390*cdf0e10cSrcweir             bRet = GetEditViewForwarder().GetSelection( aSelection );
391*cdf0e10cSrcweir         }
392*cdf0e10cSrcweir         catch( const uno::Exception& ) {}
393*cdf0e10cSrcweir 
394*cdf0e10cSrcweir         return bRet;
395*cdf0e10cSrcweir     }
396*cdf0e10cSrcweir 
397*cdf0e10cSrcweir 	// functor for sending child events (no stand-alone function, they are maybe not inlined)
398*cdf0e10cSrcweir     class AccessibleTextHelper_OffsetChildIndex : public ::std::unary_function< ::accessibility::AccessibleEditableTextPara&, void >
399*cdf0e10cSrcweir     {
400*cdf0e10cSrcweir     public:
401*cdf0e10cSrcweir         AccessibleTextHelper_OffsetChildIndex( sal_Int32 nDifference ) : mnDifference(nDifference) {}
402*cdf0e10cSrcweir         void operator()( ::accessibility::AccessibleEditableTextPara& rPara )
403*cdf0e10cSrcweir         {
404*cdf0e10cSrcweir             rPara.SetIndexInParent( rPara.GetIndexInParent() + mnDifference );
405*cdf0e10cSrcweir         }
406*cdf0e10cSrcweir 
407*cdf0e10cSrcweir     private:
408*cdf0e10cSrcweir         const sal_Int32 mnDifference;
409*cdf0e10cSrcweir     };
410*cdf0e10cSrcweir 
411*cdf0e10cSrcweir     void AccessibleTextHelper_Impl::SetStartIndex( sal_Int32 nOffset )
412*cdf0e10cSrcweir     {
413*cdf0e10cSrcweir         DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
414*cdf0e10cSrcweir 
415*cdf0e10cSrcweir         sal_Int32 nOldOffset( mnStartIndex );
416*cdf0e10cSrcweir 
417*cdf0e10cSrcweir         mnStartIndex = nOffset;
418*cdf0e10cSrcweir 
419*cdf0e10cSrcweir         if( nOldOffset != nOffset )
420*cdf0e10cSrcweir         {
421*cdf0e10cSrcweir             // update children
422*cdf0e10cSrcweir             AccessibleTextHelper_OffsetChildIndex aFunctor( nOffset - nOldOffset );
423*cdf0e10cSrcweir 
424*cdf0e10cSrcweir             ::std::for_each( maParaManager.begin(), maParaManager.end(),
425*cdf0e10cSrcweir                              AccessibleParaManager::WeakChildAdapter< AccessibleTextHelper_OffsetChildIndex > (aFunctor) );
426*cdf0e10cSrcweir         }
427*cdf0e10cSrcweir     }
428*cdf0e10cSrcweir 
429*cdf0e10cSrcweir     void AccessibleTextHelper_Impl::SetAdditionalChildStates( const VectorOfStates& rChildStates )
430*cdf0e10cSrcweir     {
431*cdf0e10cSrcweir         maParaManager.SetAdditionalChildStates( rChildStates );
432*cdf0e10cSrcweir     }
433*cdf0e10cSrcweir 
434*cdf0e10cSrcweir     const AccessibleTextHelper_Impl::VectorOfStates& AccessibleTextHelper_Impl::GetAdditionalChildStates() const
435*cdf0e10cSrcweir     {
436*cdf0e10cSrcweir         return maParaManager.GetAdditionalChildStates();
437*cdf0e10cSrcweir     }
438*cdf0e10cSrcweir 
439*cdf0e10cSrcweir     void AccessibleTextHelper_Impl::SetChildFocus( sal_Int32 nChild, sal_Bool bHaveFocus ) SAL_THROW((::com::sun::star::uno::RuntimeException))
440*cdf0e10cSrcweir     {
441*cdf0e10cSrcweir         DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
442*cdf0e10cSrcweir 
443*cdf0e10cSrcweir         if( bHaveFocus )
444*cdf0e10cSrcweir         {
445*cdf0e10cSrcweir             if( mbThisHasFocus )
446*cdf0e10cSrcweir                 SetShapeFocus( sal_False );
447*cdf0e10cSrcweir 
448*cdf0e10cSrcweir             maParaManager.SetFocus( nChild );
449*cdf0e10cSrcweir 
450*cdf0e10cSrcweir             // we just received the focus, also send caret event then
451*cdf0e10cSrcweir             UpdateSelection();
452*cdf0e10cSrcweir 
453*cdf0e10cSrcweir             DBG_TRACE1("AccessibleTextHelper_Impl::SetChildFocus(): Paragraph %d received focus", nChild );
454*cdf0e10cSrcweir         }
455*cdf0e10cSrcweir         else
456*cdf0e10cSrcweir         {
457*cdf0e10cSrcweir             maParaManager.SetFocus( -1 );
458*cdf0e10cSrcweir 
459*cdf0e10cSrcweir             DBG_TRACE1("AccessibleTextHelper_Impl::SetChildFocus(): Paragraph %d lost focus", nChild );
460*cdf0e10cSrcweir 
461*cdf0e10cSrcweir             if( mbGroupHasFocus )
462*cdf0e10cSrcweir                 SetShapeFocus( sal_True );
463*cdf0e10cSrcweir         }
464*cdf0e10cSrcweir     }
465*cdf0e10cSrcweir 
466*cdf0e10cSrcweir     void AccessibleTextHelper_Impl::ChangeChildFocus( sal_Int32 nNewChild ) SAL_THROW((::com::sun::star::uno::RuntimeException))
467*cdf0e10cSrcweir     {
468*cdf0e10cSrcweir         DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
469*cdf0e10cSrcweir 
470*cdf0e10cSrcweir         if( mbThisHasFocus )
471*cdf0e10cSrcweir             SetShapeFocus( sal_False );
472*cdf0e10cSrcweir 
473*cdf0e10cSrcweir         mbGroupHasFocus = sal_True;
474*cdf0e10cSrcweir         maParaManager.SetFocus( nNewChild );
475*cdf0e10cSrcweir 
476*cdf0e10cSrcweir         DBG_TRACE1("AccessibleTextHelper_Impl::ChangeChildFocus(): Paragraph %d received focus", nNewChild );
477*cdf0e10cSrcweir     }
478*cdf0e10cSrcweir 
479*cdf0e10cSrcweir     void AccessibleTextHelper_Impl::SetShapeFocus( sal_Bool bHaveFocus ) SAL_THROW((::com::sun::star::uno::RuntimeException))
480*cdf0e10cSrcweir     {
481*cdf0e10cSrcweir         DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
482*cdf0e10cSrcweir 
483*cdf0e10cSrcweir         sal_Bool bOldFocus( mbThisHasFocus );
484*cdf0e10cSrcweir 
485*cdf0e10cSrcweir         mbThisHasFocus = bHaveFocus;
486*cdf0e10cSrcweir 
487*cdf0e10cSrcweir         if( bOldFocus != bHaveFocus )
488*cdf0e10cSrcweir         {
489*cdf0e10cSrcweir             if( bHaveFocus )
490*cdf0e10cSrcweir             {
491*cdf0e10cSrcweir                 GotPropertyEvent( uno::makeAny(AccessibleStateType::FOCUSED), AccessibleEventId::STATE_CHANGED );
492*cdf0e10cSrcweir                 DBG_TRACE("AccessibleTextHelper_Impl::SetShapeFocus(): Parent object received focus" );
493*cdf0e10cSrcweir             }
494*cdf0e10cSrcweir             else
495*cdf0e10cSrcweir             {
496*cdf0e10cSrcweir                 LostPropertyEvent( uno::makeAny(AccessibleStateType::FOCUSED), AccessibleEventId::STATE_CHANGED );
497*cdf0e10cSrcweir                 DBG_TRACE("AccessibleTextHelper_Impl::SetShapeFocus(): Parent object lost focus" );
498*cdf0e10cSrcweir             }
499*cdf0e10cSrcweir         }
500*cdf0e10cSrcweir     }
501*cdf0e10cSrcweir 
502*cdf0e10cSrcweir     void AccessibleTextHelper_Impl::SetFocus( sal_Bool bHaveFocus ) SAL_THROW((::com::sun::star::uno::RuntimeException))
503*cdf0e10cSrcweir     {
504*cdf0e10cSrcweir         DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
505*cdf0e10cSrcweir 
506*cdf0e10cSrcweir         sal_Bool bOldFocus( mbGroupHasFocus );
507*cdf0e10cSrcweir 
508*cdf0e10cSrcweir         mbGroupHasFocus = bHaveFocus;
509*cdf0e10cSrcweir 
510*cdf0e10cSrcweir         if( IsActive() )
511*cdf0e10cSrcweir         {
512*cdf0e10cSrcweir             try
513*cdf0e10cSrcweir             {
514*cdf0e10cSrcweir                 // find the one with the cursor and get/set focus accordingly
515*cdf0e10cSrcweir                 ESelection aSelection;
516*cdf0e10cSrcweir                 if( GetEditViewForwarder().GetSelection( aSelection ) )
517*cdf0e10cSrcweir                     SetChildFocus( aSelection.nEndPara, bHaveFocus );
518*cdf0e10cSrcweir             }
519*cdf0e10cSrcweir             catch( const uno::Exception& ) {}
520*cdf0e10cSrcweir         }
521*cdf0e10cSrcweir         else if( bOldFocus != bHaveFocus )
522*cdf0e10cSrcweir         {
523*cdf0e10cSrcweir             SetShapeFocus( bHaveFocus );
524*cdf0e10cSrcweir         }
525*cdf0e10cSrcweir 
526*cdf0e10cSrcweir         DBG_TRACE2("AccessibleTextHelper_Impl::SetFocus: focus changed, Object %d, state: %s", this, bHaveFocus ? "focused" : "not focused");
527*cdf0e10cSrcweir     }
528*cdf0e10cSrcweir 
529*cdf0e10cSrcweir     sal_Bool AccessibleTextHelper_Impl::HaveFocus() SAL_THROW((::com::sun::star::uno::RuntimeException))
530*cdf0e10cSrcweir     {
531*cdf0e10cSrcweir         DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
532*cdf0e10cSrcweir 
533*cdf0e10cSrcweir         // No locking of solar mutex here, since we rely on the fact
534*cdf0e10cSrcweir         // that sal_Bool access is atomic
535*cdf0e10cSrcweir         return mbThisHasFocus;
536*cdf0e10cSrcweir     }
537*cdf0e10cSrcweir 
538*cdf0e10cSrcweir     sal_Bool AccessibleTextHelper_Impl::IsActive() const SAL_THROW((uno::RuntimeException))
539*cdf0e10cSrcweir     {
540*cdf0e10cSrcweir         DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
541*cdf0e10cSrcweir 
542*cdf0e10cSrcweir         try
543*cdf0e10cSrcweir         {
544*cdf0e10cSrcweir             SvxEditSource& rEditSource = GetEditSource();
545*cdf0e10cSrcweir             SvxEditViewForwarder* pViewForwarder = rEditSource.GetEditViewForwarder();
546*cdf0e10cSrcweir 
547*cdf0e10cSrcweir             if( !pViewForwarder )
548*cdf0e10cSrcweir                 return sal_False;
549*cdf0e10cSrcweir 
550*cdf0e10cSrcweir             if( pViewForwarder->IsValid() )
551*cdf0e10cSrcweir                 return sal_True;
552*cdf0e10cSrcweir             else
553*cdf0e10cSrcweir                 return sal_False;
554*cdf0e10cSrcweir         }
555*cdf0e10cSrcweir         catch( const uno::RuntimeException& )
556*cdf0e10cSrcweir         {
557*cdf0e10cSrcweir             return sal_False;
558*cdf0e10cSrcweir         }
559*cdf0e10cSrcweir     }
560*cdf0e10cSrcweir 
561*cdf0e10cSrcweir     void AccessibleTextHelper_Impl::UpdateSelection()
562*cdf0e10cSrcweir     {
563*cdf0e10cSrcweir         DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
564*cdf0e10cSrcweir 
565*cdf0e10cSrcweir         try
566*cdf0e10cSrcweir         {
567*cdf0e10cSrcweir             ESelection aSelection;
568*cdf0e10cSrcweir             if( GetEditViewForwarder().GetSelection( aSelection ) )
569*cdf0e10cSrcweir             {
570*cdf0e10cSrcweir                 if( !maLastSelection.IsEqual( aSelection ) &&
571*cdf0e10cSrcweir                     aSelection.nEndPara < maParaManager.GetNum() )
572*cdf0e10cSrcweir                 {
573*cdf0e10cSrcweir                     // #103998# Not that important, changed from assertion to trace
574*cdf0e10cSrcweir                     if( mbThisHasFocus )
575*cdf0e10cSrcweir                     {
576*cdf0e10cSrcweir                         DBG_TRACE("AccessibleTextHelper_Impl::UpdateSelection(): Parent has focus!");
577*cdf0e10cSrcweir                     }
578*cdf0e10cSrcweir 
579*cdf0e10cSrcweir                     sal_uInt16 nMaxValidParaIndex( static_cast< sal_uInt16 >( GetTextForwarder().GetParagraphCount() ) - 1 );
580*cdf0e10cSrcweir 
581*cdf0e10cSrcweir                     // notify all affected paragraphs (TODO: may be suboptimal,
582*cdf0e10cSrcweir                     // since some paragraphs might stay selected)
583*cdf0e10cSrcweir                     if( maLastSelection.nStartPara != EE_PARA_NOT_FOUND )
584*cdf0e10cSrcweir                     {
585*cdf0e10cSrcweir                         // Did the caret move from one paragraph to another?
586*cdf0e10cSrcweir                         // #100530# no caret events if not focused.
587*cdf0e10cSrcweir                         if( mbGroupHasFocus &&
588*cdf0e10cSrcweir                             maLastSelection.nEndPara != aSelection.nEndPara )
589*cdf0e10cSrcweir                         {
590*cdf0e10cSrcweir                             if( maLastSelection.nEndPara < maParaManager.GetNum() )
591*cdf0e10cSrcweir                             {
592*cdf0e10cSrcweir 								maParaManager.FireEvent( ::std::min( maLastSelection.nEndPara, nMaxValidParaIndex ),
593*cdf0e10cSrcweir 														 ::std::min( maLastSelection.nEndPara, nMaxValidParaIndex )+1,
594*cdf0e10cSrcweir 														 AccessibleEventId::CARET_CHANGED,
595*cdf0e10cSrcweir 														 uno::makeAny(static_cast<sal_Int32>(-1)),
596*cdf0e10cSrcweir 														 uno::makeAny(static_cast<sal_Int32>(maLastSelection.nEndPos)) );
597*cdf0e10cSrcweir                             }
598*cdf0e10cSrcweir 
599*cdf0e10cSrcweir                             ChangeChildFocus( aSelection.nEndPara );
600*cdf0e10cSrcweir 
601*cdf0e10cSrcweir                             DBG_TRACE3("AccessibleTextHelper_Impl::UpdateSelection(): focus changed, Object: %d, Paragraph: %d, Last paragraph: %d",
602*cdf0e10cSrcweir                                        this, aSelection.nEndPara, maLastSelection.nEndPara);
603*cdf0e10cSrcweir                         }
604*cdf0e10cSrcweir                     }
605*cdf0e10cSrcweir 
606*cdf0e10cSrcweir                     // #100530# no caret events if not focused.
607*cdf0e10cSrcweir                     if( mbGroupHasFocus )
608*cdf0e10cSrcweir                     {
609*cdf0e10cSrcweir                         uno::Any aOldCursor;
610*cdf0e10cSrcweir 
611*cdf0e10cSrcweir                         // #i13705# The old cursor can only contain valid
612*cdf0e10cSrcweir                         // values if it's the same paragraph!
613*cdf0e10cSrcweir                         if( maLastSelection.nStartPara != EE_PARA_NOT_FOUND &&
614*cdf0e10cSrcweir                             maLastSelection.nEndPara == aSelection.nEndPara )
615*cdf0e10cSrcweir                         {
616*cdf0e10cSrcweir                             aOldCursor <<= static_cast<sal_Int32>(maLastSelection.nEndPos);
617*cdf0e10cSrcweir                         }
618*cdf0e10cSrcweir                         else
619*cdf0e10cSrcweir                         {
620*cdf0e10cSrcweir                             aOldCursor <<= static_cast<sal_Int32>(-1);
621*cdf0e10cSrcweir                         }
622*cdf0e10cSrcweir 
623*cdf0e10cSrcweir                         maParaManager.FireEvent( aSelection.nEndPara,
624*cdf0e10cSrcweir                                                  aSelection.nEndPara+1,
625*cdf0e10cSrcweir                                                  AccessibleEventId::CARET_CHANGED,
626*cdf0e10cSrcweir                                                  uno::makeAny(static_cast<sal_Int32>(aSelection.nEndPos)),
627*cdf0e10cSrcweir                                                  aOldCursor );
628*cdf0e10cSrcweir                     }
629*cdf0e10cSrcweir 
630*cdf0e10cSrcweir                     DBG_TRACE5("AccessibleTextHelper_Impl::UpdateSelection(): caret changed, Object: %d, New pos: %d, Old pos: %d, New para: %d, Old para: %d",
631*cdf0e10cSrcweir                                this, aSelection.nEndPos, maLastSelection.nEndPos, aSelection.nEndPara, maLastSelection.nEndPara);
632*cdf0e10cSrcweir 
633*cdf0e10cSrcweir                     // #108947# Sort new range before calling FireEvent
634*cdf0e10cSrcweir                     ::std::pair< xub_StrLen, xub_StrLen > sortedSelection(
635*cdf0e10cSrcweir                         makeSortedPair(::std::min( aSelection.nStartPara, nMaxValidParaIndex ),
636*cdf0e10cSrcweir                                        ::std::min( aSelection.nEndPara, nMaxValidParaIndex ) ) );
637*cdf0e10cSrcweir 
638*cdf0e10cSrcweir                     // #108947# Sort last range before calling FireEvent
639*cdf0e10cSrcweir                     ::std::pair< xub_StrLen, xub_StrLen > sortedLastSelection(
640*cdf0e10cSrcweir                         makeSortedPair(::std::min( maLastSelection.nStartPara, nMaxValidParaIndex ),
641*cdf0e10cSrcweir                                        ::std::min( maLastSelection.nEndPara, nMaxValidParaIndex ) ) );
642*cdf0e10cSrcweir 
643*cdf0e10cSrcweir                     // --> OD 2005-12-15 #i27299#
644*cdf0e10cSrcweir                     // event TEXT_SELECTION_CHANGED has to be submitted.
645*cdf0e10cSrcweir                     const sal_Int16 nTextSelChgEventId =
646*cdf0e10cSrcweir                                     AccessibleEventId::TEXT_SELECTION_CHANGED;
647*cdf0e10cSrcweir                     // <--
648*cdf0e10cSrcweir                     // #107037# notify selection change
649*cdf0e10cSrcweir                     if( maLastSelection.nStartPara == EE_PARA_NOT_FOUND )
650*cdf0e10cSrcweir                     {
651*cdf0e10cSrcweir                         // last selection is undefined
652*cdf0e10cSrcweir                         // --> OD 2005-12-15 #i27299# - use method <ESelection::HasRange()>
653*cdf0e10cSrcweir                         if ( aSelection.HasRange() )
654*cdf0e10cSrcweir                         // <--
655*cdf0e10cSrcweir                         {
656*cdf0e10cSrcweir                             // selection was undefined, now is on
657*cdf0e10cSrcweir                             maParaManager.FireEvent( sortedSelection.first,
658*cdf0e10cSrcweir                                                      sortedSelection.second+1,
659*cdf0e10cSrcweir                                                      nTextSelChgEventId );
660*cdf0e10cSrcweir                         }
661*cdf0e10cSrcweir                     }
662*cdf0e10cSrcweir                     else
663*cdf0e10cSrcweir                     {
664*cdf0e10cSrcweir                         // last selection is valid
665*cdf0e10cSrcweir                         // --> OD 2005-12-15 #i27299# - use method <ESelection::HasRange()>
666*cdf0e10cSrcweir                         if ( maLastSelection.HasRange() &&
667*cdf0e10cSrcweir                              !aSelection.HasRange() )
668*cdf0e10cSrcweir                         // <--
669*cdf0e10cSrcweir                         {
670*cdf0e10cSrcweir                             // selection was on, now is empty
671*cdf0e10cSrcweir                             maParaManager.FireEvent( sortedLastSelection.first,
672*cdf0e10cSrcweir                                                      sortedLastSelection.second+1,
673*cdf0e10cSrcweir                                                      nTextSelChgEventId );
674*cdf0e10cSrcweir                         }
675*cdf0e10cSrcweir                         // --> OD 2005-12-15 #i27299# - use method <ESelection::HasRange()>
676*cdf0e10cSrcweir                         else if( !maLastSelection.HasRange() &&
677*cdf0e10cSrcweir                                  aSelection.HasRange() )
678*cdf0e10cSrcweir                         // <--
679*cdf0e10cSrcweir                         {
680*cdf0e10cSrcweir                             // selection was empty, now is on
681*cdf0e10cSrcweir                             maParaManager.FireEvent( sortedSelection.first,
682*cdf0e10cSrcweir                                                      sortedSelection.second+1,
683*cdf0e10cSrcweir                                                      nTextSelChgEventId );
684*cdf0e10cSrcweir                         }
685*cdf0e10cSrcweir                         // --> OD 2005-12-15 #i27299#
686*cdf0e10cSrcweir                         // - no event TEXT_SELECTION_CHANGED event, if new and
687*cdf0e10cSrcweir                         //   last selection are empty.
688*cdf0e10cSrcweir                         else if ( maLastSelection.HasRange() &&
689*cdf0e10cSrcweir                                   aSelection.HasRange() )
690*cdf0e10cSrcweir                         // <--
691*cdf0e10cSrcweir                         {
692*cdf0e10cSrcweir                             // --> OD 2005-12-16 #i27299#
693*cdf0e10cSrcweir                             // - send event TEXT_SELECTION_CHANGED for difference
694*cdf0e10cSrcweir                             //   between last and new selection.
695*cdf0e10cSrcweir //                            // selection was on, now is different: take union of ranges
696*cdf0e10cSrcweir //                            maParaManager.FireEvent( ::std::min(sortedSelection.first,
697*cdf0e10cSrcweir //                                                           sortedLastSelection.second),
698*cdf0e10cSrcweir //                                                     ::std::max(sortedSelection.first,
699*cdf0e10cSrcweir //                                                           sortedLastSelection.second)+1,
700*cdf0e10cSrcweir //                                                     nTextSelChgEventId );
701*cdf0e10cSrcweir                             // use sorted last and new selection
702*cdf0e10cSrcweir                             ESelection aTmpLastSel( maLastSelection );
703*cdf0e10cSrcweir                             aTmpLastSel.Adjust();
704*cdf0e10cSrcweir                             ESelection aTmpSel( aSelection );
705*cdf0e10cSrcweir                             aTmpSel.Adjust();
706*cdf0e10cSrcweir                             // first submit event for new and changed selection
707*cdf0e10cSrcweir                             sal_uInt32 nPara = aTmpSel.nStartPara;
708*cdf0e10cSrcweir                             for ( ; nPara <= aTmpSel.nEndPara; ++nPara )
709*cdf0e10cSrcweir                             {
710*cdf0e10cSrcweir                                 if ( nPara < aTmpLastSel.nStartPara ||
711*cdf0e10cSrcweir                                      nPara > aTmpLastSel.nEndPara )
712*cdf0e10cSrcweir                                 {
713*cdf0e10cSrcweir                                     // new selection on paragraph <nPara>
714*cdf0e10cSrcweir                                     maParaManager.FireEvent( nPara,
715*cdf0e10cSrcweir                                                              nTextSelChgEventId );
716*cdf0e10cSrcweir                                 }
717*cdf0e10cSrcweir                                 else
718*cdf0e10cSrcweir                                 {
719*cdf0e10cSrcweir                                     // check for changed selection on paragraph <nPara>
720*cdf0e10cSrcweir                                     const xub_StrLen nParaStartPos =
721*cdf0e10cSrcweir                                             nPara == aTmpSel.nStartPara
722*cdf0e10cSrcweir                                             ? aTmpSel.nStartPos : 0;
723*cdf0e10cSrcweir                                     const xub_StrLen nParaEndPos =
724*cdf0e10cSrcweir                                             nPara == aTmpSel.nEndPara
725*cdf0e10cSrcweir                                             ? aTmpSel.nEndPos : STRING_LEN;
726*cdf0e10cSrcweir                                     const xub_StrLen nLastParaStartPos =
727*cdf0e10cSrcweir                                             nPara == aTmpLastSel.nStartPara
728*cdf0e10cSrcweir                                             ? aTmpLastSel.nStartPos : 0;
729*cdf0e10cSrcweir                                     const xub_StrLen nLastParaEndPos =
730*cdf0e10cSrcweir                                             nPara == aTmpLastSel.nEndPara
731*cdf0e10cSrcweir                                             ? aTmpLastSel.nEndPos : STRING_LEN;
732*cdf0e10cSrcweir                                     if ( nParaStartPos != nLastParaStartPos ||
733*cdf0e10cSrcweir                                          nParaEndPos != nLastParaEndPos )
734*cdf0e10cSrcweir                                     {
735*cdf0e10cSrcweir                                         maParaManager.FireEvent(
736*cdf0e10cSrcweir                                                     nPara, nTextSelChgEventId );
737*cdf0e10cSrcweir                                     }
738*cdf0e10cSrcweir                                 }
739*cdf0e10cSrcweir                             }
740*cdf0e10cSrcweir                             // second submit event for 'old' selections
741*cdf0e10cSrcweir                             nPara = aTmpLastSel.nStartPara;
742*cdf0e10cSrcweir                             for ( ; nPara <= aTmpLastSel.nEndPara; ++nPara )
743*cdf0e10cSrcweir                             {
744*cdf0e10cSrcweir                                 if ( nPara < aTmpSel.nStartPara ||
745*cdf0e10cSrcweir                                      nPara > aTmpSel.nEndPara )
746*cdf0e10cSrcweir                                 {
747*cdf0e10cSrcweir                                     maParaManager.FireEvent( nPara,
748*cdf0e10cSrcweir                                                              nTextSelChgEventId );
749*cdf0e10cSrcweir                                 }
750*cdf0e10cSrcweir                             }
751*cdf0e10cSrcweir                         }
752*cdf0e10cSrcweir                     }
753*cdf0e10cSrcweir 
754*cdf0e10cSrcweir                     maLastSelection = aSelection;
755*cdf0e10cSrcweir                 }
756*cdf0e10cSrcweir             }
757*cdf0e10cSrcweir         }
758*cdf0e10cSrcweir         // no selection? no update actions
759*cdf0e10cSrcweir         catch( const uno::RuntimeException& ) {}
760*cdf0e10cSrcweir     }
761*cdf0e10cSrcweir 
762*cdf0e10cSrcweir     void AccessibleTextHelper_Impl::ShutdownEditSource() SAL_THROW((uno::RuntimeException))
763*cdf0e10cSrcweir     {
764*cdf0e10cSrcweir         DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
765*cdf0e10cSrcweir 
766*cdf0e10cSrcweir         // This should only be called with solar mutex locked, i.e. from the main office thread
767*cdf0e10cSrcweir 
768*cdf0e10cSrcweir         // This here is somewhat clumsy: As soon as our children have
769*cdf0e10cSrcweir         // a NULL EditSource (maParaManager.SetEditSource()), they
770*cdf0e10cSrcweir         // enter the disposed state and cannot be reanimated. Thus, it
771*cdf0e10cSrcweir         // is unavoidable and a hard requirement to let go and create
772*cdf0e10cSrcweir         // from scratch each and every child.
773*cdf0e10cSrcweir 
774*cdf0e10cSrcweir         // invalidate children
775*cdf0e10cSrcweir         maParaManager.Dispose();
776*cdf0e10cSrcweir         maParaManager.SetNum(0);
777*cdf0e10cSrcweir 
778*cdf0e10cSrcweir         // lost all children
779*cdf0e10cSrcweir         if( mxFrontEnd.is() )
780*cdf0e10cSrcweir             FireEvent(AccessibleEventId::INVALIDATE_ALL_CHILDREN);
781*cdf0e10cSrcweir 
782*cdf0e10cSrcweir         // quit listen on stale edit source
783*cdf0e10cSrcweir         if( maEditSource.IsValid() )
784*cdf0e10cSrcweir             EndListening( maEditSource.GetBroadcaster() );
785*cdf0e10cSrcweir 
786*cdf0e10cSrcweir         maEditSource.SetEditSource( ::std::auto_ptr< SvxEditSource >(NULL) );
787*cdf0e10cSrcweir     }
788*cdf0e10cSrcweir 
789*cdf0e10cSrcweir     void AccessibleTextHelper_Impl::SetEditSource( ::std::auto_ptr< SvxEditSource > pEditSource ) SAL_THROW((uno::RuntimeException))
790*cdf0e10cSrcweir     {
791*cdf0e10cSrcweir         DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
792*cdf0e10cSrcweir 
793*cdf0e10cSrcweir         // This should only be called with solar mutex locked, i.e. from the main office thread
794*cdf0e10cSrcweir 
795*cdf0e10cSrcweir         // shutdown old edit source
796*cdf0e10cSrcweir         ShutdownEditSource();
797*cdf0e10cSrcweir 
798*cdf0e10cSrcweir         // set new edit source
799*cdf0e10cSrcweir         maEditSource.SetEditSource( pEditSource );
800*cdf0e10cSrcweir 
801*cdf0e10cSrcweir         // init child vector to the current child count
802*cdf0e10cSrcweir         if( maEditSource.IsValid() )
803*cdf0e10cSrcweir         {
804*cdf0e10cSrcweir             maParaManager.SetNum( GetTextForwarder().GetParagraphCount() );
805*cdf0e10cSrcweir 
806*cdf0e10cSrcweir             // listen on new edit source
807*cdf0e10cSrcweir             StartListening( maEditSource.GetBroadcaster() );
808*cdf0e10cSrcweir 
809*cdf0e10cSrcweir             UpdateVisibleChildren();
810*cdf0e10cSrcweir         }
811*cdf0e10cSrcweir     }
812*cdf0e10cSrcweir 
813*cdf0e10cSrcweir     void AccessibleTextHelper_Impl::SetOffset( const Point& rPoint )
814*cdf0e10cSrcweir     {
815*cdf0e10cSrcweir         DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
816*cdf0e10cSrcweir 
817*cdf0e10cSrcweir         // guard against non-atomic access to maOffset data structure
818*cdf0e10cSrcweir         {
819*cdf0e10cSrcweir             ::osl::MutexGuard aGuard( maMutex );
820*cdf0e10cSrcweir             maOffset = rPoint;
821*cdf0e10cSrcweir         }
822*cdf0e10cSrcweir 
823*cdf0e10cSrcweir         maParaManager.SetEEOffset( rPoint );
824*cdf0e10cSrcweir 
825*cdf0e10cSrcweir         // in all cases, check visibility afterwards.
826*cdf0e10cSrcweir         UpdateVisibleChildren();
827*cdf0e10cSrcweir         UpdateBoundRect();
828*cdf0e10cSrcweir     }
829*cdf0e10cSrcweir 
830*cdf0e10cSrcweir     void AccessibleTextHelper_Impl::UpdateVisibleChildren( bool bBroadcastEvents )
831*cdf0e10cSrcweir     {
832*cdf0e10cSrcweir         DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
833*cdf0e10cSrcweir 
834*cdf0e10cSrcweir         try
835*cdf0e10cSrcweir         {
836*cdf0e10cSrcweir             SvxTextForwarder& rCacheTF = GetTextForwarder();
837*cdf0e10cSrcweir             SvxViewForwarder& rCacheVF = GetViewForwarder();
838*cdf0e10cSrcweir 
839*cdf0e10cSrcweir             Rectangle aViewArea = rCacheVF.GetVisArea();
840*cdf0e10cSrcweir 
841*cdf0e10cSrcweir             if( IsActive() )
842*cdf0e10cSrcweir             {
843*cdf0e10cSrcweir                 // maybe the edit view scrolls, adapt aViewArea
844*cdf0e10cSrcweir                 Rectangle aEditViewArea = GetEditViewForwarder().GetVisArea();
845*cdf0e10cSrcweir                 aViewArea += aEditViewArea.TopLeft();
846*cdf0e10cSrcweir 
847*cdf0e10cSrcweir                 // now determine intersection
848*cdf0e10cSrcweir                 aViewArea.Intersection( aEditViewArea );
849*cdf0e10cSrcweir             }
850*cdf0e10cSrcweir 
851*cdf0e10cSrcweir             Rectangle aTmpBB, aParaBB;
852*cdf0e10cSrcweir             sal_Bool bFirstChild = sal_True;
853*cdf0e10cSrcweir             sal_Int32 nCurrPara;
854*cdf0e10cSrcweir             sal_Int32 nParas=rCacheTF.GetParagraphCount();
855*cdf0e10cSrcweir 
856*cdf0e10cSrcweir             mnFirstVisibleChild = -1;
857*cdf0e10cSrcweir             mnLastVisibleChild = -2;
858*cdf0e10cSrcweir 
859*cdf0e10cSrcweir             for( nCurrPara=0; nCurrPara<nParas; ++nCurrPara )
860*cdf0e10cSrcweir             {
861*cdf0e10cSrcweir                 DBG_ASSERT(nCurrPara >= 0 && nCurrPara <= USHRT_MAX,
862*cdf0e10cSrcweir                            "AccessibleTextHelper_Impl::UpdateVisibleChildren: index value overflow");
863*cdf0e10cSrcweir 
864*cdf0e10cSrcweir                 aTmpBB = rCacheTF.GetParaBounds( static_cast< sal_uInt16 >( nCurrPara ) );
865*cdf0e10cSrcweir 
866*cdf0e10cSrcweir                 // convert to screen coordinates
867*cdf0e10cSrcweir                 aParaBB = ::accessibility::AccessibleEditableTextPara::LogicToPixel( aTmpBB, rCacheTF.GetMapMode(), rCacheVF );
868*cdf0e10cSrcweir 
869*cdf0e10cSrcweir                 if( aParaBB.IsOver( aViewArea ) )
870*cdf0e10cSrcweir                 {
871*cdf0e10cSrcweir                     // at least partially visible
872*cdf0e10cSrcweir                     if( bFirstChild )
873*cdf0e10cSrcweir                     {
874*cdf0e10cSrcweir                         bFirstChild = sal_False;
875*cdf0e10cSrcweir                         mnFirstVisibleChild = nCurrPara;
876*cdf0e10cSrcweir                     }
877*cdf0e10cSrcweir 
878*cdf0e10cSrcweir                     mnLastVisibleChild = nCurrPara;
879*cdf0e10cSrcweir 
880*cdf0e10cSrcweir                     // child not yet created?
881*cdf0e10cSrcweir                     ::accessibility::AccessibleParaManager::WeakChild aChild( maParaManager.GetChild(nCurrPara) );
882*cdf0e10cSrcweir                     if( aChild.second.Width == 0 &&
883*cdf0e10cSrcweir                         aChild.second.Height == 0 &&
884*cdf0e10cSrcweir                         mxFrontEnd.is() &&
885*cdf0e10cSrcweir                         bBroadcastEvents )
886*cdf0e10cSrcweir                     {
887*cdf0e10cSrcweir                         GotPropertyEvent( uno::makeAny( maParaManager.CreateChild( nCurrPara - mnFirstVisibleChild,
888*cdf0e10cSrcweir                                                                                    mxFrontEnd, GetEditSource(), nCurrPara ).first ),
889*cdf0e10cSrcweir                                           AccessibleEventId::CHILD );
890*cdf0e10cSrcweir                     }
891*cdf0e10cSrcweir                 }
892*cdf0e10cSrcweir                 else
893*cdf0e10cSrcweir                 {
894*cdf0e10cSrcweir                     // not or no longer visible
895*cdf0e10cSrcweir                     if( maParaManager.IsReferencable( nCurrPara ) )
896*cdf0e10cSrcweir                     {
897*cdf0e10cSrcweir                         if( bBroadcastEvents )
898*cdf0e10cSrcweir                             LostPropertyEvent( uno::makeAny( maParaManager.GetChild( nCurrPara ).first.get().getRef() ),
899*cdf0e10cSrcweir                                                AccessibleEventId::CHILD );
900*cdf0e10cSrcweir 
901*cdf0e10cSrcweir                         // clear reference
902*cdf0e10cSrcweir                         maParaManager.Release( nCurrPara );
903*cdf0e10cSrcweir                     }
904*cdf0e10cSrcweir                 }
905*cdf0e10cSrcweir             }
906*cdf0e10cSrcweir         }
907*cdf0e10cSrcweir         catch( const uno::Exception& )
908*cdf0e10cSrcweir         {
909*cdf0e10cSrcweir             DBG_ERROR("AccessibleTextHelper_Impl::UpdateVisibleChildren error while determining visible children");
910*cdf0e10cSrcweir 
911*cdf0e10cSrcweir             // something failed - currently no children
912*cdf0e10cSrcweir             mnFirstVisibleChild = -1;
913*cdf0e10cSrcweir             mnLastVisibleChild = -2;
914*cdf0e10cSrcweir             maParaManager.SetNum(0);
915*cdf0e10cSrcweir 
916*cdf0e10cSrcweir             // lost all children
917*cdf0e10cSrcweir             if( bBroadcastEvents )
918*cdf0e10cSrcweir                 FireEvent(AccessibleEventId::INVALIDATE_ALL_CHILDREN);
919*cdf0e10cSrcweir         }
920*cdf0e10cSrcweir     }
921*cdf0e10cSrcweir 
922*cdf0e10cSrcweir 	// functor for checking changes in paragraph bounding boxes (no stand-alone function, maybe not inlined)
923*cdf0e10cSrcweir     class AccessibleTextHelper_UpdateChildBounds : public ::std::unary_function< const ::accessibility::AccessibleParaManager::WeakChild&,
924*cdf0e10cSrcweir         ::accessibility::AccessibleParaManager::WeakChild >
925*cdf0e10cSrcweir     {
926*cdf0e10cSrcweir     public:
927*cdf0e10cSrcweir         AccessibleTextHelper_UpdateChildBounds( AccessibleTextHelper_Impl& rImpl ) : mrImpl(rImpl) {}
928*cdf0e10cSrcweir         ::accessibility::AccessibleParaManager::WeakChild operator()( const ::accessibility::AccessibleParaManager::WeakChild& rChild )
929*cdf0e10cSrcweir         {
930*cdf0e10cSrcweir             // retrieve hard reference from weak one
931*cdf0e10cSrcweir             ::accessibility::AccessibleParaManager::WeakPara::HardRefType aHardRef( rChild.first.get() );
932*cdf0e10cSrcweir 
933*cdf0e10cSrcweir             if( aHardRef.is() )
934*cdf0e10cSrcweir             {
935*cdf0e10cSrcweir                 awt::Rectangle  		aNewRect = aHardRef->getBounds();
936*cdf0e10cSrcweir                 const awt::Rectangle& 	aOldRect = rChild.second;
937*cdf0e10cSrcweir 
938*cdf0e10cSrcweir                 if( aNewRect.X != aOldRect.X ||
939*cdf0e10cSrcweir                     aNewRect.Y != aOldRect.Y ||
940*cdf0e10cSrcweir                     aNewRect.Width != aOldRect.Width ||
941*cdf0e10cSrcweir                     aNewRect.Height != aOldRect.Height )
942*cdf0e10cSrcweir                 {
943*cdf0e10cSrcweir                     // visible data changed
944*cdf0e10cSrcweir                     aHardRef->FireEvent( AccessibleEventId::BOUNDRECT_CHANGED );
945*cdf0e10cSrcweir 
946*cdf0e10cSrcweir                     // update internal bounds
947*cdf0e10cSrcweir                     return ::accessibility::AccessibleParaManager::WeakChild( rChild.first, aNewRect );
948*cdf0e10cSrcweir                 }
949*cdf0e10cSrcweir             }
950*cdf0e10cSrcweir 
951*cdf0e10cSrcweir             // identity transform
952*cdf0e10cSrcweir             return rChild;
953*cdf0e10cSrcweir         }
954*cdf0e10cSrcweir 
955*cdf0e10cSrcweir     private:
956*cdf0e10cSrcweir         AccessibleTextHelper_Impl&	mrImpl;
957*cdf0e10cSrcweir     };
958*cdf0e10cSrcweir 
959*cdf0e10cSrcweir     void AccessibleTextHelper_Impl::UpdateBoundRect()
960*cdf0e10cSrcweir     {
961*cdf0e10cSrcweir         DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
962*cdf0e10cSrcweir 
963*cdf0e10cSrcweir         // send BOUNDRECT_CHANGED to affected children
964*cdf0e10cSrcweir         AccessibleTextHelper_UpdateChildBounds aFunctor( *this );
965*cdf0e10cSrcweir         ::std::transform( maParaManager.begin(), maParaManager.end(), maParaManager.begin(), aFunctor );
966*cdf0e10cSrcweir     }
967*cdf0e10cSrcweir 
968*cdf0e10cSrcweir #ifdef DBG_UTIL
969*cdf0e10cSrcweir     void AccessibleTextHelper_Impl::CheckInvariants() const
970*cdf0e10cSrcweir     {
971*cdf0e10cSrcweir         if( mnFirstVisibleChild >= 0 &&
972*cdf0e10cSrcweir             mnFirstVisibleChild > mnLastVisibleChild )
973*cdf0e10cSrcweir         {
974*cdf0e10cSrcweir             DBG_ERROR( "AccessibleTextHelper: range invalid" );
975*cdf0e10cSrcweir         }
976*cdf0e10cSrcweir     }
977*cdf0e10cSrcweir #endif
978*cdf0e10cSrcweir 
979*cdf0e10cSrcweir 	// functor for sending child events (no stand-alone function, they are maybe not inlined)
980*cdf0e10cSrcweir     class AccessibleTextHelper_LostChildEvent : public ::std::unary_function< const ::accessibility::AccessibleParaManager::WeakChild&, void >
981*cdf0e10cSrcweir     {
982*cdf0e10cSrcweir     public:
983*cdf0e10cSrcweir         AccessibleTextHelper_LostChildEvent( AccessibleTextHelper_Impl& rImpl ) : mrImpl(rImpl) {}
984*cdf0e10cSrcweir         void operator()( const ::accessibility::AccessibleParaManager::WeakChild& rPara )
985*cdf0e10cSrcweir         {
986*cdf0e10cSrcweir             // retrieve hard reference from weak one
987*cdf0e10cSrcweir             ::accessibility::AccessibleParaManager::WeakPara::HardRefType aHardRef( rPara.first.get() );
988*cdf0e10cSrcweir 
989*cdf0e10cSrcweir             if( aHardRef.is() )
990*cdf0e10cSrcweir                 mrImpl.FireEvent(AccessibleEventId::CHILD, uno::Any(), uno::makeAny( aHardRef.getRef() ) );
991*cdf0e10cSrcweir         }
992*cdf0e10cSrcweir 
993*cdf0e10cSrcweir     private:
994*cdf0e10cSrcweir         AccessibleTextHelper_Impl&	mrImpl;
995*cdf0e10cSrcweir     };
996*cdf0e10cSrcweir 
997*cdf0e10cSrcweir     void AccessibleTextHelper_Impl::ParagraphsMoved( sal_Int32 nFirst, sal_Int32 nMiddle, sal_Int32 nLast )
998*cdf0e10cSrcweir     {
999*cdf0e10cSrcweir         DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
1000*cdf0e10cSrcweir 
1001*cdf0e10cSrcweir         const sal_Int32 nParas = GetTextForwarder().GetParagraphCount();
1002*cdf0e10cSrcweir 
1003*cdf0e10cSrcweir         /* rotate paragraphs
1004*cdf0e10cSrcweir          * =================
1005*cdf0e10cSrcweir          *
1006*cdf0e10cSrcweir          * Three cases:
1007*cdf0e10cSrcweir          *
1008*cdf0e10cSrcweir          * 1.
1009*cdf0e10cSrcweir          *   ... nParagraph ... nParam1 ... nParam2 ...
1010*cdf0e10cSrcweir          *       |______________[xxxxxxxxxxx]
1011*cdf0e10cSrcweir          *              becomes
1012*cdf0e10cSrcweir          *       [xxxxxxxxxxx]|______________
1013*cdf0e10cSrcweir          *
1014*cdf0e10cSrcweir          * tail is 0
1015*cdf0e10cSrcweir          *
1016*cdf0e10cSrcweir          * 2.
1017*cdf0e10cSrcweir          *   ... nParam1 ... nParagraph ... nParam2 ...
1018*cdf0e10cSrcweir          *       [xxxxxxxxxxx|xxxxxxxxxxxxxx]____________
1019*cdf0e10cSrcweir          *              becomes
1020*cdf0e10cSrcweir          *       ____________[xxxxxxxxxxx|xxxxxxxxxxxxxx]
1021*cdf0e10cSrcweir          *
1022*cdf0e10cSrcweir          * tail is nParagraph - nParam1
1023*cdf0e10cSrcweir          *
1024*cdf0e10cSrcweir          * 3.
1025*cdf0e10cSrcweir          *   ... nParam1 ... nParam2 ... nParagraph ...
1026*cdf0e10cSrcweir          *       [xxxxxxxxxxx]___________|____________
1027*cdf0e10cSrcweir          *              becomes
1028*cdf0e10cSrcweir          *       ___________|____________[xxxxxxxxxxx]
1029*cdf0e10cSrcweir          *
1030*cdf0e10cSrcweir          * tail is nParam2 - nParam1
1031*cdf0e10cSrcweir          */
1032*cdf0e10cSrcweir 
1033*cdf0e10cSrcweir         // sort nParagraph, nParam1 and nParam2 in ascending order, calc range
1034*cdf0e10cSrcweir         if( nMiddle < nFirst )
1035*cdf0e10cSrcweir         {
1036*cdf0e10cSrcweir             ::std::swap(nFirst, nMiddle);
1037*cdf0e10cSrcweir         }
1038*cdf0e10cSrcweir         else if( nMiddle < nLast )
1039*cdf0e10cSrcweir         {
1040*cdf0e10cSrcweir             nLast = nLast + nMiddle - nFirst;
1041*cdf0e10cSrcweir         }
1042*cdf0e10cSrcweir         else
1043*cdf0e10cSrcweir         {
1044*cdf0e10cSrcweir             ::std::swap(nMiddle, nLast);
1045*cdf0e10cSrcweir             nLast = nLast + nMiddle - nFirst;
1046*cdf0e10cSrcweir         }
1047*cdf0e10cSrcweir 
1048*cdf0e10cSrcweir         if( nFirst < nParas && nMiddle < nParas && nLast < nParas )
1049*cdf0e10cSrcweir         {
1050*cdf0e10cSrcweir             // since we have no "paragraph index
1051*cdf0e10cSrcweir             // changed" event on UAA, remove
1052*cdf0e10cSrcweir             // [first,last] and insert again later (in
1053*cdf0e10cSrcweir             // UpdateVisibleChildren)
1054*cdf0e10cSrcweir 
1055*cdf0e10cSrcweir             // maParaManager.Rotate( nFirst, nMiddle, nLast );
1056*cdf0e10cSrcweir 
1057*cdf0e10cSrcweir             // send CHILD_EVENT to affected children
1058*cdf0e10cSrcweir             ::accessibility::AccessibleParaManager::VectorOfChildren::const_iterator begin = maParaManager.begin();
1059*cdf0e10cSrcweir             ::accessibility::AccessibleParaManager::VectorOfChildren::const_iterator end = begin;
1060*cdf0e10cSrcweir 
1061*cdf0e10cSrcweir             ::std::advance( begin, nFirst );
1062*cdf0e10cSrcweir             ::std::advance( end, nLast+1 );
1063*cdf0e10cSrcweir 
1064*cdf0e10cSrcweir             // TODO: maybe optimize here in the following way.  If the
1065*cdf0e10cSrcweir             // number of removed children exceeds a certain threshold,
1066*cdf0e10cSrcweir             // use INVALIDATE_CHILDREN
1067*cdf0e10cSrcweir             AccessibleTextHelper_LostChildEvent aFunctor( *this );
1068*cdf0e10cSrcweir 
1069*cdf0e10cSrcweir             ::std::for_each( begin, end, aFunctor );
1070*cdf0e10cSrcweir 
1071*cdf0e10cSrcweir             maParaManager.Release(nFirst, nLast+1);
1072*cdf0e10cSrcweir             // should be no need for UpdateBoundRect, since all affected children are cleared.
1073*cdf0e10cSrcweir         }
1074*cdf0e10cSrcweir     }
1075*cdf0e10cSrcweir 
1076*cdf0e10cSrcweir 	// functor for sending child events (no stand-alone function, they are maybe not inlined)
1077*cdf0e10cSrcweir     class AccessibleTextHelper_ChildrenTextChanged : public ::std::unary_function< ::accessibility::AccessibleEditableTextPara&, void >
1078*cdf0e10cSrcweir     {
1079*cdf0e10cSrcweir     public:
1080*cdf0e10cSrcweir         void operator()( ::accessibility::AccessibleEditableTextPara& rPara )
1081*cdf0e10cSrcweir         {
1082*cdf0e10cSrcweir             rPara.TextChanged();
1083*cdf0e10cSrcweir         }
1084*cdf0e10cSrcweir     };
1085*cdf0e10cSrcweir 
1086*cdf0e10cSrcweir 	/** functor processing queue events
1087*cdf0e10cSrcweir 
1088*cdf0e10cSrcweir     	Reacts on TEXT_HINT_PARAINSERTED/REMOVED events and stores
1089*cdf0e10cSrcweir     	their content
1090*cdf0e10cSrcweir      */
1091*cdf0e10cSrcweir     class AccessibleTextHelper_QueueFunctor : public ::std::unary_function< const SfxHint*, void >
1092*cdf0e10cSrcweir     {
1093*cdf0e10cSrcweir     public:
1094*cdf0e10cSrcweir         AccessibleTextHelper_QueueFunctor() :
1095*cdf0e10cSrcweir             mnParasChanged( 0 ),
1096*cdf0e10cSrcweir             mnParaIndex(-1),
1097*cdf0e10cSrcweir             mnHintId(-1)
1098*cdf0e10cSrcweir         {}
1099*cdf0e10cSrcweir         void operator()( const SfxHint* pEvent )
1100*cdf0e10cSrcweir         {
1101*cdf0e10cSrcweir             if( pEvent &&
1102*cdf0e10cSrcweir                 mnParasChanged != -1 )
1103*cdf0e10cSrcweir             {
1104*cdf0e10cSrcweir                 // determine hint type
1105*cdf0e10cSrcweir                 const TextHint* pTextHint = PTR_CAST( TextHint, pEvent );
1106*cdf0e10cSrcweir                 const SvxEditSourceHint* pEditSourceHint = PTR_CAST( SvxEditSourceHint, pEvent );
1107*cdf0e10cSrcweir 
1108*cdf0e10cSrcweir                 if( !pEditSourceHint && pTextHint &&
1109*cdf0e10cSrcweir                     (pTextHint->GetId() == TEXT_HINT_PARAINSERTED ||
1110*cdf0e10cSrcweir                      pTextHint->GetId() == TEXT_HINT_PARAREMOVED ) )
1111*cdf0e10cSrcweir                 {
1112*cdf0e10cSrcweir                     if( pTextHint->GetValue() == EE_PARA_ALL )
1113*cdf0e10cSrcweir                     {
1114*cdf0e10cSrcweir                         mnParasChanged = -1;
1115*cdf0e10cSrcweir                     }
1116*cdf0e10cSrcweir                     else
1117*cdf0e10cSrcweir                     {
1118*cdf0e10cSrcweir                         mnHintId = pTextHint->GetId();
1119*cdf0e10cSrcweir                         mnParaIndex = pTextHint->GetValue();
1120*cdf0e10cSrcweir                         ++mnParasChanged;
1121*cdf0e10cSrcweir                     }
1122*cdf0e10cSrcweir                 }
1123*cdf0e10cSrcweir             }
1124*cdf0e10cSrcweir         }
1125*cdf0e10cSrcweir 
1126*cdf0e10cSrcweir         /** Query number of paragraphs changed during queue processing.
1127*cdf0e10cSrcweir 
1128*cdf0e10cSrcweir         	@return number of changed paragraphs, -1 for
1129*cdf0e10cSrcweir             "every paragraph changed"
1130*cdf0e10cSrcweir         */
1131*cdf0e10cSrcweir         int GetNumberOfParasChanged() { return mnParasChanged; }
1132*cdf0e10cSrcweir         /** Query index of last added/removed paragraph
1133*cdf0e10cSrcweir 
1134*cdf0e10cSrcweir         	@return index of lastly added paragraphs, -1 for none
1135*cdf0e10cSrcweir         	added so far.
1136*cdf0e10cSrcweir         */
1137*cdf0e10cSrcweir         int GetParaIndex() { return mnParaIndex; }
1138*cdf0e10cSrcweir         /** Query hint id of last interesting event
1139*cdf0e10cSrcweir 
1140*cdf0e10cSrcweir         	@return hint id of last interesting event (REMOVED/INSERTED).
1141*cdf0e10cSrcweir         */
1142*cdf0e10cSrcweir         int GetHintId() { return mnHintId; }
1143*cdf0e10cSrcweir 
1144*cdf0e10cSrcweir     private:
1145*cdf0e10cSrcweir         /** number of paragraphs changed during queue processing. -1 for
1146*cdf0e10cSrcweir             "every paragraph changed"
1147*cdf0e10cSrcweir         */
1148*cdf0e10cSrcweir         int mnParasChanged;
1149*cdf0e10cSrcweir         /// index of paragraph added/removed last
1150*cdf0e10cSrcweir         int mnParaIndex;
1151*cdf0e10cSrcweir         /// TextHint ID (removed/inserted) of last interesting event
1152*cdf0e10cSrcweir         int mnHintId;
1153*cdf0e10cSrcweir     };
1154*cdf0e10cSrcweir 
1155*cdf0e10cSrcweir     void AccessibleTextHelper_Impl::ProcessQueue()
1156*cdf0e10cSrcweir     {
1157*cdf0e10cSrcweir         DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
1158*cdf0e10cSrcweir 
1159*cdf0e10cSrcweir         // inspect queue for paragraph insert/remove events. If there
1160*cdf0e10cSrcweir         // is exactly _one_ of those in the queue, and the number of
1161*cdf0e10cSrcweir         // paragraphs has changed by exactly one, use that event to
1162*cdf0e10cSrcweir         // determine a priori which paragraph was added/removed. This
1163*cdf0e10cSrcweir         // is necessary, since I must sync right here with the
1164*cdf0e10cSrcweir         // EditEngine state (number of paragraphs etc.), since I'm
1165*cdf0e10cSrcweir         // potentially sending listener events right away.
1166*cdf0e10cSrcweir         AccessibleTextHelper_QueueFunctor aFunctor;
1167*cdf0e10cSrcweir         maEventQueue.ForEach( aFunctor );
1168*cdf0e10cSrcweir 
1169*cdf0e10cSrcweir         const sal_Int32 nNewParas( GetTextForwarder().GetParagraphCount() );
1170*cdf0e10cSrcweir         const sal_Int32 nCurrParas( maParaManager.GetNum() );
1171*cdf0e10cSrcweir 
1172*cdf0e10cSrcweir         // whether every paragraph already is updated (no need to
1173*cdf0e10cSrcweir         // repeat that later on, e.g. for PARA_MOVED events)
1174*cdf0e10cSrcweir         bool			bEverythingUpdated( false );
1175*cdf0e10cSrcweir 
1176*cdf0e10cSrcweir         if( labs( nNewParas - nCurrParas ) == 1 &&
1177*cdf0e10cSrcweir             aFunctor.GetNumberOfParasChanged() == 1 )
1178*cdf0e10cSrcweir         {
1179*cdf0e10cSrcweir             // #103483# Exactly one paragraph added/removed. This is
1180*cdf0e10cSrcweir             // the normal case, optimize event handling here.
1181*cdf0e10cSrcweir 
1182*cdf0e10cSrcweir             if( aFunctor.GetHintId() == TEXT_HINT_PARAINSERTED )
1183*cdf0e10cSrcweir             {
1184*cdf0e10cSrcweir                 // update num of paras
1185*cdf0e10cSrcweir                 maParaManager.SetNum( nNewParas );
1186*cdf0e10cSrcweir 
1187*cdf0e10cSrcweir                 // release everything from the insertion position until the end
1188*cdf0e10cSrcweir                 maParaManager.Release(aFunctor.GetParaIndex(), nCurrParas);
1189*cdf0e10cSrcweir 
1190*cdf0e10cSrcweir                 // TODO: Clarify whether this behaviour _really_ saves
1191*cdf0e10cSrcweir                 // anybody anything!
1192*cdf0e10cSrcweir                 // update children, _don't_ broadcast
1193*cdf0e10cSrcweir                 UpdateVisibleChildren( false );
1194*cdf0e10cSrcweir                 UpdateBoundRect();
1195*cdf0e10cSrcweir 
1196*cdf0e10cSrcweir                 // send insert event
1197*cdf0e10cSrcweir                 // #109864# Enforce creation of this paragraph
1198*cdf0e10cSrcweir                 try
1199*cdf0e10cSrcweir                 {
1200*cdf0e10cSrcweir                     GotPropertyEvent( uno::makeAny( getAccessibleChild( aFunctor.GetParaIndex() -
1201*cdf0e10cSrcweir                                                                         mnFirstVisibleChild + GetStartIndex() ) ),
1202*cdf0e10cSrcweir                                       AccessibleEventId::CHILD );
1203*cdf0e10cSrcweir                 }
1204*cdf0e10cSrcweir                 catch( const uno::Exception& )
1205*cdf0e10cSrcweir                 {
1206*cdf0e10cSrcweir                     DBG_ERROR("AccessibleTextHelper_Impl::ProcessQueue: could not create new paragraph");
1207*cdf0e10cSrcweir                 }
1208*cdf0e10cSrcweir             }
1209*cdf0e10cSrcweir             else if( aFunctor.GetHintId() == TEXT_HINT_PARAREMOVED )
1210*cdf0e10cSrcweir             {
1211*cdf0e10cSrcweir                 ::accessibility::AccessibleParaManager::VectorOfChildren::const_iterator begin = maParaManager.begin();
1212*cdf0e10cSrcweir                 ::std::advance( begin, aFunctor.GetParaIndex() );
1213*cdf0e10cSrcweir                 ::accessibility::AccessibleParaManager::VectorOfChildren::const_iterator end = begin;
1214*cdf0e10cSrcweir                 ::std::advance( end, 1 );
1215*cdf0e10cSrcweir 
1216*cdf0e10cSrcweir 				// #i61812# remember para to be removed for later notification
1217*cdf0e10cSrcweir 				// AFTER the new state is applied (that after the para got removed)
1218*cdf0e10cSrcweir 				::uno::Reference< XAccessible > xPara;
1219*cdf0e10cSrcweir 				::accessibility::AccessibleParaManager::WeakPara::HardRefType aHardRef( begin->first.get() );
1220*cdf0e10cSrcweir 				if( aHardRef.is() )
1221*cdf0e10cSrcweir 					xPara = ::uno::Reference< XAccessible >( aHardRef.getRef(), ::uno::UNO_QUERY );
1222*cdf0e10cSrcweir 
1223*cdf0e10cSrcweir                 // release everything from the remove position until the end
1224*cdf0e10cSrcweir                 maParaManager.Release(aFunctor.GetParaIndex(), nCurrParas);
1225*cdf0e10cSrcweir 
1226*cdf0e10cSrcweir                 // update num of paras
1227*cdf0e10cSrcweir                 maParaManager.SetNum( nNewParas );
1228*cdf0e10cSrcweir 
1229*cdf0e10cSrcweir                 // TODO: Clarify whether this behaviour _really_ saves
1230*cdf0e10cSrcweir                 // anybody anything!
1231*cdf0e10cSrcweir                 // update children, _don't_ broadcast
1232*cdf0e10cSrcweir                 UpdateVisibleChildren( false );
1233*cdf0e10cSrcweir                 UpdateBoundRect();
1234*cdf0e10cSrcweir 
1235*cdf0e10cSrcweir 				// #i61812# notification for removed para
1236*cdf0e10cSrcweir 				if (xPara.is())
1237*cdf0e10cSrcweir 	            	FireEvent(AccessibleEventId::CHILD, uno::Any(), uno::makeAny( xPara) );
1238*cdf0e10cSrcweir             }
1239*cdf0e10cSrcweir #ifdef DBG_UTIL
1240*cdf0e10cSrcweir             else
1241*cdf0e10cSrcweir                 DBG_ERROR("AccessibleTextHelper_Impl::ProcessQueue() invalid hint id");
1242*cdf0e10cSrcweir #endif
1243*cdf0e10cSrcweir         }
1244*cdf0e10cSrcweir         else if( nNewParas != nCurrParas )
1245*cdf0e10cSrcweir         {
1246*cdf0e10cSrcweir             // release all paras
1247*cdf0e10cSrcweir             maParaManager.Release(0, nCurrParas);
1248*cdf0e10cSrcweir 
1249*cdf0e10cSrcweir             // update num of paras
1250*cdf0e10cSrcweir             maParaManager.SetNum( nNewParas );
1251*cdf0e10cSrcweir 
1252*cdf0e10cSrcweir             // #109864# create from scratch, don't broadcast
1253*cdf0e10cSrcweir             UpdateVisibleChildren( false );
1254*cdf0e10cSrcweir             UpdateBoundRect();
1255*cdf0e10cSrcweir 
1256*cdf0e10cSrcweir             // number of paragraphs somehow changed - but we have no
1257*cdf0e10cSrcweir             // chance determining how. Thus, throw away everything and
1258*cdf0e10cSrcweir             // create from scratch.
1259*cdf0e10cSrcweir 			// (child events should be broadcast after the changes are done...)
1260*cdf0e10cSrcweir             FireEvent(AccessibleEventId::INVALIDATE_ALL_CHILDREN);
1261*cdf0e10cSrcweir 
1262*cdf0e10cSrcweir             // no need for further updates later on
1263*cdf0e10cSrcweir             bEverythingUpdated = true;
1264*cdf0e10cSrcweir         }
1265*cdf0e10cSrcweir 
1266*cdf0e10cSrcweir         while( !maEventQueue.IsEmpty() )
1267*cdf0e10cSrcweir         {
1268*cdf0e10cSrcweir             ::std::auto_ptr< SfxHint > pHint( maEventQueue.PopFront() );
1269*cdf0e10cSrcweir             if( pHint.get() )
1270*cdf0e10cSrcweir             {
1271*cdf0e10cSrcweir                 const SfxHint& rHint = *(pHint.get());
1272*cdf0e10cSrcweir 
1273*cdf0e10cSrcweir                 // determine hint type
1274*cdf0e10cSrcweir                 const SdrHint* pSdrHint = PTR_CAST( SdrHint, &rHint );
1275*cdf0e10cSrcweir                 const SfxSimpleHint* pSimpleHint = PTR_CAST( SfxSimpleHint, &rHint );
1276*cdf0e10cSrcweir                 const TextHint* pTextHint = PTR_CAST( TextHint, &rHint );
1277*cdf0e10cSrcweir                 const SvxViewHint* pViewHint = PTR_CAST( SvxViewHint, &rHint );
1278*cdf0e10cSrcweir                 const SvxEditSourceHint* pEditSourceHint = PTR_CAST( SvxEditSourceHint, &rHint );
1279*cdf0e10cSrcweir 
1280*cdf0e10cSrcweir                 try
1281*cdf0e10cSrcweir                 {
1282*cdf0e10cSrcweir                     const sal_Int32 nParas = GetTextForwarder().GetParagraphCount();
1283*cdf0e10cSrcweir 
1284*cdf0e10cSrcweir                     if( pEditSourceHint )
1285*cdf0e10cSrcweir                     {
1286*cdf0e10cSrcweir                         switch( pEditSourceHint->GetId() )
1287*cdf0e10cSrcweir                         {
1288*cdf0e10cSrcweir                             case EDITSOURCE_HINT_PARASMOVED:
1289*cdf0e10cSrcweir                             {
1290*cdf0e10cSrcweir                                 DBG_ASSERT( pEditSourceHint->GetStartValue() < GetTextForwarder().GetParagraphCount() &&
1291*cdf0e10cSrcweir                                             pEditSourceHint->GetEndValue() < GetTextForwarder().GetParagraphCount(),
1292*cdf0e10cSrcweir                                             "AccessibleTextHelper_Impl::NotifyHdl: Invalid notification");
1293*cdf0e10cSrcweir 
1294*cdf0e10cSrcweir                                 if( !bEverythingUpdated )
1295*cdf0e10cSrcweir                                 {
1296*cdf0e10cSrcweir                                     ParagraphsMoved(pEditSourceHint->GetStartValue(),
1297*cdf0e10cSrcweir                                                     pEditSourceHint->GetValue(),
1298*cdf0e10cSrcweir                                                     pEditSourceHint->GetEndValue());
1299*cdf0e10cSrcweir 
1300*cdf0e10cSrcweir                                     // in all cases, check visibility afterwards.
1301*cdf0e10cSrcweir                                     UpdateVisibleChildren();
1302*cdf0e10cSrcweir                                 }
1303*cdf0e10cSrcweir                                 break;
1304*cdf0e10cSrcweir                             }
1305*cdf0e10cSrcweir 
1306*cdf0e10cSrcweir                             case EDITSOURCE_HINT_SELECTIONCHANGED:
1307*cdf0e10cSrcweir                                 // notify listeners
1308*cdf0e10cSrcweir                                 try
1309*cdf0e10cSrcweir                                 {
1310*cdf0e10cSrcweir                                     UpdateSelection();
1311*cdf0e10cSrcweir                                 }
1312*cdf0e10cSrcweir                                 // maybe we're not in edit mode (this is not an error)
1313*cdf0e10cSrcweir                                 catch( const uno::Exception& ) {}
1314*cdf0e10cSrcweir                                 break;
1315*cdf0e10cSrcweir                         }
1316*cdf0e10cSrcweir                     }
1317*cdf0e10cSrcweir                     else if( pTextHint )
1318*cdf0e10cSrcweir                     {
1319*cdf0e10cSrcweir                         switch( pTextHint->GetId() )
1320*cdf0e10cSrcweir                         {
1321*cdf0e10cSrcweir                             case TEXT_HINT_MODIFIED:
1322*cdf0e10cSrcweir                             {
1323*cdf0e10cSrcweir                                 // notify listeners
1324*cdf0e10cSrcweir                                 sal_Int32 nPara( pTextHint->GetValue() );
1325*cdf0e10cSrcweir 
1326*cdf0e10cSrcweir                                 // #108900# Delegate change event to children
1327*cdf0e10cSrcweir                                 AccessibleTextHelper_ChildrenTextChanged aNotifyChildrenFunctor;
1328*cdf0e10cSrcweir 
1329*cdf0e10cSrcweir                                 if( nPara == static_cast<sal_Int32>(EE_PARA_ALL) )
1330*cdf0e10cSrcweir                                 {
1331*cdf0e10cSrcweir                                     // #108900# Call every child
1332*cdf0e10cSrcweir                                     ::std::for_each( maParaManager.begin(), maParaManager.end(),
1333*cdf0e10cSrcweir                                                      AccessibleParaManager::WeakChildAdapter< AccessibleTextHelper_ChildrenTextChanged > (aNotifyChildrenFunctor) );
1334*cdf0e10cSrcweir                                 }
1335*cdf0e10cSrcweir                                 else
1336*cdf0e10cSrcweir                                     if( nPara < nParas )
1337*cdf0e10cSrcweir                                     {
1338*cdf0e10cSrcweir                                         // #108900# Call child at index nPara
1339*cdf0e10cSrcweir                                         ::std::for_each( maParaManager.begin()+nPara, maParaManager.begin()+nPara+1,
1340*cdf0e10cSrcweir                                                          AccessibleParaManager::WeakChildAdapter< AccessibleTextHelper_ChildrenTextChanged > (aNotifyChildrenFunctor) );
1341*cdf0e10cSrcweir                                     }
1342*cdf0e10cSrcweir                                 break;
1343*cdf0e10cSrcweir                             }
1344*cdf0e10cSrcweir 
1345*cdf0e10cSrcweir                             case TEXT_HINT_PARAINSERTED:
1346*cdf0e10cSrcweir                                 // already happened above
1347*cdf0e10cSrcweir                                 break;
1348*cdf0e10cSrcweir 
1349*cdf0e10cSrcweir                             case TEXT_HINT_PARAREMOVED:
1350*cdf0e10cSrcweir                                 // already happened above
1351*cdf0e10cSrcweir                                 break;
1352*cdf0e10cSrcweir 
1353*cdf0e10cSrcweir                             case TEXT_HINT_TEXTHEIGHTCHANGED:
1354*cdf0e10cSrcweir                                 // visibility changed, done below
1355*cdf0e10cSrcweir                                 break;
1356*cdf0e10cSrcweir 
1357*cdf0e10cSrcweir                             case TEXT_HINT_VIEWSCROLLED:
1358*cdf0e10cSrcweir                                 // visibility changed, done below
1359*cdf0e10cSrcweir                                 break;
1360*cdf0e10cSrcweir                         }
1361*cdf0e10cSrcweir 
1362*cdf0e10cSrcweir                         // in all cases, check visibility afterwards.
1363*cdf0e10cSrcweir                         UpdateVisibleChildren();
1364*cdf0e10cSrcweir                         UpdateBoundRect();
1365*cdf0e10cSrcweir                     }
1366*cdf0e10cSrcweir                     else if( pViewHint )
1367*cdf0e10cSrcweir                     {
1368*cdf0e10cSrcweir                         switch( pViewHint->GetHintType() )
1369*cdf0e10cSrcweir                         {
1370*cdf0e10cSrcweir                             case SvxViewHint::SVX_HINT_VIEWCHANGED:
1371*cdf0e10cSrcweir                                 // just check visibility
1372*cdf0e10cSrcweir                                 UpdateVisibleChildren();
1373*cdf0e10cSrcweir                                 UpdateBoundRect();
1374*cdf0e10cSrcweir                                 break;
1375*cdf0e10cSrcweir                         }
1376*cdf0e10cSrcweir                     }
1377*cdf0e10cSrcweir                     else if( pSdrHint )
1378*cdf0e10cSrcweir                     {
1379*cdf0e10cSrcweir                         switch( pSdrHint->GetKind() )
1380*cdf0e10cSrcweir                         {
1381*cdf0e10cSrcweir                             case HINT_BEGEDIT:
1382*cdf0e10cSrcweir                             {
1383*cdf0e10cSrcweir                                 // change children state
1384*cdf0e10cSrcweir                                 maParaManager.SetActive();
1385*cdf0e10cSrcweir 
1386*cdf0e10cSrcweir                                 // per definition, edit mode text has the focus
1387*cdf0e10cSrcweir                                 SetFocus( sal_True );
1388*cdf0e10cSrcweir                                 break;
1389*cdf0e10cSrcweir                             }
1390*cdf0e10cSrcweir 
1391*cdf0e10cSrcweir                             case HINT_ENDEDIT:
1392*cdf0e10cSrcweir                             {
1393*cdf0e10cSrcweir                                 // focused child now looses focus
1394*cdf0e10cSrcweir                                 ESelection aSelection;
1395*cdf0e10cSrcweir                                 if( GetEditViewForwarder().GetSelection( aSelection ) )
1396*cdf0e10cSrcweir                                     SetChildFocus( aSelection.nEndPara, sal_False );
1397*cdf0e10cSrcweir 
1398*cdf0e10cSrcweir                                 // change children state
1399*cdf0e10cSrcweir                                 maParaManager.SetActive( sal_False );
1400*cdf0e10cSrcweir 
1401*cdf0e10cSrcweir                                 maLastSelection = ESelection( EE_PARA_NOT_FOUND, EE_PARA_NOT_FOUND,
1402*cdf0e10cSrcweir                                                               EE_PARA_NOT_FOUND, EE_PARA_NOT_FOUND);
1403*cdf0e10cSrcweir                                 break;
1404*cdf0e10cSrcweir                             }
1405*cdf0e10cSrcweir                             default:
1406*cdf0e10cSrcweir                                 break;
1407*cdf0e10cSrcweir                         }
1408*cdf0e10cSrcweir                     }
1409*cdf0e10cSrcweir                     // it's VITAL to keep the SfxSimpleHint last! It's the base of some classes above!
1410*cdf0e10cSrcweir                     else if( pSimpleHint )
1411*cdf0e10cSrcweir                     {
1412*cdf0e10cSrcweir                         switch( pSimpleHint->GetId() )
1413*cdf0e10cSrcweir                         {
1414*cdf0e10cSrcweir                             case SFX_HINT_DYING:
1415*cdf0e10cSrcweir                                 // edit source is dying under us, become defunc then
1416*cdf0e10cSrcweir                                 try
1417*cdf0e10cSrcweir                                 {
1418*cdf0e10cSrcweir                                     // make edit source inaccessible
1419*cdf0e10cSrcweir                                     // Note: cannot destroy it here, since we're called from there!
1420*cdf0e10cSrcweir                                     ShutdownEditSource();
1421*cdf0e10cSrcweir                                 }
1422*cdf0e10cSrcweir                                 catch( const uno::Exception& ) {}
1423*cdf0e10cSrcweir 
1424*cdf0e10cSrcweir                                 break;
1425*cdf0e10cSrcweir                         }
1426*cdf0e10cSrcweir                     }
1427*cdf0e10cSrcweir                 }
1428*cdf0e10cSrcweir                 catch( const uno::Exception& )
1429*cdf0e10cSrcweir                 {
1430*cdf0e10cSrcweir #ifdef DBG_UTIL
1431*cdf0e10cSrcweir                     OSL_TRACE("AccessibleTextHelper_Impl::ProcessQueue: Unhandled exception.");
1432*cdf0e10cSrcweir #endif
1433*cdf0e10cSrcweir                 }
1434*cdf0e10cSrcweir             }
1435*cdf0e10cSrcweir         }
1436*cdf0e10cSrcweir     }
1437*cdf0e10cSrcweir 
1438*cdf0e10cSrcweir     void AccessibleTextHelper_Impl::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
1439*cdf0e10cSrcweir     {
1440*cdf0e10cSrcweir         DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
1441*cdf0e10cSrcweir 
1442*cdf0e10cSrcweir         // precondition: solar mutex locked
1443*cdf0e10cSrcweir         DBG_TESTSOLARMUTEX();
1444*cdf0e10cSrcweir 
1445*cdf0e10cSrcweir         // precondition: not in a recursion
1446*cdf0e10cSrcweir         if( mbInNotify )
1447*cdf0e10cSrcweir             return;
1448*cdf0e10cSrcweir 
1449*cdf0e10cSrcweir         mbInNotify = sal_True;
1450*cdf0e10cSrcweir 
1451*cdf0e10cSrcweir         // determine hint type
1452*cdf0e10cSrcweir         const SdrHint* pSdrHint = PTR_CAST( SdrHint, &rHint );
1453*cdf0e10cSrcweir         const SfxSimpleHint* pSimpleHint = PTR_CAST( SfxSimpleHint, &rHint );
1454*cdf0e10cSrcweir         const TextHint* pTextHint = PTR_CAST( TextHint, &rHint );
1455*cdf0e10cSrcweir         const SvxViewHint* pViewHint = PTR_CAST( SvxViewHint, &rHint );
1456*cdf0e10cSrcweir         const SvxEditSourceHint* pEditSourceHint = PTR_CAST( SvxEditSourceHint, &rHint );
1457*cdf0e10cSrcweir 
1458*cdf0e10cSrcweir         try
1459*cdf0e10cSrcweir         {
1460*cdf0e10cSrcweir             // Process notification event
1461*cdf0e10cSrcweir             if( pEditSourceHint )
1462*cdf0e10cSrcweir             {
1463*cdf0e10cSrcweir                 maEventQueue.Append( *pEditSourceHint );
1464*cdf0e10cSrcweir                 // --> OD 2005-12-19 #i27299#
1465*cdf0e10cSrcweir                 if( maEventOpenFrames == 0 )
1466*cdf0e10cSrcweir                     ProcessQueue();
1467*cdf0e10cSrcweir                 // <--
1468*cdf0e10cSrcweir             }
1469*cdf0e10cSrcweir             else if( pTextHint )
1470*cdf0e10cSrcweir             {
1471*cdf0e10cSrcweir                 switch( pTextHint->GetId() )
1472*cdf0e10cSrcweir                 {
1473*cdf0e10cSrcweir                     case TEXT_HINT_BLOCKNOTIFICATION_END:
1474*cdf0e10cSrcweir                     case TEXT_HINT_INPUT_END:
1475*cdf0e10cSrcweir                         --maEventOpenFrames;
1476*cdf0e10cSrcweir 
1477*cdf0e10cSrcweir                         if( maEventOpenFrames == 0 )
1478*cdf0e10cSrcweir                         {
1479*cdf0e10cSrcweir                             // #103483#
1480*cdf0e10cSrcweir                             /* All information should have arrived
1481*cdf0e10cSrcweir                              * now, process queue. As stated in the
1482*cdf0e10cSrcweir                              * above bug, we can often avoid throwing
1483*cdf0e10cSrcweir                              * away all paragraphs by looking forward
1484*cdf0e10cSrcweir                              * in the event queue (searching for
1485*cdf0e10cSrcweir                              * PARAINSERT/REMOVE events). Furthermore,
1486*cdf0e10cSrcweir                              * processing the event queue only at the
1487*cdf0e10cSrcweir                              * end of an interaction cycle, ensures
1488*cdf0e10cSrcweir                              * that the EditEngine state and the
1489*cdf0e10cSrcweir                              * AccessibleText state are the same
1490*cdf0e10cSrcweir                              * (well, mostly. If there are _multiple_
1491*cdf0e10cSrcweir                              * interaction cycles in the EE queues, it
1492*cdf0e10cSrcweir                              * can still happen that EE state is
1493*cdf0e10cSrcweir                              * different. That's so to say broken by
1494*cdf0e10cSrcweir                              * design with that delayed EE event
1495*cdf0e10cSrcweir                              * concept).
1496*cdf0e10cSrcweir                              */
1497*cdf0e10cSrcweir                             ProcessQueue();
1498*cdf0e10cSrcweir                         }
1499*cdf0e10cSrcweir                         break;
1500*cdf0e10cSrcweir 
1501*cdf0e10cSrcweir                     case TEXT_HINT_BLOCKNOTIFICATION_START:
1502*cdf0e10cSrcweir                     case TEXT_HINT_INPUT_START:
1503*cdf0e10cSrcweir                         ++maEventOpenFrames;
1504*cdf0e10cSrcweir                         // --> OD 2005-12-19 #i27299# - no FALLTROUGH
1505*cdf0e10cSrcweir                         // reason: event will not be processes, thus appending
1506*cdf0e10cSrcweir                         // the event isn't necessary.
1507*cdf0e10cSrcweir                         break;
1508*cdf0e10cSrcweir                         // <--
1509*cdf0e10cSrcweir                     default:
1510*cdf0e10cSrcweir                         maEventQueue.Append( *pTextHint );
1511*cdf0e10cSrcweir                         // --> OD 2005-12-19 #i27299#
1512*cdf0e10cSrcweir                         if( maEventOpenFrames == 0 )
1513*cdf0e10cSrcweir                             ProcessQueue();
1514*cdf0e10cSrcweir                         // <--
1515*cdf0e10cSrcweir                         break;
1516*cdf0e10cSrcweir                 }
1517*cdf0e10cSrcweir             }
1518*cdf0e10cSrcweir             else if( pViewHint )
1519*cdf0e10cSrcweir             {
1520*cdf0e10cSrcweir                 maEventQueue.Append( *pViewHint );
1521*cdf0e10cSrcweir 
1522*cdf0e10cSrcweir                 // process visibility right away, if not within an
1523*cdf0e10cSrcweir                 // open EE notification frame. Otherwise, event
1524*cdf0e10cSrcweir                 // processing would be delayed until next EE
1525*cdf0e10cSrcweir                 // notification sequence.
1526*cdf0e10cSrcweir                 if( maEventOpenFrames == 0 )
1527*cdf0e10cSrcweir                     ProcessQueue();
1528*cdf0e10cSrcweir             }
1529*cdf0e10cSrcweir             else if( pSdrHint )
1530*cdf0e10cSrcweir             {
1531*cdf0e10cSrcweir                 maEventQueue.Append( *pSdrHint );
1532*cdf0e10cSrcweir 
1533*cdf0e10cSrcweir                 // process drawing layer events right away, if not
1534*cdf0e10cSrcweir                 // within an open EE notification frame. Otherwise,
1535*cdf0e10cSrcweir                 // event processing would be delayed until next EE
1536*cdf0e10cSrcweir                 // notification sequence.
1537*cdf0e10cSrcweir                 if( maEventOpenFrames == 0 )
1538*cdf0e10cSrcweir                     ProcessQueue();
1539*cdf0e10cSrcweir             }
1540*cdf0e10cSrcweir             // it's VITAL to keep the SfxSimpleHint last! It's the base of some classes above!
1541*cdf0e10cSrcweir             else if( pSimpleHint )
1542*cdf0e10cSrcweir             {
1543*cdf0e10cSrcweir                 // handle this event _at once_, because after that, objects are invalid
1544*cdf0e10cSrcweir                 switch( pSimpleHint->GetId() )
1545*cdf0e10cSrcweir                 {
1546*cdf0e10cSrcweir                     case SFX_HINT_DYING:
1547*cdf0e10cSrcweir                         // edit source is dying under us, become defunc then
1548*cdf0e10cSrcweir                         maEventQueue.Clear();
1549*cdf0e10cSrcweir                         try
1550*cdf0e10cSrcweir                         {
1551*cdf0e10cSrcweir                             // make edit source inaccessible
1552*cdf0e10cSrcweir                             // Note: cannot destroy it here, since we're called from there!
1553*cdf0e10cSrcweir                             ShutdownEditSource();
1554*cdf0e10cSrcweir                         }
1555*cdf0e10cSrcweir                         catch( const uno::Exception& ) {}
1556*cdf0e10cSrcweir 
1557*cdf0e10cSrcweir                         break;
1558*cdf0e10cSrcweir                 }
1559*cdf0e10cSrcweir             }
1560*cdf0e10cSrcweir         }
1561*cdf0e10cSrcweir         catch( const uno::Exception& )
1562*cdf0e10cSrcweir         {
1563*cdf0e10cSrcweir #ifdef DBG_UTIL
1564*cdf0e10cSrcweir             OSL_TRACE("AccessibleTextHelper_Impl::Notify: Unhandled exception.");
1565*cdf0e10cSrcweir #endif
1566*cdf0e10cSrcweir             mbInNotify = sal_False;
1567*cdf0e10cSrcweir         }
1568*cdf0e10cSrcweir 
1569*cdf0e10cSrcweir         mbInNotify = sal_False;
1570*cdf0e10cSrcweir     }
1571*cdf0e10cSrcweir 
1572*cdf0e10cSrcweir     void AccessibleTextHelper_Impl::Dispose()
1573*cdf0e10cSrcweir     {
1574*cdf0e10cSrcweir         DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
1575*cdf0e10cSrcweir 
1576*cdf0e10cSrcweir         if( getNotifierClientId() != -1 )
1577*cdf0e10cSrcweir         {
1578*cdf0e10cSrcweir             try
1579*cdf0e10cSrcweir             {
1580*cdf0e10cSrcweir                 // #106234# Unregister from EventNotifier
1581*cdf0e10cSrcweir                 ::comphelper::AccessibleEventNotifier::revokeClient( getNotifierClientId() );
1582*cdf0e10cSrcweir #ifdef DBG_UTIL
1583*cdf0e10cSrcweir                 OSL_TRACE( "AccessibleTextHelper_Impl disposed ID: %d", mnNotifierClientId );
1584*cdf0e10cSrcweir #endif
1585*cdf0e10cSrcweir             }
1586*cdf0e10cSrcweir             catch( const uno::Exception& ) {}
1587*cdf0e10cSrcweir 
1588*cdf0e10cSrcweir             mnNotifierClientId = -1;
1589*cdf0e10cSrcweir         }
1590*cdf0e10cSrcweir 
1591*cdf0e10cSrcweir         try
1592*cdf0e10cSrcweir         {
1593*cdf0e10cSrcweir             // dispose children
1594*cdf0e10cSrcweir             maParaManager.Dispose();
1595*cdf0e10cSrcweir         }
1596*cdf0e10cSrcweir         catch( const uno::Exception& ) {}
1597*cdf0e10cSrcweir 
1598*cdf0e10cSrcweir         // quit listen on stale edit source
1599*cdf0e10cSrcweir         if( maEditSource.IsValid() )
1600*cdf0e10cSrcweir             EndListening( maEditSource.GetBroadcaster() );
1601*cdf0e10cSrcweir 
1602*cdf0e10cSrcweir         // clear references
1603*cdf0e10cSrcweir         maEditSource.SetEditSource( ::std::auto_ptr< SvxEditSource >(NULL) );
1604*cdf0e10cSrcweir         mxFrontEnd = NULL;
1605*cdf0e10cSrcweir     }
1606*cdf0e10cSrcweir 
1607*cdf0e10cSrcweir     void AccessibleTextHelper_Impl::FireEvent( const sal_Int16 nEventId, const uno::Any& rNewValue, const uno::Any& rOldValue ) const
1608*cdf0e10cSrcweir     {
1609*cdf0e10cSrcweir         DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
1610*cdf0e10cSrcweir 
1611*cdf0e10cSrcweir 		// -- object locked --
1612*cdf0e10cSrcweir         ::osl::ClearableMutexGuard aGuard( maMutex );
1613*cdf0e10cSrcweir 
1614*cdf0e10cSrcweir         AccessibleEventObject aEvent;
1615*cdf0e10cSrcweir 
1616*cdf0e10cSrcweir         DBG_ASSERT(mxFrontEnd.is(), "AccessibleTextHelper::FireEvent: no event source set" );
1617*cdf0e10cSrcweir 
1618*cdf0e10cSrcweir         if( mxFrontEnd.is() )
1619*cdf0e10cSrcweir             aEvent = AccessibleEventObject(mxFrontEnd->getAccessibleContext(), nEventId, rNewValue, rOldValue);
1620*cdf0e10cSrcweir         else
1621*cdf0e10cSrcweir             aEvent = AccessibleEventObject(uno::Reference< uno::XInterface >(), nEventId, rNewValue, rOldValue);
1622*cdf0e10cSrcweir 
1623*cdf0e10cSrcweir         // no locking necessary, FireEvent internally copies listeners
1624*cdf0e10cSrcweir         // if someone removes/adds in between Further locking,
1625*cdf0e10cSrcweir         // actually, might lead to deadlocks, since we're calling out
1626*cdf0e10cSrcweir         // of this object
1627*cdf0e10cSrcweir         aGuard.clear();
1628*cdf0e10cSrcweir 		// -- until here --
1629*cdf0e10cSrcweir 
1630*cdf0e10cSrcweir         FireEvent(aEvent);
1631*cdf0e10cSrcweir     }
1632*cdf0e10cSrcweir 
1633*cdf0e10cSrcweir     void AccessibleTextHelper_Impl::FireEvent( const AccessibleEventObject& rEvent ) const
1634*cdf0e10cSrcweir     {
1635*cdf0e10cSrcweir         DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
1636*cdf0e10cSrcweir 
1637*cdf0e10cSrcweir         // #102261# Call global queue for focus events
1638*cdf0e10cSrcweir         if( rEvent.EventId == AccessibleStateType::FOCUSED )
1639*cdf0e10cSrcweir             vcl::unohelper::NotifyAccessibleStateEventGlobally( rEvent );
1640*cdf0e10cSrcweir 
1641*cdf0e10cSrcweir         // #106234# Delegate to EventNotifier
1642*cdf0e10cSrcweir         ::comphelper::AccessibleEventNotifier::addEvent( getNotifierClientId(),
1643*cdf0e10cSrcweir                                                          rEvent );
1644*cdf0e10cSrcweir     }
1645*cdf0e10cSrcweir 
1646*cdf0e10cSrcweir 	// XAccessibleContext
1647*cdf0e10cSrcweir     sal_Int32 SAL_CALL AccessibleTextHelper_Impl::getAccessibleChildCount() SAL_THROW((uno::RuntimeException))
1648*cdf0e10cSrcweir     {
1649*cdf0e10cSrcweir         DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
1650*cdf0e10cSrcweir 
1651*cdf0e10cSrcweir         return mnLastVisibleChild - mnFirstVisibleChild + 1;
1652*cdf0e10cSrcweir     }
1653*cdf0e10cSrcweir 
1654*cdf0e10cSrcweir     uno::Reference< XAccessible > SAL_CALL AccessibleTextHelper_Impl::getAccessibleChild( sal_Int32 i ) SAL_THROW((lang::IndexOutOfBoundsException, uno::RuntimeException))
1655*cdf0e10cSrcweir     {
1656*cdf0e10cSrcweir         DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
1657*cdf0e10cSrcweir 
1658*cdf0e10cSrcweir         i -= GetStartIndex();
1659*cdf0e10cSrcweir 
1660*cdf0e10cSrcweir         if( 0 > i || i >= getAccessibleChildCount() ||
1661*cdf0e10cSrcweir             GetTextForwarder().GetParagraphCount() <= i )
1662*cdf0e10cSrcweir         {
1663*cdf0e10cSrcweir             throw lang::IndexOutOfBoundsException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Invalid child index")), mxFrontEnd);
1664*cdf0e10cSrcweir         }
1665*cdf0e10cSrcweir 
1666*cdf0e10cSrcweir         DBG_ASSERT(mxFrontEnd.is(), "AccessibleTextHelper_Impl::UpdateVisibleChildren: no frontend set");
1667*cdf0e10cSrcweir 
1668*cdf0e10cSrcweir         if( mxFrontEnd.is() )
1669*cdf0e10cSrcweir             return maParaManager.CreateChild( i, mxFrontEnd, GetEditSource(), mnFirstVisibleChild + i ).first;
1670*cdf0e10cSrcweir         else
1671*cdf0e10cSrcweir             return NULL;
1672*cdf0e10cSrcweir     }
1673*cdf0e10cSrcweir 
1674*cdf0e10cSrcweir     void SAL_CALL AccessibleTextHelper_Impl::addEventListener( const uno::Reference< XAccessibleEventListener >& xListener ) SAL_THROW((uno::RuntimeException))
1675*cdf0e10cSrcweir     {
1676*cdf0e10cSrcweir         DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
1677*cdf0e10cSrcweir 
1678*cdf0e10cSrcweir         if( getNotifierClientId() != -1 )
1679*cdf0e10cSrcweir             ::comphelper::AccessibleEventNotifier::addEventListener( getNotifierClientId(), xListener );
1680*cdf0e10cSrcweir     }
1681*cdf0e10cSrcweir 
1682*cdf0e10cSrcweir     void SAL_CALL AccessibleTextHelper_Impl::removeEventListener( const uno::Reference< XAccessibleEventListener >& xListener ) SAL_THROW((uno::RuntimeException))
1683*cdf0e10cSrcweir     {
1684*cdf0e10cSrcweir         DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
1685*cdf0e10cSrcweir 
1686*cdf0e10cSrcweir         if( getNotifierClientId() != -1 )
1687*cdf0e10cSrcweir             ::comphelper::AccessibleEventNotifier::removeEventListener( getNotifierClientId(), xListener );
1688*cdf0e10cSrcweir     }
1689*cdf0e10cSrcweir 
1690*cdf0e10cSrcweir     uno::Reference< XAccessible > SAL_CALL AccessibleTextHelper_Impl::getAccessibleAtPoint( const awt::Point& _aPoint ) SAL_THROW((uno::RuntimeException))
1691*cdf0e10cSrcweir     {
1692*cdf0e10cSrcweir         DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
1693*cdf0e10cSrcweir 
1694*cdf0e10cSrcweir         // make given position relative
1695*cdf0e10cSrcweir         if( !mxFrontEnd.is() )
1696*cdf0e10cSrcweir             throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AccessibleTextHelper_Impl::getAccessibleAt: frontend invalid")), mxFrontEnd );
1697*cdf0e10cSrcweir 
1698*cdf0e10cSrcweir         uno::Reference< XAccessibleContext > xFrontEndContext = mxFrontEnd->getAccessibleContext();
1699*cdf0e10cSrcweir 
1700*cdf0e10cSrcweir         if( !xFrontEndContext.is() )
1701*cdf0e10cSrcweir             throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AccessibleTextHelper_Impl::getAccessibleAt: frontend invalid")), mxFrontEnd );
1702*cdf0e10cSrcweir 
1703*cdf0e10cSrcweir         uno::Reference< XAccessibleComponent > xFrontEndComponent( xFrontEndContext, uno::UNO_QUERY );
1704*cdf0e10cSrcweir 
1705*cdf0e10cSrcweir         if( !xFrontEndComponent.is() )
1706*cdf0e10cSrcweir             throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AccessibleTextHelper_Impl::getAccessibleAt: frontend is no XAccessibleComponent")),
1707*cdf0e10cSrcweir                                         mxFrontEnd );
1708*cdf0e10cSrcweir 
1709*cdf0e10cSrcweir         // #103862# No longer need to make given position relative
1710*cdf0e10cSrcweir         Point aPoint( _aPoint.X, _aPoint.Y );
1711*cdf0e10cSrcweir 
1712*cdf0e10cSrcweir         // respect EditEngine offset to surrounding shape/cell
1713*cdf0e10cSrcweir         aPoint -= GetOffset();
1714*cdf0e10cSrcweir 
1715*cdf0e10cSrcweir         // convert to EditEngine coordinate system
1716*cdf0e10cSrcweir         SvxTextForwarder& rCacheTF = GetTextForwarder();
1717*cdf0e10cSrcweir         Point aLogPoint( GetViewForwarder().PixelToLogic( aPoint, rCacheTF.GetMapMode() ) );
1718*cdf0e10cSrcweir 
1719*cdf0e10cSrcweir         // iterate over all visible children (including those not yet created)
1720*cdf0e10cSrcweir         sal_Int32 nChild;
1721*cdf0e10cSrcweir         for( nChild=mnFirstVisibleChild; nChild <= mnLastVisibleChild; ++nChild )
1722*cdf0e10cSrcweir         {
1723*cdf0e10cSrcweir             DBG_ASSERT(nChild >= 0 && nChild <= USHRT_MAX,
1724*cdf0e10cSrcweir                        "AccessibleTextHelper_Impl::getAccessibleAt: index value overflow");
1725*cdf0e10cSrcweir 
1726*cdf0e10cSrcweir             Rectangle aParaBounds( rCacheTF.GetParaBounds( static_cast< sal_uInt16 > (nChild) ) );
1727*cdf0e10cSrcweir 
1728*cdf0e10cSrcweir             if( aParaBounds.IsInside( aLogPoint ) )
1729*cdf0e10cSrcweir                 return getAccessibleChild( nChild - mnFirstVisibleChild + GetStartIndex() );
1730*cdf0e10cSrcweir         }
1731*cdf0e10cSrcweir 
1732*cdf0e10cSrcweir         // found none
1733*cdf0e10cSrcweir         return NULL;
1734*cdf0e10cSrcweir     }
1735*cdf0e10cSrcweir 
1736*cdf0e10cSrcweir 	//------------------------------------------------------------------------
1737*cdf0e10cSrcweir 	//
1738*cdf0e10cSrcweir 	// AccessibleTextHelper implementation (simply forwards to impl)
1739*cdf0e10cSrcweir 	//
1740*cdf0e10cSrcweir 	//------------------------------------------------------------------------
1741*cdf0e10cSrcweir 
1742*cdf0e10cSrcweir     AccessibleTextHelper::AccessibleTextHelper( ::std::auto_ptr< SvxEditSource > pEditSource ) :
1743*cdf0e10cSrcweir         mpImpl( new AccessibleTextHelper_Impl() )
1744*cdf0e10cSrcweir     {
1745*cdf0e10cSrcweir         ::vos::OGuard aGuard( Application::GetSolarMutex() );
1746*cdf0e10cSrcweir 
1747*cdf0e10cSrcweir         SetEditSource( pEditSource );
1748*cdf0e10cSrcweir     }
1749*cdf0e10cSrcweir 
1750*cdf0e10cSrcweir     AccessibleTextHelper::~AccessibleTextHelper()
1751*cdf0e10cSrcweir     {
1752*cdf0e10cSrcweir     }
1753*cdf0e10cSrcweir 
1754*cdf0e10cSrcweir     const SvxEditSource& AccessibleTextHelper::GetEditSource() const SAL_THROW((uno::RuntimeException))
1755*cdf0e10cSrcweir     {
1756*cdf0e10cSrcweir #ifdef DBG_UTIL
1757*cdf0e10cSrcweir         mpImpl->CheckInvariants();
1758*cdf0e10cSrcweir 
1759*cdf0e10cSrcweir         const SvxEditSource& aEditSource = mpImpl->GetEditSource();
1760*cdf0e10cSrcweir 
1761*cdf0e10cSrcweir         mpImpl->CheckInvariants();
1762*cdf0e10cSrcweir 
1763*cdf0e10cSrcweir         return aEditSource;
1764*cdf0e10cSrcweir #else
1765*cdf0e10cSrcweir         return mpImpl->GetEditSource();
1766*cdf0e10cSrcweir #endif
1767*cdf0e10cSrcweir     }
1768*cdf0e10cSrcweir 
1769*cdf0e10cSrcweir     void AccessibleTextHelper::SetEditSource( ::std::auto_ptr< SvxEditSource > pEditSource ) SAL_THROW((uno::RuntimeException))
1770*cdf0e10cSrcweir     {
1771*cdf0e10cSrcweir #ifdef DBG_UTIL
1772*cdf0e10cSrcweir         // precondition: solar mutex locked
1773*cdf0e10cSrcweir         DBG_TESTSOLARMUTEX();
1774*cdf0e10cSrcweir 
1775*cdf0e10cSrcweir         mpImpl->CheckInvariants();
1776*cdf0e10cSrcweir #endif
1777*cdf0e10cSrcweir 
1778*cdf0e10cSrcweir         mpImpl->SetEditSource( pEditSource );
1779*cdf0e10cSrcweir 
1780*cdf0e10cSrcweir #ifdef DBG_UTIL
1781*cdf0e10cSrcweir         mpImpl->CheckInvariants();
1782*cdf0e10cSrcweir #endif
1783*cdf0e10cSrcweir     }
1784*cdf0e10cSrcweir 
1785*cdf0e10cSrcweir     void AccessibleTextHelper::SetEventSource( const uno::Reference< XAccessible >& rInterface )
1786*cdf0e10cSrcweir     {
1787*cdf0e10cSrcweir #ifdef DBG_UTIL
1788*cdf0e10cSrcweir         mpImpl->CheckInvariants();
1789*cdf0e10cSrcweir #endif
1790*cdf0e10cSrcweir 
1791*cdf0e10cSrcweir         mpImpl->SetEventSource( rInterface );
1792*cdf0e10cSrcweir 
1793*cdf0e10cSrcweir #ifdef DBG_UTIL
1794*cdf0e10cSrcweir         mpImpl->CheckInvariants();
1795*cdf0e10cSrcweir #endif
1796*cdf0e10cSrcweir     }
1797*cdf0e10cSrcweir 
1798*cdf0e10cSrcweir     uno::Reference< XAccessible > AccessibleTextHelper::GetEventSource() const
1799*cdf0e10cSrcweir     {
1800*cdf0e10cSrcweir #ifdef DBG_UTIL
1801*cdf0e10cSrcweir         mpImpl->CheckInvariants();
1802*cdf0e10cSrcweir 
1803*cdf0e10cSrcweir         uno::Reference< XAccessible > xRet( mpImpl->GetEventSource() );
1804*cdf0e10cSrcweir 
1805*cdf0e10cSrcweir         mpImpl->CheckInvariants();
1806*cdf0e10cSrcweir 
1807*cdf0e10cSrcweir         return xRet;
1808*cdf0e10cSrcweir #else
1809*cdf0e10cSrcweir         return mpImpl->GetEventSource();
1810*cdf0e10cSrcweir #endif
1811*cdf0e10cSrcweir     }
1812*cdf0e10cSrcweir 
1813*cdf0e10cSrcweir     void AccessibleTextHelper::SetFocus( sal_Bool bHaveFocus ) SAL_THROW((::com::sun::star::uno::RuntimeException))
1814*cdf0e10cSrcweir     {
1815*cdf0e10cSrcweir #ifdef DBG_UTIL
1816*cdf0e10cSrcweir         // precondition: solar mutex locked
1817*cdf0e10cSrcweir         DBG_TESTSOLARMUTEX();
1818*cdf0e10cSrcweir 
1819*cdf0e10cSrcweir         mpImpl->CheckInvariants();
1820*cdf0e10cSrcweir #endif
1821*cdf0e10cSrcweir 
1822*cdf0e10cSrcweir         mpImpl->SetFocus( bHaveFocus );
1823*cdf0e10cSrcweir 
1824*cdf0e10cSrcweir #ifdef DBG_UTIL
1825*cdf0e10cSrcweir         mpImpl->CheckInvariants();
1826*cdf0e10cSrcweir #endif
1827*cdf0e10cSrcweir     }
1828*cdf0e10cSrcweir 
1829*cdf0e10cSrcweir     sal_Bool AccessibleTextHelper::HaveFocus() SAL_THROW((::com::sun::star::uno::RuntimeException))
1830*cdf0e10cSrcweir     {
1831*cdf0e10cSrcweir #ifdef DBG_UTIL
1832*cdf0e10cSrcweir         mpImpl->CheckInvariants();
1833*cdf0e10cSrcweir 
1834*cdf0e10cSrcweir         sal_Bool bRet( mpImpl->HaveFocus() );
1835*cdf0e10cSrcweir 
1836*cdf0e10cSrcweir         mpImpl->CheckInvariants();
1837*cdf0e10cSrcweir 
1838*cdf0e10cSrcweir         return bRet;
1839*cdf0e10cSrcweir #else
1840*cdf0e10cSrcweir         return mpImpl->HaveFocus();
1841*cdf0e10cSrcweir #endif
1842*cdf0e10cSrcweir     }
1843*cdf0e10cSrcweir 
1844*cdf0e10cSrcweir     void AccessibleTextHelper::FireEvent( const sal_Int16 nEventId, const uno::Any& rNewValue, const uno::Any& rOldValue ) const
1845*cdf0e10cSrcweir     {
1846*cdf0e10cSrcweir #ifdef DBG_UTIL
1847*cdf0e10cSrcweir         mpImpl->CheckInvariants();
1848*cdf0e10cSrcweir #endif
1849*cdf0e10cSrcweir 
1850*cdf0e10cSrcweir         mpImpl->FireEvent( nEventId, rNewValue, rOldValue );
1851*cdf0e10cSrcweir 
1852*cdf0e10cSrcweir #ifdef DBG_UTIL
1853*cdf0e10cSrcweir         mpImpl->CheckInvariants();
1854*cdf0e10cSrcweir #endif
1855*cdf0e10cSrcweir     }
1856*cdf0e10cSrcweir 
1857*cdf0e10cSrcweir     void AccessibleTextHelper::FireEvent( const AccessibleEventObject& rEvent ) const
1858*cdf0e10cSrcweir     {
1859*cdf0e10cSrcweir #ifdef DBG_UTIL
1860*cdf0e10cSrcweir         mpImpl->CheckInvariants();
1861*cdf0e10cSrcweir #endif
1862*cdf0e10cSrcweir 
1863*cdf0e10cSrcweir         mpImpl->FireEvent( rEvent );
1864*cdf0e10cSrcweir 
1865*cdf0e10cSrcweir #ifdef DBG_UTIL
1866*cdf0e10cSrcweir         mpImpl->CheckInvariants();
1867*cdf0e10cSrcweir #endif
1868*cdf0e10cSrcweir     }
1869*cdf0e10cSrcweir 
1870*cdf0e10cSrcweir     void AccessibleTextHelper::SetOffset( const Point& rPoint )
1871*cdf0e10cSrcweir     {
1872*cdf0e10cSrcweir #ifdef DBG_UTIL
1873*cdf0e10cSrcweir         // precondition: solar mutex locked
1874*cdf0e10cSrcweir         DBG_TESTSOLARMUTEX();
1875*cdf0e10cSrcweir 
1876*cdf0e10cSrcweir         mpImpl->CheckInvariants();
1877*cdf0e10cSrcweir #endif
1878*cdf0e10cSrcweir 
1879*cdf0e10cSrcweir         mpImpl->SetOffset( rPoint );
1880*cdf0e10cSrcweir 
1881*cdf0e10cSrcweir #ifdef DBG_UTIL
1882*cdf0e10cSrcweir         mpImpl->CheckInvariants();
1883*cdf0e10cSrcweir #endif
1884*cdf0e10cSrcweir     }
1885*cdf0e10cSrcweir 
1886*cdf0e10cSrcweir     Point AccessibleTextHelper::GetOffset() const
1887*cdf0e10cSrcweir     {
1888*cdf0e10cSrcweir #ifdef DBG_UTIL
1889*cdf0e10cSrcweir         mpImpl->CheckInvariants();
1890*cdf0e10cSrcweir 
1891*cdf0e10cSrcweir         Point aPoint( mpImpl->GetOffset() );
1892*cdf0e10cSrcweir 
1893*cdf0e10cSrcweir         mpImpl->CheckInvariants();
1894*cdf0e10cSrcweir 
1895*cdf0e10cSrcweir         return aPoint;
1896*cdf0e10cSrcweir #else
1897*cdf0e10cSrcweir         return mpImpl->GetOffset();
1898*cdf0e10cSrcweir #endif
1899*cdf0e10cSrcweir     }
1900*cdf0e10cSrcweir 
1901*cdf0e10cSrcweir     void AccessibleTextHelper::SetStartIndex( sal_Int32 nOffset )
1902*cdf0e10cSrcweir     {
1903*cdf0e10cSrcweir #ifdef DBG_UTIL
1904*cdf0e10cSrcweir         // precondition: solar mutex locked
1905*cdf0e10cSrcweir         DBG_TESTSOLARMUTEX();
1906*cdf0e10cSrcweir 
1907*cdf0e10cSrcweir         mpImpl->CheckInvariants();
1908*cdf0e10cSrcweir #endif
1909*cdf0e10cSrcweir 
1910*cdf0e10cSrcweir         mpImpl->SetStartIndex( nOffset );
1911*cdf0e10cSrcweir 
1912*cdf0e10cSrcweir #ifdef DBG_UTIL
1913*cdf0e10cSrcweir         mpImpl->CheckInvariants();
1914*cdf0e10cSrcweir #endif
1915*cdf0e10cSrcweir     }
1916*cdf0e10cSrcweir 
1917*cdf0e10cSrcweir     sal_Int32 AccessibleTextHelper::GetStartIndex() const
1918*cdf0e10cSrcweir     {
1919*cdf0e10cSrcweir #ifdef DBG_UTIL
1920*cdf0e10cSrcweir         mpImpl->CheckInvariants();
1921*cdf0e10cSrcweir 
1922*cdf0e10cSrcweir         sal_Int32 nOffset = mpImpl->GetStartIndex();
1923*cdf0e10cSrcweir 
1924*cdf0e10cSrcweir         mpImpl->CheckInvariants();
1925*cdf0e10cSrcweir 
1926*cdf0e10cSrcweir         return nOffset;
1927*cdf0e10cSrcweir #else
1928*cdf0e10cSrcweir         return mpImpl->GetStartIndex();
1929*cdf0e10cSrcweir #endif
1930*cdf0e10cSrcweir     }
1931*cdf0e10cSrcweir 
1932*cdf0e10cSrcweir     void AccessibleTextHelper::SetAdditionalChildStates( const VectorOfStates& rChildStates )
1933*cdf0e10cSrcweir     {
1934*cdf0e10cSrcweir         mpImpl->SetAdditionalChildStates( rChildStates );
1935*cdf0e10cSrcweir     }
1936*cdf0e10cSrcweir 
1937*cdf0e10cSrcweir     const AccessibleTextHelper::VectorOfStates& AccessibleTextHelper::GetAdditionalChildStates() const
1938*cdf0e10cSrcweir     {
1939*cdf0e10cSrcweir         return mpImpl->GetAdditionalChildStates();
1940*cdf0e10cSrcweir     }
1941*cdf0e10cSrcweir 
1942*cdf0e10cSrcweir     void AccessibleTextHelper::UpdateChildren() SAL_THROW((::com::sun::star::uno::RuntimeException))
1943*cdf0e10cSrcweir     {
1944*cdf0e10cSrcweir #ifdef DBG_UTIL
1945*cdf0e10cSrcweir         // precondition: solar mutex locked
1946*cdf0e10cSrcweir         DBG_TESTSOLARMUTEX();
1947*cdf0e10cSrcweir 
1948*cdf0e10cSrcweir         mpImpl->CheckInvariants();
1949*cdf0e10cSrcweir #endif
1950*cdf0e10cSrcweir 
1951*cdf0e10cSrcweir         mpImpl->UpdateVisibleChildren();
1952*cdf0e10cSrcweir         mpImpl->UpdateBoundRect();
1953*cdf0e10cSrcweir 
1954*cdf0e10cSrcweir         mpImpl->UpdateSelection();
1955*cdf0e10cSrcweir 
1956*cdf0e10cSrcweir #ifdef DBG_UTIL
1957*cdf0e10cSrcweir         mpImpl->CheckInvariants();
1958*cdf0e10cSrcweir #endif
1959*cdf0e10cSrcweir     }
1960*cdf0e10cSrcweir 
1961*cdf0e10cSrcweir     void AccessibleTextHelper::Dispose()
1962*cdf0e10cSrcweir     {
1963*cdf0e10cSrcweir         // As Dispose calls ShutdownEditSource, which in turn
1964*cdf0e10cSrcweir         // deregisters as listener on the edit source, have to lock
1965*cdf0e10cSrcweir         // here
1966*cdf0e10cSrcweir         ::vos::OGuard aGuard( Application::GetSolarMutex() );
1967*cdf0e10cSrcweir 
1968*cdf0e10cSrcweir #ifdef DBG_UTIL
1969*cdf0e10cSrcweir         mpImpl->CheckInvariants();
1970*cdf0e10cSrcweir #endif
1971*cdf0e10cSrcweir 
1972*cdf0e10cSrcweir         mpImpl->Dispose();
1973*cdf0e10cSrcweir 
1974*cdf0e10cSrcweir #ifdef DBG_UTIL
1975*cdf0e10cSrcweir         mpImpl->CheckInvariants();
1976*cdf0e10cSrcweir #endif
1977*cdf0e10cSrcweir     }
1978*cdf0e10cSrcweir 
1979*cdf0e10cSrcweir     sal_Bool AccessibleTextHelper::IsSelected() const
1980*cdf0e10cSrcweir     {
1981*cdf0e10cSrcweir         ::vos::OGuard aGuard( Application::GetSolarMutex() );
1982*cdf0e10cSrcweir 
1983*cdf0e10cSrcweir #ifdef DBG_UTIL
1984*cdf0e10cSrcweir         mpImpl->CheckInvariants();
1985*cdf0e10cSrcweir 
1986*cdf0e10cSrcweir         sal_Bool aRet = mpImpl->IsSelected();
1987*cdf0e10cSrcweir 
1988*cdf0e10cSrcweir         mpImpl->CheckInvariants();
1989*cdf0e10cSrcweir 
1990*cdf0e10cSrcweir         return aRet;
1991*cdf0e10cSrcweir #else
1992*cdf0e10cSrcweir         return mpImpl->IsSelected();
1993*cdf0e10cSrcweir #endif
1994*cdf0e10cSrcweir     }
1995*cdf0e10cSrcweir 
1996*cdf0e10cSrcweir 	// XAccessibleContext
1997*cdf0e10cSrcweir     sal_Int32 AccessibleTextHelper::GetChildCount() SAL_THROW((uno::RuntimeException))
1998*cdf0e10cSrcweir     {
1999*cdf0e10cSrcweir         ::vos::OGuard aGuard( Application::GetSolarMutex() );
2000*cdf0e10cSrcweir 
2001*cdf0e10cSrcweir #ifdef DBG_UTIL
2002*cdf0e10cSrcweir         mpImpl->CheckInvariants();
2003*cdf0e10cSrcweir 
2004*cdf0e10cSrcweir         sal_Int32 nRet = mpImpl->getAccessibleChildCount();
2005*cdf0e10cSrcweir 
2006*cdf0e10cSrcweir         mpImpl->CheckInvariants();
2007*cdf0e10cSrcweir 
2008*cdf0e10cSrcweir         return nRet;
2009*cdf0e10cSrcweir #else
2010*cdf0e10cSrcweir         return mpImpl->getAccessibleChildCount();
2011*cdf0e10cSrcweir #endif
2012*cdf0e10cSrcweir     }
2013*cdf0e10cSrcweir 
2014*cdf0e10cSrcweir     uno::Reference< XAccessible > AccessibleTextHelper::GetChild( sal_Int32 i ) SAL_THROW((lang::IndexOutOfBoundsException, uno::RuntimeException))
2015*cdf0e10cSrcweir     {
2016*cdf0e10cSrcweir         ::vos::OGuard aGuard( Application::GetSolarMutex() );
2017*cdf0e10cSrcweir 
2018*cdf0e10cSrcweir #ifdef DBG_UTIL
2019*cdf0e10cSrcweir         mpImpl->CheckInvariants();
2020*cdf0e10cSrcweir 
2021*cdf0e10cSrcweir         uno::Reference< XAccessible > xRet = mpImpl->getAccessibleChild( i );
2022*cdf0e10cSrcweir 
2023*cdf0e10cSrcweir         mpImpl->CheckInvariants();
2024*cdf0e10cSrcweir 
2025*cdf0e10cSrcweir         return xRet;
2026*cdf0e10cSrcweir #else
2027*cdf0e10cSrcweir         return mpImpl->getAccessibleChild( i );
2028*cdf0e10cSrcweir #endif
2029*cdf0e10cSrcweir     }
2030*cdf0e10cSrcweir 
2031*cdf0e10cSrcweir     void AccessibleTextHelper::AddEventListener( const uno::Reference< XAccessibleEventListener >& xListener ) SAL_THROW((uno::RuntimeException))
2032*cdf0e10cSrcweir     {
2033*cdf0e10cSrcweir #ifdef DBG_UTIL
2034*cdf0e10cSrcweir         mpImpl->CheckInvariants();
2035*cdf0e10cSrcweir 
2036*cdf0e10cSrcweir         mpImpl->addEventListener( xListener );
2037*cdf0e10cSrcweir 
2038*cdf0e10cSrcweir         mpImpl->CheckInvariants();
2039*cdf0e10cSrcweir #else
2040*cdf0e10cSrcweir         mpImpl->addEventListener( xListener );
2041*cdf0e10cSrcweir #endif
2042*cdf0e10cSrcweir     }
2043*cdf0e10cSrcweir 
2044*cdf0e10cSrcweir     void AccessibleTextHelper::RemoveEventListener( const uno::Reference< XAccessibleEventListener >& xListener ) SAL_THROW((uno::RuntimeException))
2045*cdf0e10cSrcweir     {
2046*cdf0e10cSrcweir #ifdef DBG_UTIL
2047*cdf0e10cSrcweir         mpImpl->CheckInvariants();
2048*cdf0e10cSrcweir 
2049*cdf0e10cSrcweir         mpImpl->removeEventListener( xListener );
2050*cdf0e10cSrcweir 
2051*cdf0e10cSrcweir         mpImpl->CheckInvariants();
2052*cdf0e10cSrcweir #else
2053*cdf0e10cSrcweir         mpImpl->removeEventListener( xListener );
2054*cdf0e10cSrcweir #endif
2055*cdf0e10cSrcweir     }
2056*cdf0e10cSrcweir 
2057*cdf0e10cSrcweir 	// XAccessibleComponent
2058*cdf0e10cSrcweir     uno::Reference< XAccessible > AccessibleTextHelper::GetAt( const awt::Point& aPoint ) SAL_THROW((uno::RuntimeException))
2059*cdf0e10cSrcweir     {
2060*cdf0e10cSrcweir         ::vos::OGuard aGuard( Application::GetSolarMutex() );
2061*cdf0e10cSrcweir 
2062*cdf0e10cSrcweir #ifdef DBG_UTIL
2063*cdf0e10cSrcweir         mpImpl->CheckInvariants();
2064*cdf0e10cSrcweir 
2065*cdf0e10cSrcweir         uno::Reference< XAccessible > xChild = mpImpl->getAccessibleAtPoint( aPoint );
2066*cdf0e10cSrcweir 
2067*cdf0e10cSrcweir         mpImpl->CheckInvariants();
2068*cdf0e10cSrcweir 
2069*cdf0e10cSrcweir         return xChild;
2070*cdf0e10cSrcweir #else
2071*cdf0e10cSrcweir         return mpImpl->getAccessibleAtPoint( aPoint );
2072*cdf0e10cSrcweir #endif
2073*cdf0e10cSrcweir     }
2074*cdf0e10cSrcweir 
2075*cdf0e10cSrcweir } // end of namespace accessibility
2076*cdf0e10cSrcweir 
2077*cdf0e10cSrcweir //------------------------------------------------------------------------
2078