xref: /aoo41x/main/sw/source/core/access/accmap.cxx (revision efeef26f)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sw.hxx"
26 
27 
28 #include <vos/ref.hxx>
29 #include <cppuhelper/weakref.hxx>
30 #include <vcl/window.hxx>
31 #include <svx/svdmodel.hxx>
32 #include <svx/unomod.hxx>
33 #include <tools/debug.hxx>
34 
35 #include <map>
36 #include <list>
37 #include <accmap.hxx>
38 #include <acccontext.hxx>
39 #include <accdoc.hxx>
40 #include <accpreview.hxx>
41 #include <accpage.hxx>
42 #include <accpara.hxx>
43 #include <accheaderfooter.hxx>
44 #include <accfootnote.hxx>
45 #include <acctextframe.hxx>
46 #include <accgraphic.hxx>
47 #include <accembedded.hxx>
48 #include <acccell.hxx>
49 #include <acctable.hxx>
50 #include <fesh.hxx>
51 #include <rootfrm.hxx>
52 #include <txtfrm.hxx>
53 #include <hffrm.hxx>
54 #include <ftnfrm.hxx>
55 #include <cellfrm.hxx>
56 #include <tabfrm.hxx>
57 #include <pagefrm.hxx>
58 #include <flyfrm.hxx>
59 #include <ndtyp.hxx>
60 #include <IDocumentDrawModelAccess.hxx>
61 #include <svx/ShapeTypeHandler.hxx>
62 #include <vcl/svapp.hxx>
63 #include <com/sun/star/accessibility/AccessibleRelationType.hpp>
64 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
65 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
66 #include <cppuhelper/implbase1.hxx>
67 #include <pagepreviewlayout.hxx>
68 #include <pam.hxx>
69 #include <ndtxt.hxx>
70 #include <dflyobj.hxx>
71 #include <prevwpage.hxx>
72 #include <switerator.hxx>
73 
74 using namespace ::com::sun::star;
75 using namespace ::com::sun::star::accessibility;
76 using ::rtl::OUString;
77 using namespace ::sw::access;
78 
79 struct SwFrmFunc
80 {
81 	sal_Bool operator()( const SwFrm * p1,
82 				    	 const SwFrm * p2) const
83 	{
84 		return p1 < p2;
85 	}
86 };
87 
88 typedef ::std::map < const SwFrm *, uno::WeakReference < XAccessible >, SwFrmFunc > _SwAccessibleContextMap_Impl;
89 
90 class SwAccessibleContextMap_Impl: public _SwAccessibleContextMap_Impl
91 {
92 public:
93 
94 #ifdef DBG_UTIL
95 	sal_Bool mbLocked;
96 #endif
97 
98 	SwAccessibleContextMap_Impl()
99 #ifdef DBG_UTIL
100 		: mbLocked( sal_False )
101 #endif
102 	{}
103 
104 };
105 
106 //------------------------------------------------------------------------------
107 class SwDrawModellListener_Impl : public SfxListener,
108 	public ::cppu::WeakImplHelper1< document::XEventBroadcaster >
109 {
110 	mutable ::osl::Mutex maListenerMutex;
111 	::cppu::OInterfaceContainerHelper maEventListeners;
112 	SdrModel *mpDrawModel;
113 protected:
114 	virtual ~SwDrawModellListener_Impl();
115 public:
116 
117 	SwDrawModellListener_Impl( SdrModel *pDrawModel );
118 
119 
120     virtual void SAL_CALL addEventListener( const uno::Reference< document::XEventListener >& xListener ) throw (uno::RuntimeException);
121     virtual void SAL_CALL removeEventListener( const uno::Reference< document::XEventListener >& xListener ) throw (uno::RuntimeException);
122 
123 	virtual void		Notify( SfxBroadcaster& rBC, const SfxHint& rHint );
124 	void Dispose();
125 };
126 
127 SwDrawModellListener_Impl::SwDrawModellListener_Impl( SdrModel *pDrawModel ) :
128 	maEventListeners( maListenerMutex ),
129 	mpDrawModel( pDrawModel )
130 {
131 	StartListening( *mpDrawModel );
132 }
133 
134 SwDrawModellListener_Impl::~SwDrawModellListener_Impl()
135 {
136 	EndListening( *mpDrawModel );
137 }
138 
139 void SAL_CALL SwDrawModellListener_Impl::addEventListener( const uno::Reference< document::XEventListener >& xListener ) throw (uno::RuntimeException)
140 {
141 	maEventListeners.addInterface( xListener );
142 }
143 
144 void SAL_CALL SwDrawModellListener_Impl::removeEventListener( const uno::Reference< document::XEventListener >& xListener ) throw (uno::RuntimeException)
145 {
146 	maEventListeners.removeInterface( xListener );
147 }
148 
149 void SwDrawModellListener_Impl::Notify( SfxBroadcaster& /*rBC*/,
150 		const SfxHint& rHint )
151 {
152 	// do not broadcast notifications for writer fly frames, because there
153 	// are no shapes that need to know about them.
154     // OD 01.07.2003 #110554# - correct condition in order not to broadcast
155     // notifications for writer fly frames.
156     // OD 01.07.2003 #110554# - do not broadcast notifications for plane
157     // <SdrObject>objects
158 	const SdrHint *pSdrHint = PTR_CAST( SdrHint, &rHint );
159     if ( !pSdrHint ||
160          ( pSdrHint->GetObject() &&
161            ( pSdrHint->GetObject()->ISA(SwFlyDrawObj) ||
162              pSdrHint->GetObject()->ISA(SwVirtFlyDrawObj) ||
163              IS_TYPE(SdrObject,pSdrHint->GetObject()) ) ) )
164     {
165         return;
166     }
167 
168 	ASSERT( mpDrawModel, "draw model listener is disposed" );
169 	if( !mpDrawModel )
170 		return;
171 
172 	document::EventObject aEvent;
173 	if( !SvxUnoDrawMSFactory::createEvent( mpDrawModel, pSdrHint, aEvent ) )
174 		return;
175 
176 	::cppu::OInterfaceIteratorHelper aIter( maEventListeners );
177 	while( aIter.hasMoreElements() )
178 	{
179 		uno::Reference < document::XEventListener > xListener( aIter.next(),
180 												uno::UNO_QUERY );
181 		try
182 		{
183 			xListener->notifyEvent( aEvent );
184 		}
185 		catch( uno::RuntimeException const & r )
186 		{
187             (void)r;
188 #if OSL_DEBUG_LEVEL > 1
189 			ByteString aError( "Runtime exception caught while notifying shape.:\n" );
190 			aError += ByteString( String( r.Message), RTL_TEXTENCODING_ASCII_US );
191 			DBG_ERROR( aError.GetBuffer() );
192 #endif
193 		}
194 	}
195 }
196 
197 void SwDrawModellListener_Impl::Dispose()
198 {
199 	mpDrawModel = 0;
200 }
201 
202 //------------------------------------------------------------------------------
203 struct SwShapeFunc
204 {
205 	sal_Bool operator()( const SdrObject * p1,
206 				    	 const SdrObject * p2) const
207 	{
208 		return p1 < p2;
209 	}
210 };
211 typedef ::std::map < const SdrObject *, uno::WeakReference < XAccessible >, SwShapeFunc > _SwAccessibleShapeMap_Impl;
212 typedef ::std::pair < const SdrObject *, ::vos::ORef < ::accessibility::AccessibleShape > > SwAccessibleObjShape_Impl;
213 
214 class SwAccessibleShapeMap_Impl: public _SwAccessibleShapeMap_Impl
215 
216 {
217 	::accessibility::AccessibleShapeTreeInfo maInfo;
218 
219 public:
220 
221 #ifdef DBG_UTIL
222 	sal_Bool mbLocked;
223 #endif
224 	SwAccessibleShapeMap_Impl( SwAccessibleMap *pMap )
225 #ifdef DBG_UTIL
226 		: mbLocked( sal_False )
227 #endif
228 	{
229 		maInfo.SetSdrView( pMap->GetShell()->GetDrawView() );
230 		maInfo.SetWindow( pMap->GetShell()->GetWin() );
231 		maInfo.SetViewForwarder( pMap );
232         // --> OD 2005-08-08 #i52858# - method name changed
233 		uno::Reference < document::XEventBroadcaster > xModelBroadcaster =
234 			new SwDrawModellListener_Impl(
235                     pMap->GetShell()->getIDocumentDrawModelAccess()->GetOrCreateDrawModel() );
236         // <--
237 		maInfo.SetControllerBroadcaster( xModelBroadcaster );
238 	}
239 
240 	~SwAccessibleShapeMap_Impl();
241 
242 	const ::accessibility::AccessibleShapeTreeInfo& GetInfo() const { return maInfo; }
243 
244 	SwAccessibleObjShape_Impl *Copy( size_t& rSize,
245 		const SwFEShell *pFESh = 0,
246 		SwAccessibleObjShape_Impl  **pSelShape = 0 ) const;
247 };
248 
249 SwAccessibleShapeMap_Impl::~SwAccessibleShapeMap_Impl()
250 {
251 	uno::Reference < document::XEventBroadcaster > xBrd( maInfo.GetControllerBroadcaster() );
252 	if( xBrd.is() )
253 		static_cast < SwDrawModellListener_Impl * >( xBrd.get() )->Dispose();
254 }
255 
256 SwAccessibleObjShape_Impl
257 	*SwAccessibleShapeMap_Impl::Copy(
258 			size_t& rSize, const SwFEShell *pFESh,
259 			SwAccessibleObjShape_Impl **pSelStart ) const
260 {
261 	SwAccessibleObjShape_Impl *pShapes = 0;
262 	SwAccessibleObjShape_Impl *pSelShape = 0;
263 
264 	sal_uInt16 nSelShapes = pFESh ? pFESh->IsObjSelected() : 0;
265 	rSize = size();
266 
267 	if( rSize > 0 )
268 	{
269 		pShapes =
270 			new SwAccessibleObjShape_Impl[rSize];
271 
272 		const_iterator aIter = begin();
273 		const_iterator aEndIter = end();
274 
275 		SwAccessibleObjShape_Impl *pShape = pShapes;
276 		pSelShape = &(pShapes[rSize]);
277 		while( aIter != aEndIter )
278 		{
279 			const SdrObject *pObj = (*aIter).first;
280 			uno::Reference < XAccessible > xAcc( (*aIter).second );
281 			if( nSelShapes && pFESh->IsObjSelected( *pObj ) )
282 			{
283 				// selected objects are inserted from the back
284 				--pSelShape;
285 				pSelShape->first = pObj;
286 				pSelShape->second =
287 					static_cast < ::accessibility::AccessibleShape* >(
288 													xAcc.get() );
289 				--nSelShapes;
290 			}
291 			else
292 			{
293 				pShape->first = pObj;
294 				pShape->second =
295 					static_cast < ::accessibility::AccessibleShape* >(
296 													xAcc.get() );
297 				++pShape;
298 			}
299 			++aIter;
300 		}
301 		ASSERT( pSelShape == pShape, "copying shapes went wrong!" );
302 	}
303 
304 	if( pSelStart )
305 		*pSelStart = pSelShape;
306 
307 	return pShapes;
308 }
309 
310 //------------------------------------------------------------------------------
311 struct SwAccessibleEvent_Impl
312 {
313 public:
314     enum EventType { CARET_OR_STATES,
315                      INVALID_CONTENT,
316                      POS_CHANGED,
317                      CHILD_POS_CHANGED,
318                      SHAPE_SELECTION,
319                      DISPOSE,
320                      INVALID_ATTR };
321 
322 private:
323 	SwRect		maOldBox;				// the old bounds for CHILD_POS_CHANGED
324 										// and POS_CHANGED
325 	uno::WeakReference < XAccessible > mxAcc;	// The object that fires the event
326     SwAccessibleChild   maFrmOrObj;             // the child for CHILD_POS_CHANGED and
327 										// the same as xAcc for any other
328 										// event type
329 	EventType 	meType;					// The event type
330     // --> OD 2005-12-12 #i27301# - use new type definition for <mnStates>
331     tAccessibleStates mnStates;         // check states or update caret pos
332     // <--
333 
334 	SwAccessibleEvent_Impl& operator==( const SwAccessibleEvent_Impl& );
335 
336 public:
337     SwAccessibleEvent_Impl( EventType eT,
338                             SwAccessibleContext *pA,
339                             const SwAccessibleChild& rFrmOrObj )
340         : mxAcc( pA ),
341           maFrmOrObj( rFrmOrObj ),
342           meType( eT ),
343           mnStates( 0 )
344 	{}
345 
346     SwAccessibleEvent_Impl( EventType eT,
347                             const SwAccessibleChild& rFrmOrObj )
348         : maFrmOrObj( rFrmOrObj ),
349           meType( eT ),
350           mnStates( 0 )
351 	{
352 		ASSERT( SwAccessibleEvent_Impl::DISPOSE == meType,
353 				"wrong event constructor, DISPOSE only" );
354 	}
355 
356     SwAccessibleEvent_Impl( EventType eT )
357         : meType( eT ),
358           mnStates( 0 )
359 	{
360         ASSERT( SwAccessibleEvent_Impl::SHAPE_SELECTION == meType,
361 				"wrong event constructor, SHAPE_SELECTION only" );
362 	}
363 
364     SwAccessibleEvent_Impl( EventType eT,
365                             SwAccessibleContext *pA,
366                             const SwAccessibleChild& rFrmOrObj,
367                             const SwRect& rR )
368         : maOldBox( rR ),
369           mxAcc( pA ),
370           maFrmOrObj( rFrmOrObj ),
371           meType( eT ),
372           mnStates( 0 )
373 	{
374 		ASSERT( SwAccessibleEvent_Impl::CHILD_POS_CHANGED == meType ||
375 				SwAccessibleEvent_Impl::POS_CHANGED == meType,
376 				"wrong event constructor, (CHILD_)POS_CHANGED only" );
377 	}
378 
379     // --> OD 2005-12-12 #i27301# - use new type definition for parameter <_nStates>
380     SwAccessibleEvent_Impl( EventType eT,
381                             SwAccessibleContext *pA,
382                             const SwAccessibleChild& rFrmOrObj,
383                             const tAccessibleStates _nStates )
384         : mxAcc( pA ),
385           maFrmOrObj( rFrmOrObj ),
386           meType( eT ),
387           mnStates( _nStates )
388 	{
389 		ASSERT( SwAccessibleEvent_Impl::CARET_OR_STATES == meType,
390 				"wrong event constructor, CARET_OR_STATES only" );
391 	}
392 
393     // <SetType(..)> only used in method <SwAccessibleMap::AppendEvent(..)>
394     inline void SetType( EventType eT )
395     {
396         meType = eT;
397     }
398     inline EventType GetType() const
399     {
400         return meType;
401     }
402 
403     inline ::vos::ORef < SwAccessibleContext > GetContext() const
404     {
405         uno::Reference < XAccessible > xTmp( mxAcc );
406         ::vos::ORef < SwAccessibleContext > xAccImpl(
407                             static_cast<SwAccessibleContext*>( xTmp.get() ) );
408 
409         return xAccImpl;
410     }
411 
412     inline const SwRect& GetOldBox() const
413     {
414         return maOldBox;
415     }
416     // <SetOldBox(..)> only used in method <SwAccessibleMap::AppendEvent(..)>
417     inline void SetOldBox( const SwRect& rOldBox )
418     {
419         maOldBox = rOldBox;
420     }
421 
422     inline const SwAccessibleChild& GetFrmOrObj() const
423     {
424         return maFrmOrObj;
425     }
426 
427     // <SetStates(..)> only used in method <SwAccessibleMap::AppendEvent(..)>
428     // --> OD 2005-12-12 #i27301# - use new type definition for parameter <_nStates>
429     inline void SetStates( tAccessibleStates _nStates )
430     {
431         mnStates |= _nStates;
432     }
433     // <--
434 
435     inline sal_Bool IsUpdateCursorPos() const
436     {
437         return (mnStates & ACC_STATE_CARET) != 0;
438     }
439     inline sal_Bool IsInvalidateStates() const
440     {
441         return (mnStates & ACC_STATE_MASK) != 0;
442     }
443     inline sal_Bool IsInvalidateRelation() const
444     {
445         return (mnStates & ACC_STATE_RELATION_MASK) != 0;
446     }
447     // --> OD 2005-12-12 #i27301# - new event TEXT_SELECTION_CHANGED
448     inline sal_Bool IsInvalidateTextSelection() const
449     {
450         return ( mnStates & ACC_STATE_TEXT_SELECTION_CHANGED ) != 0;
451     }
452     // <--
453     // --> OD 2009-01-07 #i88069# - new event TEXT_ATTRIBUTE_CHANGED
454     inline sal_Bool IsInvalidateTextAttrs() const
455     {
456         return ( mnStates & ACC_STATE_TEXT_ATTRIBUTE_CHANGED ) != 0;
457     }
458     // <--
459     // --> OD 2005-12-12 #i27301# - use new type definition <tAccessibleStates>
460     // for return value
461     inline tAccessibleStates GetStates() const
462     {
463         return mnStates & ACC_STATE_MASK;
464     }
465     // <--
466     // --> OD 2005-12-12 #i27301# - use new type definition <tAccessibleStates>
467     // for return value
468     inline tAccessibleStates GetAllStates() const
469     {
470         return mnStates;
471     }
472     // <--
473 };
474 
475 //------------------------------------------------------------------------------
476 typedef ::std::list < SwAccessibleEvent_Impl > _SwAccessibleEventList_Impl;
477 
478 class SwAccessibleEventList_Impl: public _SwAccessibleEventList_Impl
479 {
480 	sal_Bool mbFiring;
481 
482 public:
483 
484     SwAccessibleEventList_Impl()
485         : mbFiring( sal_False )
486     {}
487 
488     inline void SetFiring()
489     {
490         mbFiring = sal_True;
491     }
492     inline sal_Bool IsFiring() const
493     {
494         return mbFiring;
495     }
496 };
497 
498 //------------------------------------------------------------------------------
499 // The shape list is filled if an accessible shape is destroyed. It
500 // simply keeps a reference to the accessible shape's XShape. These
501 // references are destroyed within the EndAction when firing events,
502 // There are twp reason for this. First of all, a new accessible shape
503 // for the XShape might be created soon. It's then cheaper if the XShape
504 // still exists. The other reason are situations where an accessible shape
505 // is destroyed within an SwFrmFmt::Modify. In this case, destryoing
506 // the XShape at the same time (indirectly by destroying the accessible
507 // shape) leads to an assert, because a client of the Modify is destroyed
508 // within a Modify call.
509 
510 typedef ::std::list < uno::Reference < drawing::XShape > > _SwShapeList_Impl;
511 
512 class SwShapeList_Impl: public _SwShapeList_Impl
513 {
514 public:
515 
516 	SwShapeList_Impl() {}
517 };
518 
519 
520 //------------------------------------------------------------------------------
521 struct SwAccessibleChildFunc
522 {
523     sal_Bool operator()( const SwAccessibleChild& r1,
524                          const SwAccessibleChild& r2 ) const
525 	{
526 		const void *p1 = r1.GetSwFrm()
527                          ? static_cast < const void * >( r1.GetSwFrm())
528                          : ( r1.GetDrawObject()
529                              ? static_cast < const void * >( r1.GetDrawObject() )
530                              : static_cast < const void * >( r1.GetWindow() ) );
531 		const void *p2 = r2.GetSwFrm()
532                          ? static_cast < const void * >( r2.GetSwFrm())
533                          : ( r2.GetDrawObject()
534                              ? static_cast < const void * >( r2.GetDrawObject() )
535                              : static_cast < const void * >( r2.GetWindow() ) );
536 		return p1 < p2;
537 	}
538 };
539 typedef ::std::map < SwAccessibleChild, SwAccessibleEventList_Impl::iterator,
540                      SwAccessibleChildFunc > _SwAccessibleEventMap_Impl;
541 
542 class SwAccessibleEventMap_Impl: public _SwAccessibleEventMap_Impl
543 {
544 };
545 
546 //------------------------------------------------------------------------------
547 // --> OD 2005-12-13 #i27301# - map containing the accessible paragraph, which
548 // have a selection. Needed to keep this information to submit corresponding
549 // TEXT_SELECTION_CHANGED events.
550 struct SwAccessibleParaSelection
551 {
552     xub_StrLen nStartOfSelection;
553     xub_StrLen nEndOfSelection;
554 
555     SwAccessibleParaSelection( const xub_StrLen _nStartOfSelection,
556                                const xub_StrLen _nEndOfSelection )
557         : nStartOfSelection( _nStartOfSelection ),
558           nEndOfSelection( _nEndOfSelection )
559     {}
560 };
561 
562 struct SwXAccWeakRefComp
563 {
564     sal_Bool operator()( const uno::WeakReference<XAccessible>& _rXAccWeakRef1,
565                          const uno::WeakReference<XAccessible>& _rXAccWeakRef2 ) const
566     {
567         return _rXAccWeakRef1.get() < _rXAccWeakRef2.get();
568     }
569 };
570 
571 typedef ::std::map< uno::WeakReference < XAccessible >,
572                     SwAccessibleParaSelection,
573                     SwXAccWeakRefComp > _SwAccessibleSelectedParas_Impl;
574 
575 class SwAccessibleSelectedParas_Impl: public _SwAccessibleSelectedParas_Impl
576 {};
577 // <--
578 
579 // helper class that stores preview data
580 class SwAccPreviewData
581 {
582     typedef std::vector<Rectangle> Rectangles;
583     Rectangles maPreviewRects;
584     Rectangles maLogicRects;
585 
586     SwRect maVisArea;
587     Fraction maScale;
588 
589     const SwPageFrm *mpSelPage;
590 
591     /** adjust logic page retangle to its visible part
592 
593         OD 17.01.2003 #103492#
594 
595         @author OD
596 
597         @param _iorLogicPgSwRect
598         input/output parameter - reference to the logic page rectangle, which
599         has to be adjusted.
600 
601         @param _rPrevwPgSwRect
602         input parameter - constant reference to the corresponding preview page
603         rectangle; needed to determine the visible part of the logic page rectangle.
604 
605         @param _rPrevwWinSize
606         input paramter - constant reference to the preview window size in TWIP;
607         needed to determine the visible part of the logic page rectangle
608     */
609     void AdjustLogicPgRectToVisibleArea( SwRect&         _iorLogicPgSwRect,
610                                          const SwRect&   _rPrevwPgSwRect,
611                                          const Size&     _rPrevwWinSize );
612 
613 public:
614     SwAccPreviewData();
615     ~SwAccPreviewData();
616 
617     // OD 14.01.2003 #103492# - complete re-factoring of method due to new
618     // page/print preview functionality.
619     void Update( const SwAccessibleMap& rAccMap,
620                  const std::vector<PrevwPage*>& _rPrevwPages,
621                  const Fraction&  _rScale,
622                  const SwPageFrm* _pSelectedPageFrm,
623                  const Size&      _rPrevwWinSize );
624 
625     // OD 14.01.2003 #103492# - complete re-factoring of method due to new
626     // page/print preview functionality.
627     void InvalidateSelection( const SwPageFrm* _pSelectedPageFrm );
628 
629     const SwRect& GetVisArea() const;
630 
631     MapMode GetMapModeForPreview( ) const;
632 
633     /** Adjust the MapMode so that the preview page appears at the
634      * proper position. rPoint identifies the page for which the
635      * MapMode should be adjusted. If bFromPreview is true, rPoint is
636      * a preview coordinate; else it's a document coordinate. */
637     // OD 17.01.2003 #103492# - delete unused 3rd parameter.
638     void AdjustMapMode( MapMode& rMapMode,
639                         const Point& rPoint ) const;
640 
641     inline const SwPageFrm *GetSelPage() const { return mpSelPage; }
642 
643     void DisposePage(const SwPageFrm *pPageFrm );
644 };
645 
646 SwAccPreviewData::SwAccPreviewData() :
647     mpSelPage( 0 )
648 {
649 }
650 
651 SwAccPreviewData::~SwAccPreviewData()
652 {
653 }
654 
655 // OD 13.01.2003 #103492# - complete re-factoring of method due to new page/print
656 // preview functionality.
657 void SwAccPreviewData::Update( const SwAccessibleMap& rAccMap,
658                                const std::vector<PrevwPage*>& _rPrevwPages,
659                                const Fraction&  _rScale,
660                                const SwPageFrm* _pSelectedPageFrm,
661                                const Size&      _rPrevwWinSize )
662 {
663     // store preview scaling, maximal preview page size and selected page
664     maScale = _rScale;
665     mpSelPage = _pSelectedPageFrm;
666 
667     // prepare loop on preview pages
668     maPreviewRects.clear();
669     maLogicRects.clear();
670     SwAccessibleChild aPage;
671     maVisArea.Clear();
672 
673     // loop on preview pages to calculate <maPreviewRects>, <maLogicRects> and
674     // <maVisArea>
675     for ( std::vector<PrevwPage*>::const_iterator aPageIter = _rPrevwPages.begin();
676           aPageIter != _rPrevwPages.end();
677           ++aPageIter )
678     {
679         aPage = (*aPageIter)->pPage;
680 
681         // add preview page rectangle to <maPreviewRects>
682         Rectangle aPrevwPgRect( (*aPageIter)->aPrevwWinPos, (*aPageIter)->aPageSize );
683         maPreviewRects.push_back( aPrevwPgRect );
684 
685         // add logic page rectangle to <maLogicRects>
686         SwRect aLogicPgSwRect( aPage.GetBox( rAccMap ) );
687         Rectangle aLogicPgRect( aLogicPgSwRect.SVRect() );
688         maLogicRects.push_back( aLogicPgRect );
689         // union visible area with visible part of logic page rectangle
690         if ( (*aPageIter)->bVisible )
691         {
692             if ( !(*aPageIter)->pPage->IsEmptyPage() )
693             {
694                 AdjustLogicPgRectToVisibleArea( aLogicPgSwRect,
695                                                 SwRect( aPrevwPgRect ),
696                                                 _rPrevwWinSize );
697             }
698             if ( maVisArea.IsEmpty() )
699                 maVisArea = aLogicPgSwRect;
700             else
701                 maVisArea.Union( aLogicPgSwRect );
702         }
703     }
704 }
705 
706 // OD 16.01.2003 #103492# - complete re-factoring of method due to new page/print
707 // preview functionality.
708 void SwAccPreviewData::InvalidateSelection( const SwPageFrm* _pSelectedPageFrm )
709 {
710     mpSelPage = _pSelectedPageFrm;
711     ASSERT( mpSelPage, "selected page not found" );
712 }
713 
714 struct ContainsPredicate
715 {
716     const Point& mrPoint;
717     ContainsPredicate( const Point& rPoint ) : mrPoint(rPoint) {}
718     bool operator() ( const Rectangle& rRect ) const
719     {
720         return rRect.IsInside( mrPoint ) ? true : false;
721     }
722 };
723 
724 const SwRect& SwAccPreviewData::GetVisArea() const
725 {
726     return maVisArea;
727 }
728 
729 void SwAccPreviewData::AdjustMapMode( MapMode& rMapMode,
730                                       const Point& rPoint ) const
731 {
732     // adjust scale
733     rMapMode.SetScaleX( maScale );
734     rMapMode.SetScaleY( maScale );
735 
736     // find proper rectangle
737     Rectangles::const_iterator aBegin = maLogicRects.begin();
738     Rectangles::const_iterator aEnd = maLogicRects.end();
739     Rectangles::const_iterator aFound = ::std::find_if( aBegin, aEnd,
740                                                  ContainsPredicate( rPoint ) );
741 
742     if( aFound != aEnd )
743     {
744         // found! set new origin
745         Point aPoint = (maPreviewRects.begin() + (aFound - aBegin))->TopLeft();
746         aPoint -= (maLogicRects.begin() + (aFound-aBegin))->TopLeft();
747         rMapMode.SetOrigin( aPoint );
748     }
749     // else: don't adjust MapMode
750 }
751 
752 void SwAccPreviewData::DisposePage(const SwPageFrm *pPageFrm )
753 {
754     if( mpSelPage == pPageFrm )
755         mpSelPage = 0;
756 }
757 
758 /** adjust logic page retangle to its visible part
759 
760     OD 17.01.2003 #103492#
761 
762     @author OD
763 */
764 void SwAccPreviewData::AdjustLogicPgRectToVisibleArea(
765                             SwRect&         _iorLogicPgSwRect,
766                             const SwRect&   _rPrevwPgSwRect,
767                             const Size&     _rPrevwWinSize )
768 {
769     // determine preview window rectangle
770     const SwRect aPrevwWinSwRect( Point( 0, 0 ), _rPrevwWinSize );
771     // calculate visible preview page rectangle
772     SwRect aVisPrevwPgSwRect( _rPrevwPgSwRect );
773     aVisPrevwPgSwRect.Intersection( aPrevwWinSwRect );
774     // adjust logic page rectangle
775     SwTwips nTmpDiff;
776     // left
777     nTmpDiff = aVisPrevwPgSwRect.Left() - _rPrevwPgSwRect.Left();
778     if ( nTmpDiff > 0 )
779         _iorLogicPgSwRect.Left( _iorLogicPgSwRect.Left() + nTmpDiff );
780     // top
781     nTmpDiff = aVisPrevwPgSwRect.Top() - _rPrevwPgSwRect.Top();
782     if ( nTmpDiff > 0 )
783         _iorLogicPgSwRect.Top( _iorLogicPgSwRect.Top() + nTmpDiff );
784     // right
785     nTmpDiff = _rPrevwPgSwRect.Right() - aVisPrevwPgSwRect.Right();
786     if ( nTmpDiff > 0 )
787         _iorLogicPgSwRect.Right( _iorLogicPgSwRect.Right() - nTmpDiff );
788     // bottom
789     nTmpDiff = _rPrevwPgSwRect.Bottom() - aVisPrevwPgSwRect.Bottom();
790     if ( nTmpDiff > 0 )
791         _iorLogicPgSwRect.Bottom( _iorLogicPgSwRect.Bottom() - nTmpDiff );
792 }
793 
794 //------------------------------------------------------------------------------
795 static sal_Bool AreInSameTable( const uno::Reference< XAccessible >& rAcc,
796 					  		    const SwFrm *pFrm )
797 {
798 	sal_Bool bRet = sal_False;
799 
800 	if( pFrm && pFrm->IsCellFrm() && rAcc.is() )
801 	{
802 		// Is it in the same table? We check that
803 		// by comparing the last table frame in the
804 		// follow chain, because that's cheaper than
805 		// searching the first one.
806 		SwAccessibleContext *pAccImpl =
807 			static_cast< SwAccessibleContext *>( rAcc.get() );
808 		if( pAccImpl->GetFrm()->IsCellFrm() )
809 		{
810 			const SwTabFrm *pTabFrm1 = pAccImpl->GetFrm()->FindTabFrm();
811 			while( pTabFrm1->GetFollow() )
812 				   pTabFrm1 = pTabFrm1->GetFollow();
813 
814 			const SwTabFrm *pTabFrm2 = pFrm->FindTabFrm();
815 			while( pTabFrm2->GetFollow() )
816 				   pTabFrm2 = pTabFrm2->GetFollow();
817 
818 			bRet = (pTabFrm1 == pTabFrm2);
819 		}
820 	}
821 
822 	return bRet;
823 }
824 
825 void SwAccessibleMap::FireEvent( const SwAccessibleEvent_Impl& rEvent )
826 {
827 	::vos::ORef < SwAccessibleContext > xAccImpl( rEvent.GetContext() );
828 	if( SwAccessibleEvent_Impl::SHAPE_SELECTION == rEvent.GetType() )
829 	{
830 		DoInvalidateShapeSelection();
831 	}
832 	else if( xAccImpl.isValid() && xAccImpl->GetFrm() )
833 	{
834         // --> OD 2009-01-07 #i88069#
835         if ( rEvent.GetType() != SwAccessibleEvent_Impl::DISPOSE &&
836              rEvent.IsInvalidateTextAttrs() )
837         {
838             xAccImpl->InvalidateAttr();
839         }
840         // <--
841 		switch( rEvent.GetType() )
842 		{
843 		case SwAccessibleEvent_Impl::INVALID_CONTENT:
844 			xAccImpl->InvalidateContent();
845 			break;
846 		case SwAccessibleEvent_Impl::POS_CHANGED:
847 			xAccImpl->InvalidatePosOrSize( rEvent.GetOldBox() );
848 			break;
849 		case SwAccessibleEvent_Impl::CHILD_POS_CHANGED:
850 			xAccImpl->InvalidateChildPosOrSize( rEvent.GetFrmOrObj(),
851 									   rEvent.GetOldBox() );
852 			break;
853 		case SwAccessibleEvent_Impl::DISPOSE:
854 			ASSERT( xAccImpl.isValid(),
855 					"dispose event has been stored" );
856 			break;
857         // --> OD 2009-01-06 #i88069#
858         case SwAccessibleEvent_Impl::INVALID_ATTR:
859             // nothing to do here - handled above
860             break;
861         // <--
862 		default:
863 			break;
864 		}
865 		if( SwAccessibleEvent_Impl::DISPOSE != rEvent.GetType() )
866 		{
867 			if( rEvent.IsUpdateCursorPos() )
868 				xAccImpl->InvalidateCursorPos();
869 			if( rEvent.IsInvalidateStates() )
870 				xAccImpl->InvalidateStates( rEvent.GetStates() );
871             if( rEvent.IsInvalidateRelation() )
872             {
873                 // --> OD 2005-12-01 #i27138#
874                 // both events CONTENT_FLOWS_FROM_RELATION_CHANGED and
875                 // CONTENT_FLOWS_TO_RELATION_CHANGED are possible
876                 if ( rEvent.GetAllStates() & ACC_STATE_RELATION_FROM )
877                 {
878                     xAccImpl->InvalidateRelation(
879                         AccessibleEventId::CONTENT_FLOWS_FROM_RELATION_CHANGED );
880                 }
881                 if ( rEvent.GetAllStates() & ACC_STATE_RELATION_TO )
882                 {
883                     xAccImpl->InvalidateRelation(
884                         AccessibleEventId::CONTENT_FLOWS_TO_RELATION_CHANGED );
885                 }
886                 // <--
887             }
888             // --> OD 2005-12-12 #i27301# - submit event TEXT_SELECTION_CHANGED
889             if ( rEvent.IsInvalidateTextSelection() )
890             {
891                 xAccImpl->InvalidateTextSelection();
892             }
893             // <--
894 		}
895 	}
896 }
897 
898 void SwAccessibleMap::AppendEvent( const SwAccessibleEvent_Impl& rEvent )
899 {
900 	vos::OGuard aGuard( maEventMutex );
901 
902 	if( !mpEvents )
903 		mpEvents = new SwAccessibleEventList_Impl;
904 	if( !mpEventMap )
905 		mpEventMap = new SwAccessibleEventMap_Impl;
906 
907 	if( mpEvents->IsFiring() )
908 	{
909 		// While events are fired new ones are generated. They have to be fired
910 		// now. This does not work for DISPOSE events!
911 		ASSERT( rEvent.GetType() != SwAccessibleEvent_Impl::DISPOSE,
912 				"dispose event while firing events" );
913 		FireEvent( rEvent );
914 	}
915 	else
916 	{
917 
918 		SwAccessibleEventMap_Impl::iterator aIter =
919                                         mpEventMap->find( rEvent.GetFrmOrObj() );
920 		if( aIter != mpEventMap->end() )
921 		{
922 			SwAccessibleEvent_Impl aEvent( *(*aIter).second );
923 			ASSERT( aEvent.GetType() != SwAccessibleEvent_Impl::DISPOSE,
924 					"dispose events should not be stored" );
925 			sal_Bool bAppendEvent = sal_True;
926 			switch( rEvent.GetType() )
927 			{
928 			case SwAccessibleEvent_Impl::CARET_OR_STATES:
929 				// A CARET_OR_STATES event is added to any other
930 				// event only. It is broadcasted after any other event, so the
931 				// event should be put to the back.
932                 ASSERT( aEvent.GetType() != SwAccessibleEvent_Impl::CHILD_POS_CHANGED,
933 						"invalid event combination" );
934 				aEvent.SetStates( rEvent.GetAllStates() );
935 				break;
936 			case SwAccessibleEvent_Impl::INVALID_CONTENT:
937 				// An INVALID_CONTENT event overwrites a CARET_OR_STATES
938 				// event (but keeps its flags) and it is contained in a
939 				// POS_CHANGED event.
940 				// Therefor, the event's type has to be adapted and the event
941 				// has to be put at the end.
942                 ASSERT( aEvent.GetType() != SwAccessibleEvent_Impl::CHILD_POS_CHANGED,
943 						"invalid event combination" );
944                 if( aEvent.GetType() == SwAccessibleEvent_Impl::CARET_OR_STATES )
945 					aEvent.SetType( SwAccessibleEvent_Impl::INVALID_CONTENT );
946 				break;
947 			case SwAccessibleEvent_Impl::POS_CHANGED:
948 				// A pos changed event overwrites CARET_STATES (keeping its
949 				// flags) as well as INVALID_CONTENT. The old box position
950 				// has to be stored however if the old event is not a
951 				// POS_CHANGED itself.
952                 ASSERT( aEvent.GetType() != SwAccessibleEvent_Impl::CHILD_POS_CHANGED,
953 						"invalid event combination" );
954 				if( aEvent.GetType() != SwAccessibleEvent_Impl::POS_CHANGED )
955 					aEvent.SetOldBox( rEvent.GetOldBox() );
956 				aEvent.SetType( SwAccessibleEvent_Impl::POS_CHANGED );
957 				break;
958 			case SwAccessibleEvent_Impl::CHILD_POS_CHANGED:
959 				// CHILD_POS_CHANGED events can only follow CHILD_POS_CHANGED
960 				// events. The only action that needs to be done again is
961 				// to put the old event to the back. The new one cannot be used,
962 				// because we are interested in the old frame bounds.
963                 ASSERT( aEvent.GetType() == SwAccessibleEvent_Impl::CHILD_POS_CHANGED,
964 						"invalid event combination" );
965 				break;
966 			case SwAccessibleEvent_Impl::SHAPE_SELECTION:
967                 ASSERT( aEvent.GetType() == SwAccessibleEvent_Impl::SHAPE_SELECTION,
968 						"invalid event combination" );
969 				break;
970 			case SwAccessibleEvent_Impl::DISPOSE:
971 				// DISPOSE events overwrite all others. They are not stored
972 				// but executed immediatly to avoid broadcasting of
973 				// defunctional objects. So what needs to be done here is to
974 				// remove all events for the frame in question.
975 				bAppendEvent = sal_False;
976 				break;
977             // --> OD 2009-01-06 #i88069#
978             case SwAccessibleEvent_Impl::INVALID_ATTR:
979                 ASSERT( aEvent.GetType() == SwAccessibleEvent_Impl::INVALID_ATTR,
980                         "invalid event combination" );
981                 break;
982             // <--
983 			}
984 			if( bAppendEvent )
985 			{
986 				mpEvents->erase( (*aIter).second );
987 				(*aIter).second = mpEvents->insert( mpEvents->end(), aEvent );
988 			}
989 			else
990 			{
991 				mpEvents->erase( (*aIter).second );
992 				mpEventMap->erase( aIter );
993 			}
994 		}
995 		else if( SwAccessibleEvent_Impl::DISPOSE != rEvent.GetType() )
996 		{
997 			SwAccessibleEventMap_Impl::value_type aEntry( rEvent.GetFrmOrObj(),
998 					mpEvents->insert( mpEvents->end(), rEvent ) );
999 			mpEventMap->insert( aEntry );
1000 		}
1001 	}
1002 }
1003 
1004 void SwAccessibleMap::InvalidateCursorPosition(
1005 		const uno::Reference< XAccessible >& rAcc )
1006 {
1007 	SwAccessibleContext *pAccImpl =
1008 		static_cast< SwAccessibleContext *>( rAcc.get() );
1009 	ASSERT( pAccImpl, "no caret context" );
1010 	ASSERT( pAccImpl->GetFrm(), "caret context is disposed" );
1011 	if( GetShell()->ActionPend() )
1012 	{
1013         SwAccessibleEvent_Impl aEvent( SwAccessibleEvent_Impl::CARET_OR_STATES,
1014                                        pAccImpl,
1015                                        SwAccessibleChild(pAccImpl->GetFrm()),
1016                                        ACC_STATE_CARET );
1017 		AppendEvent( aEvent );
1018 	}
1019 	else
1020 	{
1021 		FireEvents();
1022 		// While firing events the current frame might have
1023 		// been disposed because it moved out of the vis area.
1024 		// Setting the cursor for such frames is useless and even
1025 		// causes asserts.
1026 		if( pAccImpl->GetFrm() )
1027 			pAccImpl->InvalidateCursorPos();
1028 	}
1029 }
1030 
1031 void SwAccessibleMap::InvalidateShapeSelection()
1032 {
1033 	if( GetShell()->ActionPend() )
1034 	{
1035 		SwAccessibleEvent_Impl aEvent(
1036 			SwAccessibleEvent_Impl::SHAPE_SELECTION );
1037 		AppendEvent( aEvent );
1038 	}
1039 	else
1040 	{
1041 		FireEvents();
1042 		DoInvalidateShapeSelection();
1043 	}
1044 }
1045 
1046 void SwAccessibleMap::DoInvalidateShapeSelection()
1047 {
1048 	SwAccessibleObjShape_Impl *pShapes = 0;
1049 	SwAccessibleObjShape_Impl *pSelShape = 0;
1050 	size_t nShapes = 0;
1051 
1052 	const ViewShell *pVSh = GetShell();
1053 	const SwFEShell *pFESh = pVSh->ISA( SwFEShell ) ?
1054 							static_cast< const SwFEShell * >( pVSh ) : 0;
1055 	sal_uInt16 nSelShapes = pFESh ? pFESh->IsObjSelected() : 0;
1056 
1057 	{
1058 		vos::OGuard aGuard( maMutex );
1059 		if( mpShapeMap )
1060 			pShapes = mpShapeMap->Copy( nShapes, pFESh, &pSelShape );
1061 	}
1062 
1063 	if( pShapes )
1064 	{
1065 		::std::list< const SwFrm * > aParents;
1066 		Window *pWin = GetShell()->GetWin();
1067 		sal_Bool bFocused = pWin && pWin->HasFocus();
1068 		SwAccessibleObjShape_Impl *pShape = pShapes;
1069 		while( nShapes )
1070 		{
1071 			if( pShape->second.isValid() )
1072 			{
1073 				sal_Bool bChanged;
1074 				if( pShape >= pSelShape )
1075 				{
1076 					bChanged =
1077 						pShape->second->SetState( AccessibleStateType::SELECTED );
1078 					if( bFocused && 1 == nSelShapes )
1079 						pShape->second->SetState( AccessibleStateType::FOCUSED );
1080 					else
1081 						pShape->second->ResetState( AccessibleStateType::FOCUSED );
1082 				}
1083 				else
1084 				{
1085 					bChanged =
1086 						pShape->second->ResetState( AccessibleStateType::SELECTED );
1087 					pShape->second->ResetState( AccessibleStateType::FOCUSED );
1088 				}
1089 				if( bChanged )
1090 				{
1091                     const SwFrm* pParent = SwAccessibleFrame::GetParent(
1092                                                     SwAccessibleChild( pShape->first ),
1093                                                     GetShell()->IsPreView() );
1094                     aParents.push_back( pParent );
1095 				}
1096 			}
1097 
1098 			--nShapes;
1099 			++pShape;
1100 		}
1101 		if( aParents.size() > 0 )
1102 		{
1103 			::std::list< const SwFrm * >::const_iterator aIter = aParents.begin();
1104 			::std::list< const SwFrm * >::const_iterator aEndIter = aParents.end();
1105 			while( aIter != aEndIter )
1106 			{
1107 				::vos::ORef< SwAccessibleContext > xParentAccImpl;
1108 				{
1109 					vos::OGuard aGuard( maMutex );
1110 					if(  mpFrmMap )
1111 					{
1112 						SwAccessibleContextMap_Impl::const_iterator aMapIter =
1113 							mpFrmMap->find( *aIter );
1114 						if( aMapIter != mpFrmMap->end() )
1115 						{
1116 							uno::Reference < XAccessible > xAcc( (*aMapIter).second );
1117 							xParentAccImpl =
1118 								static_cast< SwAccessibleContext *>( xAcc.get() );
1119 						}
1120 					}
1121 				}
1122 				if( xParentAccImpl.isValid() )
1123 				{
1124 					AccessibleEventObject aEvent;
1125 					aEvent.EventId = AccessibleEventId::SELECTION_CHANGED;
1126 					xParentAccImpl->FireAccessibleEvent( aEvent );
1127 				}
1128 
1129 				++aIter;
1130 			}
1131 		}
1132 
1133 		delete[] pShapes;
1134 	}
1135 }
1136 
1137 void SwAccessibleMap::DoInvalidateShapeFocus()
1138 {
1139 	const ViewShell *pVSh = GetShell();
1140 	const SwFEShell *pFESh = pVSh->ISA( SwFEShell ) ?
1141 							static_cast< const SwFEShell * >( pVSh ) : 0;
1142 	sal_uInt16 nSelShapes = pFESh ? pFESh->IsObjSelected() : 0;
1143 
1144 	if( nSelShapes != 1 )
1145 		return;
1146 
1147 	SwAccessibleObjShape_Impl *pShapes = 0;
1148 	SwAccessibleObjShape_Impl *pSelShape = 0;
1149 	size_t nShapes = 0;
1150 
1151 
1152 	{
1153 		vos::OGuard aGuard( maMutex );
1154 		if( mpShapeMap )
1155 			pShapes = mpShapeMap->Copy( nShapes, pFESh, &pSelShape );
1156 	}
1157 
1158 	if( pShapes )
1159 	{
1160 		Window *pWin = GetShell()->GetWin();
1161 		sal_Bool bFocused = pWin && pWin->HasFocus();
1162 		SwAccessibleObjShape_Impl  *pShape = pShapes;
1163 		while( nShapes )
1164 		{
1165 			if( pShape->second.isValid() )
1166 			{
1167 				if( bFocused && pShape >= pSelShape )
1168 					pShape->second->SetState( AccessibleStateType::FOCUSED );
1169 				else
1170 					pShape->second->ResetState( AccessibleStateType::FOCUSED );
1171 			}
1172 
1173 			--nShapes;
1174 			++pShape;
1175 		}
1176 
1177 		delete[] pShapes;
1178 	}
1179 }
1180 
1181 
1182 SwAccessibleMap::SwAccessibleMap( ViewShell *pSh ) :
1183 	mpFrmMap( 0  ),
1184 	mpShapeMap( 0  ),
1185 	mpShapes( 0  ),
1186 	mpEvents( 0  ),
1187 	mpEventMap( 0  ),
1188     // --> OD 2005-12-13 #i27301#
1189     mpSelectedParas( 0 ),
1190     // <--
1191 	mpVSh( pSh ),
1192     	mpPreview( 0 ),
1193 	mnPara( 1 ),
1194 	mnFootnote( 1 ),
1195 	mnEndnote( 1 ),
1196 	mbShapeSelected( sal_False )
1197 {
1198 	pSh->GetLayout()->AddAccessibleShell();
1199 }
1200 
1201 SwAccessibleMap::~SwAccessibleMap()
1202 {
1203 	uno::Reference < XAccessible > xAcc;
1204 	{
1205 		vos::OGuard aGuard( maMutex );
1206 		if( mpFrmMap )
1207 		{
1208 			const SwRootFrm *pRootFrm = GetShell()->GetLayout();
1209 			SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->find( pRootFrm );
1210 			if( aIter != mpFrmMap->end() )
1211 				xAcc = (*aIter).second;
1212 			if( !xAcc.is() )
1213 				xAcc = new SwAccessibleDocument( this );
1214 		}
1215 	}
1216 
1217 	SwAccessibleDocument *pAcc =
1218 		static_cast< SwAccessibleDocument * >( xAcc.get() );
1219 	pAcc->Dispose( sal_True );
1220 
1221 	{
1222 		vos::OGuard aGuard( maMutex );
1223 #ifdef DBG_UTIL
1224 		ASSERT( !mpFrmMap || mpFrmMap->empty(),
1225 				"Frame map should be empty after disposing the root frame" );
1226 		if( mpFrmMap )
1227 		{
1228 			SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->begin();
1229 			while( aIter != mpFrmMap->end() )
1230 			{
1231 				uno::Reference < XAccessible > xTmp = (*aIter).second;
1232 				if( xTmp.is() )
1233 				{
1234 					SwAccessibleContext *pTmp =
1235 						static_cast< SwAccessibleContext * >( xTmp.get() );
1236 					(void) pTmp;
1237 				}
1238 				++aIter;
1239 			}
1240 		}
1241 		ASSERT( !mpShapeMap || mpShapeMap->empty(),
1242 				"Object map should be empty after disposing the root frame" );
1243 		if( mpShapeMap )
1244 		{
1245 			SwAccessibleShapeMap_Impl::iterator aIter = mpShapeMap->begin();
1246 			while( aIter != mpShapeMap->end() )
1247 			{
1248 				uno::Reference < XAccessible > xTmp = (*aIter).second;
1249 				if( xTmp.is() )
1250 				{
1251 					::accessibility::AccessibleShape *pTmp =
1252 						static_cast< ::accessibility::AccessibleShape* >( xTmp.get() );
1253 					(void) pTmp;
1254 				}
1255 				++aIter;
1256 			}
1257 		}
1258 #endif
1259 		delete mpFrmMap;
1260 		mpFrmMap = 0;
1261 		delete mpShapeMap;
1262 		mpShapeMap = 0;
1263 		delete mpShapes;
1264 		mpShapes = 0;
1265         // --> OD 2005-12-13 #i27301#
1266         delete mpSelectedParas;
1267         mpSelectedParas = 0;
1268         // <--
1269 	}
1270 
1271 	delete mpPreview;
1272 	mpPreview = NULL;
1273 
1274     {
1275 		vos::OGuard aGuard( maEventMutex );
1276 #ifdef DBG_UTIL
1277 		ASSERT( !(mpEvents || mpEventMap), "pending events" );
1278 		if( mpEvents )
1279 		{
1280 			SwAccessibleEventList_Impl::iterator aIter = mpEvents->begin();
1281 			while( aIter != mpEvents->end() )
1282 			{
1283 				++aIter;
1284 			}
1285 		}
1286 		if( mpEventMap )
1287 		{
1288 			SwAccessibleEventMap_Impl::iterator aIter = mpEventMap->begin();
1289 			while( aIter != mpEventMap->end() )
1290 			{
1291 				++aIter;
1292 			}
1293 		}
1294 #endif
1295 		delete mpEventMap;
1296 		mpEventMap = 0;
1297 		delete mpEvents;
1298 		mpEvents = 0;
1299 	}
1300 	mpVSh->GetLayout()->RemoveAccessibleShell();
1301 }
1302 
1303 uno::Reference< XAccessible > SwAccessibleMap::_GetDocumentView(
1304     sal_Bool bPagePreview )
1305 {
1306 	uno::Reference < XAccessible > xAcc;
1307 	sal_Bool bSetVisArea = sal_False;
1308 
1309 	{
1310 		vos::OGuard aGuard( maMutex );
1311 
1312 		if( !mpFrmMap )
1313 		{
1314 			mpFrmMap = new SwAccessibleContextMap_Impl;
1315 #ifdef DBG_UTIL
1316 			mpFrmMap->mbLocked = sal_False;
1317 #endif
1318 		}
1319 
1320 #ifdef DBG_UTIL
1321 		ASSERT( !mpFrmMap->mbLocked, "Map is locked" );
1322 		mpFrmMap->mbLocked = sal_True;
1323 #endif
1324 
1325 		const SwRootFrm *pRootFrm = GetShell()->GetLayout();
1326 		SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->find( pRootFrm );
1327 		if( aIter != mpFrmMap->end() )
1328 			xAcc = (*aIter).second;
1329 		if( xAcc.is() )
1330 		{
1331 			bSetVisArea = sal_True; // Set VisArea when map mutex is not
1332 									// locked
1333 		}
1334 		else
1335 		{
1336             if( bPagePreview )
1337                 xAcc = new SwAccessiblePreview( this );
1338             else
1339                 xAcc = new SwAccessibleDocument( this );
1340 
1341 			if( aIter != mpFrmMap->end() )
1342 			{
1343 				(*aIter).second = xAcc;
1344 			}
1345 			else
1346 			{
1347 				SwAccessibleContextMap_Impl::value_type aEntry( pRootFrm, xAcc );
1348 				mpFrmMap->insert( aEntry );
1349 			}
1350 		}
1351 
1352 #ifdef DBG_UTIL
1353 		mpFrmMap->mbLocked = sal_False;
1354 #endif
1355 	}
1356 
1357 	if( bSetVisArea )
1358 	{
1359 		SwAccessibleDocumentBase *pAcc =
1360 			static_cast< SwAccessibleDocumentBase * >( xAcc.get() );
1361 		pAcc->SetVisArea();
1362 	}
1363 
1364 	return xAcc;
1365 }
1366 
1367 uno::Reference< XAccessible > SwAccessibleMap::GetDocumentView( )
1368 {
1369     return _GetDocumentView( sal_False );
1370 }
1371 
1372 // OD 14.01.2003 #103492# - complete re-factoring of method due to new page/print
1373 // preview functionality.
1374 uno::Reference<XAccessible> SwAccessibleMap::GetDocumentPreview(
1375                                     const std::vector<PrevwPage*>& _rPrevwPages,
1376                                     const Fraction&  _rScale,
1377                                     const SwPageFrm* _pSelectedPageFrm,
1378                                     const Size&      _rPrevwWinSize )
1379 {
1380     // create & update preview data object
1381     if( mpPreview == NULL )
1382         mpPreview = new SwAccPreviewData();
1383     mpPreview->Update( *this, _rPrevwPages, _rScale, _pSelectedPageFrm, _rPrevwWinSize );
1384 
1385     uno::Reference<XAccessible> xAcc = _GetDocumentView( sal_True );
1386     return xAcc;
1387 }
1388 
1389 uno::Reference< XAccessible> SwAccessibleMap::GetContext( const SwFrm *pFrm,
1390 												     sal_Bool bCreate )
1391 {
1392 	uno::Reference < XAccessible > xAcc;
1393 	uno::Reference < XAccessible > xOldCursorAcc;
1394 	sal_Bool bOldShapeSelected = sal_False;
1395 
1396 	{
1397 		vos::OGuard aGuard( maMutex );
1398 
1399 		if( !mpFrmMap && bCreate )
1400 			mpFrmMap = new SwAccessibleContextMap_Impl;
1401 		if( mpFrmMap )
1402 		{
1403 			SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->find( pFrm );
1404 			if( aIter != mpFrmMap->end() )
1405 				xAcc = (*aIter).second;
1406 
1407 			if( !xAcc.is() && bCreate )
1408 			{
1409 				SwAccessibleContext *pAcc = 0;
1410 				switch( pFrm->GetType() )
1411 				{
1412 				case FRM_TXT:
1413                     mnPara++;
1414                     pAcc = new SwAccessibleParagraph( *this,
1415                                     static_cast< const SwTxtFrm& >( *pFrm ) );
1416 					break;
1417 				case FRM_HEADER:
1418 					pAcc = new SwAccessibleHeaderFooter( this,
1419 									static_cast< const SwHeaderFrm *>( pFrm ) );
1420 					break;
1421 				case FRM_FOOTER:
1422 					pAcc = new SwAccessibleHeaderFooter( this,
1423 									static_cast< const SwFooterFrm *>( pFrm ) );
1424 					break;
1425 				case FRM_FTN:
1426 					{
1427 						const SwFtnFrm *pFtnFrm =
1428 							static_cast < const SwFtnFrm * >( pFrm );
1429 						sal_Bool bIsEndnote =
1430 							SwAccessibleFootnote::IsEndnote( pFtnFrm );
1431 						pAcc = new SwAccessibleFootnote( this, bIsEndnote,
1432 									(bIsEndnote ? mnEndnote++ : mnFootnote++),
1433 									pFtnFrm );
1434 					}
1435 					break;
1436 				case FRM_FLY:
1437 					{
1438 						const SwFlyFrm *pFlyFrm =
1439 							static_cast < const SwFlyFrm * >( pFrm );
1440 						switch( SwAccessibleFrameBase::GetNodeType( pFlyFrm ) )
1441 						{
1442 						case ND_GRFNODE:
1443 							pAcc = new SwAccessibleGraphic( this, pFlyFrm );
1444 							break;
1445 						case ND_OLENODE:
1446 							pAcc = new SwAccessibleEmbeddedObject( this, pFlyFrm );
1447 							break;
1448 						default:
1449 							pAcc = new SwAccessibleTextFrame( this, pFlyFrm );
1450 							break;
1451 						}
1452 					}
1453 					break;
1454 				case FRM_CELL:
1455 					pAcc = new SwAccessibleCell( this,
1456 									static_cast< const SwCellFrm *>( pFrm ) );
1457 					break;
1458 				case FRM_TAB:
1459                     pAcc = new SwAccessibleTable( this,
1460 									static_cast< const SwTabFrm *>( pFrm ) );
1461 					break;
1462                 case FRM_PAGE:
1463                     DBG_ASSERT( GetShell()->IsPreView(),
1464                                 "accessible page frames only in PagePreview" );
1465                     pAcc = new SwAccessiblePage( this, pFrm );
1466                     break;
1467 				}
1468 				xAcc = pAcc;
1469 
1470 				ASSERT( xAcc.is(), "unknown frame type" );
1471 				if( xAcc.is() )
1472 				{
1473 					if( aIter != mpFrmMap->end() )
1474 					{
1475 						(*aIter).second = xAcc;
1476 					}
1477 					else
1478 					{
1479 						SwAccessibleContextMap_Impl::value_type aEntry( pFrm, xAcc );
1480 						mpFrmMap->insert( aEntry );
1481 					}
1482 
1483 					if( pAcc->HasCursor() &&
1484 						!AreInSameTable( mxCursorContext, pFrm ) )
1485 					{
1486 						// If the new context has the focus, and if we know
1487 						// another context that had the focus, then the focus
1488 						// just moves from the old context to the new one. We
1489 						// have to send a focus event and a caret event for
1490 						// the old context then. We have to to that know,
1491 						// because after we have left this method, anyone might
1492 						// call getStates for the new context and will get a
1493 						// focused state then. Sending the focus changes event
1494 						// after that seems to be strange. However, we cannot
1495 						// send a focus event fo the new context now, because
1496 					    // noone except us knows it. In any case, we remeber
1497 						// the new context as the one that has the focus
1498 						// currently.
1499 
1500 						xOldCursorAcc = mxCursorContext;
1501 						mxCursorContext = xAcc;
1502 
1503 						bOldShapeSelected = mbShapeSelected;
1504 						mbShapeSelected = sal_False;
1505 					}
1506 				}
1507 			}
1508 		}
1509 	}
1510 
1511 	// Invalidate focus for old object when map is not locked
1512 	if( xOldCursorAcc.is() )
1513 		InvalidateCursorPosition( xOldCursorAcc );
1514 	if( bOldShapeSelected )
1515 		InvalidateShapeSelection();
1516 
1517 	return xAcc;
1518 }
1519 
1520 ::vos::ORef < SwAccessibleContext > SwAccessibleMap::GetContextImpl(
1521 			const SwFrm *pFrm,
1522 			sal_Bool bCreate )
1523 {
1524 	uno::Reference < XAccessible > xAcc( GetContext( pFrm, bCreate ) );
1525 
1526 	::vos::ORef < SwAccessibleContext > xAccImpl(
1527 		 static_cast< SwAccessibleContext * >( xAcc.get() ) );
1528 
1529 	return xAccImpl;
1530 }
1531 
1532 uno::Reference< XAccessible> SwAccessibleMap::GetContext(
1533 		const SdrObject *pObj,
1534 		SwAccessibleContext *pParentImpl,
1535 		sal_Bool bCreate )
1536 {
1537 	uno::Reference < XAccessible > xAcc;
1538 	uno::Reference < XAccessible > xOldCursorAcc;
1539 
1540 	{
1541 		vos::OGuard aGuard( maMutex );
1542 
1543 		if( !mpShapeMap && bCreate )
1544 			mpShapeMap = new SwAccessibleShapeMap_Impl( this );
1545 		if( mpShapeMap )
1546 		{
1547 			SwAccessibleShapeMap_Impl::iterator aIter =
1548 			   	mpShapeMap->find( pObj );
1549 			if( aIter != mpShapeMap->end() )
1550 				xAcc = (*aIter).second;
1551 
1552 			if( !xAcc.is() && bCreate )
1553 			{
1554 				::accessibility::AccessibleShape *pAcc = 0;
1555 				uno::Reference < drawing::XShape > xShape(
1556 					const_cast< SdrObject * >( pObj )->getUnoShape(),
1557 					uno::UNO_QUERY );
1558 				if( xShape.is() )
1559 				{
1560 					::accessibility::ShapeTypeHandler& rShapeTypeHandler =
1561 								::accessibility::ShapeTypeHandler::Instance();
1562 					uno::Reference < XAccessible > xParent( pParentImpl );
1563 					::accessibility::AccessibleShapeInfo aShapeInfo(
1564 							xShape, xParent, this );
1565 
1566 					pAcc = rShapeTypeHandler.CreateAccessibleObject(
1567 								aShapeInfo, mpShapeMap->GetInfo() );
1568 				}
1569 				xAcc = pAcc;
1570 
1571 				ASSERT( xAcc.is(), "unknown shape type" );
1572 				if( xAcc.is() )
1573 				{
1574 					pAcc->Init();
1575 					if( aIter != mpShapeMap->end() )
1576 					{
1577 						(*aIter).second = xAcc;
1578 					}
1579 					else
1580 					{
1581 						SwAccessibleShapeMap_Impl::value_type aEntry( pObj,
1582 																	  xAcc );
1583 						mpShapeMap->insert( aEntry );
1584 					}
1585 					// TODO: focus!!!
1586 				}
1587 			}
1588 		}
1589 	}
1590 
1591 	// Invalidate focus for old object when map is not locked
1592 	if( xOldCursorAcc.is() )
1593 		InvalidateCursorPosition( xOldCursorAcc );
1594 
1595 	return xAcc;
1596 }
1597 
1598 ::vos::ORef < ::accessibility::AccessibleShape > SwAccessibleMap::GetContextImpl(
1599 			const SdrObject *pObj,
1600 			SwAccessibleContext *pParentImpl,
1601 			sal_Bool bCreate )
1602 {
1603 	uno::Reference < XAccessible > xAcc( GetContext( pObj, pParentImpl, bCreate ) );
1604 
1605 	::vos::ORef < ::accessibility::AccessibleShape > xAccImpl(
1606 		 static_cast< ::accessibility::AccessibleShape* >( xAcc.get() ) );
1607 
1608 	return xAccImpl;
1609 }
1610 
1611 
1612 void SwAccessibleMap::RemoveContext( const SwFrm *pFrm )
1613 {
1614 	vos::OGuard aGuard( maMutex );
1615 
1616 	if( mpFrmMap )
1617 	{
1618 		SwAccessibleContextMap_Impl::iterator aIter =
1619 			mpFrmMap->find( pFrm );
1620 		if( aIter != mpFrmMap->end() )
1621 		{
1622 			mpFrmMap->erase( aIter );
1623 
1624 			// Remove reference to old caret object. Though mxCursorContext
1625 			// is a weak reference and cleared automatically, clearing it
1626 			// directly makes sure to not keep a defunctional object.
1627 			uno::Reference < XAccessible > xOldAcc( mxCursorContext );
1628 			if( xOldAcc.is() )
1629 			{
1630 				SwAccessibleContext *pOldAccImpl =
1631 					static_cast< SwAccessibleContext *>( xOldAcc.get() );
1632 				ASSERT( pOldAccImpl->GetFrm(), "old caret context is disposed" );
1633 				if( pOldAccImpl->GetFrm() == pFrm )
1634 				{
1635 					xOldAcc.clear();	// get an empty ref
1636 					mxCursorContext = xOldAcc;
1637 				}
1638 			}
1639 
1640 			if( mpFrmMap->empty() )
1641 			{
1642 				delete mpFrmMap;
1643 				mpFrmMap = 0;
1644 			}
1645 		}
1646 	}
1647 }
1648 
1649 void SwAccessibleMap::RemoveContext( const SdrObject *pObj )
1650 {
1651 	vos::OGuard aGuard( maMutex );
1652 
1653 	if( mpShapeMap )
1654 	{
1655 		SwAccessibleShapeMap_Impl::iterator aIter =
1656 			mpShapeMap->find( pObj );
1657 		if( aIter != mpShapeMap->end() )
1658 		{
1659 			mpShapeMap->erase( aIter );
1660 
1661 			// The shape selection flag is not cleared, but one might do
1662 			// so but has to make sure that the removed context is the one
1663 			// that is selected.
1664 
1665 			if( mpShapeMap->empty() )
1666 			{
1667 				delete mpShapeMap;
1668 				mpShapeMap = 0;
1669 			}
1670 		}
1671 	}
1672 }
1673 
1674 
1675 void SwAccessibleMap::Dispose( const SwFrm *pFrm,
1676                                const SdrObject *pObj,
1677                                Window* pWindow,
1678 							   sal_Bool bRecursive )
1679 {
1680     SwAccessibleChild aFrmOrObj( pFrm, pObj, pWindow );
1681 
1682 	// Indeed, the following assert checks the frame's accessible flag,
1683 	// because that's the one that is evaluated in the layout. The frame
1684 	// might not be accessible anyway. That's the case for cell frames that
1685 	// contain further cells.
1686 	ASSERT( !aFrmOrObj.GetSwFrm() || aFrmOrObj.GetSwFrm()->IsAccessibleFrm(),
1687 			"non accessible frame should be disposed" );
1688 
1689 	if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) )
1690 	{
1691         ::vos::ORef< SwAccessibleContext > xAccImpl;
1692         ::vos::ORef< SwAccessibleContext > xParentAccImpl;
1693         ::vos::ORef< ::accessibility::AccessibleShape > xShapeAccImpl;
1694 		// get accessible context for frame
1695 		{
1696 			vos::OGuard aGuard( maMutex );
1697 
1698 			// First of all look for an accessible context for a frame
1699 			if( aFrmOrObj.GetSwFrm() && mpFrmMap )
1700 			{
1701 				SwAccessibleContextMap_Impl::iterator aIter =
1702 					mpFrmMap->find( aFrmOrObj.GetSwFrm() );
1703 				if( aIter != mpFrmMap->end() )
1704 				{
1705 					uno::Reference < XAccessible > xAcc( (*aIter).second );
1706 					xAccImpl =
1707 						static_cast< SwAccessibleContext *>( xAcc.get() );
1708 				}
1709 			}
1710 			if( !xAccImpl.isValid() && mpFrmMap )
1711 			{
1712 				// If there is none, look if the parent is accessible.
1713 				const SwFrm *pParent =
1714 						SwAccessibleFrame::GetParent( aFrmOrObj,
1715                                                       GetShell()->IsPreView());
1716 
1717 				if( pParent )
1718 				{
1719 					SwAccessibleContextMap_Impl::iterator aIter =
1720 						mpFrmMap->find( pParent );
1721 					if( aIter != mpFrmMap->end() )
1722 					{
1723 						uno::Reference < XAccessible > xAcc( (*aIter).second );
1724 						xParentAccImpl =
1725 							static_cast< SwAccessibleContext *>( xAcc.get() );
1726 					}
1727 				}
1728 			}
1729 			if( !xParentAccImpl.isValid() && !aFrmOrObj.GetSwFrm() &&
1730 				mpShapeMap )
1731 			{
1732 				SwAccessibleShapeMap_Impl::iterator aIter =
1733                     mpShapeMap->find( aFrmOrObj.GetDrawObject() );
1734 				if( aIter != mpShapeMap->end() )
1735 				{
1736 					uno::Reference < XAccessible > xAcc( (*aIter).second );
1737 					xShapeAccImpl =
1738 						static_cast< ::accessibility::AccessibleShape *>( xAcc.get() );
1739 				}
1740 			}
1741 			if( pObj && GetShell()->ActionPend() &&
1742 				(xParentAccImpl.isValid() || xShapeAccImpl.isValid()) )
1743 			{
1744 				// Keep a reference to the XShape to avoid that it
1745 				// is deleted with a SwFrmFmt::Modify.
1746 				uno::Reference < drawing::XShape > xShape(
1747 					const_cast< SdrObject * >( pObj )->getUnoShape(),
1748 					uno::UNO_QUERY );
1749 				if( xShape.is() )
1750 				{
1751 					if( !mpShapes )
1752 						mpShapes = new SwShapeList_Impl;
1753 					mpShapes->push_back( xShape );
1754 				}
1755 			}
1756 		}
1757 
1758 		// remove events stored for the frame
1759 		{
1760 			vos::OGuard aGuard( maEventMutex );
1761 			if( mpEvents )
1762 			{
1763 				SwAccessibleEventMap_Impl::iterator aIter =
1764 					mpEventMap->find( aFrmOrObj );
1765 				if( aIter != mpEventMap->end() )
1766 				{
1767 					SwAccessibleEvent_Impl aEvent(
1768 							SwAccessibleEvent_Impl::DISPOSE, aFrmOrObj );
1769 					AppendEvent( aEvent );
1770 				}
1771 			}
1772 		}
1773 
1774 		// If the frame is accessible and there is a context for it, dispose
1775 		// the frame. If the frame is no context for it but disposing should
1776 		// take place recursive, the frame's children have to be disposed
1777 		// anyway, so we have to create the context then.
1778 		if( xAccImpl.isValid() )
1779 		{
1780 			xAccImpl->Dispose( bRecursive );
1781 		}
1782 		else if( xParentAccImpl.isValid() )
1783 		{
1784 			// If the frame is a cell frame, the table must be notified.
1785 			// If we are in an action, a table model change event will
1786 			// be broadcasted at the end of the action to give the table
1787 			// a chance to generate a single table change event.
1788 
1789 			xParentAccImpl->DisposeChild( aFrmOrObj, bRecursive );
1790 		}
1791 		else if( xShapeAccImpl.isValid() )
1792 		{
1793             RemoveContext( aFrmOrObj.GetDrawObject() );
1794 			xShapeAccImpl->dispose();
1795 		}
1796 
1797 		if( mpPreview && pFrm && pFrm->IsPageFrm() )
1798 			mpPreview->DisposePage( static_cast< const SwPageFrm *>( pFrm ) );
1799 	}
1800 }
1801 
1802 void SwAccessibleMap::InvalidatePosOrSize( const SwFrm *pFrm,
1803 										   const SdrObject *pObj,
1804                                            Window* pWindow,
1805 										   const SwRect& rOldBox )
1806 {
1807     SwAccessibleChild aFrmOrObj( pFrm, pObj, pWindow );
1808 	if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) )
1809 	{
1810 		::vos::ORef< SwAccessibleContext > xAccImpl;
1811 		::vos::ORef< SwAccessibleContext > xParentAccImpl;
1812 		{
1813 			vos::OGuard aGuard( maMutex );
1814 
1815 			if( mpFrmMap )
1816 			{
1817 				if( aFrmOrObj.GetSwFrm() )
1818 				{
1819 					SwAccessibleContextMap_Impl::iterator aIter =
1820 						mpFrmMap->find( aFrmOrObj.GetSwFrm() );
1821 					if( aIter != mpFrmMap->end() )
1822 					{
1823 						// If there is an accesible object already it is
1824 						// notified directly.
1825 						uno::Reference < XAccessible > xAcc( (*aIter).second );
1826 						xAccImpl =
1827 							static_cast< SwAccessibleContext *>( xAcc.get() );
1828 					}
1829 				}
1830 				if( !xAccImpl.isValid() )
1831 				{
1832 					// Otherwise we look if the parent is accessible.
1833 					// If not, there is nothing to do.
1834 					const SwFrm *pParent =
1835 						SwAccessibleFrame::GetParent( aFrmOrObj,
1836                                                       GetShell()->IsPreView());
1837 
1838 					if( pParent )
1839 					{
1840 						SwAccessibleContextMap_Impl::iterator aIter =
1841 							mpFrmMap->find( pParent );
1842 						if( aIter != mpFrmMap->end() )
1843 						{
1844 							uno::Reference < XAccessible > xAcc( (*aIter).second );
1845 							xParentAccImpl =
1846 								static_cast< SwAccessibleContext *>( xAcc.get() );
1847 						}
1848 					}
1849 				}
1850 			}
1851 		}
1852 
1853 		if( xAccImpl.isValid() )
1854 		{
1855 			if( GetShell()->ActionPend() )
1856 			{
1857 				SwAccessibleEvent_Impl aEvent(
1858 					SwAccessibleEvent_Impl::POS_CHANGED, xAccImpl.getBodyPtr(),
1859 					aFrmOrObj, rOldBox );
1860 				AppendEvent( aEvent );
1861 			}
1862 			else
1863 			{
1864 				FireEvents();
1865 				xAccImpl->InvalidatePosOrSize( rOldBox );
1866 			}
1867 		}
1868 		else if( xParentAccImpl.isValid() )
1869 		{
1870 			if( GetShell()->ActionPend() )
1871 			{
1872 				SwAccessibleEvent_Impl aEvent(
1873 					SwAccessibleEvent_Impl::CHILD_POS_CHANGED,
1874 					xParentAccImpl.getBodyPtr(), aFrmOrObj, rOldBox );
1875 				AppendEvent( aEvent );
1876 			}
1877 			else
1878 			{
1879 				FireEvents();
1880 				xParentAccImpl->InvalidateChildPosOrSize( aFrmOrObj,
1881 														  rOldBox );
1882 			}
1883 		}
1884 	}
1885 }
1886 
1887 void SwAccessibleMap::InvalidateContent( const SwFrm *pFrm )
1888 {
1889     SwAccessibleChild aFrmOrObj( pFrm );
1890 	if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) )
1891 	{
1892 		uno::Reference < XAccessible > xAcc;
1893 		{
1894 			vos::OGuard aGuard( maMutex );
1895 
1896 			if( mpFrmMap )
1897 			{
1898 				SwAccessibleContextMap_Impl::iterator aIter =
1899 					mpFrmMap->find( aFrmOrObj.GetSwFrm() );
1900 				if( aIter != mpFrmMap->end() )
1901 					xAcc = (*aIter).second;
1902 			}
1903 		}
1904 
1905 		if( xAcc.is() )
1906 		{
1907 			SwAccessibleContext *pAccImpl =
1908 				static_cast< SwAccessibleContext *>( xAcc.get() );
1909 			if( GetShell()->ActionPend() )
1910 			{
1911 				SwAccessibleEvent_Impl aEvent(
1912 					SwAccessibleEvent_Impl::INVALID_CONTENT, pAccImpl,
1913 					aFrmOrObj );
1914 				AppendEvent( aEvent );
1915 			}
1916 			else
1917 			{
1918 				FireEvents();
1919 				pAccImpl->InvalidateContent();
1920 			}
1921 		}
1922 	}
1923 }
1924 
1925 // --> OD 2009-01-06 #i88069#
1926 void SwAccessibleMap::InvalidateAttr( const SwTxtFrm& rTxtFrm )
1927 {
1928     SwAccessibleChild aFrmOrObj( &rTxtFrm );
1929     if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) )
1930     {
1931         uno::Reference < XAccessible > xAcc;
1932         {
1933             vos::OGuard aGuard( maMutex );
1934 
1935             if( mpFrmMap )
1936             {
1937                 SwAccessibleContextMap_Impl::iterator aIter =
1938                     mpFrmMap->find( aFrmOrObj.GetSwFrm() );
1939                 if( aIter != mpFrmMap->end() )
1940                     xAcc = (*aIter).second;
1941             }
1942         }
1943 
1944         if( xAcc.is() )
1945         {
1946             SwAccessibleContext *pAccImpl =
1947                 static_cast< SwAccessibleContext *>( xAcc.get() );
1948             if( GetShell()->ActionPend() )
1949             {
1950                 SwAccessibleEvent_Impl aEvent( SwAccessibleEvent_Impl::INVALID_ATTR,
1951                                                pAccImpl, aFrmOrObj );
1952                 aEvent.SetStates( ACC_STATE_TEXT_ATTRIBUTE_CHANGED );
1953                 AppendEvent( aEvent );
1954             }
1955             else
1956             {
1957                 FireEvents();
1958                 pAccImpl->InvalidateAttr();
1959             }
1960         }
1961     }
1962 }
1963 // <--
1964 
1965 void SwAccessibleMap::InvalidateCursorPosition( const SwFrm *pFrm )
1966 {
1967     SwAccessibleChild aFrmOrObj( pFrm );
1968 	sal_Bool bShapeSelected = sal_False;
1969 	const ViewShell *pVSh = GetShell();
1970 	if( pVSh->ISA( SwCrsrShell ) )
1971 	{
1972 		const SwCrsrShell *pCSh = static_cast< const SwCrsrShell * >( pVSh );
1973 		if( pCSh->IsTableMode() )
1974 		{
1975 			while( aFrmOrObj.GetSwFrm() && !aFrmOrObj.GetSwFrm()->IsCellFrm() )
1976 				aFrmOrObj = aFrmOrObj.GetSwFrm()->GetUpper();
1977 		}
1978 		else if( pVSh->ISA( SwFEShell ) )
1979 		{
1980 			sal_uInt16 nObjCount;
1981 			const SwFEShell *pFESh = static_cast< const SwFEShell * >( pVSh );
1982 			const SwFrm *pFlyFrm = pFESh->GetCurrFlyFrm();
1983 			if( pFlyFrm )
1984 			{
1985 				ASSERT( !pFrm || pFrm->FindFlyFrm() == pFlyFrm,
1986 						"cursor is not contained in fly frame" );
1987 				aFrmOrObj = pFlyFrm;
1988 			}
1989 			else if( (nObjCount = pFESh->IsObjSelected()) > 0 )
1990 			{
1991 				bShapeSelected = sal_True;
1992 				aFrmOrObj = static_cast<const SwFrm *>( 0 );
1993 			}
1994 		}
1995 	}
1996 
1997 	ASSERT( bShapeSelected || aFrmOrObj.IsAccessible(GetShell()->IsPreView()),
1998 			"frame is not accessible" );
1999 
2000 	uno::Reference < XAccessible > xOldAcc;
2001 	uno::Reference < XAccessible > xAcc;
2002 	sal_Bool bOldShapeSelected = sal_False;
2003 
2004 	{
2005 		vos::OGuard aGuard( maMutex );
2006 
2007 		xOldAcc = mxCursorContext;
2008 		mxCursorContext = xAcc;	// clear reference
2009 
2010 		bOldShapeSelected = mbShapeSelected;
2011 		mbShapeSelected = bShapeSelected;
2012 
2013 		if( aFrmOrObj.GetSwFrm() && mpFrmMap )
2014 		{
2015 			SwAccessibleContextMap_Impl::iterator aIter =
2016 				mpFrmMap->find( aFrmOrObj.GetSwFrm() );
2017 			if( aIter != mpFrmMap->end() )
2018 				xAcc = (*aIter).second;
2019 
2020 			// For cells, some extra thoughts are necessary,
2021 			// because invalidating the cursor for one cell
2022 			// invalidates the cursor for all cells of the same
2023 			// table. For this reason, we don't want to
2024 			// invalidate the cursor for the old cursor object
2025 			// and the new one if they are within the same table,
2026 			// because this would result in doing the work twice.
2027 			// Moreover, we have to make sure to invalidate the
2028 			// cursor even if the current cell has no accessible object.
2029 			// If the old cursor objects exists and is in the same
2030 			// table, its the best choice, because using it avoids
2031 			// an unnessarary cursor invalidation cycle when creating
2032 			// a new object for the current cell.
2033 			if( aFrmOrObj.GetSwFrm()->IsCellFrm() )
2034 			{
2035 				if( xOldAcc.is() &&
2036 					AreInSameTable( xOldAcc, aFrmOrObj.GetSwFrm() ) )
2037 				{
2038 					if( xAcc.is() )
2039 						xOldAcc = xAcc;	// avoid extra invalidation
2040 					else
2041 						xAcc = xOldAcc;	// make sure ate least one
2042 				}
2043 				if( !xAcc.is() )
2044 					xAcc = GetContext( aFrmOrObj.GetSwFrm(), sal_True );
2045 			}
2046 		}
2047 	}
2048 
2049 	if( xOldAcc.is() && xOldAcc != xAcc )
2050 		InvalidateCursorPosition( xOldAcc );
2051 	if( bOldShapeSelected || bShapeSelected )
2052 		InvalidateShapeSelection();
2053 	if( xAcc.is() )
2054 		InvalidateCursorPosition( xAcc );
2055 }
2056 
2057 void SwAccessibleMap::InvalidateFocus()
2058 {
2059 	uno::Reference < XAccessible > xAcc;
2060 	sal_Bool bShapeSelected;
2061 	{
2062 		vos::OGuard aGuard( maMutex );
2063 
2064 		xAcc = mxCursorContext;
2065 		bShapeSelected = mbShapeSelected;
2066 	}
2067 
2068 	if( xAcc.is() )
2069 	{
2070 		SwAccessibleContext *pAccImpl =
2071 			static_cast< SwAccessibleContext *>( xAcc.get() );
2072 		pAccImpl->InvalidateFocus();
2073 	}
2074 	else if( bShapeSelected  )
2075 	{
2076 		DoInvalidateShapeFocus();
2077 	}
2078 }
2079 
2080 void SwAccessibleMap::SetCursorContext(
2081 		const ::vos::ORef < SwAccessibleContext >& rCursorContext )
2082 {
2083 	vos::OGuard aGuard( maMutex );
2084 	uno::Reference < XAccessible > xAcc( rCursorContext.getBodyPtr() );
2085 	mxCursorContext = xAcc;
2086 }
2087 
2088 // --> OD 2005-12-12 #i27301# - use new type definition for <_nStates>
2089 void SwAccessibleMap::InvalidateStates( tAccessibleStates _nStates,
2090                                         const SwFrm* _pFrm )
2091 {
2092 	// Start with the frame or the first upper that is accessible
2093     SwAccessibleChild aFrmOrObj( _pFrm );
2094 	while( aFrmOrObj.GetSwFrm() &&
2095 			!aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) )
2096 		aFrmOrObj = aFrmOrObj.GetSwFrm()->GetUpper();
2097 	if( !aFrmOrObj.GetSwFrm() )
2098 		aFrmOrObj = GetShell()->GetLayout();
2099 
2100 	uno::Reference< XAccessible > xAcc( GetContext( aFrmOrObj.GetSwFrm(), sal_True ) );
2101 	SwAccessibleContext *pAccImpl =
2102 		static_cast< SwAccessibleContext *>( xAcc.get() );
2103 	if( GetShell()->ActionPend() )
2104 	{
2105         SwAccessibleEvent_Impl aEvent( SwAccessibleEvent_Impl::CARET_OR_STATES,
2106                                        pAccImpl,
2107                                        SwAccessibleChild(pAccImpl->GetFrm()),
2108                                        _nStates );
2109 		AppendEvent( aEvent );
2110 	}
2111 	else
2112 	{
2113 		FireEvents();
2114         pAccImpl->InvalidateStates( _nStates );
2115 	}
2116 }
2117 // <--
2118 
2119 void SwAccessibleMap::_InvalidateRelationSet( const SwFrm* pFrm,
2120                                               sal_Bool bFrom )
2121 {
2122     // first, see if this frame is accessible, and if so, get the respective
2123     SwAccessibleChild aFrmOrObj( pFrm );
2124 	if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) )
2125 	{
2126 		uno::Reference < XAccessible > xAcc;
2127 		{
2128 			vos::OGuard aGuard( maMutex );
2129 
2130 			if( mpFrmMap )
2131 			{
2132 				SwAccessibleContextMap_Impl::iterator aIter =
2133                                         mpFrmMap->find( aFrmOrObj.GetSwFrm() );
2134 				if( aIter != mpFrmMap->end() )
2135 				{
2136 					xAcc = (*aIter).second;
2137 				}
2138 			}
2139 		}
2140 
2141         // deliver event directly, or queue event
2142 		if( xAcc.is() )
2143 		{
2144 			SwAccessibleContext *pAccImpl =
2145                             static_cast< SwAccessibleContext *>( xAcc.get() );
2146             if( GetShell()->ActionPend() )
2147             {
2148                 SwAccessibleEvent_Impl aEvent( SwAccessibleEvent_Impl::CARET_OR_STATES,
2149                                                pAccImpl, SwAccessibleChild(pFrm),
2150                                                ( bFrom
2151                                                  ? ACC_STATE_RELATION_FROM
2152                                                  : ACC_STATE_RELATION_TO ) );
2153                 AppendEvent( aEvent );
2154             }
2155             else
2156             {
2157 				FireEvents();
2158                 pAccImpl->InvalidateRelation( bFrom
2159                         ? AccessibleEventId::CONTENT_FLOWS_FROM_RELATION_CHANGED
2160                         : AccessibleEventId::CONTENT_FLOWS_TO_RELATION_CHANGED );
2161             }
2162         }
2163     }
2164 }
2165 
2166 void SwAccessibleMap::InvalidateRelationSet( const SwFrm* pMaster,
2167                                              const SwFrm* pFollow )
2168 {
2169     _InvalidateRelationSet( pMaster, sal_False );
2170     _InvalidateRelationSet( pFollow, sal_True );
2171 }
2172 
2173 /** invalidation CONTENT_FLOW_FROM/_TO relation of a paragraph
2174 
2175     OD 2005-12-01 #i27138#
2176 
2177     @author OD
2178 */
2179 void SwAccessibleMap::InvalidateParaFlowRelation( const SwTxtFrm& _rTxtFrm,
2180                                                   const bool _bFrom )
2181 {
2182     _InvalidateRelationSet( &_rTxtFrm, _bFrom );
2183 }
2184 
2185 /** invalidation of text selection of a paragraph
2186 
2187     OD 2005-12-12 #i27301#
2188 
2189     @author OD
2190 */
2191 void SwAccessibleMap::InvalidateParaTextSelection( const SwTxtFrm& _rTxtFrm )
2192 {
2193     // first, see if this frame is accessible, and if so, get the respective
2194     SwAccessibleChild aFrmOrObj( &_rTxtFrm );
2195     if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) )
2196     {
2197         uno::Reference < XAccessible > xAcc;
2198         {
2199             vos::OGuard aGuard( maMutex );
2200 
2201             if( mpFrmMap )
2202             {
2203                 SwAccessibleContextMap_Impl::iterator aIter =
2204                                         mpFrmMap->find( aFrmOrObj.GetSwFrm() );
2205                 if( aIter != mpFrmMap->end() )
2206                 {
2207                     xAcc = (*aIter).second;
2208                 }
2209             }
2210         }
2211 
2212         // deliver event directly, or queue event
2213         if( xAcc.is() )
2214         {
2215             SwAccessibleContext *pAccImpl =
2216                             static_cast< SwAccessibleContext *>( xAcc.get() );
2217             if( GetShell()->ActionPend() )
2218             {
2219                 SwAccessibleEvent_Impl aEvent(
2220                     SwAccessibleEvent_Impl::CARET_OR_STATES,
2221                     pAccImpl,
2222                     SwAccessibleChild( &_rTxtFrm ),
2223                     ACC_STATE_TEXT_SELECTION_CHANGED );
2224                 AppendEvent( aEvent );
2225             }
2226             else
2227             {
2228                 FireEvents();
2229                 pAccImpl->InvalidateTextSelection();
2230             }
2231         }
2232     }
2233 }
2234 
2235 sal_Int32 SwAccessibleMap::GetChildIndex( const SwFrm& rParentFrm,
2236                                           Window& rChild ) const
2237 {
2238     sal_Int32 nIndex( -1 );
2239 
2240     SwAccessibleChild aFrmOrObj( &rParentFrm );
2241     if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) )
2242     {
2243         uno::Reference < XAccessible > xAcc;
2244         {
2245             vos::OGuard aGuard( maMutex );
2246 
2247             if( mpFrmMap )
2248             {
2249                 SwAccessibleContextMap_Impl::iterator aIter =
2250                                         mpFrmMap->find( aFrmOrObj.GetSwFrm() );
2251                 if( aIter != mpFrmMap->end() )
2252                 {
2253                     xAcc = (*aIter).second;
2254                 }
2255             }
2256         }
2257 
2258         if( xAcc.is() )
2259         {
2260             SwAccessibleContext *pAccImpl =
2261                             static_cast< SwAccessibleContext *>( xAcc.get() );
2262 
2263             nIndex = pAccImpl->GetChildIndex( const_cast<SwAccessibleMap&>(*this),
2264                                               SwAccessibleChild( &rChild ) );
2265         }
2266     }
2267 
2268     return nIndex;
2269 }
2270 
2271 
2272 // OD 15.01.2003 #103492# - complete re-factoring of method due to new page/print
2273 // preview functionality.
2274 void SwAccessibleMap::UpdatePreview( const std::vector<PrevwPage*>& _rPrevwPages,
2275                                      const Fraction&  _rScale,
2276                                      const SwPageFrm* _pSelectedPageFrm,
2277                                      const Size&      _rPrevwWinSize )
2278 {
2279     DBG_ASSERT( GetShell()->IsPreView(), "no preview?" );
2280     DBG_ASSERT( mpPreview != NULL, "no preview data?" );
2281 
2282     // OD 15.01.2003 #103492# - adjustments for changed method signature
2283     mpPreview->Update( *this, _rPrevwPages, _rScale, _pSelectedPageFrm, _rPrevwWinSize );
2284 
2285     // propagate change of VisArea through the document's
2286     // accessibility tree; this will also send appropriate scroll
2287     // events
2288     SwAccessibleContext* pDoc =
2289         GetContextImpl( GetShell()->GetLayout() ).getBodyPtr();
2290     static_cast<SwAccessibleDocumentBase*>( pDoc )->SetVisArea();
2291 
2292 	uno::Reference < XAccessible > xOldAcc;
2293 	uno::Reference < XAccessible > xAcc;
2294 	{
2295 		vos::OGuard aGuard( maMutex );
2296 
2297 		xOldAcc = mxCursorContext;
2298 
2299 		const SwPageFrm *pSelPage = mpPreview->GetSelPage();
2300 		if( pSelPage && mpFrmMap )
2301 		{
2302 			SwAccessibleContextMap_Impl::iterator aIter =
2303 				mpFrmMap->find( pSelPage );
2304 			if( aIter != mpFrmMap->end() )
2305 				xAcc = (*aIter).second;
2306 		}
2307 	}
2308 
2309 	if( xOldAcc.is() && xOldAcc != xAcc )
2310 		InvalidateCursorPosition( xOldAcc );
2311 	if( xAcc.is() )
2312 		InvalidateCursorPosition( xAcc );
2313 }
2314 
2315 void SwAccessibleMap::InvalidatePreViewSelection( sal_uInt16 nSelPage )
2316 {
2317     DBG_ASSERT( GetShell()->IsPreView(), "no preview?" );
2318     DBG_ASSERT( mpPreview != NULL, "no preview data?" );
2319 
2320     // OD 16.01.2003 #103492# - changed metthod call due to method signature change.
2321     mpPreview->InvalidateSelection( GetShell()->GetLayout()->GetPageByPageNum( nSelPage ) );
2322 
2323 	uno::Reference < XAccessible > xOldAcc;
2324 	uno::Reference < XAccessible > xAcc;
2325 	{
2326 		vos::OGuard aGuard( maMutex );
2327 
2328 		xOldAcc = mxCursorContext;
2329 
2330 		const SwPageFrm *pSelPage = mpPreview->GetSelPage();
2331 		if( pSelPage && mpFrmMap )
2332 		{
2333 			SwAccessibleContextMap_Impl::iterator aIter =
2334 				mpFrmMap->find( pSelPage );
2335 			if( aIter != mpFrmMap->end() )
2336 				xAcc = (*aIter).second;
2337 		}
2338 	}
2339 
2340 	if( xOldAcc.is() && xOldAcc != xAcc )
2341 		InvalidateCursorPosition( xOldAcc );
2342 	if( xAcc.is() )
2343 		InvalidateCursorPosition( xAcc );
2344 }
2345 
2346 
2347 sal_Bool SwAccessibleMap::IsPageSelected( const SwPageFrm *pPageFrm ) const
2348 {
2349 	return mpPreview && mpPreview->GetSelPage() == pPageFrm;
2350 }
2351 
2352 
2353 void SwAccessibleMap::FireEvents()
2354 {
2355 	{
2356 		vos::OGuard aGuard( maEventMutex );
2357 		if( mpEvents )
2358 		{
2359 			mpEvents->SetFiring();
2360 			SwAccessibleEventList_Impl::iterator aIter = mpEvents->begin();
2361 			while( aIter != mpEvents->end() )
2362 			{
2363 				FireEvent( *aIter );
2364 				++aIter;
2365 			}
2366 
2367 			delete mpEventMap;
2368 			mpEventMap = 0;
2369 
2370 			delete mpEvents;
2371 			mpEvents = 0;
2372 		}
2373 	}
2374 	{
2375 		vos::OGuard aGuard( maMutex );
2376 		if( mpShapes )
2377 		{
2378 			delete mpShapes;
2379 			mpShapes = 0;
2380 		}
2381 	}
2382 
2383 }
2384 
2385 sal_Bool SwAccessibleMap::IsValid() const
2386 {
2387 	return sal_True;
2388 }
2389 
2390 Rectangle SwAccessibleMap::GetVisibleArea() const
2391 {
2392     MapMode aSrc( MAP_TWIP );
2393 	MapMode aDest( MAP_100TH_MM );
2394 	return OutputDevice::LogicToLogic( GetVisArea().SVRect(), aSrc, aDest );
2395 }
2396 
2397 // Convert a MM100 value realtive to the document root into a pixel value
2398 // realtive to the screen!
2399 Point SwAccessibleMap::LogicToPixel( const Point& rPoint ) const
2400 {
2401 	MapMode aSrc( MAP_100TH_MM );
2402 	MapMode aDest( MAP_TWIP );
2403 
2404     Point aPoint = rPoint;
2405 
2406 	aPoint = OutputDevice::LogicToLogic( aPoint, aSrc, aDest );
2407 	Window *pWin = GetShell()->GetWin();
2408 	if( pWin )
2409     {
2410         // OD 16.01.2003 #103492# - get mapping mode for LogicToPixel conversion
2411         MapMode aMapMode;
2412         GetMapMode( aPoint, aMapMode );
2413         aPoint = pWin->LogicToPixel( aPoint, aMapMode );
2414 		aPoint = pWin->OutputToAbsoluteScreenPixel( aPoint );
2415     }
2416 
2417 	return aPoint;
2418 }
2419 
2420 Size SwAccessibleMap::LogicToPixel( const Size& rSize ) const
2421 {
2422 	MapMode aSrc( MAP_100TH_MM );
2423 	MapMode aDest( MAP_TWIP );
2424 	Size aSize( OutputDevice::LogicToLogic( rSize, aSrc, aDest ) );
2425 	if( GetShell()->GetWin() )
2426     {
2427         // OD 16.01.2003 #103492# - get mapping mode for LogicToPixel conversion
2428         MapMode aMapMode;
2429         GetMapMode( Point(0,0), aMapMode );
2430         aSize = GetShell()->GetWin()->LogicToPixel( aSize, aMapMode );
2431     }
2432 
2433 	return aSize;
2434 }
2435 
2436 Point SwAccessibleMap::PixelToLogic( const Point& rPoint ) const
2437 {
2438 	Point aPoint;
2439 	Window *pWin = GetShell()->GetWin();
2440 	if( pWin )
2441 	{
2442 		aPoint = pWin->ScreenToOutputPixel( rPoint );
2443         // OD 16.01.2003 #103492# - get mapping mode for PixelToLogic conversion
2444         MapMode aMapMode;
2445         GetMapMode( aPoint, aMapMode );
2446         aPoint = pWin->PixelToLogic( aPoint, aMapMode );
2447 		MapMode aSrc( MAP_TWIP );
2448 		MapMode aDest( MAP_100TH_MM );
2449 		aPoint = OutputDevice::LogicToLogic( aPoint, aSrc, aDest );
2450 	}
2451 
2452 	return aPoint;
2453 }
2454 
2455 Size SwAccessibleMap::PixelToLogic( const Size& rSize ) const
2456 {
2457 	Size aSize;
2458 	if( GetShell()->GetWin() )
2459 	{
2460         // OD 16.01.2003 #103492# - get mapping mode for PixelToLogic conversion
2461         MapMode aMapMode;
2462         GetMapMode( Point(0,0), aMapMode );
2463         aSize = GetShell()->GetWin()->PixelToLogic( rSize, aMapMode );
2464 		MapMode aSrc( MAP_TWIP );
2465 		MapMode aDest( MAP_100TH_MM );
2466 		aSize = OutputDevice::LogicToLogic( aSize, aSrc, aDest );
2467 	}
2468 
2469 	return aSize;
2470 }
2471 
2472 sal_Bool SwAccessibleMap::ReplaceChild (
2473         ::accessibility::AccessibleShape* pCurrentChild,
2474 		const uno::Reference< drawing::XShape >& _rxShape,
2475         const long /*_nIndex*/,
2476         const ::accessibility::AccessibleShapeTreeInfo& /*_rShapeTreeInfo*/
2477 	)	throw (uno::RuntimeException)
2478 {
2479 	const SdrObject *pObj = 0;
2480 	{
2481 		vos::OGuard aGuard( maMutex );
2482 		if( mpShapeMap )
2483 		{
2484 			SwAccessibleShapeMap_Impl::const_iterator aIter = mpShapeMap->begin();
2485 			SwAccessibleShapeMap_Impl::const_iterator aEndIter = mpShapeMap->end();
2486 			while( aIter != aEndIter && !pObj )
2487 			{
2488 				uno::Reference < XAccessible > xAcc( (*aIter).second );
2489 				::accessibility::AccessibleShape *pAccShape =
2490 					static_cast < ::accessibility::AccessibleShape* >( xAcc.get() );
2491 				if( pAccShape == pCurrentChild )
2492 				{
2493 					pObj = (*aIter).first;
2494 				}
2495 				++aIter;
2496 			}
2497 		}
2498 	}
2499 	if( !pObj )
2500 		return sal_False;
2501 
2502 	uno::Reference < drawing::XShape > xShape( _rxShape ); //keep reference to shape, because
2503 											 // we might be the only one that
2504 											 // hold it.
2505 	// Also get keep parent.
2506 	uno::Reference < XAccessible > xParent( pCurrentChild->getAccessibleParent() );
2507 	pCurrentChild = 0;	// well be realease by dispose
2508     Dispose( 0, pObj, 0 );
2509 
2510 	{
2511 		vos::OGuard aGuard( maMutex );
2512 
2513 		if( !mpShapeMap )
2514 			mpShapeMap = new SwAccessibleShapeMap_Impl( this );
2515 
2516 		// create the new child
2517 		::accessibility::ShapeTypeHandler& rShapeTypeHandler =
2518 						::accessibility::ShapeTypeHandler::Instance();
2519 		::accessibility::AccessibleShapeInfo aShapeInfo(
2520 											xShape, xParent, this );
2521 		::accessibility::AccessibleShape* pReplacement =
2522 			rShapeTypeHandler.CreateAccessibleObject (
2523 				aShapeInfo, mpShapeMap->GetInfo() );
2524 
2525 		uno::Reference < XAccessible > xAcc( pReplacement );
2526 		if( xAcc.is() )
2527 		{
2528 			pReplacement->Init();
2529 
2530 			SwAccessibleShapeMap_Impl::iterator aIter =
2531 				mpShapeMap->find( pObj );
2532 			if( aIter != mpShapeMap->end() )
2533 			{
2534 				(*aIter).second = xAcc;
2535 			}
2536 			else
2537 			{
2538 				SwAccessibleShapeMap_Impl::value_type aEntry( pObj, xAcc );
2539 				mpShapeMap->insert( aEntry );
2540 			}
2541 		}
2542 	}
2543 
2544 	SwRect aEmptyRect;
2545     InvalidatePosOrSize( 0, pObj, 0, aEmptyRect );
2546 
2547 	return sal_True;
2548 }
2549 
2550 Point SwAccessibleMap::PixelToCore( const Point& rPoint ) const
2551 {
2552 	Point aPoint;
2553 	if( GetShell()->GetWin() )
2554 	{
2555         // OD 15.01.2003 #103492# - replace <PreviewAdjust(..)> by <GetMapMode(..)>
2556         MapMode aMapMode;
2557         GetMapMode( rPoint, aMapMode );
2558         aPoint = GetShell()->GetWin()->PixelToLogic( rPoint, aMapMode );
2559 	}
2560 	return aPoint;
2561 }
2562 
2563 static inline long lcl_CorrectCoarseValue(long aCoarseValue, long aFineValue,
2564                                           long aRefValue, bool bToLower)
2565 {
2566     long aResult = aCoarseValue;
2567 
2568     if (bToLower)
2569     {
2570         if (aFineValue < aRefValue)
2571             aResult -= 1;
2572     }
2573     else
2574     {
2575         if (aFineValue > aRefValue)
2576             aResult += 1;
2577     }
2578 
2579     return aResult;
2580 }
2581 
2582 static inline void lcl_CorrectRectangle(Rectangle & rRect,
2583                                         const Rectangle & rSource,
2584                                         const Rectangle & rInGrid)
2585 {
2586     rRect.nLeft = lcl_CorrectCoarseValue(rRect.nLeft, rSource.nLeft,
2587                                          rInGrid.nLeft, false);
2588     rRect.nTop = lcl_CorrectCoarseValue(rRect.nTop, rSource.nTop,
2589                                         rInGrid.nTop, false);
2590     rRect.nRight = lcl_CorrectCoarseValue(rRect.nRight, rSource.nRight,
2591                                           rInGrid.nRight, true);
2592     rRect.nBottom = lcl_CorrectCoarseValue(rRect.nBottom, rSource.nBottom,
2593                                            rInGrid.nBottom, true);
2594 }
2595 
2596 Rectangle SwAccessibleMap::CoreToPixel( const Rectangle& rRect ) const
2597 {
2598     Rectangle aRect;
2599 	if( GetShell()->GetWin() )
2600     {
2601         // OD 15.01.2003 #103492# - replace <PreviewAdjust(..)> by <GetMapMode(..)>
2602         MapMode aMapMode;
2603         GetMapMode( rRect.TopLeft(), aMapMode );
2604         aRect = GetShell()->GetWin()->LogicToPixel( rRect, aMapMode );
2605 
2606         Rectangle aTmpRect = GetShell()->GetWin()->PixelToLogic( aRect, aMapMode );
2607         lcl_CorrectRectangle(aRect, rRect, aTmpRect);
2608     }
2609 
2610 	return aRect;
2611 }
2612 
2613 /** get mapping mode for LogicToPixel and PixelToLogic conversions
2614 
2615     OD 15.01.2003 #103492#
2616     Replacement method <PreviewAdjust(..)> by new method <GetMapMode>.
2617     Method returns mapping mode of current output device and adjusts it,
2618     if the shell is in page/print preview.
2619     Necessary, because <PreviewAdjust(..)> changes mapping mode at current
2620     output device for mapping logic document positions to page preview window
2621     positions and vice versa and doesn't take care to recover its changes.
2622 
2623     @author OD
2624 */
2625 void SwAccessibleMap::GetMapMode( const Point& _rPoint,
2626                                   MapMode&     _orMapMode ) const
2627 {
2628     MapMode aMapMode = GetShell()->GetWin()->GetMapMode();
2629     if( GetShell()->IsPreView() )
2630     {
2631         DBG_ASSERT( mpPreview != NULL, "need preview data" );
2632 
2633         mpPreview->AdjustMapMode( aMapMode, _rPoint );
2634     }
2635     _orMapMode = aMapMode;
2636 }
2637 
2638 /** get size of a dedicated preview page
2639 
2640     OD 15.01.2003 #103492#
2641 
2642     @author OD
2643 */
2644 Size SwAccessibleMap::GetPreViewPageSize( sal_uInt16 _nPrevwPageNum ) const
2645 {
2646     DBG_ASSERT( mpVSh->IsPreView(), "no page preview accessible." );
2647     DBG_ASSERT( mpVSh->IsPreView() && ( mpPreview != NULL ),
2648                 "missing accessible preview data at page preview" );
2649     if ( mpVSh->IsPreView() && ( mpPreview != NULL ) )
2650     {
2651         return mpVSh->PagePreviewLayout()->GetPrevwPageSizeByPageNum( _nPrevwPageNum );
2652     }
2653     else
2654     {
2655         return Size( 0, 0 );
2656     }
2657 }
2658 
2659 /** method to build up a new data structure of the accessible pararaphs,
2660     which have a selection
2661 
2662     OD 2005-12-13 #i27301#
2663     Important note: method has to used inside a mutual exclusive section
2664 
2665     @author OD
2666 */
2667 SwAccessibleSelectedParas_Impl* SwAccessibleMap::_BuildSelectedParas()
2668 {
2669     // no accessible contexts, no selection
2670     if ( !mpFrmMap )
2671     {
2672         return 0L;
2673     }
2674 
2675     // get cursor as an instance of its base class <SwPaM>
2676     SwPaM* pCrsr( 0L );
2677     {
2678         SwCrsrShell* pCrsrShell = dynamic_cast<SwCrsrShell*>(GetShell());
2679         if ( pCrsrShell )
2680         {
2681             SwFEShell* pFEShell = dynamic_cast<SwFEShell*>(pCrsrShell);
2682             if ( !pFEShell ||
2683                  ( !pFEShell->IsFrmSelected() &&
2684                    pFEShell->IsObjSelected() == 0 ) )
2685             {
2686                 // get cursor without updating an existing table cursor.
2687                 pCrsr = pCrsrShell->GetCrsr( sal_False );
2688             }
2689         }
2690     }
2691     // no cursor, no selection
2692     if ( !pCrsr )
2693     {
2694         return 0L;
2695     }
2696 
2697     SwAccessibleSelectedParas_Impl* pRetSelectedParas( 0L );
2698 
2699     // loop on all cursors
2700     SwPaM* pRingStart = pCrsr;
2701     do {
2702 
2703         // for a selection the cursor has to have a mark.
2704         // for savety reasons assure that point and mark are in text nodes
2705         if ( pCrsr->HasMark() &&
2706              pCrsr->GetPoint()->nNode.GetNode().IsTxtNode() &&
2707              pCrsr->GetMark()->nNode.GetNode().IsTxtNode() )
2708         {
2709             SwPosition* pStartPos = pCrsr->Start();
2710             SwPosition* pEndPos = pCrsr->End();
2711             // loop on all text nodes inside the selection
2712             SwNodeIndex aIdx( pStartPos->nNode );
2713             for ( ; aIdx.GetIndex() <= pEndPos->nNode.GetIndex(); ++aIdx )
2714             {
2715                 SwTxtNode* pTxtNode( aIdx.GetNode().GetTxtNode() );
2716                 if ( pTxtNode )
2717                 {
2718                     // loop on all text frames registered at the text node.
2719                     SwIterator<SwTxtFrm,SwTxtNode> aIter( *pTxtNode );
2720                     for( SwTxtFrm* pTxtFrm = aIter.First(); pTxtFrm; pTxtFrm = aIter.Next() )
2721                         {
2722                             uno::WeakReference < XAccessible > xWeakAcc;
2723                             SwAccessibleContextMap_Impl::iterator aMapIter =
2724                                                     mpFrmMap->find( pTxtFrm );
2725                             if( aMapIter != mpFrmMap->end() )
2726                             {
2727                                 xWeakAcc = (*aMapIter).second;
2728                                 SwAccessibleParaSelection aDataEntry(
2729                                     pTxtNode == &(pStartPos->nNode.GetNode())
2730                                                 ? pStartPos->nContent.GetIndex()
2731                                                 : 0,
2732                                     pTxtNode == &(pEndPos->nNode.GetNode())
2733                                                 ? pEndPos->nContent.GetIndex()
2734                                                 : STRING_LEN );
2735                                 SwAccessibleSelectedParas_Impl::value_type
2736                                                 aEntry( xWeakAcc, aDataEntry );
2737                                 if ( !pRetSelectedParas )
2738                                 {
2739                                     pRetSelectedParas =
2740                                             new SwAccessibleSelectedParas_Impl;
2741                                 }
2742                                 pRetSelectedParas->insert( aEntry );
2743                             }
2744                         }
2745                     }
2746                 }
2747             }
2748 
2749         // prepare next turn: get next cursor in ring
2750         pCrsr = static_cast<SwPaM*>( pCrsr->GetNext() );
2751     } while ( pCrsr != pRingStart );
2752 
2753     return pRetSelectedParas;
2754 }
2755 
2756 /** invalidation of text selection of all paragraphs
2757 
2758     OD 2005-12-13 #i27301#
2759 
2760     @author OD
2761 */
2762 void SwAccessibleMap::InvalidateTextSelectionOfAllParas()
2763 {
2764     vos::OGuard aGuard( maMutex );
2765 
2766     // keep previously known selected paragraphs
2767     SwAccessibleSelectedParas_Impl* pPrevSelectedParas( mpSelectedParas );
2768 
2769     // determine currently selected paragraphs
2770     mpSelectedParas = _BuildSelectedParas();
2771 
2772     // compare currently selected paragraphs with the previously selected
2773     // paragraphs and submit corresponding TEXT_SELECTION_CHANGED events.
2774     // first, search for new and changed selections.
2775     // on the run remove selections from previously known ones, if they are
2776     // also in the current ones.
2777     if ( mpSelectedParas )
2778     {
2779         SwAccessibleSelectedParas_Impl::iterator aIter = mpSelectedParas->begin();
2780         for ( ; aIter != mpSelectedParas->end(); ++aIter )
2781         {
2782             bool bSubmitEvent( false );
2783             if ( !pPrevSelectedParas )
2784             {
2785                 // new selection
2786                 bSubmitEvent = true;
2787             }
2788             else
2789             {
2790                 SwAccessibleSelectedParas_Impl::iterator aPrevSelected =
2791                                         pPrevSelectedParas->find( (*aIter).first );
2792                 if ( aPrevSelected != pPrevSelectedParas->end() )
2793                 {
2794                     // check, if selection has changed
2795                     if ( (*aIter).second.nStartOfSelection !=
2796                                     (*aPrevSelected).second.nStartOfSelection ||
2797                          (*aIter).second.nEndOfSelection !=
2798                                     (*aPrevSelected).second.nEndOfSelection )
2799                     {
2800                         // changed selection
2801                         bSubmitEvent = true;
2802                     }
2803                     pPrevSelectedParas->erase( aPrevSelected );
2804                 }
2805                 else
2806                 {
2807                     // new selection
2808                     bSubmitEvent = true;
2809                 }
2810             }
2811 
2812             if ( bSubmitEvent )
2813             {
2814                 uno::Reference < XAccessible > xAcc( (*aIter).first );
2815                 if ( xAcc.is() )
2816                 {
2817                     ::vos::ORef < SwAccessibleContext > xAccImpl(
2818                                 static_cast<SwAccessibleContext*>( xAcc.get() ) );
2819                     if ( xAccImpl.isValid() && xAccImpl->GetFrm() )
2820                     {
2821                         const SwTxtFrm* pTxtFrm(
2822                             dynamic_cast<const SwTxtFrm*>(xAccImpl->GetFrm()) );
2823                         ASSERT( pTxtFrm,
2824                                 "<SwAccessibleMap::_SubmitTextSelectionChangedEvents()> - unexcepted type of frame" );
2825                         if ( pTxtFrm )
2826                         {
2827                             InvalidateParaTextSelection( *pTxtFrm );
2828                         }
2829                     }
2830                 }
2831             }
2832         }
2833     }
2834 
2835     // second, handle previous selections - after the first step the data
2836     // structure of the previously known only contains the 'old' selections
2837     if ( pPrevSelectedParas )
2838     {
2839         SwAccessibleSelectedParas_Impl::iterator aIter = pPrevSelectedParas->begin();
2840         for ( ; aIter != pPrevSelectedParas->end(); ++aIter )
2841         {
2842             uno::Reference < XAccessible > xAcc( (*aIter).first );
2843             if ( xAcc.is() )
2844             {
2845                 ::vos::ORef < SwAccessibleContext > xAccImpl(
2846                             static_cast<SwAccessibleContext*>( xAcc.get() ) );
2847                 if ( xAccImpl.isValid() && xAccImpl->GetFrm() )
2848                 {
2849                     const SwTxtFrm* pTxtFrm(
2850                             dynamic_cast<const SwTxtFrm*>(xAccImpl->GetFrm()) );
2851                     ASSERT( pTxtFrm,
2852                             "<SwAccessibleMap::_SubmitTextSelectionChangedEvents()> - unexcepted type of frame" );
2853                     if ( pTxtFrm )
2854                     {
2855                         InvalidateParaTextSelection( *pTxtFrm );
2856                     }
2857                 }
2858             }
2859         }
2860 
2861         delete pPrevSelectedParas;
2862     }
2863 }
2864 
2865 const SwRect& SwAccessibleMap::GetVisArea() const
2866 {
2867     DBG_ASSERT( !GetShell()->IsPreView() || (mpPreview != NULL),
2868                 "preview without preview data?" );
2869 
2870     return GetShell()->IsPreView()
2871            ? mpPreview->GetVisArea()
2872            : GetShell()->VisArea();
2873 }
2874 
2875