xref: /aoo4110/main/sw/source/core/access/accmap.cxx (revision b1cdbd2c)
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 <vector>
38 #include <accmap.hxx>
39 #include <acccontext.hxx>
40 #include <accdoc.hxx>
41 #include <accpreview.hxx>
42 #include <accpage.hxx>
43 #include <accpara.hxx>
44 #include <accheaderfooter.hxx>
45 #include <accfootnote.hxx>
46 #include <acctextframe.hxx>
47 #include <accgraphic.hxx>
48 #include <accembedded.hxx>
49 #include <acccell.hxx>
50 #include <acctable.hxx>
51 #include <fesh.hxx>
52 #include <rootfrm.hxx>
53 #include <txtfrm.hxx>
54 #include <hffrm.hxx>
55 #include <ftnfrm.hxx>
56 #include <cellfrm.hxx>
57 #include <tabfrm.hxx>
58 #include <pagefrm.hxx>
59 #include <flyfrm.hxx>
60 #include <ndtyp.hxx>
61 #include <IDocumentDrawModelAccess.hxx>
62 #include <svx/ShapeTypeHandler.hxx>
63 #include <vcl/svapp.hxx>
64 #ifndef _SVX_ACCESSIBILITY_SHAPE_TYPE_HANDLER_HXX
65 #include <svx/ShapeTypeHandler.hxx>
66 #endif
67 #ifndef _SVX_ACCESSIBILITY_SVX_SHAPE_TYPES_HXX
68 #include <svx/SvxShapeTypes.hxx>
69 #endif
70 #ifndef _SVDPAGE_HXX
71 #include <svx/svdpage.hxx>
72 #endif
73 #include <com/sun/star/accessibility/AccessibleRelationType.hpp>
74 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
75 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
76 #include <com/sun/star/accessibility/AccessibleRole.hpp>
77 #include <cppuhelper/implbase1.hxx>
78 #include <pagepreviewlayout.hxx>
79 #include <dcontact.hxx>
80 #include <svx/unoapi.hxx>
81 #include <svx/svdmark.hxx>
82 #include <doc.hxx>
83 #include <pam.hxx>
84 #include <ndtxt.hxx>
85 #include <dflyobj.hxx>
86 #include <prevwpage.hxx>
87 #include <switerator.hxx>
88 
89 using namespace ::com::sun::star;
90 using namespace ::com::sun::star::accessibility;
91 using ::rtl::OUString;
92 using namespace ::sw::access;
93 
94 struct SwFrmFunc
95 {
operator ()SwFrmFunc96 	sal_Bool operator()( const SwFrm * p1,
97 				    	 const SwFrm * p2) const
98 	{
99 		return p1 < p2;
100 	}
101 };
102 
103 typedef ::std::map < const SwFrm *, uno::WeakReference < XAccessible >, SwFrmFunc > _SwAccessibleContextMap_Impl;
104 
105 class SwAccessibleContextMap_Impl: public _SwAccessibleContextMap_Impl
106 {
107 public:
108 
109 #ifdef DBG_UTIL
110 	sal_Bool mbLocked;
111 #endif
112 
SwAccessibleContextMap_Impl()113 	SwAccessibleContextMap_Impl()
114 #ifdef DBG_UTIL
115 		: mbLocked( sal_False )
116 #endif
117 	{}
118 
119 };
120 
121 //------------------------------------------------------------------------------
122 class SwDrawModellListener_Impl : public SfxListener,
123 	public ::cppu::WeakImplHelper1< document::XEventBroadcaster >
124 {
125 	mutable ::osl::Mutex maListenerMutex;
126 	::cppu::OInterfaceContainerHelper maEventListeners;
127 	SdrModel *mpDrawModel;
128 protected:
129 	virtual ~SwDrawModellListener_Impl();
130 public:
131 
132 	SwDrawModellListener_Impl( SdrModel *pDrawModel );
133 
134 
135     virtual void SAL_CALL addEventListener( const uno::Reference< document::XEventListener >& xListener ) throw (uno::RuntimeException);
136     virtual void SAL_CALL removeEventListener( const uno::Reference< document::XEventListener >& xListener ) throw (uno::RuntimeException);
137 
138 	virtual void		Notify( SfxBroadcaster& rBC, const SfxHint& rHint );
139 	void Dispose();
140 };
141 
SwDrawModellListener_Impl(SdrModel * pDrawModel)142 SwDrawModellListener_Impl::SwDrawModellListener_Impl( SdrModel *pDrawModel ) :
143 	maEventListeners( maListenerMutex ),
144 	mpDrawModel( pDrawModel )
145 {
146 	StartListening( *mpDrawModel );
147 }
148 
~SwDrawModellListener_Impl()149 SwDrawModellListener_Impl::~SwDrawModellListener_Impl()
150 {
151 	EndListening( *mpDrawModel );
152 }
153 
addEventListener(const uno::Reference<document::XEventListener> & xListener)154 void SAL_CALL SwDrawModellListener_Impl::addEventListener( const uno::Reference< document::XEventListener >& xListener ) throw (uno::RuntimeException)
155 {
156 	maEventListeners.addInterface( xListener );
157 }
158 
removeEventListener(const uno::Reference<document::XEventListener> & xListener)159 void SAL_CALL SwDrawModellListener_Impl::removeEventListener( const uno::Reference< document::XEventListener >& xListener ) throw (uno::RuntimeException)
160 {
161 	maEventListeners.removeInterface( xListener );
162 }
163 
Notify(SfxBroadcaster &,const SfxHint & rHint)164 void SwDrawModellListener_Impl::Notify( SfxBroadcaster& /*rBC*/,
165 		const SfxHint& rHint )
166 {
167 	// do not broadcast notifications for writer fly frames, because there
168 	// are no shapes that need to know about them.
169     // OD 01.07.2003 #110554# - correct condition in order not to broadcast
170     // notifications for writer fly frames.
171     // OD 01.07.2003 #110554# - do not broadcast notifications for plane
172     // <SdrObject>objects
173 	const SdrHint *pSdrHint = PTR_CAST( SdrHint, &rHint );
174     if ( !pSdrHint ||
175          ( pSdrHint->GetObject() &&
176            ( pSdrHint->GetObject()->ISA(SwFlyDrawObj) ||
177              pSdrHint->GetObject()->ISA(SwVirtFlyDrawObj) ||
178              IS_TYPE(SdrObject,pSdrHint->GetObject()) ) ) )
179     {
180         return;
181     }
182 
183 	ASSERT( mpDrawModel, "draw model listener is disposed" );
184 	if( !mpDrawModel )
185 		return;
186 
187 	document::EventObject aEvent;
188 	if( !SvxUnoDrawMSFactory::createEvent( mpDrawModel, pSdrHint, aEvent ) )
189 		return;
190 
191 	::cppu::OInterfaceIteratorHelper aIter( maEventListeners );
192 	while( aIter.hasMoreElements() )
193 	{
194 		uno::Reference < document::XEventListener > xListener( aIter.next(),
195 												uno::UNO_QUERY );
196 		try
197 		{
198 			xListener->notifyEvent( aEvent );
199 		}
200 		catch( uno::RuntimeException const & r )
201 		{
202             (void)r;
203 #if OSL_DEBUG_LEVEL > 1
204 			ByteString aError( "Runtime exception caught while notifying shape.:\n" );
205 			aError += ByteString( String( r.Message), RTL_TEXTENCODING_ASCII_US );
206 			DBG_ERROR( aError.GetBuffer() );
207 #endif
208 		}
209 	}
210 }
211 
Dispose()212 void SwDrawModellListener_Impl::Dispose()
213 {
214 	mpDrawModel = 0;
215 }
216 
217 //------------------------------------------------------------------------------
218 struct SwShapeFunc
219 {
operator ()SwShapeFunc220 	sal_Bool operator()( const SdrObject * p1,
221 				    	 const SdrObject * p2) const
222 	{
223 		return p1 < p2;
224 	}
225 };
226 typedef ::std::map < const SdrObject *, uno::WeakReference < XAccessible >, SwShapeFunc > _SwAccessibleShapeMap_Impl;
227 typedef ::std::pair < const SdrObject *, ::vos::ORef < ::accessibility::AccessibleShape > > SwAccessibleObjShape_Impl;
228 
229 class SwAccessibleShapeMap_Impl: public _SwAccessibleShapeMap_Impl
230 
231 {
232 	::accessibility::AccessibleShapeTreeInfo maInfo;
233 
234 public:
235 
236 #ifdef DBG_UTIL
237 	sal_Bool mbLocked;
238 #endif
SwAccessibleShapeMap_Impl(SwAccessibleMap * pMap)239 	SwAccessibleShapeMap_Impl( SwAccessibleMap *pMap )
240 #ifdef DBG_UTIL
241 		: mbLocked( sal_False )
242 #endif
243 	{
244 		maInfo.SetSdrView( pMap->GetShell()->GetDrawView() );
245 		maInfo.SetWindow( pMap->GetShell()->GetWin() );
246 		maInfo.SetViewForwarder( pMap );
247         // --> OD 2005-08-08 #i52858# - method name changed
248 		uno::Reference < document::XEventBroadcaster > xModelBroadcaster =
249 			new SwDrawModellListener_Impl(
250                     pMap->GetShell()->getIDocumentDrawModelAccess()->GetOrCreateDrawModel() );
251         // <--
252 		maInfo.SetControllerBroadcaster( xModelBroadcaster );
253 	}
254 
255 	~SwAccessibleShapeMap_Impl();
256 
GetInfo() const257 	const ::accessibility::AccessibleShapeTreeInfo& GetInfo() const { return maInfo; }
258 
259 	SwAccessibleObjShape_Impl *Copy( size_t& rSize,
260 		const SwFEShell *pFESh = 0,
261 		SwAccessibleObjShape_Impl  **pSelShape = 0 ) const;
262 };
263 
~SwAccessibleShapeMap_Impl()264 SwAccessibleShapeMap_Impl::~SwAccessibleShapeMap_Impl()
265 {
266 	uno::Reference < document::XEventBroadcaster > xBrd( maInfo.GetControllerBroadcaster() );
267 	if( xBrd.is() )
268 		static_cast < SwDrawModellListener_Impl * >( xBrd.get() )->Dispose();
269 }
270 
271 SwAccessibleObjShape_Impl
Copy(size_t & rSize,const SwFEShell * pFESh,SwAccessibleObjShape_Impl ** pSelStart) const272 	*SwAccessibleShapeMap_Impl::Copy(
273 			size_t& rSize, const SwFEShell *pFESh,
274 			SwAccessibleObjShape_Impl **pSelStart ) const
275 {
276 	SwAccessibleObjShape_Impl *pShapes = 0;
277 	SwAccessibleObjShape_Impl *pSelShape = 0;
278 
279 	sal_uInt16 nSelShapes = pFESh ? pFESh->IsObjSelected() : 0;
280 	rSize = size();
281 
282 	if( rSize > 0 )
283 	{
284 		pShapes =
285 			new SwAccessibleObjShape_Impl[rSize];
286 
287 		const_iterator aIter = begin();
288 		const_iterator aEndIter = end();
289 
290 		SwAccessibleObjShape_Impl *pShape = pShapes;
291 		pSelShape = &(pShapes[rSize]);
292 		while( aIter != aEndIter )
293 		{
294 			const SdrObject *pObj = (*aIter).first;
295 			uno::Reference < XAccessible > xAcc( (*aIter).second );
296 			if( nSelShapes && pFESh &&pFESh->IsObjSelected( *pObj ) )
297 			{
298 				// selected objects are inserted from the back
299 				--pSelShape;
300 				pSelShape->first = pObj;
301 				pSelShape->second =
302 					static_cast < ::accessibility::AccessibleShape* >(
303 													xAcc.get() );
304 				--nSelShapes;
305 			}
306 			else
307 			{
308 				pShape->first = pObj;
309 				pShape->second =
310 					static_cast < ::accessibility::AccessibleShape* >(
311 													xAcc.get() );
312 				++pShape;
313 			}
314 			++aIter;
315 		}
316 		ASSERT( pSelShape == pShape, "copying shapes went wrong!" );
317 	}
318 
319 	if( pSelStart )
320 		*pSelStart = pSelShape;
321 
322 	return pShapes;
323 }
324 
325 //------------------------------------------------------------------------------
326 struct SwAccessibleEvent_Impl
327 {
328 public:
329     enum EventType { CARET_OR_STATES,
330                      INVALID_CONTENT,
331                      POS_CHANGED,
332                      CHILD_POS_CHANGED,
333                      SHAPE_SELECTION,
334                      DISPOSE,
335                      INVALID_ATTR };
336 
337 private:
338 	SwRect		maOldBox;				// the old bounds for CHILD_POS_CHANGED
339 										// and POS_CHANGED
340 	uno::WeakReference < XAccessible > mxAcc;	// The object that fires the event
341     SwAccessibleChild   maFrmOrObj;             // the child for CHILD_POS_CHANGED and
342 										// the same as xAcc for any other
343 										// event type
344 	EventType 	meType;					// The event type
345     // --> OD 2005-12-12 #i27301# - use new type definition for <mnStates>
346     tAccessibleStates mnStates;         // check states or update caret pos
347     // <--
348 
349 	SwAccessibleEvent_Impl& operator==( const SwAccessibleEvent_Impl& );
350 
351 public:
352 	const SwFrm* mpParentFrm;	// The object that fires the event
IsNoXaccParentFrmSwAccessibleEvent_Impl353 	sal_Bool IsNoXaccParentFrm() const
354 	{
355 		return CHILD_POS_CHANGED == meType && mpParentFrm != 0;
356 	}
GetxAccSwAccessibleEvent_Impl357 	uno::WeakReference < XAccessible > GetxAcc() const { return mxAcc;}
358 public:
SwAccessibleEvent_ImplSwAccessibleEvent_Impl359     SwAccessibleEvent_Impl( EventType eT,
360                             SwAccessibleContext *pA,
361                             const SwAccessibleChild& rFrmOrObj )
362         : mxAcc( pA ),
363           maFrmOrObj( rFrmOrObj ),
364           meType( eT ),
365           mnStates( 0 ),
366           mpParentFrm( 0 )
367 	{}
368 
SwAccessibleEvent_ImplSwAccessibleEvent_Impl369     SwAccessibleEvent_Impl( EventType eT,
370                             const SwAccessibleChild& rFrmOrObj )
371         : maFrmOrObj( rFrmOrObj ),
372           meType( eT ),
373           mnStates( 0 ),
374           mpParentFrm( 0 )
375 	{
376 		ASSERT( SwAccessibleEvent_Impl::DISPOSE == meType,
377 				"wrong event constructor, DISPOSE only" );
378 	}
379 
SwAccessibleEvent_ImplSwAccessibleEvent_Impl380     SwAccessibleEvent_Impl( EventType eT )
381         : meType( eT ),
382           mnStates( 0 ),
383           mpParentFrm( 0 )
384 	{
385         ASSERT( SwAccessibleEvent_Impl::SHAPE_SELECTION == meType,
386 				"wrong event constructor, SHAPE_SELECTION only" );
387 	}
388 
SwAccessibleEvent_ImplSwAccessibleEvent_Impl389     SwAccessibleEvent_Impl( EventType eT,
390                             SwAccessibleContext *pA,
391                             const SwAccessibleChild& rFrmOrObj,
392                             const SwRect& rR )
393         : maOldBox( rR ),
394           mxAcc( pA ),
395           maFrmOrObj( rFrmOrObj ),
396           meType( eT ),
397           mnStates( 0 ),
398           mpParentFrm( 0 )
399 	{
400 		ASSERT( SwAccessibleEvent_Impl::CHILD_POS_CHANGED == meType ||
401 				SwAccessibleEvent_Impl::POS_CHANGED == meType,
402 				"wrong event constructor, (CHILD_)POS_CHANGED only" );
403 	}
404 
405     // --> OD 2005-12-12 #i27301# - use new type definition for parameter <_nStates>
SwAccessibleEvent_ImplSwAccessibleEvent_Impl406     SwAccessibleEvent_Impl( EventType eT,
407                             SwAccessibleContext *pA,
408                             const SwAccessibleChild& rFrmOrObj,
409                             const tAccessibleStates _nStates )
410         : mxAcc( pA ),
411           maFrmOrObj( rFrmOrObj ),
412           meType( eT ),
413           mnStates( _nStates ),
414           mpParentFrm( 0 )
415 	{
416 		ASSERT( SwAccessibleEvent_Impl::CARET_OR_STATES == meType,
417 				"wrong event constructor, CARET_OR_STATES only" );
418 	}
419 
SwAccessibleEvent_ImplSwAccessibleEvent_Impl420 	SwAccessibleEvent_Impl( EventType eT,
421                                 const SwFrm *pParentFrm,
422 				const SwAccessibleChild& rFrmOrObj,
423                                 const SwRect& rR ) :
424 		maOldBox( rR ),
425                 maFrmOrObj( rFrmOrObj ),
426                 meType( eT ),
427 		mnStates( 0 ),
428                 mpParentFrm( pParentFrm )
429 	{
430 		OSL_ENSURE( SwAccessibleEvent_Impl::CHILD_POS_CHANGED == meType,
431 			"wrong event constructor, CHILD_POS_CHANGED only" );
432 	}
433     // <SetType(..)> only used in method <SwAccessibleMap::AppendEvent(..)>
SetTypeSwAccessibleEvent_Impl434     inline void SetType( EventType eT )
435     {
436         meType = eT;
437     }
GetTypeSwAccessibleEvent_Impl438     inline EventType GetType() const
439     {
440         return meType;
441     }
442 
GetContextSwAccessibleEvent_Impl443     inline ::vos::ORef < SwAccessibleContext > GetContext() const
444     {
445         uno::Reference < XAccessible > xTmp( mxAcc );
446         ::vos::ORef < SwAccessibleContext > xAccImpl(
447                             static_cast<SwAccessibleContext*>( xTmp.get() ) );
448 
449         return xAccImpl;
450     }
451 
GetOldBoxSwAccessibleEvent_Impl452     inline const SwRect& GetOldBox() const
453     {
454         return maOldBox;
455     }
456     // <SetOldBox(..)> only used in method <SwAccessibleMap::AppendEvent(..)>
SetOldBoxSwAccessibleEvent_Impl457     inline void SetOldBox( const SwRect& rOldBox )
458     {
459         maOldBox = rOldBox;
460     }
461 
GetFrmOrObjSwAccessibleEvent_Impl462     inline const SwAccessibleChild& GetFrmOrObj() const
463     {
464         return maFrmOrObj;
465     }
466 
467     // <SetStates(..)> only used in method <SwAccessibleMap::AppendEvent(..)>
468     // --> OD 2005-12-12 #i27301# - use new type definition for parameter <_nStates>
SetStatesSwAccessibleEvent_Impl469     inline void SetStates( tAccessibleStates _nStates )
470     {
471         mnStates |= _nStates;
472     }
473     // <--
474 
IsUpdateCursorPosSwAccessibleEvent_Impl475     inline sal_Bool IsUpdateCursorPos() const
476     {
477         return (mnStates & ACC_STATE_CARET) != 0;
478     }
IsInvalidateStatesSwAccessibleEvent_Impl479     inline sal_Bool IsInvalidateStates() const
480     {
481         return (mnStates & ACC_STATE_MASK) != 0;
482     }
IsInvalidateRelationSwAccessibleEvent_Impl483     inline sal_Bool IsInvalidateRelation() const
484     {
485         return (mnStates & ACC_STATE_RELATION_MASK) != 0;
486     }
487     // --> OD 2005-12-12 #i27301# - new event TEXT_SELECTION_CHANGED
IsInvalidateTextSelectionSwAccessibleEvent_Impl488     inline sal_Bool IsInvalidateTextSelection() const
489     {
490         return ( mnStates & ACC_STATE_TEXT_SELECTION_CHANGED ) != 0;
491     }
492     // <--
493     // --> OD 2009-01-07 #i88069# - new event TEXT_ATTRIBUTE_CHANGED
IsInvalidateTextAttrsSwAccessibleEvent_Impl494     inline sal_Bool IsInvalidateTextAttrs() const
495     {
496         return ( mnStates & ACC_STATE_TEXT_ATTRIBUTE_CHANGED ) != 0;
497     }
498     // <--
499     // --> OD 2005-12-12 #i27301# - use new type definition <tAccessibleStates>
500     // for return value
GetStatesSwAccessibleEvent_Impl501     inline tAccessibleStates GetStates() const
502     {
503         return mnStates & ACC_STATE_MASK;
504     }
505     // <--
506     // --> OD 2005-12-12 #i27301# - use new type definition <tAccessibleStates>
507     // for return value
GetAllStatesSwAccessibleEvent_Impl508     inline tAccessibleStates GetAllStates() const
509     {
510         return mnStates;
511     }
512     // <--
513 };
514 
515 //------------------------------------------------------------------------------
516 typedef ::std::list < SwAccessibleEvent_Impl > _SwAccessibleEventList_Impl;
517 
518 class SwAccessibleEventList_Impl: public _SwAccessibleEventList_Impl
519 {
520 	sal_Bool mbFiring;
521 
522 public:
523 
SwAccessibleEventList_Impl()524     SwAccessibleEventList_Impl()
525         : mbFiring( sal_False )
526     {}
527 
SetFiring()528     inline void SetFiring()
529     {
530         mbFiring = sal_True;
531     }
IsFiring() const532     inline sal_Bool IsFiring() const
533     {
534         return mbFiring;
535     }
536 	struct XAccisNULL
537 	{
operator ()SwAccessibleEventList_Impl::XAccisNULL538 		bool operator()(const SwAccessibleEvent_Impl& e)
539 		{
540 			return e.IsNoXaccParentFrm();
541 		}
542 	};
543 	void MoveInvalidXAccToEnd();
544 };
545 
MoveInvalidXAccToEnd()546 void SwAccessibleEventList_Impl::MoveInvalidXAccToEnd()
547 {
548 	int nSize = size();
549 	if (nSize < 2 )
550 	{
551 		return;
552 	}
553 	SwAccessibleEventList_Impl lstEvent;
554 	iterator li = begin();
555 	for ( ;li != end();)
556 	{
557 		SwAccessibleEvent_Impl e = *li;
558 		if (e.IsNoXaccParentFrm())
559 		{
560 			iterator liNext = li;
561 			++liNext;
562 			erase(li);
563 			li = liNext;
564 			lstEvent.insert(lstEvent.end(),e);
565 		}
566 		else
567 			++li;
568 	}
569 	OSL_ENSURE(size() + lstEvent.size() == nSize ,"");
570 	insert(end(),lstEvent.begin(),lstEvent.end());
571 	OSL_ENSURE(size() == nSize ,"");
572 }
573 //------------------------------------------------------------------------------
574 // The shape list is filled if an accessible shape is destroyed. It
575 // simply keeps a reference to the accessible shape's XShape. These
576 // references are destroyed within the EndAction when firing events,
577 // There are twp reason for this. First of all, a new accessible shape
578 // for the XShape might be created soon. It's then cheaper if the XShape
579 // still exists. The other reason are situations where an accessible shape
580 // is destroyed within an SwFrmFmt::Modify. In this case, destryoing
581 // the XShape at the same time (indirectly by destroying the accessible
582 // shape) leads to an assert, because a client of the Modify is destroyed
583 // within a Modify call.
584 
585 typedef ::std::list < uno::Reference < drawing::XShape > > _SwShapeList_Impl;
586 
587 class SwShapeList_Impl: public _SwShapeList_Impl
588 {
589 public:
590 
SwShapeList_Impl()591 	SwShapeList_Impl() {}
592 };
593 
594 
595 //------------------------------------------------------------------------------
596 struct SwAccessibleChildFunc
597 {
operator ()SwAccessibleChildFunc598     sal_Bool operator()( const SwAccessibleChild& r1,
599                          const SwAccessibleChild& r2 ) const
600 	{
601 		const void *p1 = r1.GetSwFrm()
602                          ? static_cast < const void * >( r1.GetSwFrm())
603                          : ( r1.GetDrawObject()
604                              ? static_cast < const void * >( r1.GetDrawObject() )
605                              : static_cast < const void * >( r1.GetWindow() ) );
606 		const void *p2 = r2.GetSwFrm()
607                          ? static_cast < const void * >( r2.GetSwFrm())
608                          : ( r2.GetDrawObject()
609                              ? static_cast < const void * >( r2.GetDrawObject() )
610                              : static_cast < const void * >( r2.GetWindow() ) );
611 		return p1 < p2;
612 	}
613 };
614 typedef ::std::map < SwAccessibleChild, SwAccessibleEventList_Impl::iterator,
615                      SwAccessibleChildFunc > _SwAccessibleEventMap_Impl;
616 
617 class SwAccessibleEventMap_Impl: public _SwAccessibleEventMap_Impl
618 {
619 };
620 
621 //------------------------------------------------------------------------------
622 // --> OD 2005-12-13 #i27301# - map containing the accessible paragraph, which
623 // have a selection. Needed to keep this information to submit corresponding
624 // TEXT_SELECTION_CHANGED events.
625 struct SwAccessibleParaSelection
626 {
627     xub_StrLen nStartOfSelection;
628     xub_StrLen nEndOfSelection;
629 
SwAccessibleParaSelectionSwAccessibleParaSelection630     SwAccessibleParaSelection( const xub_StrLen _nStartOfSelection,
631                                const xub_StrLen _nEndOfSelection )
632         : nStartOfSelection( _nStartOfSelection ),
633           nEndOfSelection( _nEndOfSelection )
634     {}
635 };
636 
637 struct SwXAccWeakRefComp
638 {
operator ()SwXAccWeakRefComp639     sal_Bool operator()( const uno::WeakReference<XAccessible>& _rXAccWeakRef1,
640                          const uno::WeakReference<XAccessible>& _rXAccWeakRef2 ) const
641     {
642         return _rXAccWeakRef1.get() < _rXAccWeakRef2.get();
643     }
644 };
645 
646 typedef ::std::map< uno::WeakReference < XAccessible >,
647                     SwAccessibleParaSelection,
648                     SwXAccWeakRefComp > _SwAccessibleSelectedParas_Impl;
649 
650 class SwAccessibleSelectedParas_Impl: public _SwAccessibleSelectedParas_Impl
651 {};
652 // <--
653 
654 // helper class that stores preview data
655 class SwAccPreviewData
656 {
657     typedef std::vector<Rectangle> Rectangles;
658     Rectangles maPreviewRects;
659     Rectangles maLogicRects;
660 
661     SwRect maVisArea;
662     Fraction maScale;
663 
664     const SwPageFrm *mpSelPage;
665 
666     /** adjust logic page retangle to its visible part
667 
668         OD 17.01.2003 #103492#
669 
670         @author OD
671 
672         @param _iorLogicPgSwRect
673         input/output parameter - reference to the logic page rectangle, which
674         has to be adjusted.
675 
676         @param _rPrevwPgSwRect
677         input parameter - constant reference to the corresponding preview page
678         rectangle; needed to determine the visible part of the logic page rectangle.
679 
680         @param _rPrevwWinSize
681         input paramter - constant reference to the preview window size in TWIP;
682         needed to determine the visible part of the logic page rectangle
683     */
684     void AdjustLogicPgRectToVisibleArea( SwRect&         _iorLogicPgSwRect,
685                                          const SwRect&   _rPrevwPgSwRect,
686                                          const Size&     _rPrevwWinSize );
687 
688 public:
689     SwAccPreviewData();
690     ~SwAccPreviewData();
691 
692     // OD 14.01.2003 #103492# - complete re-factoring of method due to new
693     // page/print preview functionality.
694     void Update( const SwAccessibleMap& rAccMap,
695                  const std::vector<PrevwPage*>& _rPrevwPages,
696                  const Fraction&  _rScale,
697                  const SwPageFrm* _pSelectedPageFrm,
698                  const Size&      _rPrevwWinSize );
699 
700     // OD 14.01.2003 #103492# - complete re-factoring of method due to new
701     // page/print preview functionality.
702     void InvalidateSelection( const SwPageFrm* _pSelectedPageFrm );
703 
704     const SwRect& GetVisArea() const;
705 
706     MapMode GetMapModeForPreview( ) const;
707 
708     /** Adjust the MapMode so that the preview page appears at the
709      * proper position. rPoint identifies the page for which the
710      * MapMode should be adjusted. If bFromPreview is true, rPoint is
711      * a preview coordinate; else it's a document coordinate. */
712     // OD 17.01.2003 #103492# - delete unused 3rd parameter.
713     void AdjustMapMode( MapMode& rMapMode,
714                         const Point& rPoint ) const;
715 
GetSelPage() const716     inline const SwPageFrm *GetSelPage() const { return mpSelPage; }
717 
718     void DisposePage(const SwPageFrm *pPageFrm );
719 };
720 
SwAccPreviewData()721 SwAccPreviewData::SwAccPreviewData() :
722     mpSelPage( 0 )
723 {
724 }
725 
~SwAccPreviewData()726 SwAccPreviewData::~SwAccPreviewData()
727 {
728 }
729 
730 // OD 13.01.2003 #103492# - complete re-factoring of method due to new page/print
731 // preview functionality.
Update(const SwAccessibleMap & rAccMap,const std::vector<PrevwPage * > & _rPrevwPages,const Fraction & _rScale,const SwPageFrm * _pSelectedPageFrm,const Size & _rPrevwWinSize)732 void SwAccPreviewData::Update( const SwAccessibleMap& rAccMap,
733                                const std::vector<PrevwPage*>& _rPrevwPages,
734                                const Fraction&  _rScale,
735                                const SwPageFrm* _pSelectedPageFrm,
736                                const Size&      _rPrevwWinSize )
737 {
738     // store preview scaling, maximal preview page size and selected page
739     maScale = _rScale;
740     mpSelPage = _pSelectedPageFrm;
741 
742     // prepare loop on preview pages
743     maPreviewRects.clear();
744     maLogicRects.clear();
745     SwAccessibleChild aPage;
746     maVisArea.Clear();
747 
748     // loop on preview pages to calculate <maPreviewRects>, <maLogicRects> and
749     // <maVisArea>
750     for ( std::vector<PrevwPage*>::const_iterator aPageIter = _rPrevwPages.begin();
751           aPageIter != _rPrevwPages.end();
752           ++aPageIter )
753     {
754         aPage = (*aPageIter)->pPage;
755 
756         // add preview page rectangle to <maPreviewRects>
757         Rectangle aPrevwPgRect( (*aPageIter)->aPrevwWinPos, (*aPageIter)->aPageSize );
758         maPreviewRects.push_back( aPrevwPgRect );
759 
760         // add logic page rectangle to <maLogicRects>
761         SwRect aLogicPgSwRect( aPage.GetBox( rAccMap ) );
762         Rectangle aLogicPgRect( aLogicPgSwRect.SVRect() );
763         maLogicRects.push_back( aLogicPgRect );
764         // union visible area with visible part of logic page rectangle
765         if ( (*aPageIter)->bVisible )
766         {
767             if ( !(*aPageIter)->pPage->IsEmptyPage() )
768             {
769                 AdjustLogicPgRectToVisibleArea( aLogicPgSwRect,
770                                                 SwRect( aPrevwPgRect ),
771                                                 _rPrevwWinSize );
772             }
773             if ( maVisArea.IsEmpty() )
774                 maVisArea = aLogicPgSwRect;
775             else
776                 maVisArea.Union( aLogicPgSwRect );
777         }
778     }
779 }
780 
781 // OD 16.01.2003 #103492# - complete re-factoring of method due to new page/print
782 // preview functionality.
InvalidateSelection(const SwPageFrm * _pSelectedPageFrm)783 void SwAccPreviewData::InvalidateSelection( const SwPageFrm* _pSelectedPageFrm )
784 {
785     mpSelPage = _pSelectedPageFrm;
786     ASSERT( mpSelPage, "selected page not found" );
787 }
788 
789 struct ContainsPredicate
790 {
791     const Point& mrPoint;
ContainsPredicateContainsPredicate792     ContainsPredicate( const Point& rPoint ) : mrPoint(rPoint) {}
operator ()ContainsPredicate793     bool operator() ( const Rectangle& rRect ) const
794     {
795         return rRect.IsInside( mrPoint ) ? true : false;
796     }
797 };
798 
GetVisArea() const799 const SwRect& SwAccPreviewData::GetVisArea() const
800 {
801     return maVisArea;
802 }
803 
AdjustMapMode(MapMode & rMapMode,const Point & rPoint) const804 void SwAccPreviewData::AdjustMapMode( MapMode& rMapMode,
805                                       const Point& rPoint ) const
806 {
807     // adjust scale
808     rMapMode.SetScaleX( maScale );
809     rMapMode.SetScaleY( maScale );
810 
811     // find proper rectangle
812     Rectangles::const_iterator aBegin = maLogicRects.begin();
813     Rectangles::const_iterator aEnd = maLogicRects.end();
814     Rectangles::const_iterator aFound = ::std::find_if( aBegin, aEnd,
815                                                  ContainsPredicate( rPoint ) );
816 
817     if( aFound != aEnd )
818     {
819         // found! set new origin
820         Point aPoint = (maPreviewRects.begin() + (aFound - aBegin))->TopLeft();
821         aPoint -= (maLogicRects.begin() + (aFound-aBegin))->TopLeft();
822         rMapMode.SetOrigin( aPoint );
823     }
824     // else: don't adjust MapMode
825 }
826 
DisposePage(const SwPageFrm * pPageFrm)827 void SwAccPreviewData::DisposePage(const SwPageFrm *pPageFrm )
828 {
829     if( mpSelPage == pPageFrm )
830         mpSelPage = 0;
831 }
832 
833 /** adjust logic page retangle to its visible part
834 
835     OD 17.01.2003 #103492#
836 
837     @author OD
838 */
AdjustLogicPgRectToVisibleArea(SwRect & _iorLogicPgSwRect,const SwRect & _rPrevwPgSwRect,const Size & _rPrevwWinSize)839 void SwAccPreviewData::AdjustLogicPgRectToVisibleArea(
840                             SwRect&         _iorLogicPgSwRect,
841                             const SwRect&   _rPrevwPgSwRect,
842                             const Size&     _rPrevwWinSize )
843 {
844     // determine preview window rectangle
845     const SwRect aPrevwWinSwRect( Point( 0, 0 ), _rPrevwWinSize );
846     // calculate visible preview page rectangle
847     SwRect aVisPrevwPgSwRect( _rPrevwPgSwRect );
848     aVisPrevwPgSwRect.Intersection( aPrevwWinSwRect );
849     // adjust logic page rectangle
850     SwTwips nTmpDiff;
851     // left
852     nTmpDiff = aVisPrevwPgSwRect.Left() - _rPrevwPgSwRect.Left();
853     if ( nTmpDiff > 0 )
854         _iorLogicPgSwRect.Left( _iorLogicPgSwRect.Left() + nTmpDiff );
855     // top
856     nTmpDiff = aVisPrevwPgSwRect.Top() - _rPrevwPgSwRect.Top();
857     if ( nTmpDiff > 0 )
858         _iorLogicPgSwRect.Top( _iorLogicPgSwRect.Top() + nTmpDiff );
859     // right
860     nTmpDiff = _rPrevwPgSwRect.Right() - aVisPrevwPgSwRect.Right();
861     if ( nTmpDiff > 0 )
862         _iorLogicPgSwRect.Right( _iorLogicPgSwRect.Right() - nTmpDiff );
863     // bottom
864     nTmpDiff = _rPrevwPgSwRect.Bottom() - aVisPrevwPgSwRect.Bottom();
865     if ( nTmpDiff > 0 )
866         _iorLogicPgSwRect.Bottom( _iorLogicPgSwRect.Bottom() - nTmpDiff );
867 }
868 
869 //------------------------------------------------------------------------------
AreInSameTable(const uno::Reference<XAccessible> & rAcc,const SwFrm * pFrm)870 static sal_Bool AreInSameTable( const uno::Reference< XAccessible >& rAcc,
871 					  		    const SwFrm *pFrm )
872 {
873 	sal_Bool bRet = sal_False;
874 
875 	if( pFrm && pFrm->IsCellFrm() && rAcc.is() )
876 	{
877 		// Is it in the same table? We check that
878 		// by comparing the last table frame in the
879 		// follow chain, because that's cheaper than
880 		// searching the first one.
881 		SwAccessibleContext *pAccImpl =
882 			static_cast< SwAccessibleContext *>( rAcc.get() );
883 		if( pAccImpl->GetFrm()->IsCellFrm() )
884 		{
885 			const SwTabFrm *pTabFrm1 = pAccImpl->GetFrm()->FindTabFrm();
886 			while( pTabFrm1->GetFollow() )
887 				   pTabFrm1 = pTabFrm1->GetFollow();
888 
889 			const SwTabFrm *pTabFrm2 = pFrm->FindTabFrm();
890 			while( pTabFrm2->GetFollow() )
891 				   pTabFrm2 = pTabFrm2->GetFollow();
892 
893 			bRet = (pTabFrm1 == pTabFrm2);
894 		}
895 	}
896 
897 	return bRet;
898 }
899 
FireEvent(const SwAccessibleEvent_Impl & rEvent)900 void SwAccessibleMap::FireEvent( const SwAccessibleEvent_Impl& rEvent )
901 {
902 	::vos::ORef < SwAccessibleContext > xAccImpl( rEvent.GetContext() );
903 	if (!xAccImpl.isValid() && rEvent.mpParentFrm != 0 )
904 	{
905 		SwAccessibleContextMap_Impl::iterator aIter =
906 			mpFrmMap->find( rEvent.mpParentFrm );
907 		if( aIter != mpFrmMap->end() )
908 		{
909 			uno::Reference < XAccessible > xAcc( (*aIter).second );
910 			if (xAcc.is())
911 			{
912 				uno::Reference < XAccessibleContext >  xContext(xAcc,uno::UNO_QUERY);
913 				if (xContext.is() && xContext->getAccessibleRole() == AccessibleRole::PARAGRAPH)
914 				{
915 					xAccImpl = static_cast< SwAccessibleContext *>( xAcc.get() );
916 				}
917 			}
918 		}
919 	}
920 	if( SwAccessibleEvent_Impl::SHAPE_SELECTION == rEvent.GetType() )
921 	{
922 		DoInvalidateShapeSelection();
923 	}
924 	else if( xAccImpl.isValid() && xAccImpl->GetFrm() )
925 	{
926         // --> OD 2009-01-07 #i88069#
927         if ( rEvent.GetType() != SwAccessibleEvent_Impl::DISPOSE &&
928              rEvent.IsInvalidateTextAttrs() )
929         {
930             xAccImpl->InvalidateAttr();
931         }
932         // <--
933 		switch( rEvent.GetType() )
934 		{
935 		case SwAccessibleEvent_Impl::INVALID_CONTENT:
936 			xAccImpl->InvalidateContent();
937 			break;
938 		case SwAccessibleEvent_Impl::POS_CHANGED:
939 			xAccImpl->InvalidatePosOrSize( rEvent.GetOldBox() );
940 			break;
941 		case SwAccessibleEvent_Impl::CHILD_POS_CHANGED:
942 			xAccImpl->InvalidateChildPosOrSize( rEvent.GetFrmOrObj(),
943 									   rEvent.GetOldBox() );
944 			break;
945 		case SwAccessibleEvent_Impl::DISPOSE:
946 			ASSERT( xAccImpl.isValid(),
947 					"dispose event has been stored" );
948 			break;
949         // --> OD 2009-01-06 #i88069#
950         case SwAccessibleEvent_Impl::INVALID_ATTR:
951             // nothing to do here - handled above
952             break;
953         // <--
954 		default:
955 			break;
956 		}
957 		if( SwAccessibleEvent_Impl::DISPOSE != rEvent.GetType() )
958 		{
959 			if( rEvent.IsUpdateCursorPos() )
960 				xAccImpl->InvalidateCursorPos();
961 			if( rEvent.IsInvalidateStates() )
962 				xAccImpl->InvalidateStates( rEvent.GetStates() );
963             if( rEvent.IsInvalidateRelation() )
964             {
965                 // --> OD 2005-12-01 #i27138#
966                 // both events CONTENT_FLOWS_FROM_RELATION_CHANGED and
967                 // CONTENT_FLOWS_TO_RELATION_CHANGED are possible
968                 if ( rEvent.GetAllStates() & ACC_STATE_RELATION_FROM )
969                 {
970                     xAccImpl->InvalidateRelation(
971                         AccessibleEventId::CONTENT_FLOWS_FROM_RELATION_CHANGED );
972                 }
973                 if ( rEvent.GetAllStates() & ACC_STATE_RELATION_TO )
974                 {
975                     xAccImpl->InvalidateRelation(
976                         AccessibleEventId::CONTENT_FLOWS_TO_RELATION_CHANGED );
977                 }
978                 // <--
979             }
980             // --> OD 2005-12-12 #i27301# - submit event TEXT_SELECTION_CHANGED
981             if ( rEvent.IsInvalidateTextSelection() )
982             {
983                 xAccImpl->InvalidateTextSelection();
984             }
985             // <--
986 		}
987 	}
988 }
989 
AppendEvent(const SwAccessibleEvent_Impl & rEvent)990 void SwAccessibleMap::AppendEvent( const SwAccessibleEvent_Impl& rEvent )
991 {
992 	vos::OGuard aGuard( maEventMutex );
993 
994 	if( !mpEvents )
995 		mpEvents = new SwAccessibleEventList_Impl;
996 	if( !mpEventMap )
997 		mpEventMap = new SwAccessibleEventMap_Impl;
998 
999 	if( mpEvents->IsFiring() )
1000 	{
1001 		// While events are fired new ones are generated. They have to be fired
1002 		// now. This does not work for DISPOSE events!
1003 		ASSERT( rEvent.GetType() != SwAccessibleEvent_Impl::DISPOSE,
1004 				"dispose event while firing events" );
1005 		FireEvent( rEvent );
1006 	}
1007 	else
1008 	{
1009 
1010 		SwAccessibleEventMap_Impl::iterator aIter =
1011                                         mpEventMap->find( rEvent.GetFrmOrObj() );
1012 		if( aIter != mpEventMap->end() )
1013 		{
1014 			SwAccessibleEvent_Impl aEvent( *(*aIter).second );
1015 			ASSERT( aEvent.GetType() != SwAccessibleEvent_Impl::DISPOSE,
1016 					"dispose events should not be stored" );
1017 			sal_Bool bAppendEvent = sal_True;
1018 			switch( rEvent.GetType() )
1019 			{
1020 			case SwAccessibleEvent_Impl::CARET_OR_STATES:
1021 				// A CARET_OR_STATES event is added to any other
1022 				// event only. It is broadcasted after any other event, so the
1023 				// event should be put to the back.
1024                 ASSERT( aEvent.GetType() != SwAccessibleEvent_Impl::CHILD_POS_CHANGED,
1025 						"invalid event combination" );
1026 				aEvent.SetStates( rEvent.GetAllStates() );
1027 				break;
1028 			case SwAccessibleEvent_Impl::INVALID_CONTENT:
1029 				// An INVALID_CONTENT event overwrites a CARET_OR_STATES
1030 				// event (but keeps its flags) and it is contained in a
1031 				// POS_CHANGED event.
1032 				// Therefor, the event's type has to be adapted and the event
1033 				// has to be put at the end.
1034                 ASSERT( aEvent.GetType() != SwAccessibleEvent_Impl::CHILD_POS_CHANGED,
1035 						"invalid event combination" );
1036                 if( aEvent.GetType() == SwAccessibleEvent_Impl::CARET_OR_STATES )
1037 					aEvent.SetType( SwAccessibleEvent_Impl::INVALID_CONTENT );
1038 				break;
1039 			case SwAccessibleEvent_Impl::POS_CHANGED:
1040 				// A pos changed event overwrites CARET_STATES (keeping its
1041 				// flags) as well as INVALID_CONTENT. The old box position
1042 				// has to be stored however if the old event is not a
1043 				// POS_CHANGED itself.
1044                 ASSERT( aEvent.GetType() != SwAccessibleEvent_Impl::CHILD_POS_CHANGED,
1045 						"invalid event combination" );
1046 				if( aEvent.GetType() != SwAccessibleEvent_Impl::POS_CHANGED )
1047 					aEvent.SetOldBox( rEvent.GetOldBox() );
1048 				aEvent.SetType( SwAccessibleEvent_Impl::POS_CHANGED );
1049 				break;
1050 			case SwAccessibleEvent_Impl::CHILD_POS_CHANGED:
1051 				// CHILD_POS_CHANGED events can only follow CHILD_POS_CHANGED
1052 				// events. The only action that needs to be done again is
1053 				// to put the old event to the back. The new one cannot be used,
1054 				// because we are interested in the old frame bounds.
1055                 ASSERT( aEvent.GetType() == SwAccessibleEvent_Impl::CHILD_POS_CHANGED,
1056 						"invalid event combination" );
1057 				break;
1058 			case SwAccessibleEvent_Impl::SHAPE_SELECTION:
1059                 ASSERT( aEvent.GetType() == SwAccessibleEvent_Impl::SHAPE_SELECTION,
1060 						"invalid event combination" );
1061 				break;
1062 			case SwAccessibleEvent_Impl::DISPOSE:
1063 				// DISPOSE events overwrite all others. They are not stored
1064 				// but executed immediatly to avoid broadcasting of
1065 				// defunctional objects. So what needs to be done here is to
1066 				// remove all events for the frame in question.
1067 				bAppendEvent = sal_False;
1068 				break;
1069             // --> OD 2009-01-06 #i88069#
1070             case SwAccessibleEvent_Impl::INVALID_ATTR:
1071                 ASSERT( aEvent.GetType() == SwAccessibleEvent_Impl::INVALID_ATTR,
1072                         "invalid event combination" );
1073                 break;
1074             // <--
1075 			}
1076 			if( bAppendEvent )
1077 			{
1078 				mpEvents->erase( (*aIter).second );
1079 				(*aIter).second = mpEvents->insert( mpEvents->end(), aEvent );
1080 			}
1081 			else
1082 			{
1083 				mpEvents->erase( (*aIter).second );
1084 				mpEventMap->erase( aIter );
1085 			}
1086 		}
1087 		else if( SwAccessibleEvent_Impl::DISPOSE != rEvent.GetType() )
1088 		{
1089 			SwAccessibleEventMap_Impl::value_type aEntry( rEvent.GetFrmOrObj(),
1090 					mpEvents->insert( mpEvents->end(), rEvent ) );
1091 			mpEventMap->insert( aEntry );
1092 		}
1093 	}
1094 }
1095 
InvalidateCursorPosition(const uno::Reference<XAccessible> & rAcc)1096 void SwAccessibleMap::InvalidateCursorPosition(
1097 		const uno::Reference< XAccessible >& rAcc )
1098 {
1099 	SwAccessibleContext *pAccImpl =
1100 		static_cast< SwAccessibleContext *>( rAcc.get() );
1101 	ASSERT( pAccImpl, "no caret context" );
1102 	ASSERT( pAccImpl->GetFrm(), "caret context is disposed" );
1103 	if( GetShell()->ActionPend() )
1104 	{
1105         SwAccessibleEvent_Impl aEvent( SwAccessibleEvent_Impl::CARET_OR_STATES,
1106                                        pAccImpl,
1107                                        SwAccessibleChild(pAccImpl->GetFrm()),
1108                                        ACC_STATE_CARET );
1109 		AppendEvent( aEvent );
1110 	}
1111 	else
1112 	{
1113 		FireEvents();
1114 		// While firing events the current frame might have
1115 		// been disposed because it moved out of the vis area.
1116 		// Setting the cursor for such frames is useless and even
1117 		// causes asserts.
1118 		if( pAccImpl->GetFrm() )
1119 			pAccImpl->InvalidateCursorPos();
1120 	}
1121 }
1122 
InvalidateShapeSelection()1123 void SwAccessibleMap::InvalidateShapeSelection()
1124 {
1125 	if( GetShell()->ActionPend() )
1126 	{
1127 		SwAccessibleEvent_Impl aEvent(
1128 			SwAccessibleEvent_Impl::SHAPE_SELECTION );
1129 		AppendEvent( aEvent );
1130 	}
1131 	else
1132 	{
1133 		FireEvents();
1134 		DoInvalidateShapeSelection();
1135 	}
1136 }
1137 //This method should implement the following functions:
1138 //1.find the shape objects and set the selected state.
1139 //2.find the Swframe objects and set the selected state.
1140 //3.find the paragraph objects and set the selected state.
InvalidateShapeInParaSelection()1141 void SwAccessibleMap::InvalidateShapeInParaSelection()
1142 {
1143 	SwAccessibleObjShape_Impl *pShapes = 0;
1144 	SwAccessibleObjShape_Impl *pSelShape = 0;
1145 	size_t nShapes = 0;
1146 
1147 	const ViewShell *pVSh = GetShell();
1148 	const SwFEShell *pFESh = pVSh->ISA( SwFEShell ) ?
1149 							static_cast< const SwFEShell * >( pVSh ) : 0;
1150 	SwPaM* pCrsr = pFESh ? pFESh->GetCrsr( sal_False /* ??? */ ) : NULL;
1151 	//sal_uInt16 nSelShapes = pFESh ? pFESh->IsObjSelected() : 0;
1152 
1153 	{
1154 		vos::OGuard aGuard( maMutex );
1155 		if( mpShapeMap )
1156 			pShapes = mpShapeMap->Copy( nShapes, pFESh, &pSelShape );
1157 	}
1158 
1159 	sal_Bool bIsSelAll =IsDocumentSelAll();
1160 
1161 	if( mpShapeMap )
1162 	{
1163 		//Checked for shapes.
1164 		_SwAccessibleShapeMap_Impl::const_iterator aIter = mpShapeMap->begin();
1165 		_SwAccessibleShapeMap_Impl::const_iterator aEndIter = mpShapeMap->end();
1166 		::vos::ORef< SwAccessibleContext > xParentAccImpl;
1167 
1168 		if( bIsSelAll)
1169 		{
1170 			while( aIter != aEndIter )
1171 			{
1172 				uno::Reference < XAccessible > xAcc( (*aIter).second );
1173 				if( xAcc.is() )
1174 					(static_cast < ::accessibility::AccessibleShape* >(xAcc.get()))->SetState( AccessibleStateType::SELECTED );
1175 
1176 				++aIter;
1177 			}
1178 		}
1179 		else
1180 		{
1181 			while( aIter != aEndIter )
1182 			{
1183 				sal_Bool bChanged = sal_False;
1184 				sal_Bool bMarked = sal_False;
1185 				SwAccessibleChild pFrm( (*aIter).first );
1186 
1187 				const SwFrmFmt *pFrmFmt = (*aIter).first ? ::FindFrmFmt( (*aIter).first ) : 0;
1188 				if( !pFrmFmt ) { ++aIter; continue; }
1189 				const SwFmtAnchor& pAnchor = pFrmFmt->GetAnchor();
1190 				const SwPosition *pPos = pAnchor.GetCntntAnchor();
1191 
1192 				if(pAnchor.GetAnchorId() == FLY_AT_PAGE)
1193 				{
1194 					uno::Reference < XAccessible > xAcc( (*aIter).second );
1195 					if(xAcc.is())
1196 						(static_cast < ::accessibility::AccessibleShape* >(xAcc.get()))->ResetState( AccessibleStateType::SELECTED );
1197 
1198 					++aIter; continue;
1199 				}
1200 
1201 				if( !pPos ) { ++aIter; continue; }
1202 				if( pPos->nNode.GetNode().GetTxtNode() )
1203 				{
1204 					int pIndex = pPos->nContent.GetIndex();
1205 					SwPaM* pTmpCrsr = pCrsr;
1206 					if( pTmpCrsr != NULL )
1207 					{
1208 						const SwTxtNode* pNode = pPos->nNode.GetNode().GetTxtNode();
1209 						sal_uLong nHere = pNode->GetIndex();
1210 
1211 						do
1212 						{
1213 							// ignore, if no mark
1214 							if( pTmpCrsr->HasMark() )
1215 							{
1216 								bMarked = sal_True;
1217 								// check whether nHere is 'inside' pCrsr
1218 								SwPosition* pStart = pTmpCrsr->Start();
1219 								sal_uLong nStartIndex = pStart->nNode.GetIndex();
1220 								SwPosition* pEnd = pTmpCrsr->End();
1221 								sal_uLong nEndIndex = pEnd->nNode.GetIndex();
1222 								if( ( nHere >= nStartIndex ) && (nHere <= nEndIndex)  )
1223 								{
1224 									if( pAnchor.GetAnchorId() == FLY_AS_CHAR )
1225 									{
1226 										if( ( (nHere == nStartIndex) && (pIndex >= pStart->nContent.GetIndex()) || (nHere > nStartIndex) )
1227 											&&( (nHere == nEndIndex) && (pIndex < pEnd->nContent.GetIndex()) || (nHere < nEndIndex) ) )
1228 										{
1229 											uno::Reference < XAccessible > xAcc( (*aIter).second );
1230 											if( xAcc.is() )
1231 												bChanged = (static_cast < ::accessibility::AccessibleShape* >(xAcc.get()))->SetState( AccessibleStateType::SELECTED );
1232 										}
1233 										else
1234 										{
1235 											uno::Reference < XAccessible > xAcc( (*aIter).second );
1236 											if( xAcc.is() )
1237 												bChanged = (static_cast < ::accessibility::AccessibleShape* >(xAcc.get()))->ResetState( AccessibleStateType::SELECTED );
1238 										}
1239 									}
1240 									else if( pAnchor.GetAnchorId() == FLY_AT_PARA )
1241 									{
1242 										if( ((nHere > nStartIndex) || pStart->nContent.GetIndex() ==0 )
1243 											&& (nHere < nEndIndex ) )
1244 										{
1245 											uno::Reference < XAccessible > xAcc( (*aIter).second );
1246 											if( xAcc.is() )
1247 												bChanged = (static_cast < ::accessibility::AccessibleShape* >(xAcc.get()))->SetState( AccessibleStateType::SELECTED );
1248 										}
1249 										else
1250 										{
1251 											uno::Reference < XAccessible > xAcc( (*aIter).second );
1252 											if(xAcc.is())
1253 												bChanged = (static_cast < ::accessibility::AccessibleShape* >(xAcc.get()))->ResetState( AccessibleStateType::SELECTED );
1254 										}
1255 									}
1256 								}
1257 							}
1258 							// next PaM in ring
1259 							pTmpCrsr = static_cast<SwPaM*>( pTmpCrsr->GetNext() );
1260 						}
1261 						while( pTmpCrsr != pCrsr );
1262 					}
1263 					if( !bMarked )
1264 					{
1265 						SwAccessibleObjShape_Impl  *pShape = pShapes;
1266 						size_t nNumShapes = nShapes;
1267 						while( nNumShapes )
1268 						{
1269 							if( pShape < pSelShape && (pShape->first==(*aIter).first) )
1270 							{
1271 								uno::Reference < XAccessible > xAcc( (*aIter).second );
1272 								if(xAcc.is())
1273 									bChanged = (static_cast < ::accessibility::AccessibleShape* >(xAcc.get()))->ResetState( AccessibleStateType::SELECTED );
1274 							}
1275 							--nNumShapes;
1276 							++pShape;
1277 						}
1278 					}
1279 				}
1280 				++aIter;
1281 			}//while( aIter != aEndIter )
1282 		}//else
1283 	}
1284 
1285 	//Checked for FlyFrm
1286 	SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->begin();
1287 	while( aIter != mpFrmMap->end() )
1288 	{
1289 		const SwFrm *pFrm = (*aIter).first;
1290 		if(pFrm->IsFlyFrm())
1291 		{
1292 			sal_Bool bFrmChanged = sal_False;
1293 			uno::Reference < XAccessible > xAcc = (*aIter).second;
1294 
1295 			if(xAcc.is())
1296 			{
1297 				SwAccessibleFrameBase *pAccFrame = (static_cast< SwAccessibleFrameBase * >(xAcc.get()));
1298 				bFrmChanged = pAccFrame->SetSelectedState( sal_True );
1299 				if (bFrmChanged)
1300 				{
1301 					const SwFlyFrm *pFlyFrm = static_cast< const SwFlyFrm * >( pFrm );
1302 					const SwFrmFmt *pFrmFmt = pFlyFrm->GetFmt();
1303 					if (pFrmFmt)
1304 					{
1305 						const SwFmtAnchor& pAnchor = pFrmFmt->GetAnchor();
1306 						if( pAnchor.GetAnchorId() == FLY_AS_CHAR )
1307 						{
1308 							uno::Reference< XAccessible > xAccParent = pAccFrame->getAccessibleParent();
1309 							if (xAccParent.is())
1310 							{
1311 								uno::Reference< XAccessibleContext > xAccContext = xAccParent->getAccessibleContext();
1312 								if(xAccContext.is() && xAccContext->getAccessibleRole() == AccessibleRole::PARAGRAPH)
1313 								{
1314 									SwAccessibleParagraph* pAccPara = static_cast< SwAccessibleParagraph *>(xAccContext.get());
1315 									if(pAccFrame->IsSeletedInDoc())
1316 									{
1317 										m_setParaAdd.insert(pAccPara);
1318 									}
1319 									else if(m_setParaAdd.count(pAccPara) == 0)
1320 									{
1321 										m_setParaRemove.insert(pAccPara);
1322 									}
1323 								}
1324 							}
1325 						}
1326 					}
1327                 }
1328 			}
1329 		}
1330 		++aIter;
1331 	}
1332 	typedef std::vector< SwAccessibleContext* > VEC_PARA;
1333 	VEC_PARA vecAdd;
1334 	VEC_PARA vecRemove;
1335 	//Checked for Paras.
1336 	SwPaM* pTmpCrsr = pCrsr;
1337 	sal_Bool bMarkChanged = sal_False;
1338 	SwAccessibleContextMap_Impl mapTemp;
1339 	if( pTmpCrsr != NULL )
1340 	{
1341 		do
1342 		{
1343 			if( pTmpCrsr->HasMark() )
1344 			{
1345 				SwNodeIndex nStartIndex( pTmpCrsr->Start()->nNode );
1346 				SwNodeIndex nEndIndex( pTmpCrsr->End()->nNode );
1347 				while(nStartIndex <= nEndIndex)
1348 				{
1349 					SwFrm *pFrm = NULL;
1350 					if(nStartIndex.GetNode().IsCntntNode())
1351 					{
1352 						SwCntntNode* pCNd = (SwCntntNode*)&(nStartIndex.GetNode());
1353 						SwClientIter aClientIter( *pCNd );
1354 						pFrm = (SwFrm*)aClientIter.First( TYPE(SwFrm));
1355 					}
1356 					else if( nStartIndex.GetNode().IsTableNode() )
1357 					{
1358 						SwTableNode * pTable= (SwTableNode *)&(nStartIndex.GetNode());
1359 						SwFrmFmt* pFmt = const_cast<SwFrmFmt*>(pTable->GetTable().GetFrmFmt());
1360 						SwClientIter aClientIter( *pFmt );
1361 						pFrm = (SwFrm*)aClientIter.First( TYPE(SwFrm));
1362 					}
1363 
1364                     if( pFrm && mpFrmMap)
1365 					{
1366 						aIter = mpFrmMap->find( pFrm );
1367 						if( aIter != mpFrmMap->end() )
1368 						{
1369 							uno::Reference < XAccessible > xAcc = (*aIter).second;
1370 							sal_Bool isChanged = sal_False;
1371 							if( xAcc.is() )
1372 							{
1373 								isChanged = (static_cast< SwAccessibleContext * >(xAcc.get()))->SetSelectedState( sal_True );
1374 							}
1375 							if(!isChanged)
1376 							{
1377 								SwAccessibleContextMap_Impl::iterator aEraseIter = mpSeletedFrmMap->find( pFrm );
1378 								if(aEraseIter != mpSeletedFrmMap->end())
1379 									mpSeletedFrmMap->erase(aEraseIter);
1380 							}
1381 							else
1382 							{
1383 								bMarkChanged = sal_True;
1384 								vecAdd.push_back(static_cast< SwAccessibleContext * >(xAcc.get()));
1385 							}
1386 
1387 							mapTemp.insert( SwAccessibleContextMap_Impl::value_type( pFrm, xAcc ) );
1388 						}
1389 					}
1390 					nStartIndex++;
1391 				}
1392 			}
1393 			pTmpCrsr = static_cast<SwPaM*>( pTmpCrsr->GetNext() );
1394 		}
1395 		while( pTmpCrsr != pCrsr );
1396 	}
1397 	if( !mpSeletedFrmMap )
1398 		mpSeletedFrmMap = new SwAccessibleContextMap_Impl;
1399 	if( !mpSeletedFrmMap->empty() )
1400 	{
1401 		aIter = mpSeletedFrmMap->begin();
1402 		while( aIter != mpSeletedFrmMap->end() )
1403 		{
1404 			uno::Reference < XAccessible > xAcc = (*aIter).second;
1405 			if(xAcc.is())
1406 				(static_cast< SwAccessibleContext * >(xAcc.get()))->SetSelectedState( sal_False );
1407 			++aIter;
1408 			vecRemove.push_back(static_cast< SwAccessibleContext * >(xAcc.get()));
1409 		}
1410 		bMarkChanged = sal_True;
1411 		mpSeletedFrmMap->clear();
1412 	}
1413 
1414 	if( !mapTemp.empty() )
1415 	{
1416 		aIter = mapTemp.begin();
1417 		while( aIter != mapTemp.end() )
1418 		{
1419 			mpSeletedFrmMap->insert( SwAccessibleContextMap_Impl::value_type( (*aIter).first, (*aIter).second ) );
1420 			++aIter;
1421 		}
1422 		mapTemp.clear();
1423 	}
1424 	if( bMarkChanged && mpFrmMap)
1425 	{
1426 		VEC_PARA::iterator vi = vecAdd.begin();
1427 		for (; vi != vecAdd.end() ; ++vi)
1428 		{
1429 			AccessibleEventObject aEvent;
1430 			aEvent.EventId = AccessibleEventId::SELECTION_CHANGED;
1431 			SwAccessibleContext* pAccPara = *vi;
1432 			if (pAccPara)
1433 			{
1434 				pAccPara->FireAccessibleEvent( aEvent );
1435 			}
1436 		}
1437 		vi = vecRemove.begin();
1438 		for (; vi != vecRemove.end() ; ++vi)
1439 		{
1440 			AccessibleEventObject aEvent;
1441 			aEvent.EventId = AccessibleEventId::SELECTION_CHANGED_REMOVE;
1442 			SwAccessibleContext* pAccPara = *vi;
1443 			if (pAccPara)
1444 			{
1445 				pAccPara->FireAccessibleEvent( aEvent );
1446 			}
1447 		}
1448 	}
1449 }
1450 
1451 //Marge with DoInvalidateShapeFocus
DoInvalidateShapeSelection(sal_Bool bInvalidateFocusMode)1452 void SwAccessibleMap::DoInvalidateShapeSelection(sal_Bool bInvalidateFocusMode /*=sal_False*/)
1453 {
1454 	SwAccessibleObjShape_Impl *pShapes = 0;
1455 	SwAccessibleObjShape_Impl *pSelShape = 0;
1456 	size_t nShapes = 0;
1457 
1458 	const ViewShell *pVSh = GetShell();
1459 	const SwFEShell *pFESh = pVSh->ISA( SwFEShell ) ?
1460 							static_cast< const SwFEShell * >( pVSh ) : 0;
1461 	sal_uInt16 nSelShapes = pFESh ? pFESh->IsObjSelected() : 0;
1462 
1463 
1464 	//when InvalidateFocus Call this function ,and the current selected shape count is not 1 ,
1465 	//return
1466 	if (bInvalidateFocusMode && nSelShapes != 1)
1467 	{
1468 		return;
1469 	}
1470 	{
1471 		vos::OGuard aGuard( maMutex );
1472 		if( mpShapeMap )
1473 			pShapes = mpShapeMap->Copy( nShapes, pFESh, &pSelShape );
1474 	}
1475 
1476 	if( pShapes )
1477 	{
1478 		typedef std::vector< ::vos::ORef < ::accessibility::AccessibleShape >  >  VEC_SHAPE;
1479 		VEC_SHAPE vecxShapeAdd;
1480 		VEC_SHAPE vecxShapeRemove;
1481 		int nCountSelectedShape=0;
1482 
1483 		Window *pWin = GetShell()->GetWin();
1484 		sal_Bool bFocused = pWin && pWin->HasFocus();
1485 		SwAccessibleObjShape_Impl *pShape = pShapes;
1486 		int nShapeCount = nShapes;
1487 		while( nShapeCount )
1488 		{
1489 			//if( pShape->second.isValid() )
1490 			if (pShape->second.isValid() && IsInSameLevel(pShape->first, pFESh))
1491 				{
1492 				if( pShape < pSelShape )
1493 				{
1494 					if(pShape->second->ResetState( AccessibleStateType::SELECTED ))
1495 					{
1496 						vecxShapeRemove.push_back(pShape->second);
1497 					}
1498 					pShape->second->ResetState( AccessibleStateType::FOCUSED );
1499 				}
1500 			}
1501 			--nShapeCount;
1502 			++pShape;
1503 		}
1504 
1505 		VEC_SHAPE::iterator vi =vecxShapeRemove.begin();
1506 		for (; vi != vecxShapeRemove.end(); ++vi)
1507 		{
1508 			::accessibility::AccessibleShape *pAccShape = static_cast< ::accessibility::AccessibleShape * >(vi->getBodyPtr());
1509 			if (pAccShape)
1510 			{
1511 				pAccShape->CommitChange(AccessibleEventId::SELECTION_CHANGED_REMOVE, uno::Any(), uno::Any());
1512 			}
1513 		}
1514 
1515 		pShape = pShapes;
1516 		while( nShapes )
1517 		{
1518 			//if( pShape->second.isValid() )
1519 			if (pShape->second.isValid() && IsInSameLevel(pShape->first, pFESh))
1520 			{
1521 				// IA2 - why?
1522 				// sal_Bool bChanged;
1523 				if( pShape >= pSelShape )
1524 				{
1525 					// IA2: first fire focus event
1526 					// bChanged = pShape->second->SetState( AccessibleStateType::SELECTED );
1527 
1528 					//first fire focus event
1529 					if( bFocused && 1 == nSelShapes )
1530 						pShape->second->SetState( AccessibleStateType::FOCUSED );
1531 					else
1532 						pShape->second->ResetState( AccessibleStateType::FOCUSED );
1533 
1534 					if(pShape->second->SetState( AccessibleStateType::SELECTED ))
1535 					{
1536 						vecxShapeAdd.push_back(pShape->second);
1537 					}
1538 					++nCountSelectedShape;
1539 				}
1540 				/* MT: This still was in DEV300m80, but was removed in IA2 CWS.
1541 				   Someone needs to check what should happen here, see original diff CWS oo31ia2 vs. OOO310M11
1542 				else
1543 				{
1544 					bChanged =
1545 						pShape->second->ResetState( AccessibleStateType::SELECTED );
1546 					pShape->second->ResetState( AccessibleStateType::FOCUSED );
1547 				}
1548 				if( bChanged )
1549 				{
1550                     const SwFrm* pParent = SwAccessibleFrame::GetParent(
1551                                                     SwAccessibleChild( pShape->first ),
1552                                                     GetShell()->IsPreView() );
1553                     aParents.push_back( pParent );
1554 				}
1555 				*/
1556 			}
1557 
1558 			--nShapes;
1559 			++pShape;
1560 		}
1561 
1562 		const unsigned int SELECTION_WITH_NUM = 10;
1563 		if (vecxShapeAdd.size() > SELECTION_WITH_NUM )
1564 		{
1565 			uno::Reference< XAccessible > xDoc = GetDocumentView( );
1566 			 SwAccessibleContext * pCont = static_cast<SwAccessibleContext *>(xDoc.get());
1567 			 if (pCont)
1568 			 {
1569 				 AccessibleEventObject aEvent;
1570 				 aEvent.EventId = AccessibleEventId::SELECTION_CHANGED_WITHIN;
1571 				 pCont->FireAccessibleEvent(aEvent);
1572 			 }
1573 		}
1574 		else
1575 		{
1576 			short nEventID = AccessibleEventId::SELECTION_CHANGED_ADD;
1577 			if (nCountSelectedShape <= 1 && vecxShapeAdd.size() == 1 )
1578 			{
1579 				nEventID = AccessibleEventId::SELECTION_CHANGED;
1580 			}
1581 			vi = vecxShapeAdd.begin();
1582 			for (; vi != vecxShapeAdd.end(); ++vi)
1583 			{
1584 				::accessibility::AccessibleShape *pAccShape = static_cast< ::accessibility::AccessibleShape * >(vi->getBodyPtr());
1585 				if (pAccShape)
1586 				{
1587 					pAccShape->CommitChange(nEventID, uno::Any(), uno::Any());
1588 				}
1589 			}
1590 		}
1591 
1592 		vi = vecxShapeAdd.begin();
1593 		for (; vi != vecxShapeAdd.end(); ++vi)
1594 		{
1595 			::accessibility::AccessibleShape *pAccShape = static_cast< ::accessibility::AccessibleShape * >(vi->getBodyPtr());
1596 			if (pAccShape)
1597 			{
1598 				SdrObject *pObj = GetSdrObjectFromXShape(pAccShape->GetXShape());
1599 				SwFrmFmt *pFrmFmt = pObj ? FindFrmFmt( pObj ) : NULL;
1600 				if (pFrmFmt)
1601 				{
1602 					const SwFmtAnchor& pAnchor = pFrmFmt->GetAnchor();
1603 					if( pAnchor.GetAnchorId() == FLY_AS_CHAR )
1604 					{
1605 						uno::Reference< XAccessible > xPara = pAccShape->getAccessibleParent();
1606 						if (xPara.is())
1607 						{
1608 							uno::Reference< XAccessibleContext > xParaContext = xPara->getAccessibleContext();
1609 							if (xParaContext.is() && xParaContext->getAccessibleRole() == AccessibleRole::PARAGRAPH)
1610 							{
1611 								SwAccessibleParagraph* pAccPara = static_cast< SwAccessibleParagraph *>(xPara.get());
1612 								if (pAccPara)
1613 								{
1614 									m_setParaAdd.insert(pAccPara);
1615 								}
1616 							}
1617 						}
1618 					}
1619 				}
1620 			}
1621 		}
1622 		vi = vecxShapeRemove.begin();
1623 		for (; vi != vecxShapeRemove.end(); ++vi)
1624 		{
1625 			::accessibility::AccessibleShape *pAccShape = static_cast< ::accessibility::AccessibleShape * >(vi->getBodyPtr());
1626 			if (pAccShape)
1627 			{
1628 				uno::Reference< XAccessible > xPara = pAccShape->getAccessibleParent();
1629 				uno::Reference< XAccessibleContext > xParaContext = xPara->getAccessibleContext();
1630 				if (xParaContext.is() && xParaContext->getAccessibleRole() == AccessibleRole::PARAGRAPH)
1631 				{
1632 					SwAccessibleParagraph* pAccPara = static_cast< SwAccessibleParagraph *>(xPara.get());
1633 					if (m_setParaAdd.count(pAccPara) == 0 )
1634 					{
1635 						m_setParaRemove.insert(pAccPara);
1636 					}
1637 				}
1638 			}
1639 		}
1640 		delete[] pShapes;
1641 	}
1642 }
1643 
1644 //Marge with DoInvalidateShapeSelection
1645 /*
1646 void SwAccessibleMap::DoInvalidateShapeFocus()
1647 {
1648 	const ViewShell *pVSh = GetShell();
1649 	const SwFEShell *pFESh = pVSh->ISA( SwFEShell ) ?
1650 							static_cast< const SwFEShell * >( pVSh ) : 0;
1651 	sal_uInt16 nSelShapes = pFESh ? pFESh->IsObjSelected() : 0;
1652 
1653 	if( nSelShapes != 1 )
1654 		return;
1655 
1656 	SwAccessibleObjShape_Impl *pShapes = 0;
1657 	SwAccessibleObjShape_Impl *pSelShape = 0;
1658 	size_t nShapes = 0;
1659 
1660 
1661 	{
1662 		vos::OGuard aGuard( maMutex );
1663 		if( mpShapeMap )
1664 			pShapes = mpShapeMap->Copy( nShapes, pFESh, &pSelShape );
1665 	}
1666 
1667 	if( pShapes )
1668 	{
1669 		Window *pWin = GetShell()->GetWin();
1670 		sal_Bool bFocused = pWin && pWin->HasFocus();
1671 		SwAccessibleObjShape_Impl  *pShape = pShapes;
1672 		while( nShapes )
1673 		{
1674 			if( pShape->second.isValid() )
1675 			{
1676 				if( bFocused && pShape >= pSelShape )
1677 					pShape->second->SetState( AccessibleStateType::FOCUSED );
1678 				else
1679 					pShape->second->ResetState( AccessibleStateType::FOCUSED );
1680 			}
1681 
1682 			--nShapes;
1683 			++pShape;
1684 		}
1685 
1686 		delete[] pShapes;
1687 	}
1688 }
1689 */
1690 
SwAccessibleMap(ViewShell * pSh)1691 SwAccessibleMap::SwAccessibleMap( ViewShell *pSh ) :
1692 	mpFrmMap( 0  ),
1693 	mpShapeMap( 0  ),
1694 	mpShapes( 0  ),
1695 	mpEvents( 0  ),
1696 	mpEventMap( 0  ),
1697     // --> OD 2005-12-13 #i27301#
1698     mpSelectedParas( 0 ),
1699     // <--
1700 	mpVSh( pSh ),
1701     	mpPreview( 0 ),
1702 	mnPara( 1 ),
1703 	mnFootnote( 1 ),
1704 	mnEndnote( 1 ),
1705 	mbShapeSelected( sal_False ),
1706 	mpSeletedFrmMap(NULL)
1707 {
1708 	pSh->GetLayout()->AddAccessibleShell();
1709 }
1710 
~SwAccessibleMap()1711 SwAccessibleMap::~SwAccessibleMap()
1712 {
1713 	uno::Reference < XAccessible > xAcc;
1714 	{
1715 		vos::OGuard aGuard( maMutex );
1716 		if( mpFrmMap )
1717 		{
1718 			const SwRootFrm *pRootFrm = GetShell()->GetLayout();
1719 			SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->find( pRootFrm );
1720 			if( aIter != mpFrmMap->end() )
1721 				xAcc = (*aIter).second;
1722 			if( !xAcc.is() )
1723 				xAcc = new SwAccessibleDocument( this );
1724 		}
1725 	}
1726 
1727 	if(xAcc.is())
1728 	{
1729 	SwAccessibleDocument *pAcc =
1730 		static_cast< SwAccessibleDocument * >( xAcc.get() );
1731 	pAcc->Dispose( sal_True );
1732 	}
1733 	if( mpFrmMap )
1734 	{
1735 		SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->begin();
1736 		while( aIter != mpFrmMap->end() )
1737 		{
1738 			uno::Reference < XAccessible > xTmp = (*aIter).second;
1739 			if( xTmp.is() )
1740 			{
1741 				SwAccessibleContext *pTmp = static_cast< SwAccessibleContext * >( xTmp.get() );
1742 				pTmp->SetMap(NULL);
1743 			}
1744 			++aIter;
1745 		}
1746 	}
1747 	{
1748 		vos::OGuard aGuard( maMutex );
1749 #ifdef DBG_UTIL
1750 		ASSERT( !mpFrmMap || mpFrmMap->empty(),
1751 				"Frame map should be empty after disposing the root frame" );
1752 		if( mpFrmMap )
1753 		{
1754 			SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->begin();
1755 			while( aIter != mpFrmMap->end() )
1756 			{
1757 				uno::Reference < XAccessible > xTmp = (*aIter).second;
1758 				if( xTmp.is() )
1759 				{
1760 					SwAccessibleContext *pTmp =
1761 						static_cast< SwAccessibleContext * >( xTmp.get() );
1762 					(void) pTmp;
1763 				}
1764 				++aIter;
1765 			}
1766 		}
1767 		ASSERT( !mpShapeMap || mpShapeMap->empty(),
1768 				"Object map should be empty after disposing the root frame" );
1769 		if( mpShapeMap )
1770 		{
1771 			SwAccessibleShapeMap_Impl::iterator aIter = mpShapeMap->begin();
1772 			while( aIter != mpShapeMap->end() )
1773 			{
1774 				uno::Reference < XAccessible > xTmp = (*aIter).second;
1775 				if( xTmp.is() )
1776 				{
1777 					::accessibility::AccessibleShape *pTmp =
1778 						static_cast< ::accessibility::AccessibleShape* >( xTmp.get() );
1779 					(void) pTmp;
1780 				}
1781 				++aIter;
1782 			}
1783 		}
1784 #endif
1785 		delete mpFrmMap;
1786 		mpFrmMap = 0;
1787 		delete mpShapeMap;
1788 		mpShapeMap = 0;
1789 		delete mpShapes;
1790 		mpShapes = 0;
1791         // --> OD 2005-12-13 #i27301#
1792         delete mpSelectedParas;
1793         mpSelectedParas = 0;
1794         // <--
1795 	}
1796 
1797 	delete mpPreview;
1798 	mpPreview = NULL;
1799 
1800     {
1801 		vos::OGuard aGuard( maEventMutex );
1802 #ifdef DBG_UTIL
1803 		ASSERT( !(mpEvents || mpEventMap), "pending events" );
1804 		if( mpEvents )
1805 		{
1806 			SwAccessibleEventList_Impl::iterator aIter = mpEvents->begin();
1807 			while( aIter != mpEvents->end() )
1808 			{
1809 				++aIter;
1810 			}
1811 		}
1812 		if( mpEventMap )
1813 		{
1814 			SwAccessibleEventMap_Impl::iterator aIter = mpEventMap->begin();
1815 			while( aIter != mpEventMap->end() )
1816 			{
1817 				++aIter;
1818 			}
1819 		}
1820 #endif
1821 		delete mpEventMap;
1822 		mpEventMap = 0;
1823 		delete mpEvents;
1824 		mpEvents = 0;
1825 	}
1826 	mpVSh->GetLayout()->RemoveAccessibleShell();
1827 	delete mpSeletedFrmMap;
1828 }
1829 
_GetDocumentView(sal_Bool bPagePreview)1830 uno::Reference< XAccessible > SwAccessibleMap::_GetDocumentView(
1831     sal_Bool bPagePreview )
1832 {
1833 	uno::Reference < XAccessible > xAcc;
1834 	sal_Bool bSetVisArea = sal_False;
1835 
1836 	{
1837 		vos::OGuard aGuard( maMutex );
1838 
1839 		if( !mpFrmMap )
1840 		{
1841 			mpFrmMap = new SwAccessibleContextMap_Impl;
1842 #ifdef DBG_UTIL
1843 			mpFrmMap->mbLocked = sal_False;
1844 #endif
1845 		}
1846 
1847 #ifdef DBG_UTIL
1848 		ASSERT( !mpFrmMap->mbLocked, "Map is locked" );
1849 		mpFrmMap->mbLocked = sal_True;
1850 #endif
1851 
1852 		const SwRootFrm *pRootFrm = GetShell()->GetLayout();
1853 		SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->find( pRootFrm );
1854 		if( aIter != mpFrmMap->end() )
1855 			xAcc = (*aIter).second;
1856 		if( xAcc.is() )
1857 		{
1858 			bSetVisArea = sal_True; // Set VisArea when map mutex is not
1859 									// locked
1860 		}
1861 		else
1862 		{
1863             if( bPagePreview )
1864                 xAcc = new SwAccessiblePreview( this );
1865             else
1866                 xAcc = new SwAccessibleDocument( this );
1867 
1868 			if( aIter != mpFrmMap->end() )
1869 			{
1870 				(*aIter).second = xAcc;
1871 			}
1872 			else
1873 			{
1874 				SwAccessibleContextMap_Impl::value_type aEntry( pRootFrm, xAcc );
1875 				mpFrmMap->insert( aEntry );
1876 			}
1877 		}
1878 
1879 #ifdef DBG_UTIL
1880 		mpFrmMap->mbLocked = sal_False;
1881 #endif
1882 	}
1883 
1884 	if( bSetVisArea )
1885 	{
1886 		SwAccessibleDocumentBase *pAcc =
1887 			static_cast< SwAccessibleDocumentBase * >( xAcc.get() );
1888 		pAcc->SetVisArea();
1889 	}
1890 
1891 	return xAcc;
1892 }
1893 
GetDocumentView()1894 uno::Reference< XAccessible > SwAccessibleMap::GetDocumentView( )
1895 {
1896     return _GetDocumentView( sal_False );
1897 }
1898 
1899 // OD 14.01.2003 #103492# - complete re-factoring of method due to new page/print
1900 // preview functionality.
GetDocumentPreview(const std::vector<PrevwPage * > & _rPrevwPages,const Fraction & _rScale,const SwPageFrm * _pSelectedPageFrm,const Size & _rPrevwWinSize)1901 uno::Reference<XAccessible> SwAccessibleMap::GetDocumentPreview(
1902                                     const std::vector<PrevwPage*>& _rPrevwPages,
1903                                     const Fraction&  _rScale,
1904                                     const SwPageFrm* _pSelectedPageFrm,
1905                                     const Size&      _rPrevwWinSize )
1906 {
1907     // create & update preview data object
1908     if( mpPreview == NULL )
1909         mpPreview = new SwAccPreviewData();
1910     mpPreview->Update( *this, _rPrevwPages, _rScale, _pSelectedPageFrm, _rPrevwWinSize );
1911 
1912     uno::Reference<XAccessible> xAcc = _GetDocumentView( sal_True );
1913     return xAcc;
1914 }
1915 
GetContext(const SwFrm * pFrm,sal_Bool bCreate)1916 uno::Reference< XAccessible> SwAccessibleMap::GetContext( const SwFrm *pFrm,
1917 												     sal_Bool bCreate )
1918 {
1919 	uno::Reference < XAccessible > xAcc;
1920 	uno::Reference < XAccessible > xOldCursorAcc;
1921 	sal_Bool bOldShapeSelected = sal_False;
1922 
1923 	{
1924 		vos::OGuard aGuard( maMutex );
1925 
1926 		if( !mpFrmMap && bCreate )
1927 			mpFrmMap = new SwAccessibleContextMap_Impl;
1928 		if( mpFrmMap )
1929 		{
1930 			SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->find( pFrm );
1931 			if( aIter != mpFrmMap->end() )
1932 				xAcc = (*aIter).second;
1933 
1934 			if( !xAcc.is() && bCreate )
1935 			{
1936 				SwAccessibleContext *pAcc = 0;
1937 				switch( pFrm->GetType() )
1938 				{
1939 				case FRM_TXT:
1940                     mnPara++;
1941                     pAcc = new SwAccessibleParagraph( *this,
1942                                     static_cast< const SwTxtFrm& >( *pFrm ) );
1943 					break;
1944 				case FRM_HEADER:
1945 					pAcc = new SwAccessibleHeaderFooter( this,
1946 									static_cast< const SwHeaderFrm *>( pFrm ) );
1947 					break;
1948 				case FRM_FOOTER:
1949 					pAcc = new SwAccessibleHeaderFooter( this,
1950 									static_cast< const SwFooterFrm *>( pFrm ) );
1951 					break;
1952 				case FRM_FTN:
1953 					{
1954 						const SwFtnFrm *pFtnFrm =
1955 							static_cast < const SwFtnFrm * >( pFrm );
1956 						sal_Bool bIsEndnote =
1957 							SwAccessibleFootnote::IsEndnote( pFtnFrm );
1958 						pAcc = new SwAccessibleFootnote( this, bIsEndnote,
1959 									/*(bIsEndnote ? mnEndnote++ : mnFootnote++),*/
1960 									pFtnFrm );
1961 					}
1962 					break;
1963 				case FRM_FLY:
1964 					{
1965 						const SwFlyFrm *pFlyFrm =
1966 							static_cast < const SwFlyFrm * >( pFrm );
1967 						switch( SwAccessibleFrameBase::GetNodeType( pFlyFrm ) )
1968 						{
1969 						case ND_GRFNODE:
1970 							pAcc = new SwAccessibleGraphic( this, pFlyFrm );
1971 							break;
1972 						case ND_OLENODE:
1973 							pAcc = new SwAccessibleEmbeddedObject( this, pFlyFrm );
1974 							break;
1975 						default:
1976 							pAcc = new SwAccessibleTextFrame( this, pFlyFrm );
1977 							break;
1978 						}
1979 					}
1980 					break;
1981 				case FRM_CELL:
1982 					pAcc = new SwAccessibleCell( this,
1983 									static_cast< const SwCellFrm *>( pFrm ) );
1984 					break;
1985 				case FRM_TAB:
1986                     pAcc = new SwAccessibleTable( this,
1987 									static_cast< const SwTabFrm *>( pFrm ) );
1988 					break;
1989                 case FRM_PAGE:
1990                     DBG_ASSERT( GetShell()->IsPreView(),
1991                                 "accessible page frames only in PagePreview" );
1992                     pAcc = new SwAccessiblePage( this, pFrm );
1993                     break;
1994 				}
1995 				xAcc = pAcc;
1996 
1997 				ASSERT( xAcc.is(), "unknown frame type" );
1998 				if( xAcc.is() )
1999 				{
2000 					if( aIter != mpFrmMap->end() )
2001 					{
2002 						(*aIter).second = xAcc;
2003 					}
2004 					else
2005 					{
2006 						SwAccessibleContextMap_Impl::value_type aEntry( pFrm, xAcc );
2007 						mpFrmMap->insert( aEntry );
2008 					}
2009 
2010 					if( pAcc->HasCursor() &&
2011 						!AreInSameTable( mxCursorContext, pFrm ) )
2012 					{
2013 						// If the new context has the focus, and if we know
2014 						// another context that had the focus, then the focus
2015 						// just moves from the old context to the new one. We
2016 						// have to send a focus event and a caret event for
2017 						// the old context then. We have to to that know,
2018 						// because after we have left this method, anyone might
2019 						// call getStates for the new context and will get a
2020 						// focused state then. Sending the focus changes event
2021 						// after that seems to be strange. However, we cannot
2022 						// send a focus event fo the new context now, because
2023 					    // noone except us knows it. In any case, we remeber
2024 						// the new context as the one that has the focus
2025 						// currently.
2026 
2027 						xOldCursorAcc = mxCursorContext;
2028 						mxCursorContext = xAcc;
2029 
2030 						bOldShapeSelected = mbShapeSelected;
2031 						mbShapeSelected = sal_False;
2032 					}
2033 				}
2034 			}
2035 		}
2036 	}
2037 
2038 	// Invalidate focus for old object when map is not locked
2039 	if( xOldCursorAcc.is() )
2040 		InvalidateCursorPosition( xOldCursorAcc );
2041 	if( bOldShapeSelected )
2042 		InvalidateShapeSelection();
2043 
2044 	return xAcc;
2045 }
2046 
GetContextImpl(const SwFrm * pFrm,sal_Bool bCreate)2047 ::vos::ORef < SwAccessibleContext > SwAccessibleMap::GetContextImpl(
2048 			const SwFrm *pFrm,
2049 			sal_Bool bCreate )
2050 {
2051 	uno::Reference < XAccessible > xAcc( GetContext( pFrm, bCreate ) );
2052 
2053 	::vos::ORef < SwAccessibleContext > xAccImpl(
2054 		 static_cast< SwAccessibleContext * >( xAcc.get() ) );
2055 
2056 	return xAccImpl;
2057 }
2058 
GetContext(const SdrObject * pObj,SwAccessibleContext * pParentImpl,sal_Bool bCreate)2059 uno::Reference< XAccessible> SwAccessibleMap::GetContext(
2060 		const SdrObject *pObj,
2061 		SwAccessibleContext *pParentImpl,
2062 		sal_Bool bCreate )
2063 {
2064 	uno::Reference < XAccessible > xAcc;
2065 	uno::Reference < XAccessible > xOldCursorAcc;
2066 
2067 	{
2068 		vos::OGuard aGuard( maMutex );
2069 
2070 		if( !mpShapeMap && bCreate )
2071 			mpShapeMap = new SwAccessibleShapeMap_Impl( this );
2072 		if( mpShapeMap )
2073 		{
2074 			SwAccessibleShapeMap_Impl::iterator aIter =
2075 			   	mpShapeMap->find( pObj );
2076 			if( aIter != mpShapeMap->end() )
2077 				xAcc = (*aIter).second;
2078 
2079 			if( !xAcc.is() && bCreate )
2080 			{
2081 				::accessibility::AccessibleShape *pAcc = 0;
2082 				uno::Reference < drawing::XShape > xShape(
2083 					const_cast< SdrObject * >( pObj )->getUnoShape(),
2084 					uno::UNO_QUERY );
2085 				if( xShape.is() )
2086 				{
2087 					::accessibility::ShapeTypeHandler& rShapeTypeHandler =
2088 								::accessibility::ShapeTypeHandler::Instance();
2089 					uno::Reference < XAccessible > xParent( pParentImpl );
2090 					::accessibility::AccessibleShapeInfo aShapeInfo(
2091 							xShape, xParent, this );
2092 
2093 					pAcc = rShapeTypeHandler.CreateAccessibleObject(
2094 								aShapeInfo, mpShapeMap->GetInfo() );
2095 				}
2096 				xAcc = pAcc;
2097 
2098 				ASSERT( xAcc.is(), "unknown shape type" );
2099 				if( xAcc.is() )
2100 				{
2101 					pAcc->Init();
2102 					if( aIter != mpShapeMap->end() )
2103 					{
2104 						(*aIter).second = xAcc;
2105 					}
2106 					else
2107 					{
2108 						SwAccessibleShapeMap_Impl::value_type aEntry( pObj,
2109 																	  xAcc );
2110 						mpShapeMap->insert( aEntry );
2111 					}
2112 					// TODO: focus!!!
2113 				}
2114 				if (xAcc.is())
2115 					AddGroupContext(pObj, xAcc);
2116 			}
2117 		}
2118 	}
2119 
2120 	// Invalidate focus for old object when map is not locked
2121 	if( xOldCursorAcc.is() )
2122 		InvalidateCursorPosition( xOldCursorAcc );
2123 
2124 	return xAcc;
2125 }
IsInSameLevel(const SdrObject * pObj,const SwFEShell * pFESh)2126 sal_Bool SwAccessibleMap::IsInSameLevel(const SdrObject* pObj, const SwFEShell* pFESh)
2127 {
2128 	if (pFESh)
2129 		return pFESh->IsObjSameLevelWithMarked(pObj);
2130 	return sal_False;
2131 }
AddShapeContext(const SdrObject * pObj,uno::Reference<XAccessible> xAccShape)2132 void SwAccessibleMap::AddShapeContext(const SdrObject *pObj, uno::Reference < XAccessible > xAccShape)
2133 {
2134 	vos::OGuard aGuard( maMutex );
2135 
2136 	if( mpShapeMap )
2137 	{
2138 		SwAccessibleShapeMap_Impl::value_type aEntry( pObj, xAccShape );
2139 		mpShapeMap->insert( aEntry );
2140 	}
2141 
2142 }
2143 
2144 //Added by yanjun for sym2_6407
RemoveGroupContext(const SdrObject * pParentObj,::com::sun::star::uno::Reference<::com::sun::star::accessibility::XAccessible> xAccParent)2145 void SwAccessibleMap::RemoveGroupContext(const SdrObject *pParentObj, ::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessible > xAccParent)
2146 {
2147 	vos::OGuard aGuard( maMutex );
2148 	if (mpShapeMap && pParentObj && pParentObj->IsGroupObject() && xAccParent.is())
2149 	{
2150 		uno::Reference < XAccessibleContext > xContext = xAccParent->getAccessibleContext();
2151 		if (xContext.is())
2152 		{
2153 			for (sal_Int32 i = 0; i < xContext->getAccessibleChildCount(); ++i)
2154 			{
2155 				uno::Reference < XAccessible > xChild = xContext->getAccessibleChild(i);
2156 				if (xChild.is())
2157 				{
2158 					uno::Reference < XAccessibleContext > xChildContext = xChild->getAccessibleContext();
2159 					if (xChildContext.is())
2160 					{
2161 						if (xChildContext->getAccessibleRole() == AccessibleRole::SHAPE)
2162 						{
2163 							::accessibility::AccessibleShape* pAccShape = static_cast < ::accessibility::AccessibleShape* >( xChild.get());
2164 							uno::Reference < drawing::XShape > xShape = pAccShape->GetXShape();
2165 							if (xShape.is())
2166 							{
2167 								SdrObject* pObj = GetSdrObjectFromXShape(xShape);
2168 								if (pObj)
2169 									RemoveContext(pObj);
2170 							}
2171 						}
2172 					}
2173 				}
2174 			}
2175 		}
2176 	}
2177 }
2178 //End
2179 
2180 
AddGroupContext(const SdrObject * pParentObj,uno::Reference<XAccessible> xAccParent)2181 void SwAccessibleMap::AddGroupContext(const SdrObject *pParentObj, uno::Reference < XAccessible > xAccParent)
2182 {
2183 	vos::OGuard aGuard( maMutex );
2184 	if( mpShapeMap )
2185 	{
2186 		//here get all the sub list.
2187 		if (pParentObj->IsGroupObject())
2188 		{
2189 			if (xAccParent.is())
2190 			{
2191 				uno::Reference < XAccessibleContext > xContext = xAccParent->getAccessibleContext();
2192 				if (xContext.is())
2193 				{
2194 					sal_Int32 nChildren = xContext->getAccessibleChildCount();
2195 					for(sal_Int32 i = 0; i<nChildren; i++)
2196 					{
2197 						uno::Reference < XAccessible > xChild = xContext->getAccessibleChild(i);
2198 						if (xChild.is())
2199 						{
2200 							uno::Reference < XAccessibleContext > xChildContext = xChild->getAccessibleContext();
2201 							if (xChildContext.is())
2202 							{
2203 								short nRole = xChildContext->getAccessibleRole();
2204 								if (nRole == AccessibleRole::SHAPE)
2205 								{
2206 									::accessibility::AccessibleShape* pAccShape = static_cast < ::accessibility::AccessibleShape* >( xChild.get());
2207 									uno::Reference < drawing::XShape > xShape = pAccShape->GetXShape();
2208 									if (xShape.is())
2209 									{
2210 										SdrObject* pObj = GetSdrObjectFromXShape(xShape);
2211 										AddShapeContext(pObj, xChild);
2212 										AddGroupContext(pObj,xChild);
2213 									}
2214 								}
2215 							}
2216 						}
2217 					}
2218 				}
2219 			}
2220 		}
2221 	}
2222 }
2223 
GetContextImpl(const SdrObject * pObj,SwAccessibleContext * pParentImpl,sal_Bool bCreate)2224 ::vos::ORef < ::accessibility::AccessibleShape > SwAccessibleMap::GetContextImpl(
2225 			const SdrObject *pObj,
2226 			SwAccessibleContext *pParentImpl,
2227 			sal_Bool bCreate )
2228 {
2229 	uno::Reference < XAccessible > xAcc( GetContext( pObj, pParentImpl, bCreate ) );
2230 
2231 	::vos::ORef < ::accessibility::AccessibleShape > xAccImpl(
2232 		 static_cast< ::accessibility::AccessibleShape* >( xAcc.get() ) );
2233 
2234 	return xAccImpl;
2235 }
2236 
2237 
RemoveContext(const SwFrm * pFrm)2238 void SwAccessibleMap::RemoveContext( const SwFrm *pFrm )
2239 {
2240 	vos::OGuard aGuard( maMutex );
2241 
2242 	if( mpFrmMap )
2243 	{
2244 		SwAccessibleContextMap_Impl::iterator aIter =
2245 			mpFrmMap->find( pFrm );
2246 		if( aIter != mpFrmMap->end() )
2247 		{
2248 			mpFrmMap->erase( aIter );
2249 
2250 			// Remove reference to old caret object. Though mxCursorContext
2251 			// is a weak reference and cleared automatically, clearing it
2252 			// directly makes sure to not keep a defunctional object.
2253 			uno::Reference < XAccessible > xOldAcc( mxCursorContext );
2254 			if( xOldAcc.is() )
2255 			{
2256 				SwAccessibleContext *pOldAccImpl =
2257 					static_cast< SwAccessibleContext *>( xOldAcc.get() );
2258 				ASSERT( pOldAccImpl->GetFrm(), "old caret context is disposed" );
2259 				if( pOldAccImpl->GetFrm() == pFrm )
2260 				{
2261 					xOldAcc.clear();	// get an empty ref
2262 					mxCursorContext = xOldAcc;
2263 				}
2264 			}
2265 
2266 			if( mpFrmMap->empty() )
2267 			{
2268 				delete mpFrmMap;
2269 				mpFrmMap = 0;
2270 			}
2271 		}
2272 	}
2273 }
2274 
RemoveContext(const SdrObject * pObj)2275 void SwAccessibleMap::RemoveContext( const SdrObject *pObj )
2276 {
2277 	vos::OGuard aGuard( maMutex );
2278 
2279 	if( mpShapeMap )
2280 	{
2281 		SwAccessibleShapeMap_Impl::iterator aIter =
2282 			mpShapeMap->find( pObj );
2283 		if( aIter != mpShapeMap->end() )
2284 		{
2285 			uno::Reference < XAccessible > xAcc( (*aIter).second );
2286 			mpShapeMap->erase( aIter );
2287 			RemoveGroupContext(pObj, xAcc);
2288 			// The shape selection flag is not cleared, but one might do
2289 			// so but has to make sure that the removed context is the one
2290 			// that is selected.
2291 
2292 			if( mpShapeMap && mpShapeMap->empty() )
2293 			{
2294 				delete mpShapeMap;
2295 				mpShapeMap = 0;
2296 			}
2297 		}
2298 	}
2299 }
2300 
2301 
Dispose(const SwFrm * pFrm,const SdrObject * pObj,Window * pWindow,sal_Bool bRecursive)2302 void SwAccessibleMap::Dispose( const SwFrm *pFrm,
2303                                const SdrObject *pObj,
2304                                Window* pWindow,
2305 							   sal_Bool bRecursive )
2306 {
2307     SwAccessibleChild aFrmOrObj( pFrm, pObj, pWindow );
2308 
2309 	// Indeed, the following assert checks the frame's accessible flag,
2310 	// because that's the one that is evaluated in the layout. The frame
2311 	// might not be accessible anyway. That's the case for cell frames that
2312 	// contain further cells.
2313 	ASSERT( !aFrmOrObj.GetSwFrm() || aFrmOrObj.GetSwFrm()->IsAccessibleFrm(),
2314 			"non accessible frame should be disposed" );
2315 
2316 	if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) )
2317 	{
2318         ::vos::ORef< SwAccessibleContext > xAccImpl;
2319         ::vos::ORef< SwAccessibleContext > xParentAccImpl;
2320         ::vos::ORef< ::accessibility::AccessibleShape > xShapeAccImpl;
2321 		// get accessible context for frame
2322 		{
2323 			vos::OGuard aGuard( maMutex );
2324 
2325 			// First of all look for an accessible context for a frame
2326 			if( aFrmOrObj.GetSwFrm() && mpFrmMap )
2327 			{
2328 				SwAccessibleContextMap_Impl::iterator aIter =
2329 					mpFrmMap->find( aFrmOrObj.GetSwFrm() );
2330 				if( aIter != mpFrmMap->end() )
2331 				{
2332 					uno::Reference < XAccessible > xAcc( (*aIter).second );
2333 					xAccImpl =
2334 						static_cast< SwAccessibleContext *>( xAcc.get() );
2335 				}
2336 			}
2337 			if( !xAccImpl.isValid() && mpFrmMap )
2338 			{
2339 				// If there is none, look if the parent is accessible.
2340 				const SwFrm *pParent =
2341 						SwAccessibleFrame::GetParent( aFrmOrObj,
2342                                                       GetShell()->IsPreView());
2343 
2344 				if( pParent )
2345 				{
2346 					SwAccessibleContextMap_Impl::iterator aIter =
2347 						mpFrmMap->find( pParent );
2348 					if( aIter != mpFrmMap->end() )
2349 					{
2350 						uno::Reference < XAccessible > xAcc( (*aIter).second );
2351 						xParentAccImpl =
2352 							static_cast< SwAccessibleContext *>( xAcc.get() );
2353 					}
2354 				}
2355 			}
2356 			if( !xParentAccImpl.isValid() && !aFrmOrObj.GetSwFrm() &&
2357 				mpShapeMap )
2358 			{
2359 				SwAccessibleShapeMap_Impl::iterator aIter =
2360                     mpShapeMap->find( aFrmOrObj.GetDrawObject() );
2361 				if( aIter != mpShapeMap->end() )
2362 				{
2363 					uno::Reference < XAccessible > xAcc( (*aIter).second );
2364 					xShapeAccImpl =
2365 						static_cast< ::accessibility::AccessibleShape *>( xAcc.get() );
2366 				}
2367 			}
2368 			if( pObj && GetShell()->ActionPend() &&
2369 				(xParentAccImpl.isValid() || xShapeAccImpl.isValid()) )
2370 			{
2371 				// Keep a reference to the XShape to avoid that it
2372 				// is deleted with a SwFrmFmt::Modify.
2373 				uno::Reference < drawing::XShape > xShape(
2374 					const_cast< SdrObject * >( pObj )->getUnoShape(),
2375 					uno::UNO_QUERY );
2376 				if( xShape.is() )
2377 				{
2378 					if( !mpShapes )
2379 						mpShapes = new SwShapeList_Impl;
2380 					mpShapes->push_back( xShape );
2381 				}
2382 			}
2383 		}
2384 
2385 		// remove events stored for the frame
2386 		{
2387 			vos::OGuard aGuard( maEventMutex );
2388 			if( mpEvents )
2389 			{
2390 				SwAccessibleEventMap_Impl::iterator aIter =
2391 					mpEventMap->find( aFrmOrObj );
2392 				if( aIter != mpEventMap->end() )
2393 				{
2394 					SwAccessibleEvent_Impl aEvent(
2395 							SwAccessibleEvent_Impl::DISPOSE, aFrmOrObj );
2396 					AppendEvent( aEvent );
2397 				}
2398 			}
2399 		}
2400 
2401 		// If the frame is accessible and there is a context for it, dispose
2402 		// the frame. If the frame is no context for it but disposing should
2403 		// take place recursive, the frame's children have to be disposed
2404 		// anyway, so we have to create the context then.
2405 		if( xAccImpl.isValid() )
2406 		{
2407 			xAccImpl->Dispose( bRecursive );
2408 		}
2409 		else if( xParentAccImpl.isValid() )
2410 		{
2411 			// If the frame is a cell frame, the table must be notified.
2412 			// If we are in an action, a table model change event will
2413 			// be broadcasted at the end of the action to give the table
2414 			// a chance to generate a single table change event.
2415 
2416 			xParentAccImpl->DisposeChild( aFrmOrObj, bRecursive );
2417 		}
2418 		else if( xShapeAccImpl.isValid() )
2419 		{
2420             RemoveContext( aFrmOrObj.GetDrawObject() );
2421 			xShapeAccImpl->dispose();
2422 		}
2423 
2424 		if( mpPreview && pFrm && pFrm->IsPageFrm() )
2425 			mpPreview->DisposePage( static_cast< const SwPageFrm *>( pFrm ) );
2426 	}
2427 }
2428 
InvalidatePosOrSize(const SwFrm * pFrm,const SdrObject * pObj,Window * pWindow,const SwRect & rOldBox)2429 void SwAccessibleMap::InvalidatePosOrSize( const SwFrm *pFrm,
2430 										   const SdrObject *pObj,
2431                                            Window* pWindow,
2432 										   const SwRect& rOldBox )
2433 {
2434     SwAccessibleChild aFrmOrObj( pFrm, pObj, pWindow );
2435 	if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) )
2436 	{
2437 		::vos::ORef< SwAccessibleContext > xAccImpl;
2438 		::vos::ORef< SwAccessibleContext > xParentAccImpl;
2439 		const SwFrm *pParent =NULL;
2440 		{
2441 			vos::OGuard aGuard( maMutex );
2442 
2443 			if( mpFrmMap )
2444 			{
2445 				if( aFrmOrObj.GetSwFrm() )
2446 				{
2447 					SwAccessibleContextMap_Impl::iterator aIter =
2448 						mpFrmMap->find( aFrmOrObj.GetSwFrm() );
2449 					if( aIter != mpFrmMap->end() )
2450 					{
2451 						// If there is an accesible object already it is
2452 						// notified directly.
2453 						uno::Reference < XAccessible > xAcc( (*aIter).second );
2454 						xAccImpl =
2455 							static_cast< SwAccessibleContext *>( xAcc.get() );
2456 					}
2457 				}
2458 				if( !xAccImpl.isValid() )
2459 				{
2460 					// Otherwise we look if the parent is accessible.
2461 					// If not, there is nothing to do.
2462 					pParent = SwAccessibleFrame::GetParent( aFrmOrObj,
2463                                                       GetShell()->IsPreView());
2464 
2465 					if( pParent )
2466 					{
2467 						SwAccessibleContextMap_Impl::iterator aIter =
2468 							mpFrmMap->find( pParent );
2469 						if( aIter != mpFrmMap->end() )
2470 						{
2471 							uno::Reference < XAccessible > xAcc( (*aIter).second );
2472 							xParentAccImpl =
2473 								static_cast< SwAccessibleContext *>( xAcc.get() );
2474 						}
2475 					}
2476 				}
2477 			}
2478 		}
2479 
2480 		if( xAccImpl.isValid() )
2481 		{
2482 			if( GetShell()->ActionPend() )
2483 			{
2484 				SwAccessibleEvent_Impl aEvent(
2485 					SwAccessibleEvent_Impl::POS_CHANGED, xAccImpl.getBodyPtr(),
2486 					aFrmOrObj, rOldBox );
2487 				AppendEvent( aEvent );
2488 			}
2489 			else
2490 			{
2491 				FireEvents();
2492 				xAccImpl->InvalidatePosOrSize( rOldBox );
2493 			}
2494 		}
2495 		else if( xParentAccImpl.isValid() )
2496 		{
2497 			if( GetShell()->ActionPend() )
2498 			{
2499 				SwAccessibleEvent_Impl aEvent(
2500 					SwAccessibleEvent_Impl::CHILD_POS_CHANGED,
2501 					xParentAccImpl.getBodyPtr(), aFrmOrObj, rOldBox );
2502 				AppendEvent( aEvent );
2503 			}
2504 			else
2505 			{
2506 				FireEvents();
2507 				xParentAccImpl->InvalidateChildPosOrSize( aFrmOrObj,
2508 														  rOldBox );
2509 			}
2510 		}
2511 		else if(pParent)
2512 		{
2513 /*
2514 For child graphic and it's parent paragraph,if split 2 graphic to 2 paragraph,
2515 will delete one graphic swfrm and new create 1 graphic swfrm ,
2516 then the new paragraph and the new graphic SwFrm will add .
2517 but when add graphic SwFrm ,the accessible of the new Paragraph is not created yet.
2518 so the new graphic accessible 'parent is NULL,
2519 so run here: save the parent's SwFrm not the accessible object parent,
2520 */
2521 			sal_Bool bIsValidFrm = sal_False;
2522 			sal_Bool bIsTxtParent = sal_False;
2523 			if (aFrmOrObj.GetSwFrm())
2524 			{
2525 				int nType = pFrm->GetType();
2526 				if ( FRM_FLY == nType )
2527 				{
2528 					bIsValidFrm =sal_True;
2529 				}
2530 			}
2531 			else if(pObj)
2532 			{
2533 				int nType = pParent->GetType();
2534 				if (FRM_TXT == nType)
2535 				{
2536 					bIsTxtParent =sal_True;
2537 				}
2538 			}
2539 //			sal_Bool bIsVisibleChildrenOnly =aFrmOrObj.IsVisibleChildrenOnly() ;
2540 //			sal_Bool bIsBoundAsChar =aFrmOrObj.IsBoundAsChar() ;//bIsVisibleChildrenOnly && bIsBoundAsChar &&
2541 			if((bIsValidFrm || bIsTxtParent) )
2542 			{
2543 				if( GetShell()->ActionPend() )
2544 				{
2545 					SwAccessibleEvent_Impl aEvent(
2546 						SwAccessibleEvent_Impl::CHILD_POS_CHANGED,
2547 						pParent, aFrmOrObj, rOldBox );
2548 					AppendEvent( aEvent );
2549 				}
2550 				else
2551 				{
2552 					OSL_ENSURE(false,"");
2553 				}
2554 			}
2555 		}
2556 	}
2557 }
2558 
InvalidateContent(const SwFrm * pFrm)2559 void SwAccessibleMap::InvalidateContent( const SwFrm *pFrm )
2560 {
2561     SwAccessibleChild aFrmOrObj( pFrm );
2562 	if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) )
2563 	{
2564 		uno::Reference < XAccessible > xAcc;
2565 		{
2566 			vos::OGuard aGuard( maMutex );
2567 
2568 			if( mpFrmMap )
2569 			{
2570 				SwAccessibleContextMap_Impl::iterator aIter =
2571 					mpFrmMap->find( aFrmOrObj.GetSwFrm() );
2572 				if( aIter != mpFrmMap->end() )
2573 					xAcc = (*aIter).second;
2574 			}
2575 		}
2576 
2577 		if( xAcc.is() )
2578 		{
2579 			SwAccessibleContext *pAccImpl =
2580 				static_cast< SwAccessibleContext *>( xAcc.get() );
2581 			if( GetShell()->ActionPend() )
2582 			{
2583 				SwAccessibleEvent_Impl aEvent(
2584 					SwAccessibleEvent_Impl::INVALID_CONTENT, pAccImpl,
2585 					aFrmOrObj );
2586 				AppendEvent( aEvent );
2587 			}
2588 			else
2589 			{
2590 				FireEvents();
2591 				pAccImpl->InvalidateContent();
2592 			}
2593 		}
2594 	}
2595 }
2596 
2597 // --> OD 2009-01-06 #i88069#
InvalidateAttr(const SwTxtFrm & rTxtFrm)2598 void SwAccessibleMap::InvalidateAttr( const SwTxtFrm& rTxtFrm )
2599 {
2600     SwAccessibleChild aFrmOrObj( &rTxtFrm );
2601     if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) )
2602     {
2603         uno::Reference < XAccessible > xAcc;
2604         {
2605             vos::OGuard aGuard( maMutex );
2606 
2607             if( mpFrmMap )
2608             {
2609                 SwAccessibleContextMap_Impl::iterator aIter =
2610                     mpFrmMap->find( aFrmOrObj.GetSwFrm() );
2611                 if( aIter != mpFrmMap->end() )
2612                     xAcc = (*aIter).second;
2613             }
2614         }
2615 
2616         if( xAcc.is() )
2617         {
2618             SwAccessibleContext *pAccImpl =
2619                 static_cast< SwAccessibleContext *>( xAcc.get() );
2620             if( GetShell()->ActionPend() )
2621             {
2622                 SwAccessibleEvent_Impl aEvent( SwAccessibleEvent_Impl::INVALID_ATTR,
2623                                                pAccImpl, aFrmOrObj );
2624                 aEvent.SetStates( ACC_STATE_TEXT_ATTRIBUTE_CHANGED );
2625                 AppendEvent( aEvent );
2626             }
2627             else
2628             {
2629                 FireEvents();
2630                 pAccImpl->InvalidateAttr();
2631             }
2632         }
2633     }
2634 }
2635 // <--
2636 
InvalidateCursorPosition(const SwFrm * pFrm)2637 void SwAccessibleMap::InvalidateCursorPosition( const SwFrm *pFrm )
2638 {
2639     SwAccessibleChild aFrmOrObj( pFrm );
2640 	sal_Bool bShapeSelected = sal_False;
2641 	const ViewShell *pVSh = GetShell();
2642 	if( pVSh->ISA( SwCrsrShell ) )
2643 	{
2644 		const SwCrsrShell *pCSh = static_cast< const SwCrsrShell * >( pVSh );
2645 		if( pCSh->IsTableMode() )
2646 		{
2647 			while( aFrmOrObj.GetSwFrm() && !aFrmOrObj.GetSwFrm()->IsCellFrm() )
2648 				aFrmOrObj = aFrmOrObj.GetSwFrm()->GetUpper();
2649 		}
2650 		else if( pVSh->ISA( SwFEShell ) )
2651 		{
2652 			sal_uInt16 nObjCount;
2653 			const SwFEShell *pFESh = static_cast< const SwFEShell * >( pVSh );
2654 			const SwFrm *pFlyFrm = pFESh->GetCurrFlyFrm();
2655 			if( pFlyFrm )
2656 			{
2657 				ASSERT( !pFrm || pFrm->FindFlyFrm() == pFlyFrm,
2658 						"cursor is not contained in fly frame" );
2659 				aFrmOrObj = pFlyFrm;
2660 			}
2661 			else if( (nObjCount = pFESh->IsObjSelected()) > 0 )
2662 			{
2663 				bShapeSelected = sal_True;
2664 				aFrmOrObj = static_cast<const SwFrm *>( 0 );
2665 			}
2666 		}
2667 	}
2668 
2669 	ASSERT( bShapeSelected || aFrmOrObj.IsAccessible(GetShell()->IsPreView()),
2670 			"frame is not accessible" );
2671 
2672 	uno::Reference < XAccessible > xOldAcc;
2673 	uno::Reference < XAccessible > xAcc;
2674 	sal_Bool bOldShapeSelected = sal_False;
2675 
2676 	{
2677 		vos::OGuard aGuard( maMutex );
2678 
2679 		xOldAcc = mxCursorContext;
2680 		mxCursorContext = xAcc;	// clear reference
2681 
2682 		bOldShapeSelected = mbShapeSelected;
2683 		mbShapeSelected = bShapeSelected;
2684 
2685 		if( aFrmOrObj.GetSwFrm() && mpFrmMap )
2686 		{
2687 			SwAccessibleContextMap_Impl::iterator aIter =
2688 				mpFrmMap->find( aFrmOrObj.GetSwFrm() );
2689 			if( aIter != mpFrmMap->end() )
2690 				xAcc = (*aIter).second;
2691 			else
2692 			{
2693 				SwRect rcEmpty;
2694 				const SwTabFrm* pTabFrm = aFrmOrObj.GetSwFrm()->FindTabFrm();
2695 				if (pTabFrm)
2696 				{
2697 					InvalidatePosOrSize(pTabFrm,0,0,rcEmpty);
2698 				}
2699 				else
2700 				{
2701 					InvalidatePosOrSize(aFrmOrObj.GetSwFrm(),0,0,rcEmpty);
2702 				}
2703 
2704 
2705 				aIter =
2706 					mpFrmMap->find( aFrmOrObj.GetSwFrm() );
2707 				if( aIter != mpFrmMap->end() )
2708 				{
2709 					xAcc = (*aIter).second;
2710 				}
2711 			}
2712 
2713 			// For cells, some extra thoughts are necessary,
2714 			// because invalidating the cursor for one cell
2715 			// invalidates the cursor for all cells of the same
2716 			// table. For this reason, we don't want to
2717 			// invalidate the cursor for the old cursor object
2718 			// and the new one if they are within the same table,
2719 			// because this would result in doing the work twice.
2720 			// Moreover, we have to make sure to invalidate the
2721 			// cursor even if the current cell has no accessible object.
2722 			// If the old cursor objects exists and is in the same
2723 			// table, its the best choice, because using it avoids
2724 			// an unnessarary cursor invalidation cycle when creating
2725 			// a new object for the current cell.
2726 			if( aFrmOrObj.GetSwFrm()->IsCellFrm() )
2727 			{
2728 				if( xOldAcc.is() &&
2729 					AreInSameTable( xOldAcc, aFrmOrObj.GetSwFrm() ) )
2730 				{
2731 					if( xAcc.is() )
2732 						xOldAcc = xAcc;	// avoid extra invalidation
2733 					else
2734 						xAcc = xOldAcc;	// make sure ate least one
2735 				}
2736 				if( !xAcc.is() )
2737 					xAcc = GetContext( aFrmOrObj.GetSwFrm(), sal_True );
2738 			}
2739 		}
2740         else if (bShapeSelected)
2741         {
2742             const SwFEShell *pFESh = pVSh ? static_cast< const SwFEShell * >( pVSh ) : NULL ;
2743             if(pFESh)
2744             {
2745                 const SdrMarkList *pMarkList = pFESh->GetMarkList();
2746                 if (pMarkList != NULL && pMarkList->GetMarkCount() == 1)
2747                 {
2748                     SdrObject *pObj = pMarkList->GetMark( 0 )->GetMarkedSdrObj();
2749 					::vos::ORef < ::accessibility::AccessibleShape > pAccShapeImpl = GetContextImpl(pObj,NULL,sal_False);
2750                     if (!pAccShapeImpl.isValid())
2751                     {
2752                         while (pObj && pObj->GetUpGroup())
2753                         {
2754                             pObj = pObj->GetUpGroup();
2755                         }
2756                         if (pObj != NULL)
2757                         {
2758                             const SwFrm *pParent = SwAccessibleFrame::GetParent( SwAccessibleChild(pObj), GetShell()->IsPreView() );
2759                             if( pParent )
2760                             {
2761                                 ::vos::ORef< SwAccessibleContext > xParentAccImpl = GetContextImpl(pParent,sal_False);
2762                                 if (!xParentAccImpl.isValid())
2763                                 {
2764                                     const SwTabFrm* pTabFrm = pParent->FindTabFrm();
2765                                     if (pTabFrm)
2766                                     {
2767                                         //The Table should not add in acc.because the "pParent" is not add to acc .
2768                                         uno::Reference< XAccessible>  xAccParentTab = GetContext(pTabFrm,sal_True);//Should Create.
2769 
2770                                         const SwFrm *pParentRoot = SwAccessibleFrame::GetParent( SwAccessibleChild(pTabFrm), GetShell()->IsPreView() );
2771                                         if (pParentRoot)
2772                                         {
2773                                             ::vos::ORef< SwAccessibleContext > xParentAccImplRoot = GetContextImpl(pParentRoot,sal_False);
2774                                             if(xParentAccImplRoot.isValid())
2775                                             {
2776                                                 AccessibleEventObject aEvent;
2777                                                 aEvent.EventId = AccessibleEventId::CHILD;
2778                                                 aEvent.NewValue <<= xAccParentTab;
2779                                                 xParentAccImplRoot->FireAccessibleEvent( aEvent );
2780                                             }
2781                                         }
2782 
2783                                         //Get "pParent" acc again.
2784                                         xParentAccImpl = GetContextImpl(pParent,sal_False);
2785                                     }
2786                                     else
2787                                     {
2788                                         //directly create this acc para .
2789                                         xParentAccImpl = GetContextImpl(pParent,sal_True);//Should Create.
2790 
2791                                         const SwFrm *pParentRoot = SwAccessibleFrame::GetParent( SwAccessibleChild(pParent), GetShell()->IsPreView() );
2792 
2793                                         ::vos::ORef< SwAccessibleContext > xParentAccImplRoot = GetContextImpl(pParentRoot,sal_False);
2794                                         if(xParentAccImplRoot.isValid())
2795                                         {
2796                                             AccessibleEventObject aEvent;
2797                                             aEvent.EventId = AccessibleEventId::CHILD;
2798                                             aEvent.NewValue <<= uno::Reference< XAccessible>(xParentAccImpl.getBodyPtr());
2799                                             xParentAccImplRoot->FireAccessibleEvent( aEvent );
2800                                         }
2801                                     }
2802                                 }
2803                                 if (xParentAccImpl.isValid())
2804                                 {
2805                                     uno::Reference< XAccessible>  xAccShape =
2806                                         GetContext(pObj,xParentAccImpl.getBodyPtr(),sal_True);
2807 
2808                                     AccessibleEventObject aEvent;
2809                                     aEvent.EventId = AccessibleEventId::CHILD;
2810                                     aEvent.NewValue <<= xAccShape;
2811                                     xParentAccImpl->FireAccessibleEvent( aEvent );
2812                                 }
2813                             }
2814                         }
2815                     }
2816                 }
2817             }
2818         }
2819 	}
2820 
2821 	m_setParaAdd.clear();
2822 	m_setParaRemove.clear();
2823 	if( xOldAcc.is() && xOldAcc != xAcc )
2824 		InvalidateCursorPosition( xOldAcc );
2825 	if( bOldShapeSelected || bShapeSelected )
2826 		InvalidateShapeSelection();
2827 	if( xAcc.is() )
2828 		InvalidateCursorPosition( xAcc );
2829 
2830 	InvalidateShapeInParaSelection();
2831 
2832 	SET_PARA::iterator si = m_setParaRemove.begin();
2833 	for (; si != m_setParaRemove.end() ; ++si)
2834 	{
2835 		SwAccessibleParagraph* pAccPara = *si;
2836 		if(pAccPara && pAccPara->getSelectedAccessibleChildCount() == 0 && pAccPara->getSelectedText().getLength() == 0)
2837 		{
2838 			if(pAccPara->SetSelectedState(sal_False))
2839 			{
2840 				AccessibleEventObject aEvent;
2841 				aEvent.EventId = AccessibleEventId::SELECTION_CHANGED_REMOVE;
2842 				pAccPara->FireAccessibleEvent( aEvent );
2843 			}
2844 		}
2845 	}
2846 	si = m_setParaAdd.begin();
2847 	for (; si != m_setParaAdd.end() ; ++si)
2848 	{
2849 		SwAccessibleParagraph* pAccPara = *si;
2850 		if(pAccPara && pAccPara->SetSelectedState(sal_True))
2851 		{
2852 			AccessibleEventObject aEvent;
2853 			aEvent.EventId = AccessibleEventId::SELECTION_CHANGED;
2854 			pAccPara->FireAccessibleEvent( aEvent );
2855 		}
2856 	}
2857 }
2858 
2859 //Notify the page change event to bridge.
FirePageChangeEvent(sal_uInt16 nOldPage,sal_uInt16 nNewPage)2860 void SwAccessibleMap::FirePageChangeEvent(sal_uInt16 nOldPage, sal_uInt16 nNewPage)
2861 {
2862 	uno::Reference<XAccessible> xAcc = GetDocumentView( );
2863     	if ( xAcc.is() )
2864     	{
2865     		SwAccessibleDocumentBase *pAcc =
2866 			static_cast< SwAccessibleDocumentBase * >( xAcc.get() );
2867 			if (pAcc)
2868 			{
2869 				AccessibleEventObject aEvent;
2870 				aEvent.EventId = AccessibleEventId::PAGE_CHANGED;
2871 				aEvent.OldValue <<= nOldPage;
2872 				aEvent.NewValue <<= nNewPage;
2873 				pAcc->FireAccessibleEvent( aEvent );
2874 			}
2875     	}
2876 }
2877 
FireSectionChangeEvent(sal_uInt16 nOldSection,sal_uInt16 nNewSection)2878 void SwAccessibleMap::FireSectionChangeEvent(sal_uInt16 nOldSection, sal_uInt16 nNewSection)
2879 {
2880 	uno::Reference<XAccessible> xAcc = GetDocumentView( );
2881     	if ( xAcc.is() )
2882     	{
2883     		SwAccessibleDocumentBase *pAcc =
2884 			static_cast< SwAccessibleDocumentBase * >( xAcc.get() );
2885 			if (pAcc)
2886 			{
2887 				AccessibleEventObject aEvent;
2888 				aEvent.EventId = AccessibleEventId::SECTION_CHANGED;
2889 				aEvent.OldValue <<= nOldSection;
2890 				aEvent.NewValue <<= nNewSection;
2891 				pAcc->FireAccessibleEvent( aEvent );
2892 
2893 			}
2894     	}
2895 }
FireColumnChangeEvent(sal_uInt16 nOldColumn,sal_uInt16 nNewColumn)2896 void SwAccessibleMap::FireColumnChangeEvent(sal_uInt16 nOldColumn, sal_uInt16 nNewColumn)
2897 {
2898 	uno::Reference<XAccessible> xAcc = GetDocumentView( );
2899     	if ( xAcc.is() )
2900     	{
2901     		SwAccessibleDocumentBase *pAcc =
2902 			static_cast< SwAccessibleDocumentBase * >( xAcc.get() );
2903 		if (pAcc)
2904 		{
2905 				AccessibleEventObject aEvent;
2906 				aEvent.EventId = AccessibleEventId::COLUMN_CHANGED;
2907 				aEvent.OldValue <<= nOldColumn;
2908 				aEvent.NewValue <<= nNewColumn;
2909 				pAcc->FireAccessibleEvent( aEvent );
2910 
2911 		}
2912     	}
2913 }
2914 
InvalidateFocus()2915 void SwAccessibleMap::InvalidateFocus()
2916 {
2917 	if(GetShell()->IsPreView())
2918 	{
2919 		uno::Reference<XAccessible> xAcc = _GetDocumentView( sal_True );
2920 		if (xAcc.get())
2921 		{
2922 			SwAccessiblePreview *pAccPreview = static_cast<SwAccessiblePreview *>(xAcc.get());
2923 			if (pAccPreview)
2924 			{
2925 				pAccPreview->InvalidateFocus();
2926 				return ;
2927 			}
2928 		}
2929 	}
2930 	uno::Reference < XAccessible > xAcc;
2931 	sal_Bool bShapeSelected;
2932 	{
2933 		vos::OGuard aGuard( maMutex );
2934 
2935 		xAcc = mxCursorContext;
2936 		bShapeSelected = mbShapeSelected;
2937 	}
2938 
2939 	if( xAcc.is() )
2940 	{
2941 		SwAccessibleContext *pAccImpl =
2942 			static_cast< SwAccessibleContext *>( xAcc.get() );
2943 		pAccImpl->InvalidateFocus();
2944 	}
2945 	else
2946 	{
2947 		DoInvalidateShapeSelection(sal_True);
2948 	}
2949 }
2950 
SetCursorContext(const::vos::ORef<SwAccessibleContext> & rCursorContext)2951 void SwAccessibleMap::SetCursorContext(
2952 		const ::vos::ORef < SwAccessibleContext >& rCursorContext )
2953 {
2954 	vos::OGuard aGuard( maMutex );
2955 	uno::Reference < XAccessible > xAcc( rCursorContext.getBodyPtr() );
2956 	mxCursorContext = xAcc;
2957 }
2958 
2959 // --> OD 2005-12-12 #i27301# - use new type definition for <_nStates>
InvalidateStates(tAccessibleStates _nStates,const SwFrm * _pFrm)2960 void SwAccessibleMap::InvalidateStates( tAccessibleStates _nStates,
2961                                         const SwFrm* _pFrm )
2962 {
2963 	// Start with the frame or the first upper that is accessible
2964     SwAccessibleChild aFrmOrObj( _pFrm );
2965 	while( aFrmOrObj.GetSwFrm() &&
2966 			!aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) )
2967 		aFrmOrObj = aFrmOrObj.GetSwFrm()->GetUpper();
2968 	if( !aFrmOrObj.GetSwFrm() )
2969 		aFrmOrObj = GetShell()->GetLayout();
2970 
2971 	uno::Reference< XAccessible > xAcc( GetContext( aFrmOrObj.GetSwFrm(), sal_True ) );
2972 	SwAccessibleContext *pAccImpl =
2973 		static_cast< SwAccessibleContext *>( xAcc.get() );
2974 	if( GetShell()->ActionPend() )
2975 	{
2976         SwAccessibleEvent_Impl aEvent( SwAccessibleEvent_Impl::CARET_OR_STATES,
2977                                        pAccImpl,
2978                                        SwAccessibleChild(pAccImpl->GetFrm()),
2979                                        _nStates );
2980 		AppendEvent( aEvent );
2981 	}
2982 	else
2983 	{
2984 		FireEvents();
2985         pAccImpl->InvalidateStates( _nStates );
2986 	}
2987 }
2988 // <--
2989 
_InvalidateRelationSet(const SwFrm * pFrm,sal_Bool bFrom)2990 void SwAccessibleMap::_InvalidateRelationSet( const SwFrm* pFrm,
2991                                               sal_Bool bFrom )
2992 {
2993     // first, see if this frame is accessible, and if so, get the respective
2994     SwAccessibleChild aFrmOrObj( pFrm );
2995 	if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) )
2996 	{
2997 		uno::Reference < XAccessible > xAcc;
2998 		{
2999 			vos::OGuard aGuard( maMutex );
3000 
3001 			if( mpFrmMap )
3002 			{
3003 				SwAccessibleContextMap_Impl::iterator aIter =
3004                                         mpFrmMap->find( aFrmOrObj.GetSwFrm() );
3005 				if( aIter != mpFrmMap->end() )
3006 				{
3007 					xAcc = (*aIter).second;
3008 				}
3009 			}
3010 		}
3011 
3012         // deliver event directly, or queue event
3013 		if( xAcc.is() )
3014 		{
3015 			SwAccessibleContext *pAccImpl =
3016                             static_cast< SwAccessibleContext *>( xAcc.get() );
3017             if( GetShell()->ActionPend() )
3018             {
3019                 SwAccessibleEvent_Impl aEvent( SwAccessibleEvent_Impl::CARET_OR_STATES,
3020                                                pAccImpl, SwAccessibleChild(pFrm),
3021                                                ( bFrom
3022                                                  ? ACC_STATE_RELATION_FROM
3023                                                  : ACC_STATE_RELATION_TO ) );
3024                 AppendEvent( aEvent );
3025             }
3026             else
3027             {
3028 				FireEvents();
3029                 pAccImpl->InvalidateRelation( bFrom
3030                         ? AccessibleEventId::CONTENT_FLOWS_FROM_RELATION_CHANGED
3031                         : AccessibleEventId::CONTENT_FLOWS_TO_RELATION_CHANGED );
3032             }
3033         }
3034     }
3035 }
3036 
InvalidateRelationSet(const SwFrm * pMaster,const SwFrm * pFollow)3037 void SwAccessibleMap::InvalidateRelationSet( const SwFrm* pMaster,
3038                                              const SwFrm* pFollow )
3039 {
3040     _InvalidateRelationSet( pMaster, sal_False );
3041     _InvalidateRelationSet( pFollow, sal_True );
3042 }
3043 
3044 /** invalidation CONTENT_FLOW_FROM/_TO relation of a paragraph
3045 
3046     OD 2005-12-01 #i27138#
3047 
3048     @author OD
3049 */
InvalidateParaFlowRelation(const SwTxtFrm & _rTxtFrm,const bool _bFrom)3050 void SwAccessibleMap::InvalidateParaFlowRelation( const SwTxtFrm& _rTxtFrm,
3051                                                   const bool _bFrom )
3052 {
3053     _InvalidateRelationSet( &_rTxtFrm, _bFrom );
3054 }
3055 
3056 /** invalidation of text selection of a paragraph
3057 
3058     OD 2005-12-12 #i27301#
3059 
3060     @author OD
3061 */
InvalidateParaTextSelection(const SwTxtFrm & _rTxtFrm)3062 void SwAccessibleMap::InvalidateParaTextSelection( const SwTxtFrm& _rTxtFrm )
3063 {
3064     // first, see if this frame is accessible, and if so, get the respective
3065     SwAccessibleChild aFrmOrObj( &_rTxtFrm );
3066     if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) )
3067     {
3068         uno::Reference < XAccessible > xAcc;
3069         {
3070             vos::OGuard aGuard( maMutex );
3071 
3072             if( mpFrmMap )
3073             {
3074                 SwAccessibleContextMap_Impl::iterator aIter =
3075                                         mpFrmMap->find( aFrmOrObj.GetSwFrm() );
3076                 if( aIter != mpFrmMap->end() )
3077                 {
3078                     xAcc = (*aIter).second;
3079                 }
3080             }
3081         }
3082 
3083         // deliver event directly, or queue event
3084         if( xAcc.is() )
3085         {
3086             SwAccessibleContext *pAccImpl =
3087                             static_cast< SwAccessibleContext *>( xAcc.get() );
3088             if( GetShell()->ActionPend() )
3089             {
3090                 SwAccessibleEvent_Impl aEvent(
3091                     SwAccessibleEvent_Impl::CARET_OR_STATES,
3092                     pAccImpl,
3093                     SwAccessibleChild( &_rTxtFrm ),
3094                     ACC_STATE_TEXT_SELECTION_CHANGED );
3095                 AppendEvent( aEvent );
3096             }
3097             else
3098             {
3099                 FireEvents();
3100                 pAccImpl->InvalidateTextSelection();
3101             }
3102         }
3103     }
3104 }
3105 
GetChildIndex(const SwFrm & rParentFrm,Window & rChild) const3106 sal_Int32 SwAccessibleMap::GetChildIndex( const SwFrm& rParentFrm,
3107                                           Window& rChild ) const
3108 {
3109     sal_Int32 nIndex( -1 );
3110 
3111     SwAccessibleChild aFrmOrObj( &rParentFrm );
3112     if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) )
3113     {
3114         uno::Reference < XAccessible > xAcc;
3115         {
3116             vos::OGuard aGuard( maMutex );
3117 
3118             if( mpFrmMap )
3119             {
3120                 SwAccessibleContextMap_Impl::iterator aIter =
3121                                         mpFrmMap->find( aFrmOrObj.GetSwFrm() );
3122                 if( aIter != mpFrmMap->end() )
3123                 {
3124                     xAcc = (*aIter).second;
3125                 }
3126             }
3127         }
3128 
3129         if( xAcc.is() )
3130         {
3131             SwAccessibleContext *pAccImpl =
3132                             static_cast< SwAccessibleContext *>( xAcc.get() );
3133 
3134             nIndex = pAccImpl->GetChildIndex( const_cast<SwAccessibleMap&>(*this),
3135                                               SwAccessibleChild( &rChild ) );
3136         }
3137     }
3138 
3139     return nIndex;
3140 }
3141 
3142 
3143 // OD 15.01.2003 #103492# - complete re-factoring of method due to new page/print
3144 // preview functionality.
UpdatePreview(const std::vector<PrevwPage * > & _rPrevwPages,const Fraction & _rScale,const SwPageFrm * _pSelectedPageFrm,const Size & _rPrevwWinSize)3145 void SwAccessibleMap::UpdatePreview( const std::vector<PrevwPage*>& _rPrevwPages,
3146                                      const Fraction&  _rScale,
3147                                      const SwPageFrm* _pSelectedPageFrm,
3148                                      const Size&      _rPrevwWinSize )
3149 {
3150     DBG_ASSERT( GetShell()->IsPreView(), "no preview?" );
3151     DBG_ASSERT( mpPreview != NULL, "no preview data?" );
3152 
3153     // OD 15.01.2003 #103492# - adjustments for changed method signature
3154     mpPreview->Update( *this, _rPrevwPages, _rScale, _pSelectedPageFrm, _rPrevwWinSize );
3155 
3156     // propagate change of VisArea through the document's
3157     // accessibility tree; this will also send appropriate scroll
3158     // events
3159     SwAccessibleContext* pDoc =
3160         GetContextImpl( GetShell()->GetLayout() ).getBodyPtr();
3161     static_cast<SwAccessibleDocumentBase*>( pDoc )->SetVisArea();
3162 
3163 	uno::Reference < XAccessible > xOldAcc;
3164 	uno::Reference < XAccessible > xAcc;
3165 	{
3166 		vos::OGuard aGuard( maMutex );
3167 
3168 		xOldAcc = mxCursorContext;
3169 
3170 		const SwPageFrm *pSelPage = mpPreview->GetSelPage();
3171 		if( pSelPage && mpFrmMap )
3172 		{
3173 			SwAccessibleContextMap_Impl::iterator aIter =
3174 				mpFrmMap->find( pSelPage );
3175 			if( aIter != mpFrmMap->end() )
3176 				xAcc = (*aIter).second;
3177 		}
3178 	}
3179 
3180 	if( xOldAcc.is() && xOldAcc != xAcc )
3181 		InvalidateCursorPosition( xOldAcc );
3182 	if( xAcc.is() )
3183 		InvalidateCursorPosition( xAcc );
3184 }
3185 
InvalidatePreViewSelection(sal_uInt16 nSelPage)3186 void SwAccessibleMap::InvalidatePreViewSelection( sal_uInt16 nSelPage )
3187 {
3188     DBG_ASSERT( GetShell()->IsPreView(), "no preview?" );
3189     DBG_ASSERT( mpPreview != NULL, "no preview data?" );
3190 
3191     // OD 16.01.2003 #103492# - changed metthod call due to method signature change.
3192     mpPreview->InvalidateSelection( GetShell()->GetLayout()->GetPageByPageNum( nSelPage ) );
3193 
3194 	uno::Reference < XAccessible > xOldAcc;
3195 	uno::Reference < XAccessible > xAcc;
3196 	{
3197 		vos::OGuard aGuard( maMutex );
3198 
3199 		xOldAcc = mxCursorContext;
3200 
3201 		const SwPageFrm *pSelPage = mpPreview->GetSelPage();
3202 		if( pSelPage && mpFrmMap )
3203 		{
3204 			SwAccessibleContextMap_Impl::iterator aIter =
3205 				mpFrmMap->find( pSelPage );
3206 			if( aIter != mpFrmMap->end() )
3207 				xAcc = (*aIter).second;
3208 		}
3209 	}
3210 
3211 	if( xOldAcc.is() && xOldAcc != xAcc )
3212 		InvalidateCursorPosition( xOldAcc );
3213 	if( xAcc.is() )
3214 		InvalidateCursorPosition( xAcc );
3215 }
3216 
3217 
IsPageSelected(const SwPageFrm * pPageFrm) const3218 sal_Bool SwAccessibleMap::IsPageSelected( const SwPageFrm *pPageFrm ) const
3219 {
3220 	return mpPreview && mpPreview->GetSelPage() == pPageFrm;
3221 }
3222 
3223 
FireEvents()3224 void SwAccessibleMap::FireEvents()
3225 {
3226 	{
3227 		vos::OGuard aGuard( maEventMutex );
3228 		if( mpEvents )
3229 		{
3230 			mpEvents->SetFiring();
3231 			mpEvents->MoveInvalidXAccToEnd();
3232 			SwAccessibleEventList_Impl::iterator aIter = mpEvents->begin();
3233 			while( aIter != mpEvents->end() )
3234 			{
3235 				FireEvent( *aIter );
3236 				++aIter;
3237 			}
3238 
3239 			delete mpEventMap;
3240 			mpEventMap = 0;
3241 
3242 			delete mpEvents;
3243 			mpEvents = 0;
3244 		}
3245 	}
3246 	{
3247 		vos::OGuard aGuard( maMutex );
3248 		if( mpShapes )
3249 		{
3250 			delete mpShapes;
3251 			mpShapes = 0;
3252 		}
3253 	}
3254 
3255 }
3256 
IsValid() const3257 sal_Bool SwAccessibleMap::IsValid() const
3258 {
3259 	return sal_True;
3260 }
3261 
GetVisibleArea() const3262 Rectangle SwAccessibleMap::GetVisibleArea() const
3263 {
3264     MapMode aSrc( MAP_TWIP );
3265 	MapMode aDest( MAP_100TH_MM );
3266 	return OutputDevice::LogicToLogic( GetVisArea().SVRect(), aSrc, aDest );
3267 }
3268 
3269 // Convert a MM100 value realtive to the document root into a pixel value
3270 // realtive to the screen!
LogicToPixel(const Point & rPoint) const3271 Point SwAccessibleMap::LogicToPixel( const Point& rPoint ) const
3272 {
3273 	MapMode aSrc( MAP_100TH_MM );
3274 	MapMode aDest( MAP_TWIP );
3275 
3276     Point aPoint = rPoint;
3277 
3278 	aPoint = OutputDevice::LogicToLogic( aPoint, aSrc, aDest );
3279 	Window *pWin = GetShell()->GetWin();
3280 	if( pWin )
3281     {
3282         // OD 16.01.2003 #103492# - get mapping mode for LogicToPixel conversion
3283         MapMode aMapMode;
3284         GetMapMode( aPoint, aMapMode );
3285         aPoint = pWin->LogicToPixel( aPoint, aMapMode );
3286 		aPoint = pWin->OutputToAbsoluteScreenPixel( aPoint );
3287     }
3288 
3289 	return aPoint;
3290 }
3291 
LogicToPixel(const Size & rSize) const3292 Size SwAccessibleMap::LogicToPixel( const Size& rSize ) const
3293 {
3294 	MapMode aSrc( MAP_100TH_MM );
3295 	MapMode aDest( MAP_TWIP );
3296 	Size aSize( OutputDevice::LogicToLogic( rSize, aSrc, aDest ) );
3297 	if( GetShell()->GetWin() )
3298     {
3299         // OD 16.01.2003 #103492# - get mapping mode for LogicToPixel conversion
3300         MapMode aMapMode;
3301         GetMapMode( Point(0,0), aMapMode );
3302         aSize = GetShell()->GetWin()->LogicToPixel( aSize, aMapMode );
3303     }
3304 
3305 	return aSize;
3306 }
3307 
PixelToLogic(const Point & rPoint) const3308 Point SwAccessibleMap::PixelToLogic( const Point& rPoint ) const
3309 {
3310 	Point aPoint;
3311 	Window *pWin = GetShell()->GetWin();
3312 	if( pWin )
3313 	{
3314 		aPoint = pWin->ScreenToOutputPixel( rPoint );
3315         // OD 16.01.2003 #103492# - get mapping mode for PixelToLogic conversion
3316         MapMode aMapMode;
3317         GetMapMode( aPoint, aMapMode );
3318         aPoint = pWin->PixelToLogic( aPoint, aMapMode );
3319 		MapMode aSrc( MAP_TWIP );
3320 		MapMode aDest( MAP_100TH_MM );
3321 		aPoint = OutputDevice::LogicToLogic( aPoint, aSrc, aDest );
3322 	}
3323 
3324 	return aPoint;
3325 }
3326 
PixelToLogic(const Size & rSize) const3327 Size SwAccessibleMap::PixelToLogic( const Size& rSize ) const
3328 {
3329 	Size aSize;
3330 	if( GetShell()->GetWin() )
3331 	{
3332         // OD 16.01.2003 #103492# - get mapping mode for PixelToLogic conversion
3333         MapMode aMapMode;
3334         GetMapMode( Point(0,0), aMapMode );
3335         aSize = GetShell()->GetWin()->PixelToLogic( rSize, aMapMode );
3336 		MapMode aSrc( MAP_TWIP );
3337 		MapMode aDest( MAP_100TH_MM );
3338 		aSize = OutputDevice::LogicToLogic( aSize, aSrc, aDest );
3339 	}
3340 
3341 	return aSize;
3342 }
3343 
ReplaceChild(::accessibility::AccessibleShape * pCurrentChild,const uno::Reference<drawing::XShape> & _rxShape,const long,const::accessibility::AccessibleShapeTreeInfo &)3344 sal_Bool SwAccessibleMap::ReplaceChild (
3345         ::accessibility::AccessibleShape* pCurrentChild,
3346 		const uno::Reference< drawing::XShape >& _rxShape,
3347         const long /*_nIndex*/,
3348         const ::accessibility::AccessibleShapeTreeInfo& /*_rShapeTreeInfo*/
3349 	)	throw (uno::RuntimeException)
3350 {
3351 	const SdrObject *pObj = 0;
3352 	{
3353 		vos::OGuard aGuard( maMutex );
3354 		if( mpShapeMap )
3355 		{
3356 			SwAccessibleShapeMap_Impl::const_iterator aIter = mpShapeMap->begin();
3357 			SwAccessibleShapeMap_Impl::const_iterator aEndIter = mpShapeMap->end();
3358 			while( aIter != aEndIter && !pObj )
3359 			{
3360 				uno::Reference < XAccessible > xAcc( (*aIter).second );
3361 				::accessibility::AccessibleShape *pAccShape =
3362 					static_cast < ::accessibility::AccessibleShape* >( xAcc.get() );
3363 				if( pAccShape == pCurrentChild )
3364 				{
3365 					pObj = (*aIter).first;
3366 				}
3367 				++aIter;
3368 			}
3369 		}
3370 	}
3371 	if( !pObj )
3372 		return sal_False;
3373 
3374 	uno::Reference < drawing::XShape > xShape( _rxShape ); //keep reference to shape, because
3375 											 // we might be the only one that
3376 											 // hold it.
3377 	// Also get keep parent.
3378 	uno::Reference < XAccessible > xParent( pCurrentChild->getAccessibleParent() );
3379 	pCurrentChild = 0;	// well be realease by dispose
3380     Dispose( 0, pObj, 0 );
3381 
3382 	{
3383 		vos::OGuard aGuard( maMutex );
3384 
3385 		if( !mpShapeMap )
3386 			mpShapeMap = new SwAccessibleShapeMap_Impl( this );
3387 
3388 		// create the new child
3389 		::accessibility::ShapeTypeHandler& rShapeTypeHandler =
3390 						::accessibility::ShapeTypeHandler::Instance();
3391 		::accessibility::AccessibleShapeInfo aShapeInfo(
3392 											xShape, xParent, this );
3393 		::accessibility::AccessibleShape* pReplacement =
3394 			rShapeTypeHandler.CreateAccessibleObject (
3395 				aShapeInfo, mpShapeMap->GetInfo() );
3396 
3397 		uno::Reference < XAccessible > xAcc( pReplacement );
3398 		if( xAcc.is() )
3399 		{
3400 			pReplacement->Init();
3401 
3402 			SwAccessibleShapeMap_Impl::iterator aIter =
3403 				mpShapeMap->find( pObj );
3404 			if( aIter != mpShapeMap->end() )
3405 			{
3406 				(*aIter).second = xAcc;
3407 			}
3408 			else
3409 			{
3410 				SwAccessibleShapeMap_Impl::value_type aEntry( pObj, xAcc );
3411 				mpShapeMap->insert( aEntry );
3412 			}
3413 		}
3414 	}
3415 
3416 	SwRect aEmptyRect;
3417     InvalidatePosOrSize( 0, pObj, 0, aEmptyRect );
3418 
3419 	return sal_True;
3420 }
3421 
3422 //Get the accessible control shape from the model object, here model object is with XPropertySet type
GetAccControlShapeFromModel(::com::sun::star::beans::XPropertySet * pSet)3423 ::accessibility::AccessibleControlShape * SwAccessibleMap::GetAccControlShapeFromModel(::com::sun::star::beans::XPropertySet* pSet) throw (::com::sun::star::uno::RuntimeException)
3424 {
3425 	if( mpShapeMap )
3426 	{
3427 		SwAccessibleShapeMap_Impl::const_iterator aIter = mpShapeMap->begin();
3428 		SwAccessibleShapeMap_Impl::const_iterator aEndIter = mpShapeMap->end();
3429 		while( aIter != aEndIter)
3430 		{
3431 			uno::Reference < XAccessible > xAcc( (*aIter).second );
3432 			::accessibility::AccessibleShape *pAccShape =
3433 				static_cast < ::accessibility::AccessibleShape* >( xAcc.get() );
3434 			if(pAccShape && ::accessibility::ShapeTypeHandler::Instance().GetTypeId (pAccShape->GetXShape()) == ::accessibility::DRAWING_CONTROL)
3435 			{
3436 				::accessibility::AccessibleControlShape *pCtlAccShape = static_cast < ::accessibility::AccessibleControlShape* >(pAccShape);
3437 				if (pCtlAccShape && pCtlAccShape->GetControlModel() == pSet)
3438 					return pCtlAccShape;
3439 			}
3440 			++aIter;
3441 		}
3442 	}
3443 	return NULL;
3444 }
3445 
3446 ::com::sun::star::uno::Reference< XAccessible >
GetAccessibleCaption(const::com::sun::star::uno::Reference<::com::sun::star::drawing::XShape> & xShape)3447     SwAccessibleMap::GetAccessibleCaption (const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >& xShape)
3448     throw (::com::sun::star::uno::RuntimeException)
3449 {
3450 		SdrObject* captionedObject = GetSdrObjectFromXShape(xShape);
3451 
3452 		SwDrawContact *pContact = (SwDrawContact*)GetUserCall( captionedObject );
3453 		ASSERT( RES_DRAWFRMFMT == pContact->GetFmt()->Which(),
3454 				"fail" );
3455 		if( !pContact )
3456 			return 0;
3457 
3458 		SwDrawFrmFmt *pCaptionedFmt = (SwDrawFrmFmt *)pContact->GetFmt();
3459 		if( !pCaptionedFmt )
3460 			return 0;
3461 
3462 		SwFlyFrm* pFrm = NULL;
3463 		if (pCaptionedFmt->HasCaption())
3464 		{
3465 			const SwFrmFmt *pCaptionFrmFmt = pCaptionedFmt->GetCaptionFmt();
3466 			SwClientIter aIter (*(SwModify*)pCaptionFrmFmt);
3467 			pFrm = (SwFlyFrm*)aIter.First( TYPE ( SwFlyFrm ));
3468 		}
3469 		if (!pFrm)
3470 			return 0;
3471 		//SwFrmFmt* pFrm = pCaptionedFmt->GetCaptionFmt();
3472 		uno::Reference < XAccessible > xAcc( GetContext((SwFrm*)pFrm,sal_True) );
3473 		//Reference < XAccessibleShape > xAccShape( xAcc, UNO_QUERY );
3474 
3475 		uno::Reference< XAccessibleContext > xAccContext = xAcc->getAccessibleContext();
3476 		if( xAccContext.is() )
3477 		{	//get the parent of caption frame, which is paragaph
3478 			uno::Reference< XAccessible > xAccParent = xAccContext->getAccessibleParent();
3479 			if(xAccParent.is())
3480 			{
3481 				//get the great parent of caption frame which is text frame.
3482 				uno::Reference< XAccessibleContext > xAccParentContext = xAccParent->getAccessibleContext();
3483 				uno::Reference< XAccessible > xAccGreatParent = xAccParentContext->getAccessibleParent();
3484 				if(xAccGreatParent.is())
3485 				{
3486 					AccessibleEventObject aEvent;
3487 					aEvent.EventId = AccessibleEventId::CHILD;
3488 					aEvent.NewValue <<= xAccParent;
3489 					( static_cast< SwAccessibleContext * >(xAccGreatParent.get()) )->FireAccessibleEvent( aEvent );
3490 
3491 				}
3492 
3493 				AccessibleEventObject aEvent;
3494 				aEvent.EventId = AccessibleEventId::CHILD;
3495 				aEvent.NewValue <<= xAcc;
3496 				( static_cast< SwAccessibleContext * >(xAccParent.get()) )->FireAccessibleEvent( aEvent );
3497 			}
3498 		}
3499 
3500 		if(xAcc.get())
3501 			return xAcc;
3502 		else
3503 			return NULL;
3504 
3505 }
PixelToCore(const Point & rPoint) const3506 Point SwAccessibleMap::PixelToCore( const Point& rPoint ) const
3507 {
3508 	Point aPoint;
3509 	if( GetShell()->GetWin() )
3510 	{
3511         // OD 15.01.2003 #103492# - replace <PreviewAdjust(..)> by <GetMapMode(..)>
3512         MapMode aMapMode;
3513         GetMapMode( rPoint, aMapMode );
3514         aPoint = GetShell()->GetWin()->PixelToLogic( rPoint, aMapMode );
3515 	}
3516 	return aPoint;
3517 }
3518 
lcl_CorrectCoarseValue(long aCoarseValue,long aFineValue,long aRefValue,bool bToLower)3519 static inline long lcl_CorrectCoarseValue(long aCoarseValue, long aFineValue,
3520                                           long aRefValue, bool bToLower)
3521 {
3522     long aResult = aCoarseValue;
3523 
3524     if (bToLower)
3525     {
3526         if (aFineValue < aRefValue)
3527             aResult -= 1;
3528     }
3529     else
3530     {
3531         if (aFineValue > aRefValue)
3532             aResult += 1;
3533     }
3534 
3535     return aResult;
3536 }
3537 
lcl_CorrectRectangle(Rectangle & rRect,const Rectangle & rSource,const Rectangle & rInGrid)3538 static inline void lcl_CorrectRectangle(Rectangle & rRect,
3539                                         const Rectangle & rSource,
3540                                         const Rectangle & rInGrid)
3541 {
3542     rRect.nLeft = lcl_CorrectCoarseValue(rRect.nLeft, rSource.nLeft,
3543                                          rInGrid.nLeft, false);
3544     rRect.nTop = lcl_CorrectCoarseValue(rRect.nTop, rSource.nTop,
3545                                         rInGrid.nTop, false);
3546     rRect.nRight = lcl_CorrectCoarseValue(rRect.nRight, rSource.nRight,
3547                                           rInGrid.nRight, true);
3548     rRect.nBottom = lcl_CorrectCoarseValue(rRect.nBottom, rSource.nBottom,
3549                                            rInGrid.nBottom, true);
3550 }
3551 
CoreToPixel(const Rectangle & rRect) const3552 Rectangle SwAccessibleMap::CoreToPixel( const Rectangle& rRect ) const
3553 {
3554     Rectangle aRect;
3555 	if( GetShell()->GetWin() )
3556     {
3557         // OD 15.01.2003 #103492# - replace <PreviewAdjust(..)> by <GetMapMode(..)>
3558         MapMode aMapMode;
3559         GetMapMode( rRect.TopLeft(), aMapMode );
3560         aRect = GetShell()->GetWin()->LogicToPixel( rRect, aMapMode );
3561 
3562         Rectangle aTmpRect = GetShell()->GetWin()->PixelToLogic( aRect, aMapMode );
3563         lcl_CorrectRectangle(aRect, rRect, aTmpRect);
3564     }
3565 
3566 	return aRect;
3567 }
3568 
3569 /** get mapping mode for LogicToPixel and PixelToLogic conversions
3570 
3571     OD 15.01.2003 #103492#
3572     Replacement method <PreviewAdjust(..)> by new method <GetMapMode>.
3573     Method returns mapping mode of current output device and adjusts it,
3574     if the shell is in page/print preview.
3575     Necessary, because <PreviewAdjust(..)> changes mapping mode at current
3576     output device for mapping logic document positions to page preview window
3577     positions and vice versa and doesn't take care to recover its changes.
3578 
3579     @author OD
3580 */
GetMapMode(const Point & _rPoint,MapMode & _orMapMode) const3581 void SwAccessibleMap::GetMapMode( const Point& _rPoint,
3582                                   MapMode&     _orMapMode ) const
3583 {
3584     MapMode aMapMode = GetShell()->GetWin()->GetMapMode();
3585     if( GetShell()->IsPreView() )
3586     {
3587         DBG_ASSERT( mpPreview != NULL, "need preview data" );
3588 
3589         mpPreview->AdjustMapMode( aMapMode, _rPoint );
3590     }
3591     _orMapMode = aMapMode;
3592 }
3593 
3594 /** get size of a dedicated preview page
3595 
3596     OD 15.01.2003 #103492#
3597 
3598     @author OD
3599 */
GetPreViewPageSize(sal_uInt16 _nPrevwPageNum) const3600 Size SwAccessibleMap::GetPreViewPageSize( sal_uInt16 _nPrevwPageNum ) const
3601 {
3602     DBG_ASSERT( mpVSh->IsPreView(), "no page preview accessible." );
3603     DBG_ASSERT( mpVSh->IsPreView() && ( mpPreview != NULL ),
3604                 "missing accessible preview data at page preview" );
3605     if ( mpVSh->IsPreView() && ( mpPreview != NULL ) )
3606     {
3607         return mpVSh->PagePreviewLayout()->GetPrevwPageSizeByPageNum( _nPrevwPageNum );
3608     }
3609     else
3610     {
3611         return Size( 0, 0 );
3612     }
3613 }
3614 
3615 /** method to build up a new data structure of the accessible pararaphs,
3616     which have a selection
3617 
3618     OD 2005-12-13 #i27301#
3619     Important note: method has to used inside a mutual exclusive section
3620 
3621     @author OD
3622 */
_BuildSelectedParas()3623 SwAccessibleSelectedParas_Impl* SwAccessibleMap::_BuildSelectedParas()
3624 {
3625     // no accessible contexts, no selection
3626     if ( !mpFrmMap )
3627     {
3628         return 0L;
3629     }
3630 
3631     // get cursor as an instance of its base class <SwPaM>
3632     SwPaM* pCrsr( 0L );
3633     {
3634         SwCrsrShell* pCrsrShell = dynamic_cast<SwCrsrShell*>(GetShell());
3635         if ( pCrsrShell )
3636         {
3637             SwFEShell* pFEShell = dynamic_cast<SwFEShell*>(pCrsrShell);
3638             if ( !pFEShell ||
3639                  ( !pFEShell->IsFrmSelected() &&
3640                    pFEShell->IsObjSelected() == 0 ) )
3641             {
3642                 // get cursor without updating an existing table cursor.
3643                 pCrsr = pCrsrShell->GetCrsr( sal_False );
3644             }
3645         }
3646     }
3647     // no cursor, no selection
3648     if ( !pCrsr )
3649     {
3650         return 0L;
3651     }
3652 
3653     SwAccessibleSelectedParas_Impl* pRetSelectedParas( 0L );
3654 
3655     // loop on all cursors
3656     SwPaM* pRingStart = pCrsr;
3657     do {
3658 
3659         // for a selection the cursor has to have a mark.
3660         // for savety reasons assure that point and mark are in text nodes
3661         if ( pCrsr->HasMark() &&
3662              pCrsr->GetPoint()->nNode.GetNode().IsTxtNode() &&
3663              pCrsr->GetMark()->nNode.GetNode().IsTxtNode() )
3664         {
3665             SwPosition* pStartPos = pCrsr->Start();
3666             SwPosition* pEndPos = pCrsr->End();
3667             // loop on all text nodes inside the selection
3668             SwNodeIndex aIdx( pStartPos->nNode );
3669             for ( ; aIdx.GetIndex() <= pEndPos->nNode.GetIndex(); ++aIdx )
3670             {
3671                 SwTxtNode* pTxtNode( aIdx.GetNode().GetTxtNode() );
3672                 if ( pTxtNode )
3673                 {
3674                     // loop on all text frames registered at the text node.
3675                     SwIterator<SwTxtFrm,SwTxtNode> aIter( *pTxtNode );
3676                     for( SwTxtFrm* pTxtFrm = aIter.First(); pTxtFrm; pTxtFrm = aIter.Next() )
3677                         {
3678                             uno::WeakReference < XAccessible > xWeakAcc;
3679                             SwAccessibleContextMap_Impl::iterator aMapIter =
3680                                                     mpFrmMap->find( pTxtFrm );
3681                             if( aMapIter != mpFrmMap->end() )
3682                             {
3683                                 xWeakAcc = (*aMapIter).second;
3684                                 SwAccessibleParaSelection aDataEntry(
3685                                     pTxtNode == &(pStartPos->nNode.GetNode())
3686                                                 ? pStartPos->nContent.GetIndex()
3687                                                 : 0,
3688                                     pTxtNode == &(pEndPos->nNode.GetNode())
3689                                                 ? pEndPos->nContent.GetIndex()
3690                                                 : STRING_LEN );
3691                                 SwAccessibleSelectedParas_Impl::value_type
3692                                                 aEntry( xWeakAcc, aDataEntry );
3693                                 if ( !pRetSelectedParas )
3694                                 {
3695                                     pRetSelectedParas =
3696                                             new SwAccessibleSelectedParas_Impl;
3697                                 }
3698                                 pRetSelectedParas->insert( aEntry );
3699                             }
3700                         }
3701                     }
3702                 }
3703             }
3704 
3705         // prepare next turn: get next cursor in ring
3706         pCrsr = static_cast<SwPaM*>( pCrsr->GetNext() );
3707     } while ( pCrsr != pRingStart );
3708 
3709     return pRetSelectedParas;
3710 }
3711 
3712 /** invalidation of text selection of all paragraphs
3713 
3714     OD 2005-12-13 #i27301#
3715 
3716     @author OD
3717 */
InvalidateTextSelectionOfAllParas()3718 void SwAccessibleMap::InvalidateTextSelectionOfAllParas()
3719 {
3720     vos::OGuard aGuard( maMutex );
3721 
3722     // keep previously known selected paragraphs
3723     SwAccessibleSelectedParas_Impl* pPrevSelectedParas( mpSelectedParas );
3724 
3725     // determine currently selected paragraphs
3726     mpSelectedParas = _BuildSelectedParas();
3727 
3728     // compare currently selected paragraphs with the previously selected
3729     // paragraphs and submit corresponding TEXT_SELECTION_CHANGED events.
3730     // first, search for new and changed selections.
3731     // on the run remove selections from previously known ones, if they are
3732     // also in the current ones.
3733     if ( mpSelectedParas )
3734     {
3735         SwAccessibleSelectedParas_Impl::iterator aIter = mpSelectedParas->begin();
3736         for ( ; aIter != mpSelectedParas->end(); ++aIter )
3737         {
3738             bool bSubmitEvent( false );
3739             if ( !pPrevSelectedParas )
3740             {
3741                 // new selection
3742                 bSubmitEvent = true;
3743             }
3744             else
3745             {
3746                 SwAccessibleSelectedParas_Impl::iterator aPrevSelected =
3747                                         pPrevSelectedParas->find( (*aIter).first );
3748                 if ( aPrevSelected != pPrevSelectedParas->end() )
3749                 {
3750                     // check, if selection has changed
3751                     if ( (*aIter).second.nStartOfSelection !=
3752                                     (*aPrevSelected).second.nStartOfSelection ||
3753                          (*aIter).second.nEndOfSelection !=
3754                                     (*aPrevSelected).second.nEndOfSelection )
3755                     {
3756                         // changed selection
3757                         bSubmitEvent = true;
3758                     }
3759                     pPrevSelectedParas->erase( aPrevSelected );
3760                 }
3761                 else
3762                 {
3763                     // new selection
3764                     bSubmitEvent = true;
3765                 }
3766             }
3767 
3768             if ( bSubmitEvent )
3769             {
3770                 uno::Reference < XAccessible > xAcc( (*aIter).first );
3771                 if ( xAcc.is() )
3772                 {
3773                     ::vos::ORef < SwAccessibleContext > xAccImpl(
3774                                 static_cast<SwAccessibleContext*>( xAcc.get() ) );
3775                     if ( xAccImpl.isValid() && xAccImpl->GetFrm() )
3776                     {
3777                         const SwTxtFrm* pTxtFrm(
3778                             dynamic_cast<const SwTxtFrm*>(xAccImpl->GetFrm()) );
3779                         ASSERT( pTxtFrm,
3780                                 "<SwAccessibleMap::_SubmitTextSelectionChangedEvents()> - unexcepted type of frame" );
3781                         if ( pTxtFrm )
3782                         {
3783                             InvalidateParaTextSelection( *pTxtFrm );
3784                         }
3785                     }
3786                 }
3787             }
3788         }
3789     }
3790 
3791     // second, handle previous selections - after the first step the data
3792     // structure of the previously known only contains the 'old' selections
3793     if ( pPrevSelectedParas )
3794     {
3795         SwAccessibleSelectedParas_Impl::iterator aIter = pPrevSelectedParas->begin();
3796         for ( ; aIter != pPrevSelectedParas->end(); ++aIter )
3797         {
3798             uno::Reference < XAccessible > xAcc( (*aIter).first );
3799             if ( xAcc.is() )
3800             {
3801                 ::vos::ORef < SwAccessibleContext > xAccImpl(
3802                             static_cast<SwAccessibleContext*>( xAcc.get() ) );
3803                 if ( xAccImpl.isValid() && xAccImpl->GetFrm() )
3804                 {
3805                     const SwTxtFrm* pTxtFrm(
3806                             dynamic_cast<const SwTxtFrm*>(xAccImpl->GetFrm()) );
3807                     ASSERT( pTxtFrm,
3808                             "<SwAccessibleMap::_SubmitTextSelectionChangedEvents()> - unexcepted type of frame" );
3809                     if ( pTxtFrm )
3810                     {
3811                         InvalidateParaTextSelection( *pTxtFrm );
3812                     }
3813                 }
3814             }
3815         }
3816 
3817         delete pPrevSelectedParas;
3818     }
3819 }
3820 
GetVisArea() const3821 const SwRect& SwAccessibleMap::GetVisArea() const
3822 {
3823     DBG_ASSERT( !GetShell()->IsPreView() || (mpPreview != NULL),
3824                 "preview without preview data?" );
3825 
3826     return GetShell()->IsPreView()
3827            ? mpPreview->GetVisArea()
3828            : GetShell()->VisArea();
3829 }
3830 
IsDocumentSelAll()3831 sal_Bool SwAccessibleMap::IsDocumentSelAll()
3832 {
3833 	return GetShell()->GetDoc()->IsPrepareSelAll();
3834 }
3835 
3836