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