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