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