1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sc.hxx"
30 
31 
32 #include "AccessibleDocument.hxx"
33 #include "AccessibleSpreadsheet.hxx"
34 #include "tabvwsh.hxx"
35 #include "AccessibilityHints.hxx"
36 #include "document.hxx"
37 #include "drwlayer.hxx"
38 #include "unoguard.hxx"
39 #include "shapeuno.hxx"
40 #include "DrawModelBroadcaster.hxx"
41 #include "drawview.hxx"
42 #include "gridwin.hxx"
43 #include "AccessibleEditObject.hxx"
44 #include "scresid.hxx"
45 #ifndef SC_SC_HRC
46 #include "sc.hrc"
47 #endif
48 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
49 #ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLESTATETYPE_HPP_
50 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
51 #endif
52 #ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLERELATIONTYPE_HPP_
53 #include <com/sun/star/accessibility/AccessibleRelationType.hpp>
54 #endif
55 #include <com/sun/star/view/XSelectionSupplier.hpp>
56 #include <com/sun/star/drawing/XShape.hpp>
57 #include <com/sun/star/drawing/XShapes.hpp>
58 
59 #ifndef _UTL_ACCESSIBLESTATESETHELPER_HXX
60 #include <unotools/accessiblestatesethelper.hxx>
61 #endif
62 #include <tools/debug.hxx>
63 #include <tools/gen.hxx>
64 #include <svx/svdpage.hxx>
65 #include <svx/svdobj.hxx>
66 #include <svx/ShapeTypeHandler.hxx>
67 #include <svx/AccessibleShape.hxx>
68 #include <svx/AccessibleShapeTreeInfo.hxx>
69 #include <svx/AccessibleShapeInfo.hxx>
70 #include <comphelper/sequence.hxx>
71 #include <sfx2/viewfrm.hxx>
72 #include <svx/unoshcol.hxx>
73 #include <svx/unoshape.hxx>
74 #include <unotools/accessiblerelationsethelper.hxx>
75 #include <toolkit/helper/convert.hxx>
76 
77 #include <list>
78 #include <algorithm>
79 
80 using namespace	::com::sun::star;
81 using namespace	::com::sun::star::accessibility;
82 using ::std::for_each;
83 
84 	//=====  internal  ========================================================
85 
86 struct ScAccessibleShapeData
87 {
88 	ScAccessibleShapeData() : pAccShape(NULL), pRelationCell(NULL), bSelected(sal_False), bSelectable(sal_True) {}
89 	~ScAccessibleShapeData();
90 	mutable ::accessibility::AccessibleShape* pAccShape;
91     mutable ScAddress*          pRelationCell; // if it is NULL this shape is anchored on the table
92 //    SdrObject*                  pShape;
93 	com::sun::star::uno::Reference< com::sun::star::drawing::XShape > xShape;
94 	mutable sal_Bool			bSelected;
95     sal_Bool                    bSelectable;
96 };
97 
98 ScAccessibleShapeData::~ScAccessibleShapeData()
99 {
100     if (pAccShape)
101     {
102         pAccShape->dispose();
103         pAccShape->release();
104     }
105 }
106 
107 struct ScShapeDataLess
108 {
109     rtl::OUString msLayerId;
110     rtl::OUString msZOrder;
111     ScShapeDataLess()
112         : msLayerId(RTL_CONSTASCII_USTRINGPARAM( "LayerID" )),
113         msZOrder(RTL_CONSTASCII_USTRINGPARAM( "ZOrder" ))
114     {
115     }
116     void ConvertLayerId(sal_Int16& rLayerID) const // changes the number of the LayerId so it the accessibility order
117     {
118         switch (rLayerID)
119         {
120         case SC_LAYER_FRONT:
121             rLayerID = 1;
122             break;
123         case SC_LAYER_BACK:
124             rLayerID = 0;
125             break;
126         case SC_LAYER_INTERN:
127             rLayerID = 2;
128             break;
129         case SC_LAYER_CONTROLS:
130             rLayerID = 3;
131             break;
132         }
133     }
134     sal_Bool LessThanSheet(const ScAccessibleShapeData* pData) const
135     {
136         sal_Bool bResult(sal_False);
137         uno::Reference< beans::XPropertySet> xProps(pData->xShape, uno::UNO_QUERY);
138         if (xProps.is())
139         {
140 			uno::Any aPropAny = xProps->getPropertyValue(msLayerId);
141 			sal_Int16 nLayerID = 0;
142 			if( (aPropAny >>= nLayerID) )
143             {
144                 if (nLayerID == SC_LAYER_BACK)
145                     bResult = sal_True;
146             }
147         }
148         return bResult;
149     }
150     sal_Bool operator()(const ScAccessibleShapeData* pData1, const ScAccessibleShapeData* pData2) const
151     {
152         sal_Bool bResult(sal_False);
153         if (pData1 && pData2)
154         {
155             uno::Reference< beans::XPropertySet> xProps1(pData1->xShape, uno::UNO_QUERY);
156             uno::Reference< beans::XPropertySet> xProps2(pData2->xShape, uno::UNO_QUERY);
157             if (xProps1.is() && xProps2.is())
158             {
159 				uno::Any aPropAny1 = xProps1->getPropertyValue(msLayerId);
160                 uno::Any aPropAny2 = xProps2->getPropertyValue(msLayerId);
161 				sal_Int16 nLayerID1(0);
162                 sal_Int16 nLayerID2(0);
163 				if( (aPropAny1 >>= nLayerID1) && (aPropAny2 >>= nLayerID2) )
164                 {
165                     if (nLayerID1 == nLayerID2)
166                     {
167 		                uno::Any aAny1 = xProps1->getPropertyValue(msZOrder);
168 		                sal_Int32 nZOrder1 = 0;
169 		                uno::Any aAny2 = xProps2->getPropertyValue(msZOrder);
170 		                sal_Int32 nZOrder2 = 0;
171 		                if ( (aAny1 >>= nZOrder1) && (aAny2 >>= nZOrder2) )
172                             bResult = (nZOrder1 < nZOrder2);
173                     }
174                     else
175                     {
176                         ConvertLayerId(nLayerID1);
177                         ConvertLayerId(nLayerID2);
178                         bResult = (nLayerID1 < nLayerID2);
179                     }
180                 }
181             }
182         }
183         else if (pData1 && !pData2)
184             bResult = LessThanSheet(pData1);
185         else if (!pData1 && pData2)
186             bResult = !LessThanSheet(pData2);
187         else
188             bResult = sal_False;
189         return bResult;
190     }
191 };
192 
193 struct DeselectShape
194 {
195 	void operator() (const ScAccessibleShapeData* pAccShapeData) const
196 	{
197         if (pAccShapeData)
198         {
199 		    pAccShapeData->bSelected = sal_False;
200 		    if (pAccShapeData->pAccShape)
201 			    pAccShapeData->pAccShape->ResetState(AccessibleStateType::SELECTED);
202         }
203 	}
204 };
205 
206 struct SelectShape
207 {
208     uno::Reference < drawing::XShapes > xShapes;
209     SelectShape(uno::Reference<drawing::XShapes>& xTemp) : xShapes(xTemp) {}
210 	void operator() (const ScAccessibleShapeData* pAccShapeData) const
211     {
212         if (pAccShapeData && pAccShapeData->bSelectable)
213         {
214 	        pAccShapeData->bSelected = sal_True;
215 	        if (pAccShapeData->pAccShape)
216 		        pAccShapeData->pAccShape->SetState(AccessibleStateType::SELECTED);
217             if (xShapes.is())
218                 xShapes->add(pAccShapeData->xShape);
219         }
220     }
221 };
222 
223 struct Destroy
224 {
225     void operator() (ScAccessibleShapeData* pData)
226     {
227         if (pData)
228             DELETEZ(pData);
229     }
230 };
231 
232 class ScChildrenShapes : public SfxListener,
233 	public ::accessibility::IAccessibleParent
234 {
235 public:
236     ScChildrenShapes(ScAccessibleDocument* pAccessibleDocument, ScTabViewShell* pViewShell, ScSplitPos eSplitPos);
237     ~ScChildrenShapes();
238 
239     ///=====  SfxListener  =====================================================
240 
241 	virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint );
242 
243     ///=====  IAccessibleParent  ===============================================
244 
245     virtual sal_Bool ReplaceChild (
246         ::accessibility::AccessibleShape* pCurrentChild,
247 		const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >& _rxShape,
248 		const long _nIndex,
249 		const ::accessibility::AccessibleShapeTreeInfo& _rShapeTreeInfo
250 	)	throw (::com::sun::star::uno::RuntimeException);
251 
252     ///=====  Internal  ========================================================
253     void SetDrawBroadcaster();
254 
255     sal_Int32 GetCount() const;
256     uno::Reference< XAccessible > Get(const ScAccessibleShapeData* pData) const;
257     uno::Reference< XAccessible > Get(sal_Int32 nIndex) const;
258 	uno::Reference< XAccessible > GetAt(const awt::Point& rPoint) const;
259 
260 	// gets the index of the shape starting on 0 (without the index of the table)
261 	// returns the selected shape
262 	sal_Bool IsSelected(sal_Int32 nIndex,
263 		com::sun::star::uno::Reference<com::sun::star::drawing::XShape>& rShape) const;
264 
265     sal_Bool SelectionChanged();
266 
267     void Select(sal_Int32 nIndex);
268     void DeselectAll(); // deselect also the table
269     void SelectAll();
270     sal_Int32 GetSelectedCount() const;
271     uno::Reference< XAccessible > GetSelected(sal_Int32 nSelectedChildIndex, sal_Bool bTabSelected) const;
272     void Deselect(sal_Int32 nChildIndex);
273 
274     SdrPage* GetDrawPage() const;
275 
276     utl::AccessibleRelationSetHelper* GetRelationSet(const ScAddress* pAddress) const;
277 
278     void VisAreaChanged() const;
279 private:
280     typedef std::vector<ScAccessibleShapeData*> SortedShapes;
281 
282     mutable SortedShapes maZOrderedShapes; // a null pointer represents the sheet in the correct order
283 
284     mutable ::accessibility::AccessibleShapeTreeInfo maShapeTreeInfo;
285 	mutable com::sun::star::uno::Reference<com::sun::star::view::XSelectionSupplier> xSelectionSupplier;
286 	mutable sal_uInt32 mnSdrObjCount;
287 	mutable sal_uInt32 mnShapesSelected;
288     ScTabViewShell* mpViewShell;
289     ScAccessibleDocument* mpAccessibleDocument;
290     ScSplitPos meSplitPos;
291 
292     void FillShapes(std::vector < uno::Reference < drawing::XShape > >& rShapes) const;
293     sal_Bool FindSelectedShapesChanges(const com::sun::star::uno::Reference<com::sun::star::drawing::XShapes>& xShapes, sal_Bool bCommitChange) const;
294 	void FillSelectionSupplier() const;
295 
296     ScAddress* GetAnchor(const uno::Reference<drawing::XShape>& xShape) const;
297     uno::Reference<XAccessibleRelationSet> GetRelationSet(const ScAccessibleShapeData* pData) const;
298     void CheckWhetherAnchorChanged(const uno::Reference<drawing::XShape>& xShape) const;
299     void SetAnchor(const uno::Reference<drawing::XShape>& xShape, ScAccessibleShapeData* pData) const;
300     void AddShape(const uno::Reference<drawing::XShape>& xShape, sal_Bool bCommitChange) const;
301     void RemoveShape(const uno::Reference<drawing::XShape>& xShape) const;
302 
303     sal_Bool FindShape(const uno::Reference<drawing::XShape>& xShape, SortedShapes::iterator& rItr) const;
304 
305 	sal_Int8 Compare(const ScAccessibleShapeData* pData1,
306 		const ScAccessibleShapeData* pData2) const;
307 };
308 
309 ScChildrenShapes::ScChildrenShapes(ScAccessibleDocument* pAccessibleDocument, ScTabViewShell* pViewShell, ScSplitPos eSplitPos)
310     :
311     mnShapesSelected(0),
312     mpViewShell(pViewShell),
313     mpAccessibleDocument(pAccessibleDocument),
314     meSplitPos(eSplitPos)
315 {
316 	FillSelectionSupplier();
317     maZOrderedShapes.push_back(NULL); // add an element which represents the table
318 
319 	GetCount(); // fill list with filtered shapes (no internal shapes)
320 
321 	if (mnShapesSelected)
322 	{
323 		//set flag on every selected shape
324 		if (!xSelectionSupplier.is())
325 			throw uno::RuntimeException();
326 
327 		uno::Reference<drawing::XShapes> xShapes(xSelectionSupplier->getSelection(), uno::UNO_QUERY);
328 		if (xShapes.is())
329 			FindSelectedShapesChanges(xShapes, sal_False);
330 	}
331     if (pViewShell)
332     {
333 	    SfxBroadcaster* pDrawBC = pViewShell->GetViewData()->GetDocument()->GetDrawBroadcaster();
334 	    if (pDrawBC)
335         {
336 		    StartListening(*pDrawBC);
337 
338             maShapeTreeInfo.SetModelBroadcaster( new ScDrawModelBroadcaster(pViewShell->GetViewData()->GetDocument()->GetDrawLayer()) );
339             maShapeTreeInfo.SetSdrView(pViewShell->GetViewData()->GetScDrawView());
340             maShapeTreeInfo.SetController(NULL);
341             maShapeTreeInfo.SetWindow(pViewShell->GetWindowByPos(meSplitPos));
342             maShapeTreeInfo.SetViewForwarder(mpAccessibleDocument);
343         }
344     }
345 }
346 
347 ScChildrenShapes::~ScChildrenShapes()
348 {
349     std::for_each(maZOrderedShapes.begin(), maZOrderedShapes.end(), Destroy());
350     if (mpViewShell)
351     {
352 	    SfxBroadcaster* pDrawBC = mpViewShell->GetViewData()->GetDocument()->GetDrawBroadcaster();
353 	    if (pDrawBC)
354 		    EndListening(*pDrawBC);
355     }
356 }
357 
358 void ScChildrenShapes::SetDrawBroadcaster()
359 {
360     if (mpViewShell)
361     {
362 	    SfxBroadcaster* pDrawBC = mpViewShell->GetViewData()->GetDocument()->GetDrawBroadcaster();
363 	    if (pDrawBC)
364         {
365 		    StartListening(*pDrawBC, sal_True);
366 
367             maShapeTreeInfo.SetModelBroadcaster( new ScDrawModelBroadcaster(mpViewShell->GetViewData()->GetDocument()->GetDrawLayer()) );
368             maShapeTreeInfo.SetSdrView(mpViewShell->GetViewData()->GetScDrawView());
369             maShapeTreeInfo.SetController(NULL);
370             maShapeTreeInfo.SetWindow(mpViewShell->GetWindowByPos(meSplitPos));
371             maShapeTreeInfo.SetViewForwarder(mpAccessibleDocument);
372         }
373     }
374 }
375 
376 void ScChildrenShapes::Notify(SfxBroadcaster&, const SfxHint& rHint)
377 {
378 	if ( rHint.ISA( SdrHint ) )
379 	{
380 		const SdrHint* pSdrHint = PTR_CAST( SdrHint, &rHint );
381         if (pSdrHint)
382         {
383             SdrObject* pObj = const_cast<SdrObject*>(pSdrHint->GetObject());
384             if (pObj && /*(pObj->GetLayer() != SC_LAYER_INTERN) && */(pObj->GetPage() == GetDrawPage()) &&
385                 (pObj->GetPage() == pObj->GetObjList()) ) //#108480# only do something if the object lies direct on the page
386             {
387                 switch (pSdrHint->GetKind())
388                 {
389                     case HINT_OBJCHG :         // Objekt geaendert
390                     {
391                         uno::Reference<drawing::XShape> xShape (pObj->getUnoShape(), uno::UNO_QUERY);
392                         if (xShape.is())
393                         {
394                             ScShapeDataLess aLess;
395                             std::sort(maZOrderedShapes.begin(), maZOrderedShapes.end(), aLess); // sort, because the z index or layer could be changed
396                             CheckWhetherAnchorChanged(xShape);
397                         }
398                     }
399                     break;
400                     case HINT_OBJINSERTED :    // Neues Zeichenobjekt eingefuegt
401                     {
402                         uno::Reference<drawing::XShape> xShape (pObj->getUnoShape(), uno::UNO_QUERY);
403                         if (xShape.is())
404                             AddShape(xShape, sal_True);
405                     }
406                     break;
407                     case HINT_OBJREMOVED :     // Zeichenobjekt aus Liste entfernt
408                     {
409                         uno::Reference<drawing::XShape> xShape (pObj->getUnoShape(), uno::UNO_QUERY);
410                         if (xShape.is())
411                             RemoveShape(xShape);
412                     }
413                     break;
414                     default :
415                     {
416                         // other events are not interesting
417                     }
418                     break;
419                 }
420             }
421         }
422     }
423 }
424 
425 sal_Bool ScChildrenShapes::ReplaceChild (::accessibility::AccessibleShape* pCurrentChild,
426 		const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >& _rxShape,
427 		const long _nIndex, const ::accessibility::AccessibleShapeTreeInfo& _rShapeTreeInfo)
428     throw (uno::RuntimeException)
429 {
430 	// create the new child
431 	::accessibility::AccessibleShape* pReplacement = ::accessibility::ShapeTypeHandler::Instance().CreateAccessibleObject (
432 		::accessibility::AccessibleShapeInfo ( _rxShape, pCurrentChild->getAccessibleParent(), this, _nIndex ),
433 		_rShapeTreeInfo
434 	);
435 	::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > xNewChild( pReplacement );	// keep this alive (do this before calling Init!)
436 	if ( pReplacement )
437 		pReplacement->Init();
438 
439     sal_Bool bResult(sal_False);
440     if (pCurrentChild && pReplacement)
441     {
442         DBG_ASSERT(pCurrentChild->GetXShape().get() == pReplacement->GetXShape().get(), "XShape changes and should be inserted sorted");
443         SortedShapes::iterator aItr;
444         FindShape(pCurrentChild->GetXShape(), aItr);
445         if (aItr != maZOrderedShapes.end() && (*aItr))
446         {
447             if ((*aItr)->pAccShape)
448             {
449                 DBG_ASSERT((*aItr)->pAccShape == pCurrentChild, "wrong child found");
450                 AccessibleEventObject aEvent;
451 			    aEvent.EventId = AccessibleEventId::CHILD;
452 			    aEvent.Source = uno::Reference< XAccessibleContext >(mpAccessibleDocument);
453                 aEvent.OldValue <<= uno::makeAny(uno::Reference<XAccessible>(pCurrentChild));
454 
455 			    mpAccessibleDocument->CommitChange(aEvent); // child is gone - event
456 
457                 pCurrentChild->dispose();
458             }
459             (*aItr)->pAccShape = pReplacement;
460             AccessibleEventObject aEvent;
461 			aEvent.EventId = AccessibleEventId::CHILD;
462 			aEvent.Source = uno::Reference< XAccessibleContext >(mpAccessibleDocument);
463             aEvent.NewValue <<= uno::makeAny(uno::Reference<XAccessible>(pReplacement));
464 
465 			mpAccessibleDocument->CommitChange(aEvent); // child is new - event
466             bResult = sal_True;
467         }
468     }
469     return bResult;
470 }
471 
472 sal_Int32 ScChildrenShapes::GetCount() const
473 {
474 	SdrPage* pDrawPage = GetDrawPage();
475 	if (pDrawPage && (maZOrderedShapes.size() == 1)) // the table is always in
476 	{
477 		mnSdrObjCount = pDrawPage->GetObjCount();
478 		maZOrderedShapes.reserve(mnSdrObjCount + 1); // the table is always in
479 		for (sal_uInt32 i = 0; i < mnSdrObjCount; ++i)
480 		{
481 			SdrObject* pObj = pDrawPage->GetObj(i);
482 			if (pObj/* && (pObj->GetLayer() != SC_LAYER_INTERN)*/)
483 			{
484 				uno::Reference< drawing::XShape > xShape (pObj->getUnoShape(), uno::UNO_QUERY);
485                 AddShape(xShape, sal_False); //inserts in the correct order
486 			}
487 		}
488 	}
489 	return maZOrderedShapes.size();
490 }
491 
492 uno::Reference< XAccessible > ScChildrenShapes::Get(const ScAccessibleShapeData* pData) const
493 {
494     if (!pData)
495         return NULL;
496 
497 	if (!pData->pAccShape)
498 	{
499 		::accessibility::ShapeTypeHandler& rShapeHandler = ::accessibility::ShapeTypeHandler::Instance();
500         ::accessibility::AccessibleShapeInfo aShapeInfo(pData->xShape, mpAccessibleDocument, const_cast<ScChildrenShapes*>(this));
501 		pData->pAccShape = rShapeHandler.CreateAccessibleObject(
502 			aShapeInfo, maShapeTreeInfo);
503 		if (pData->pAccShape)
504         {
505 			pData->pAccShape->acquire();
506 			pData->pAccShape->Init();
507             if (pData->bSelected)
508                 pData->pAccShape->SetState(AccessibleStateType::SELECTED);
509             if (!pData->bSelectable)
510                 pData->pAccShape->ResetState(AccessibleStateType::SELECTABLE);
511             pData->pAccShape->SetRelationSet(GetRelationSet(pData));
512         }
513 	}
514     return pData->pAccShape;
515  }
516 
517 uno::Reference< XAccessible > ScChildrenShapes::Get(sal_Int32 nIndex) const
518 {
519 	if (maZOrderedShapes.size() <= 1)
520 		GetCount(); // fill list with filtered shapes (no internal shapes)
521 
522 	if (static_cast<sal_uInt32>(nIndex) >= maZOrderedShapes.size())
523 		return NULL;
524 
525     return Get(maZOrderedShapes[nIndex]);
526 }
527 
528 uno::Reference< XAccessible > ScChildrenShapes::GetAt(const awt::Point& rPoint) const
529 {
530     uno::Reference<XAccessible> xAccessible;
531     if(mpViewShell)
532     {
533         sal_Int32 i(maZOrderedShapes.size() - 1);
534         sal_Bool bFound(sal_False);
535         while (!bFound && i >= 0)
536         {
537             ScAccessibleShapeData* pShape = maZOrderedShapes[i];
538             if (pShape)
539             {
540                 if (!pShape->pAccShape)
541                     Get(pShape);
542 
543                 if (pShape->pAccShape)
544                 {
545                     Point aPoint(VCLPoint(rPoint));
546                     aPoint -= VCLRectangle(pShape->pAccShape->getBounds()).TopLeft();
547                     if (pShape->pAccShape->containsPoint(AWTPoint(aPoint)))
548                     {
549                         xAccessible = pShape->pAccShape;
550                         bFound = sal_True;
551                     }
552                 }
553                 else
554                 {
555                     DBG_ERRORFILE("I should have an accessible shape now!");
556                 }
557             }
558             else
559                 bFound = sal_True; // this is the sheet and it lies before the rest of the shapes which are background shapes
560 
561             --i;
562         }
563     }
564     return xAccessible;
565 }
566 
567 sal_Bool ScChildrenShapes::IsSelected(sal_Int32 nIndex,
568 						uno::Reference<drawing::XShape>& rShape) const
569 {
570 	sal_Bool bResult (sal_False);
571 	if (maZOrderedShapes.size() <= 1)
572 		GetCount(); // fill list with filtered shapes (no internal shapes)
573 
574 	if (!xSelectionSupplier.is())
575 		throw uno::RuntimeException();
576 
577     if (!maZOrderedShapes[nIndex])
578         return sal_False;
579 
580     bResult = maZOrderedShapes[nIndex]->bSelected;
581     rShape = maZOrderedShapes[nIndex]->xShape;
582 
583 #ifdef DBG_UTIL // test whether it is truly selected by a slower method
584     uno::Reference< drawing::XShape > xReturnShape;
585     sal_Bool bDebugResult(sal_False);
586 	uno::Reference<container::XIndexAccess> xIndexAccess;
587 	xSelectionSupplier->getSelection() >>= xIndexAccess;
588 
589 	if (xIndexAccess.is())
590 	{
591 		sal_Int32 nCount(xIndexAccess->getCount());
592 		if (nCount)
593 		{
594 			uno::Reference< drawing::XShape > xShape;
595             uno::Reference< drawing::XShape > xIndexShape = maZOrderedShapes[nIndex]->xShape;
596 			sal_Int32 i(0);
597 			while (!bDebugResult && (i < nCount))
598 			{
599 				xIndexAccess->getByIndex(i) >>= xShape;
600 				if (xShape.is() && (xIndexShape.get() == xShape.get()))
601 				{
602 					bDebugResult = sal_True;
603 					xReturnShape = xShape;
604 				}
605 				else
606 					++i;
607 			}
608 		}
609 	}
610     DBG_ASSERT((bResult == bDebugResult) && ((bResult && (rShape.get() == xReturnShape.get())) || !bResult), "found the wrong shape or result");
611 #endif
612 
613     return bResult;
614 }
615 
616 sal_Bool ScChildrenShapes::SelectionChanged()
617 {
618     sal_Bool bResult(sal_False);
619 	if (!xSelectionSupplier.is())
620 		throw uno::RuntimeException();
621 
622 	uno::Reference<drawing::XShapes> xShapes(xSelectionSupplier->getSelection(), uno::UNO_QUERY);
623 
624 	bResult = FindSelectedShapesChanges(xShapes, sal_True);
625 
626     return bResult;
627 }
628 
629 void ScChildrenShapes::Select(sal_Int32 nIndex)
630 {
631 	if (maZOrderedShapes.size() <= 1)
632 		GetCount(); // fill list with filtered shapes (no internal shapes)
633 
634 	if (!xSelectionSupplier.is())
635 		throw uno::RuntimeException();
636 
637     if (!maZOrderedShapes[nIndex])
638         return;
639 
640 	uno::Reference<drawing::XShape> xShape;
641 	if (!IsSelected(nIndex, xShape) && maZOrderedShapes[nIndex]->bSelectable)
642 	{
643 		uno::Reference<drawing::XShapes> xShapes;
644 		xSelectionSupplier->getSelection() >>= xShapes;
645 
646 		if (!xShapes.is())
647 			xShapes = new SvxShapeCollection();
648 
649 		xShapes->add(maZOrderedShapes[nIndex]->xShape);
650 
651         try
652         {
653             xSelectionSupplier->select(uno::makeAny(xShapes));
654 		    maZOrderedShapes[nIndex]->bSelected = sal_True;
655 		    if (maZOrderedShapes[nIndex]->pAccShape)
656 			    maZOrderedShapes[nIndex]->pAccShape->SetState(AccessibleStateType::SELECTED);
657         }
658         catch (lang::IllegalArgumentException&)
659         {
660         }
661 	}
662 }
663 
664 void ScChildrenShapes::DeselectAll()
665 {
666 	if (!xSelectionSupplier.is())
667 		throw uno::RuntimeException();
668 
669     sal_Bool bSomethingSelected(sal_True);
670     try
671     {
672         xSelectionSupplier->select(uno::Any()); //deselects all
673     }
674     catch (lang::IllegalArgumentException&)
675     {
676         DBG_ERRORFILE("nothing selected before");
677         bSomethingSelected = sal_False;
678     }
679 
680     if (bSomethingSelected)
681         std::for_each(maZOrderedShapes.begin(), maZOrderedShapes.end(), DeselectShape());
682 }
683 
684 void ScChildrenShapes::SelectAll()
685 {
686 	if (!xSelectionSupplier.is())
687 		throw uno::RuntimeException();
688 
689 	if (maZOrderedShapes.size() <= 1)
690 		GetCount(); // fill list with filtered shapes (no internal shapes)
691 
692     if (maZOrderedShapes.size() > 1)
693     {
694 	    uno::Reference<drawing::XShapes> xShapes;
695 	    xShapes = new SvxShapeCollection();
696 
697         try
698         {
699             std::for_each(maZOrderedShapes.begin(), maZOrderedShapes.end(), SelectShape(xShapes));
700     	    xSelectionSupplier->select(uno::makeAny(xShapes));
701         }
702         catch (lang::IllegalArgumentException&)
703         {
704             SelectionChanged(); // find all selected shapes and set the flags
705         }
706     }
707 }
708 
709 void ScChildrenShapes::FillShapes(std::vector < uno::Reference < drawing::XShape > >& rShapes) const
710 {
711 	uno::Reference<container::XIndexAccess> xIndexAccess;
712 	xSelectionSupplier->getSelection() >>= xIndexAccess;
713 
714 	if (xIndexAccess.is())
715     {
716         sal_uInt32 nCount(xIndexAccess->getCount());
717         for (sal_uInt32 i = 0; i < nCount; ++i)
718         {
719     		uno::Reference<drawing::XShape> xShape;
720             xIndexAccess->getByIndex(i) >>= xShape;
721             if (xShape.is())
722                 rShapes.push_back(xShape);
723         }
724     }
725 }
726 
727 sal_Int32 ScChildrenShapes::GetSelectedCount() const
728 {
729 	if (!xSelectionSupplier.is())
730 		throw uno::RuntimeException();
731 
732     std::vector < uno::Reference < drawing::XShape > > aShapes;
733     FillShapes(aShapes);
734 
735     return aShapes.size();
736 }
737 
738 uno::Reference< XAccessible > ScChildrenShapes::GetSelected(sal_Int32 nSelectedChildIndex, sal_Bool bTabSelected) const
739 {
740     uno::Reference< XAccessible > xAccessible;
741 
742 	if (maZOrderedShapes.size() <= 1)
743 		GetCount(); // fill list with shapes
744 
745     if (!bTabSelected)
746     {
747         std::vector < uno::Reference < drawing::XShape > > aShapes;
748         FillShapes(aShapes);
749 
750         SortedShapes::iterator aItr;
751         if (FindShape(aShapes[nSelectedChildIndex], aItr))
752             xAccessible = Get(aItr - maZOrderedShapes.begin());
753     }
754     else
755     {
756         SortedShapes::iterator aItr = maZOrderedShapes.begin();
757         SortedShapes::iterator aEndItr = maZOrderedShapes.end();
758         sal_Bool bFound(sal_False);
759         while(!bFound && aItr != aEndItr)
760         {
761             if (*aItr)
762             {
763                 if ((*aItr)->bSelected)
764                 {
765                     if (nSelectedChildIndex == 0)
766                         bFound = sal_True;
767                     else
768                         --nSelectedChildIndex;
769                 }
770             }
771             else
772             {
773                 if (nSelectedChildIndex == 0)
774                     bFound = sal_True;
775                 else
776                     --nSelectedChildIndex;
777             }
778             if (!bFound)
779                 ++aItr;
780         }
781         if (bFound && *aItr)
782             xAccessible = (*aItr)->pAccShape;
783     }
784 
785     return xAccessible;
786 }
787 
788 void ScChildrenShapes::Deselect(sal_Int32 nChildIndex)
789 {
790 	uno::Reference<drawing::XShape> xShape;
791 	if (IsSelected(nChildIndex, xShape)) // returns false if it is the sheet
792 	{
793 		if (xShape.is())
794 		{
795 			uno::Reference<drawing::XShapes> xShapes;
796 			xSelectionSupplier->getSelection() >>= xShapes;
797 			if (xShapes.is())
798 				xShapes->remove(xShape);
799 
800             try
801             {
802 			    xSelectionSupplier->select(uno::makeAny(xShapes));
803             }
804             catch (lang::IllegalArgumentException&)
805             {
806                 DBG_ERRORFILE("something not selectable");
807             }
808 
809 			maZOrderedShapes[nChildIndex]->bSelected = sal_False;
810 			if (maZOrderedShapes[nChildIndex]->pAccShape)
811 				maZOrderedShapes[nChildIndex]->pAccShape->ResetState(AccessibleStateType::SELECTED);
812 		}
813 	}
814 }
815 
816 
817 SdrPage* ScChildrenShapes::GetDrawPage() const
818 {
819 	SCTAB nTab(mpAccessibleDocument->getVisibleTable());
820 	SdrPage* pDrawPage = NULL;
821 	if (mpViewShell)
822 	{
823 		ScDocument* pDoc = mpViewShell->GetViewData()->GetDocument();
824 		if (pDoc && pDoc->GetDrawLayer())
825 		{
826 			ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer();
827 			if (pDrawLayer->HasObjects() && (pDrawLayer->GetPageCount() > nTab))
828 				pDrawPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(static_cast<sal_Int16>(nTab)));
829 		}
830 	}
831 	return pDrawPage;
832 }
833 
834 struct SetRelation
835 {
836     const ScChildrenShapes* mpChildrenShapes;
837     mutable utl::AccessibleRelationSetHelper* mpRelationSet;
838     const ScAddress* mpAddress;
839     SetRelation(const ScChildrenShapes* pChildrenShapes, const ScAddress* pAddress)
840         :
841         mpChildrenShapes(pChildrenShapes),
842         mpRelationSet(NULL),
843         mpAddress(pAddress)
844     {
845     }
846 	void operator() (const ScAccessibleShapeData* pAccShapeData) const
847     {
848 	    if (pAccShapeData &&
849             ((!pAccShapeData->pRelationCell && !mpAddress) ||
850             (pAccShapeData->pRelationCell && mpAddress && (*(pAccShapeData->pRelationCell) == *mpAddress))))
851         {
852             if (!mpRelationSet)
853                 mpRelationSet = new utl::AccessibleRelationSetHelper();
854 
855             AccessibleRelation aRelation;
856             aRelation.TargetSet.realloc(1);
857             aRelation.TargetSet[0] = mpChildrenShapes->Get(pAccShapeData);
858             aRelation.RelationType = AccessibleRelationType::CONTROLLER_FOR;
859 
860             mpRelationSet->AddRelation(aRelation);
861         }
862     }
863 };
864 
865 utl::AccessibleRelationSetHelper* ScChildrenShapes::GetRelationSet(const ScAddress* pAddress) const
866 {
867     SetRelation aSetRelation(this, pAddress);
868     ::std::for_each(maZOrderedShapes.begin(), maZOrderedShapes.end(), aSetRelation);
869     return aSetRelation.mpRelationSet;
870 }
871 
872 sal_Bool ScChildrenShapes::FindSelectedShapesChanges(const uno::Reference<drawing::XShapes>& xShapes, sal_Bool /* bCommitChange */) const
873 {
874     sal_Bool bResult(sal_False);
875     SortedShapes aShapesList;
876     uno::Reference<container::XIndexAccess> xIndexAcc(xShapes, uno::UNO_QUERY);
877     if (xIndexAcc.is())
878     {
879         mnShapesSelected = xIndexAcc->getCount();
880         for (sal_uInt32 i = 0; i < mnShapesSelected; ++i)
881         {
882 			uno::Reference< drawing::XShape > xShape;
883             xIndexAcc->getByIndex(i) >>= xShape;
884             if (xShape.is())
885             {
886                 ScAccessibleShapeData* pShapeData = new ScAccessibleShapeData();
887                 pShapeData->xShape = xShape;
888                 aShapesList.push_back(pShapeData);
889             }
890         }
891     }
892     else
893         mnShapesSelected = 0;
894     ScShapeDataLess aLess;
895     std::sort(aShapesList.begin(), aShapesList.end(), aLess);
896 
897     SortedShapes::iterator aXShapesItr(aShapesList.begin());
898     SortedShapes::const_iterator aXShapesEndItr(aShapesList.end());
899     SortedShapes::iterator aDataItr(maZOrderedShapes.begin());
900     SortedShapes::const_iterator aDataEndItr(maZOrderedShapes.end());
901     SortedShapes::const_iterator aFocusedItr = aDataEndItr;
902     while((aDataItr != aDataEndItr))
903     {
904         if (*aDataItr) // is it realy a shape or only the sheet
905         {
906             sal_Int8 nComp(0);
907             if (aXShapesItr == aXShapesEndItr)
908                 nComp = -1; // simulate that the Shape is lower, so the selction state will be removed
909             else
910                 nComp = Compare(*aDataItr, *aXShapesItr);
911             if (nComp == 0)
912             {
913                 if (!(*aDataItr)->bSelected)
914                 {
915                     (*aDataItr)->bSelected = sal_True;
916                     if ((*aDataItr)->pAccShape)
917                     {
918                         (*aDataItr)->pAccShape->SetState(AccessibleStateType::SELECTED);
919                         (*aDataItr)->pAccShape->ResetState(AccessibleStateType::FOCUSED);
920                         bResult = sal_True;
921                     }
922                     aFocusedItr = aDataItr;
923                 }
924                 ++aDataItr;
925                 ++aXShapesItr;
926             }
927             else if (nComp < 0)
928             {
929                 if ((*aDataItr)->bSelected)
930                 {
931                     (*aDataItr)->bSelected = sal_False;
932                     if ((*aDataItr)->pAccShape)
933                     {
934                         (*aDataItr)->pAccShape->ResetState(AccessibleStateType::SELECTED);
935                         (*aDataItr)->pAccShape->ResetState(AccessibleStateType::FOCUSED);
936                         bResult = sal_True;
937                     }
938                 }
939                 ++aDataItr;
940             }
941             else
942             {
943                 DBG_ERRORFILE("here is a selected shape which is not in the childlist");
944                 ++aXShapesItr;
945                 --mnShapesSelected;
946             }
947         }
948         else
949             ++aDataItr;
950     }
951     if ((aFocusedItr != aDataEndItr) && (*aFocusedItr)->pAccShape && (mnShapesSelected == 1))
952         (*aFocusedItr)->pAccShape->SetState(AccessibleStateType::FOCUSED);
953 
954     std::for_each(aShapesList.begin(), aShapesList.end(), Destroy());
955 
956     return bResult;
957 }
958 
959 void ScChildrenShapes::FillSelectionSupplier() const
960 {
961 	if (!xSelectionSupplier.is() && mpViewShell)
962 	{
963 		SfxViewFrame* pViewFrame = mpViewShell->GetViewFrame();
964 		if (pViewFrame)
965 		{
966 			xSelectionSupplier = uno::Reference<view::XSelectionSupplier>(pViewFrame->GetFrame().GetController(), uno::UNO_QUERY);
967 			if (xSelectionSupplier.is())
968 			{
969                 if (mpAccessibleDocument)
970                     xSelectionSupplier->addSelectionChangeListener(mpAccessibleDocument);
971 				uno::Reference<drawing::XShapes> xShapes (xSelectionSupplier->getSelection(), uno::UNO_QUERY);
972 				if (xShapes.is())
973 					mnShapesSelected = xShapes->getCount();
974 			}
975 		}
976 	}
977 }
978 
979 ScAddress* ScChildrenShapes::GetAnchor(const uno::Reference<drawing::XShape>& xShape) const
980 {
981     ScAddress* pAddress = NULL;
982     if (mpViewShell)
983     {
984 	    SvxShape* pShapeImp = SvxShape::getImplementation(xShape);
985         uno::Reference<beans::XPropertySet> xShapeProp(xShape, uno::UNO_QUERY);
986 	    if (pShapeImp && xShapeProp.is())
987 	    {
988 		    SdrObject *pSdrObj = pShapeImp->GetSdrObject();
989 		    if (pSdrObj)
990 		    {
991 			    if (ScDrawLayer::GetAnchor(pSdrObj) == SCA_CELL)
992 			    {
993                     ScDocument* pDoc = mpViewShell->GetViewData()->GetDocument();
994 				    if (pDoc)
995 				    {
996                         rtl::OUString sCaptionShape(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.CaptionShape"));
997 					    awt::Point aPoint(xShape->getPosition());
998 					    awt::Size aSize(xShape->getSize());
999 					    rtl::OUString sType(xShape->getShapeType());
1000 					    Rectangle aRectangle(aPoint.X, aPoint.Y, aPoint.X + aSize.Width, aPoint.Y + aSize.Height);
1001 					    if ( sType.equals(sCaptionShape) )
1002 					    {
1003 						    awt::Point aRelativeCaptionPoint;
1004                             rtl::OUString sCaptionPoint( RTL_CONSTASCII_USTRINGPARAM( "CaptionPoint" ));
1005 						    xShapeProp->getPropertyValue( sCaptionPoint ) >>= aRelativeCaptionPoint;
1006 						    Point aCoreRelativeCaptionPoint(aRelativeCaptionPoint.X, aRelativeCaptionPoint.Y);
1007 						    Point aCoreAbsoluteCaptionPoint(aPoint.X, aPoint.Y);
1008 						    aCoreAbsoluteCaptionPoint += aCoreRelativeCaptionPoint;
1009 						    aRectangle.Union(Rectangle(aCoreAbsoluteCaptionPoint, aCoreAbsoluteCaptionPoint));
1010 					    }
1011 					    ScRange aRange = pDoc->GetRange(mpAccessibleDocument->getVisibleTable(), aRectangle);
1012                         pAddress = new ScAddress(aRange.aStart);
1013 				    }
1014 			    }
1015 //			    else
1016 //				    do nothing, because it is always a NULL Pointer
1017 		    }
1018 	    }
1019     }
1020 
1021     return pAddress;
1022 }
1023 
1024 uno::Reference<XAccessibleRelationSet> ScChildrenShapes::GetRelationSet(const ScAccessibleShapeData* pData) const
1025 {
1026     utl::AccessibleRelationSetHelper* pRelationSet = new utl::AccessibleRelationSetHelper();
1027 
1028     if(pData && pRelationSet && mpAccessibleDocument)
1029     {
1030         uno::Reference<XAccessible> xAccessible = mpAccessibleDocument->GetAccessibleSpreadsheet(); // should be the current table
1031         if (pData->pRelationCell && xAccessible.is())
1032         {
1033             uno::Reference<XAccessibleTable> xAccTable (xAccessible->getAccessibleContext(), uno::UNO_QUERY);
1034             if (xAccTable.is())
1035                 xAccessible = xAccTable->getAccessibleCellAt(pData->pRelationCell->Row(), pData->pRelationCell->Col());
1036         }
1037         AccessibleRelation aRelation;
1038         aRelation.TargetSet.realloc(1);
1039         aRelation.TargetSet[0] = xAccessible;
1040         aRelation.RelationType = AccessibleRelationType::CONTROLLED_BY;
1041         pRelationSet->AddRelation(aRelation);
1042     }
1043 
1044     return pRelationSet;
1045 }
1046 
1047 void ScChildrenShapes::CheckWhetherAnchorChanged(const uno::Reference<drawing::XShape>& xShape) const
1048 {
1049     SortedShapes::iterator aItr;
1050     if (FindShape(xShape, aItr))
1051         SetAnchor(xShape, *aItr);
1052 }
1053 
1054 void ScChildrenShapes::SetAnchor(const uno::Reference<drawing::XShape>& xShape, ScAccessibleShapeData* pData) const
1055 {
1056     if (pData)
1057     {
1058         ScAddress* pAddress = GetAnchor(xShape);
1059         if ((pAddress && pData->pRelationCell && (*pAddress != *(pData->pRelationCell))) ||
1060             (!pAddress && pData->pRelationCell) || (pAddress && !pData->pRelationCell))
1061         {
1062             if (pData->pRelationCell)
1063                 delete pData->pRelationCell;
1064             pData->pRelationCell = pAddress;
1065             if (pData->pAccShape)
1066                 pData->pAccShape->SetRelationSet(GetRelationSet(pData));
1067         }
1068     }
1069 }
1070 
1071 void ScChildrenShapes::AddShape(const uno::Reference<drawing::XShape>& xShape, sal_Bool bCommitChange) const
1072 {
1073     SortedShapes::iterator aFindItr;
1074     if (!FindShape(xShape, aFindItr))
1075     {
1076         ScAccessibleShapeData* pShape = new ScAccessibleShapeData();
1077         pShape->xShape = xShape;
1078         SortedShapes::iterator aNewItr = maZOrderedShapes.insert(aFindItr, pShape);
1079         SetAnchor(xShape, pShape);
1080 
1081         uno::Reference< beans::XPropertySet > xShapeProp(xShape, uno::UNO_QUERY);
1082         if (xShapeProp.is())
1083         {
1084             uno::Any aPropAny = xShapeProp->getPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(  "LayerID" )));
1085 		    sal_Int16 nLayerID = 0;
1086 		    if( aPropAny >>= nLayerID )
1087 		    {
1088                 if( (nLayerID == SC_LAYER_INTERN) || (nLayerID == SC_LAYER_HIDDEN) )
1089                     pShape->bSelectable = sal_False;
1090                 else
1091                     pShape->bSelectable = sal_True;
1092             }
1093         }
1094 
1095 
1096         if (!xSelectionSupplier.is())
1097 		    throw uno::RuntimeException();
1098 
1099         uno::Reference<container::XEnumerationAccess> xEnumAcc(xSelectionSupplier->getSelection(), uno::UNO_QUERY);
1100 	    if (xEnumAcc.is())
1101 	    {
1102             uno::Reference<container::XEnumeration> xEnum = xEnumAcc->createEnumeration();
1103             if (xEnum.is())
1104             {
1105                 uno::Reference<drawing::XShape> xSelectedShape;
1106                 sal_Bool bFound(sal_False);
1107                 while (!bFound && xEnum->hasMoreElements())
1108                 {
1109                     xEnum->nextElement() >>= xSelectedShape;
1110                     if (xShape.is() && (xShape.get() == xSelectedShape.get()))
1111                     {
1112                         pShape->bSelected = sal_True;
1113                         bFound = sal_True;
1114                     }
1115                 }
1116             }
1117         }
1118         if (mpAccessibleDocument && bCommitChange)
1119         {
1120 			AccessibleEventObject aEvent;
1121 			aEvent.EventId = AccessibleEventId::CHILD;
1122 			aEvent.Source = uno::Reference< XAccessibleContext >(mpAccessibleDocument);
1123 			aEvent.NewValue <<= Get(aNewItr - maZOrderedShapes.begin());
1124 
1125 			mpAccessibleDocument->CommitChange(aEvent); // new child - event
1126         }
1127     }
1128     else
1129     {
1130         DBG_ERRORFILE("shape is always in the list");
1131     }
1132 }
1133 
1134 void ScChildrenShapes::RemoveShape(const uno::Reference<drawing::XShape>& xShape) const
1135 {
1136     SortedShapes::iterator aItr;
1137     if (FindShape(xShape, aItr))
1138     {
1139         if (mpAccessibleDocument)
1140         {
1141             uno::Reference<XAccessible> xOldAccessible (Get(aItr - maZOrderedShapes.begin()));
1142 
1143             delete *aItr;
1144             maZOrderedShapes.erase(aItr);
1145 
1146             AccessibleEventObject aEvent;
1147 			aEvent.EventId = AccessibleEventId::CHILD;
1148 			aEvent.Source = uno::Reference< XAccessibleContext >(mpAccessibleDocument);
1149             aEvent.OldValue <<= uno::makeAny(xOldAccessible);
1150 
1151 			mpAccessibleDocument->CommitChange(aEvent); // child is gone - event
1152         }
1153         else
1154         {
1155             delete *aItr;
1156             maZOrderedShapes.erase(aItr);
1157         }
1158     }
1159     else
1160     {
1161         DBG_ERRORFILE("shape was not in internal list");
1162     }
1163 }
1164 
1165 sal_Bool ScChildrenShapes::FindShape(const uno::Reference<drawing::XShape>& xShape, ScChildrenShapes::SortedShapes::iterator& rItr) const
1166 {
1167     sal_Bool bResult(sal_False);
1168     ScAccessibleShapeData aShape;
1169     aShape.xShape = xShape;
1170     ScShapeDataLess aLess;
1171     rItr = std::lower_bound(maZOrderedShapes.begin(), maZOrderedShapes.end(), &aShape, aLess);
1172     if ((rItr != maZOrderedShapes.end()) && (*rItr != NULL) && ((*rItr)->xShape.get() == xShape.get()))
1173         bResult = sal_True; // if the shape is found
1174 
1175 #ifdef DBG_UTIL // test whether it finds truly the correct shape (perhaps it is not really sorted)
1176     SortedShapes::iterator aDebugItr = maZOrderedShapes.begin();
1177     SortedShapes::iterator aEndItr = maZOrderedShapes.end();
1178     sal_Bool bFound(sal_False);
1179     while (!bFound && aDebugItr != aEndItr)
1180     {
1181         if (*aDebugItr && ((*aDebugItr)->xShape.get() == xShape.get()))
1182             bFound = sal_True;
1183         else
1184             ++aDebugItr;
1185     }
1186     sal_Bool bResult2 = (aDebugItr != maZOrderedShapes.end());
1187     DBG_ASSERT((bResult == bResult2) && ((bResult && (rItr == aDebugItr)) || !bResult), "wrong Shape found");
1188 #endif
1189     return bResult;
1190 }
1191 
1192 sal_Int8 ScChildrenShapes::Compare(const ScAccessibleShapeData* pData1,
1193 		const ScAccessibleShapeData* pData2) const
1194 {
1195     ScShapeDataLess aLess;
1196 
1197     sal_Bool bResult1(aLess(pData1, pData2));
1198     sal_Bool bResult2(aLess(pData2, pData1));
1199 
1200 	sal_Int8 nResult(0);
1201     if (!bResult1 && bResult2)
1202         nResult = 1;
1203     else if (bResult1 && !bResult2)
1204         nResult = -1;
1205 
1206 	return nResult;
1207 }
1208 
1209 struct ScVisAreaChanged
1210 {
1211     ScAccessibleDocument* mpAccDoc;
1212     ScVisAreaChanged(ScAccessibleDocument* pAccDoc) : mpAccDoc(pAccDoc) {}
1213 	void operator() (const ScAccessibleShapeData* pAccShapeData) const
1214     {
1215 	    if (pAccShapeData && pAccShapeData->pAccShape)
1216         {
1217             pAccShapeData->pAccShape->ViewForwarderChanged(::accessibility::IAccessibleViewForwarderListener::VISIBLE_AREA, mpAccDoc);
1218         }
1219     }
1220 };
1221 
1222 void ScChildrenShapes::VisAreaChanged() const
1223 {
1224     ScVisAreaChanged aVisAreaChanged(mpAccessibleDocument);
1225     std::for_each(maZOrderedShapes.begin(), maZOrderedShapes.end(), aVisAreaChanged);
1226 }
1227 
1228 // ============================================================================
1229 
1230 ScAccessibleDocument::ScAccessibleDocument(
1231         const uno::Reference<XAccessible>& rxParent,
1232 		ScTabViewShell* pViewShell,
1233 		ScSplitPos eSplitPos)
1234 	: ScAccessibleDocumentBase(rxParent),
1235 	mpViewShell(pViewShell),
1236 	meSplitPos(eSplitPos),
1237 	mpAccessibleSpreadsheet(NULL),
1238     mpChildrenShapes(NULL),
1239     mpTempAccEdit(NULL),
1240 	mbCompleteSheetSelected(sal_False)
1241 {
1242 	if (pViewShell)
1243     {
1244 		pViewShell->AddAccessibilityObject(*this);
1245 	    Window *pWin = pViewShell->GetWindowByPos(eSplitPos);
1246 	    if( pWin )
1247 	    {
1248 		    pWin->AddChildEventListener( LINK( this, ScAccessibleDocument, WindowChildEventListener ));
1249 		    sal_uInt16 nCount =   pWin->GetChildCount();
1250 		    for( sal_uInt16 i=0; i < nCount; ++i )
1251 		    {
1252 			    Window *pChildWin = pWin->GetChild( i );
1253 			    if( pChildWin &&
1254 				    AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() )
1255 				    AddChild( pChildWin->GetAccessible(), sal_False );
1256 		    }
1257 	    }
1258         if (pViewShell->GetViewData()->HasEditView( eSplitPos ))
1259         {
1260             uno::Reference<XAccessible> xAcc = new ScAccessibleEditObject(this, pViewShell->GetViewData()->GetEditView(eSplitPos),
1261                 pViewShell->GetWindowByPos(eSplitPos), GetCurrentCellName(), GetCurrentCellDescription(),
1262                 CellInEditMode);
1263             AddChild(xAcc, sal_False);
1264         }
1265     }
1266     maVisArea = GetVisibleArea_Impl();
1267 }
1268 
1269 void ScAccessibleDocument::Init()
1270 {
1271     if(!mpChildrenShapes)
1272         mpChildrenShapes = new ScChildrenShapes(this, mpViewShell, meSplitPos);
1273 }
1274 
1275 ScAccessibleDocument::~ScAccessibleDocument(void)
1276 {
1277 	if (!ScAccessibleContextBase::IsDefunc() && !rBHelper.bInDispose)
1278 	{
1279 		// increment refcount to prevent double call off dtor
1280 		osl_incrementInterlockedCount( &m_refCount );
1281 		dispose();
1282 	}
1283 }
1284 
1285 void SAL_CALL ScAccessibleDocument::disposing()
1286 {
1287     ScUnoGuard aGuard;
1288 	FreeAccessibleSpreadsheet();
1289 	if (mpViewShell)
1290 	{
1291         Window *pWin = mpViewShell->GetWindowByPos(meSplitPos);
1292 	    if( pWin )
1293 		    pWin->RemoveChildEventListener( LINK( this, ScAccessibleDocument, WindowChildEventListener ));
1294 
1295         mpViewShell->RemoveAccessibilityObject(*this);
1296 		mpViewShell = NULL;
1297 	}
1298     if (mpChildrenShapes)
1299         DELETEZ(mpChildrenShapes);
1300 
1301 	ScAccessibleDocumentBase::disposing();
1302 }
1303 
1304 void SAL_CALL ScAccessibleDocument::disposing( const lang::EventObject& /* Source */ )
1305 		throw (uno::RuntimeException)
1306 {
1307 	disposing();
1308 }
1309 
1310 	//=====  SfxListener  =====================================================
1311 
1312 IMPL_LINK( ScAccessibleDocument, WindowChildEventListener, VclSimpleEvent*, pEvent )
1313 {
1314 	DBG_ASSERT( pEvent && pEvent->ISA( VclWindowEvent ), "Unknown WindowEvent!" );
1315 	if ( pEvent && pEvent->ISA( VclWindowEvent ) )
1316 	{
1317 		VclWindowEvent *pVclEvent = static_cast< VclWindowEvent * >( pEvent );
1318 		DBG_ASSERT( pVclEvent->GetWindow(), "Window???" );
1319 		switch ( pVclEvent->GetId() )
1320 		{
1321         case VCLEVENT_WINDOW_SHOW:  // send create on show for direct accessible children
1322 			{
1323 				Window* pChildWin = static_cast < Window * >( pVclEvent->GetData() );
1324 				if( pChildWin && AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() )
1325 				{
1326 					AddChild( pChildWin->GetAccessible(), sal_True );
1327 				}
1328 			}
1329 			break;
1330         case VCLEVENT_WINDOW_HIDE:  // send destroy on hide for direct accessible children
1331 			{
1332 				Window* pChildWin = static_cast < Window * >( pVclEvent->GetData() );
1333 				if( pChildWin && AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() )
1334 				{
1335 					RemoveChild( pChildWin->GetAccessible(), sal_True );
1336 				}
1337 			}
1338 			break;
1339 		}
1340 	}
1341 	return 0;
1342 }
1343 
1344 void ScAccessibleDocument::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
1345 {
1346 	if (rHint.ISA( ScAccGridWinFocusLostHint ) )
1347 	{
1348 		const ScAccGridWinFocusLostHint& rRef = (const ScAccGridWinFocusLostHint&)rHint;
1349 		if (rRef.GetOldGridWin() == meSplitPos)
1350         {
1351             if (mxTempAcc.is() && mpTempAccEdit)
1352                 mpTempAccEdit->LostFocus();
1353             else if (mpAccessibleSpreadsheet)
1354                 mpAccessibleSpreadsheet->LostFocus();
1355             else
1356                 CommitFocusLost();
1357         }
1358 	}
1359     else if (rHint.ISA( ScAccGridWinFocusGotHint ) )
1360 	{
1361 		const ScAccGridWinFocusGotHint& rRef = (const ScAccGridWinFocusGotHint&)rHint;
1362 		if (rRef.GetNewGridWin() == meSplitPos)
1363         {
1364             if (mxTempAcc.is() && mpTempAccEdit)
1365                 mpTempAccEdit->GotFocus();
1366             else if (mpAccessibleSpreadsheet)
1367                 mpAccessibleSpreadsheet->GotFocus();
1368             else
1369                 CommitFocusGained();
1370         }
1371 	}
1372 	else if (rHint.ISA( SfxSimpleHint ))
1373 	{
1374 		const SfxSimpleHint& rRef = (const SfxSimpleHint&)rHint;
1375 		// only notify if child exist, otherwise it is not necessary
1376 		if ((rRef.GetId() == SC_HINT_ACC_TABLECHANGED) &&
1377 			mpAccessibleSpreadsheet)
1378 		{
1379 			FreeAccessibleSpreadsheet();
1380             if (mpChildrenShapes)
1381                 DELETEZ(mpChildrenShapes);
1382 
1383             // #124567# Accessibility: Shapes / form controls after reload not accessible
1384             if ( !mpChildrenShapes )
1385             {
1386                 mpChildrenShapes = new ScChildrenShapes( this, mpViewShell, meSplitPos );
1387             }
1388 
1389 			AccessibleEventObject aEvent;
1390 			aEvent.EventId = AccessibleEventId::INVALIDATE_ALL_CHILDREN;
1391 			aEvent.Source = uno::Reference< XAccessibleContext >(this);
1392 			CommitChange(aEvent); // all childs changed
1393 		}
1394         else if (rRef.GetId() == SC_HINT_ACC_MAKEDRAWLAYER)
1395         {
1396             if (mpChildrenShapes)
1397                 mpChildrenShapes->SetDrawBroadcaster();
1398         }
1399         else if ((rRef.GetId() == SC_HINT_ACC_ENTEREDITMODE)) // this event comes only on creating edit field of a cell
1400         {
1401             if (mpViewShell && mpViewShell->GetViewData()->HasEditView(meSplitPos))
1402             {
1403                 mpTempAccEdit = new ScAccessibleEditObject(this, mpViewShell->GetViewData()->GetEditView(meSplitPos),
1404                     mpViewShell->GetWindowByPos(meSplitPos), GetCurrentCellName(),
1405                     rtl::OUString(String(ScResId(STR_ACC_EDITLINE_DESCR))), CellInEditMode);
1406                 uno::Reference<XAccessible> xAcc = mpTempAccEdit;
1407 
1408                 AddChild(xAcc, sal_True);
1409 
1410                 if (mpAccessibleSpreadsheet)
1411                     mpAccessibleSpreadsheet->LostFocus();
1412                 else
1413                     CommitFocusLost();
1414 
1415                 mpTempAccEdit->GotFocus();
1416             }
1417         }
1418         else if (rRef.GetId() == SC_HINT_ACC_LEAVEEDITMODE)
1419         {
1420             if (mxTempAcc.is())
1421             {
1422                 if (mpTempAccEdit)
1423                     mpTempAccEdit->LostFocus();
1424 
1425                 mpTempAccEdit = NULL;
1426                 RemoveChild(mxTempAcc, sal_True);
1427 
1428                 if (mpAccessibleSpreadsheet)
1429                     mpAccessibleSpreadsheet->GotFocus();
1430                 else
1431                     CommitFocusGained();
1432             }
1433         }
1434         else if ((rRef.GetId() == SC_HINT_ACC_VISAREACHANGED) || (rRef.GetId() == SC_HINT_ACC_WINDOWRESIZED))
1435         {
1436             Rectangle aOldVisArea(maVisArea);
1437             maVisArea = GetVisibleArea_Impl();
1438 
1439             if (maVisArea != aOldVisArea)
1440             {
1441                 if (maVisArea.GetSize() != aOldVisArea.GetSize())
1442                 {
1443 			        AccessibleEventObject aEvent;
1444 			        aEvent.EventId = AccessibleEventId::BOUNDRECT_CHANGED;
1445 			        aEvent.Source = uno::Reference< XAccessibleContext >(this);
1446 
1447 			        CommitChange(aEvent);
1448 
1449                     if (mpAccessibleSpreadsheet)
1450                         mpAccessibleSpreadsheet->BoundingBoxChanged();
1451                 }
1452                 else if (mpAccessibleSpreadsheet)
1453                 {
1454                     mpAccessibleSpreadsheet->VisAreaChanged();
1455                 }
1456                 if (mpChildrenShapes)
1457                     mpChildrenShapes->VisAreaChanged();
1458             }
1459         }
1460 	}
1461 
1462 	ScAccessibleDocumentBase::Notify(rBC, rHint);
1463 }
1464 
1465 void SAL_CALL ScAccessibleDocument::selectionChanged( const lang::EventObject& /* aEvent */ )
1466 		throw (uno::RuntimeException)
1467 {
1468 	sal_Bool bSelectionChanged(sal_False);
1469 	if (mpAccessibleSpreadsheet)
1470 	{
1471 		sal_Bool bOldSelected(mbCompleteSheetSelected);
1472 		mbCompleteSheetSelected = IsTableSelected();
1473 		if (bOldSelected != mbCompleteSheetSelected)
1474 		{
1475 			mpAccessibleSpreadsheet->CompleteSelectionChanged(mbCompleteSheetSelected);
1476 			bSelectionChanged = sal_True;
1477 		}
1478 	}
1479 
1480     if (mpChildrenShapes && mpChildrenShapes->SelectionChanged())
1481         bSelectionChanged = sal_True;
1482 
1483 	if (bSelectionChanged)
1484 	{
1485 		AccessibleEventObject aEvent;
1486 		aEvent.EventId = AccessibleEventId::SELECTION_CHANGED;
1487 		aEvent.Source = uno::Reference< XAccessibleContext >(this);
1488 
1489 		CommitChange(aEvent);
1490 	}
1491 }
1492 
1493 	//=====  XInterface  =====================================================
1494 
1495 uno::Any SAL_CALL ScAccessibleDocument::queryInterface( uno::Type const & rType )
1496 	throw (uno::RuntimeException)
1497 {
1498 	uno::Any aAny (ScAccessibleDocumentImpl::queryInterface(rType));
1499 	return aAny.hasValue() ? aAny : ScAccessibleContextBase::queryInterface(rType);
1500 }
1501 
1502 void SAL_CALL ScAccessibleDocument::acquire()
1503 	throw ()
1504 {
1505 	ScAccessibleContextBase::acquire();
1506 }
1507 
1508 void SAL_CALL ScAccessibleDocument::release()
1509 	throw ()
1510 {
1511 	ScAccessibleContextBase::release();
1512 }
1513 
1514 	//=====  XAccessibleComponent  ============================================
1515 
1516 uno::Reference< XAccessible > SAL_CALL ScAccessibleDocument::getAccessibleAtPoint(
1517 		const awt::Point& rPoint )
1518 		throw (uno::RuntimeException)
1519 {
1520 	uno::Reference<XAccessible> xAccessible = NULL;
1521     if (containsPoint(rPoint))
1522     {
1523     	ScUnoGuard aGuard;
1524         IsObjectValid();
1525         if (mpChildrenShapes)
1526             xAccessible = mpChildrenShapes->GetAt(rPoint);
1527 	    if(!xAccessible.is())
1528         {
1529             if (mxTempAcc.is())
1530             {
1531                 uno::Reference< XAccessibleContext > xCont(mxTempAcc->getAccessibleContext());
1532                 uno::Reference< XAccessibleComponent > xComp(xCont, uno::UNO_QUERY);
1533                 if (xComp.is())
1534                 {
1535                     Rectangle aBound(VCLRectangle(xComp->getBounds()));
1536                     if (aBound.IsInside(VCLPoint(rPoint)))
1537                         xAccessible = mxTempAcc;
1538                 }
1539             }
1540             if (!xAccessible.is())
1541 		        xAccessible = GetAccessibleSpreadsheet();
1542         }
1543     }
1544 	return xAccessible;
1545 }
1546 
1547 void SAL_CALL ScAccessibleDocument::grabFocus(  )
1548 		throw (uno::RuntimeException)
1549 {
1550 	ScUnoGuard aGuard;
1551     IsObjectValid();
1552 	if (getAccessibleParent().is())
1553 	{
1554 		uno::Reference<XAccessibleComponent> xAccessibleComponent(getAccessibleParent()->getAccessibleContext(), uno::UNO_QUERY);
1555 		if (xAccessibleComponent.is())
1556 		{
1557 			xAccessibleComponent->grabFocus();
1558 			// grab only focus if it does not have the focus and it is not hidden
1559 			if (mpViewShell && mpViewShell->GetViewData() &&
1560 				(mpViewShell->GetViewData()->GetActivePart() != meSplitPos) &&
1561 				mpViewShell->GetWindowByPos(meSplitPos)->IsVisible())
1562 			{
1563 				mpViewShell->ActivatePart(meSplitPos);
1564 			}
1565 		}
1566 	}
1567 }
1568 
1569 	//=====  XAccessibleContext  ==============================================
1570 
1571     ///	Return the number of currently visible children.
1572 sal_Int32 SAL_CALL
1573     ScAccessibleDocument::getAccessibleChildCount(void)
1574     throw (uno::RuntimeException)
1575 {
1576 	ScUnoGuard aGuard;
1577     IsObjectValid();
1578     sal_Int32 nCount(1);
1579     if (mpChildrenShapes)
1580         nCount = mpChildrenShapes->GetCount(); // returns the count of the shapes inclusive the table
1581 
1582     if (mxTempAcc.is())
1583         ++nCount;
1584 
1585 	return nCount;
1586 }
1587 
1588     ///	Return the specified child or NULL if index is invalid.
1589 uno::Reference<XAccessible> SAL_CALL
1590     ScAccessibleDocument::getAccessibleChild(sal_Int32 nIndex)
1591     throw (uno::RuntimeException,
1592 		lang::IndexOutOfBoundsException)
1593 {
1594 	ScUnoGuard aGuard;
1595     IsObjectValid();
1596 	uno::Reference<XAccessible> xAccessible;
1597 	if (nIndex >= 0)
1598 	{
1599         sal_Int32 nCount(1);
1600         if (mpChildrenShapes)
1601         {
1602             xAccessible = mpChildrenShapes->Get(nIndex); // returns NULL if it is the table or out of range
1603             nCount = mpChildrenShapes->GetCount(); //there is always a table
1604         }
1605         if (!xAccessible.is())
1606         {
1607             if (nIndex < nCount)
1608                 xAccessible = GetAccessibleSpreadsheet();
1609             else if (nIndex == nCount && mxTempAcc.is())
1610                 xAccessible = mxTempAcc;
1611         }
1612 	}
1613 
1614     if (!xAccessible.is())
1615         throw lang::IndexOutOfBoundsException();
1616 
1617 	return xAccessible;
1618 }
1619 
1620     ///	Return the set of current states.
1621 uno::Reference<XAccessibleStateSet> SAL_CALL
1622     ScAccessibleDocument::getAccessibleStateSet(void)
1623     throw (uno::RuntimeException)
1624 {
1625 	ScUnoGuard aGuard;
1626 	uno::Reference<XAccessibleStateSet> xParentStates;
1627 	if (getAccessibleParent().is())
1628 	{
1629 		uno::Reference<XAccessibleContext> xParentContext = getAccessibleParent()->getAccessibleContext();
1630 		xParentStates = xParentContext->getAccessibleStateSet();
1631 	}
1632 	utl::AccessibleStateSetHelper* pStateSet = new utl::AccessibleStateSetHelper();
1633 	if (IsDefunc(xParentStates))
1634 		pStateSet->AddState(AccessibleStateType::DEFUNC);
1635     else
1636     {
1637 	    if (IsEditable(xParentStates))
1638 		    pStateSet->AddState(AccessibleStateType::EDITABLE);
1639 	    pStateSet->AddState(AccessibleStateType::ENABLED);
1640 	    pStateSet->AddState(AccessibleStateType::OPAQUE);
1641 	    if (isShowing())
1642 		    pStateSet->AddState(AccessibleStateType::SHOWING);
1643 	    if (isVisible())
1644 		    pStateSet->AddState(AccessibleStateType::VISIBLE);
1645     }
1646 	return pStateSet;
1647 }
1648 
1649 	///=====  XAccessibleSelection  ===========================================
1650 
1651 void SAL_CALL
1652 	ScAccessibleDocument::selectAccessibleChild( sal_Int32 nChildIndex )
1653 		throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
1654 {
1655 	ScUnoGuard aGuard;
1656     IsObjectValid();
1657 
1658     if (mpChildrenShapes)
1659     {
1660         sal_Int32 nCount(mpChildrenShapes->GetCount()); //all shapes and the table
1661         if (mxTempAcc.is())
1662             ++nCount;
1663         if (nChildIndex < 0 || nChildIndex >= nCount)
1664             throw lang::IndexOutOfBoundsException();
1665 
1666         uno::Reference < XAccessible > xAccessible = mpChildrenShapes->Get(nChildIndex);
1667         if (xAccessible.is())
1668         {
1669 		    sal_Bool bWasTableSelected(IsTableSelected());
1670 
1671             if (mpChildrenShapes)
1672                 mpChildrenShapes->Select(nChildIndex); // throws no lang::IndexOutOfBoundsException if Index is to high
1673 
1674 		    if (bWasTableSelected)
1675 			    mpViewShell->SelectAll();
1676         }
1677         else
1678         {
1679 		    if (mpViewShell)
1680 			    mpViewShell->SelectAll();
1681         }
1682     }
1683 }
1684 
1685 sal_Bool SAL_CALL
1686 	ScAccessibleDocument::isAccessibleChildSelected( sal_Int32 nChildIndex )
1687 		throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
1688 {
1689 	ScUnoGuard aGuard;
1690     IsObjectValid();
1691 	sal_Bool bResult(sal_False);
1692 
1693     if (mpChildrenShapes)
1694     {
1695         sal_Int32 nCount(mpChildrenShapes->GetCount()); //all shapes and the table
1696         if (mxTempAcc.is())
1697             ++nCount;
1698         if (nChildIndex < 0 || nChildIndex >= nCount)
1699             throw lang::IndexOutOfBoundsException();
1700 
1701         uno::Reference < XAccessible > xAccessible = mpChildrenShapes->Get(nChildIndex);
1702         if (xAccessible.is())
1703         {
1704 		    uno::Reference<drawing::XShape> xShape;
1705 		    bResult = mpChildrenShapes->IsSelected(nChildIndex, xShape); // throws no lang::IndexOutOfBoundsException if Index is to high
1706         }
1707         else
1708         {
1709             if (mxTempAcc.is() && nChildIndex == nCount)
1710                 bResult = sal_True;
1711             else
1712     		    bResult = IsTableSelected();
1713         }
1714     }
1715 	return bResult;
1716 }
1717 
1718 void SAL_CALL
1719 	ScAccessibleDocument::clearAccessibleSelection(  )
1720 		throw (uno::RuntimeException)
1721 {
1722 	ScUnoGuard aGuard;
1723     IsObjectValid();
1724 
1725     if (mpChildrenShapes)
1726         mpChildrenShapes->DeselectAll(); //deselects all (also the table)
1727 }
1728 
1729 void SAL_CALL
1730 	ScAccessibleDocument::selectAllAccessibleChildren(  )
1731 		throw (uno::RuntimeException)
1732 {
1733 	ScUnoGuard aGuard;
1734     IsObjectValid();
1735 
1736     if (mpChildrenShapes)
1737         mpChildrenShapes->SelectAll();
1738 
1739 	// select table after shapes, because while selecting shapes the table will be deselected
1740 	if (mpViewShell)
1741 	{
1742 		mpViewShell->SelectAll();
1743 	}
1744 }
1745 
1746 sal_Int32 SAL_CALL
1747 	ScAccessibleDocument::getSelectedAccessibleChildCount(  )
1748 		throw (uno::RuntimeException)
1749 {
1750 	ScUnoGuard aGuard;
1751     IsObjectValid();
1752 	sal_Int32 nCount(0);
1753 
1754     if (mpChildrenShapes)
1755         nCount = mpChildrenShapes->GetSelectedCount();
1756 
1757 	if (IsTableSelected())
1758 		++nCount;
1759 
1760     if (mxTempAcc.is())
1761         ++nCount;
1762 
1763 	return nCount;
1764 }
1765 
1766 uno::Reference<XAccessible > SAL_CALL
1767 	ScAccessibleDocument::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex )
1768 		throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
1769 {
1770 	ScUnoGuard aGuard;
1771     IsObjectValid();
1772 	uno::Reference<XAccessible> xAccessible;
1773     if (mpChildrenShapes)
1774     {
1775         sal_Int32 nCount(getSelectedAccessibleChildCount()); //all shapes and the table
1776         if (nSelectedChildIndex < 0 || nSelectedChildIndex >= nCount)
1777             throw lang::IndexOutOfBoundsException();
1778 
1779         sal_Bool bTabMarked(IsTableSelected());
1780 
1781         if (mpChildrenShapes)
1782             xAccessible = mpChildrenShapes->GetSelected(nSelectedChildIndex, bTabMarked); // throws no lang::IndexOutOfBoundsException if Index is to high
1783         if (mxTempAcc.is() && nSelectedChildIndex == nCount - 1)
1784             xAccessible = mxTempAcc;
1785         else if (bTabMarked)
1786             xAccessible = GetAccessibleSpreadsheet();
1787     }
1788 
1789     DBG_ASSERT(xAccessible.is(), "here should always be an accessible object or a exception throwed");
1790 
1791 	return xAccessible;
1792 }
1793 
1794 void SAL_CALL
1795 	ScAccessibleDocument::deselectAccessibleChild( sal_Int32 nChildIndex )
1796 		throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
1797 {
1798 	ScUnoGuard aGuard;
1799     IsObjectValid();
1800 
1801     if (mpChildrenShapes)
1802     {
1803         sal_Int32 nCount(mpChildrenShapes->GetCount()); //all shapes and the table
1804         if (mxTempAcc.is())
1805             ++nCount;
1806         if (nChildIndex < 0 || nChildIndex >= nCount)
1807             throw lang::IndexOutOfBoundsException();
1808 
1809         sal_Bool bTabMarked(IsTableSelected());
1810 
1811         uno::Reference < XAccessible > xAccessible = mpChildrenShapes->Get(nChildIndex);
1812         if (xAccessible.is())
1813         {
1814             if (mpChildrenShapes)
1815                 mpChildrenShapes->Deselect(nChildIndex); // throws no lang::IndexOutOfBoundsException if Index is to high
1816 
1817 		    if (bTabMarked)
1818 			    mpViewShell->SelectAll(); // select the table again
1819         }
1820         else if (bTabMarked)
1821             mpViewShell->Unmark();
1822     }
1823 }
1824 
1825 	//=====  XServiceInfo  ====================================================
1826 
1827 ::rtl::OUString SAL_CALL
1828     ScAccessibleDocument::getImplementationName(void)
1829     throw (uno::RuntimeException)
1830 {
1831 	return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM ("ScAccessibleDocument"));
1832 }
1833 
1834 uno::Sequence< ::rtl::OUString> SAL_CALL
1835 	ScAccessibleDocument::getSupportedServiceNames(void)
1836         throw (uno::RuntimeException)
1837 {
1838 	uno::Sequence< ::rtl::OUString > aSequence = ScAccessibleContextBase::getSupportedServiceNames();
1839     sal_Int32 nOldSize(aSequence.getLength());
1840     aSequence.realloc(nOldSize + 1);
1841     ::rtl::OUString* pNames = aSequence.getArray();
1842 
1843 	pNames[nOldSize] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.AccessibleSpreadsheetDocumentView"));
1844 
1845 	return aSequence;
1846 }
1847 
1848 //=====  XTypeProvider  =======================================================
1849 
1850 uno::Sequence< uno::Type > SAL_CALL ScAccessibleDocument::getTypes()
1851 		throw (uno::RuntimeException)
1852 {
1853 	return comphelper::concatSequences(ScAccessibleDocumentImpl::getTypes(), ScAccessibleContextBase::getTypes());
1854 }
1855 
1856 uno::Sequence<sal_Int8> SAL_CALL
1857 	ScAccessibleDocument::getImplementationId(void)
1858     throw (uno::RuntimeException)
1859 {
1860     ScUnoGuard aGuard;
1861     IsObjectValid();
1862 	static uno::Sequence<sal_Int8> aId;
1863 	if (aId.getLength() == 0)
1864 	{
1865 		aId.realloc (16);
1866 		rtl_createUuid (reinterpret_cast<sal_uInt8 *>(aId.getArray()), 0, sal_True);
1867 	}
1868 	return aId;
1869 }
1870 
1871 ///=====  IAccessibleViewForwarder  ========================================
1872 
1873 sal_Bool ScAccessibleDocument::IsValid (void) const
1874 {
1875     ScUnoGuard aGuard;
1876     IsObjectValid();
1877     return (!ScAccessibleContextBase::IsDefunc() && !rBHelper.bInDispose);
1878 }
1879 
1880 Rectangle ScAccessibleDocument::GetVisibleArea_Impl() const
1881 {
1882     Rectangle aVisRect(GetBoundingBox());
1883 
1884     Point aPoint(mpViewShell->GetViewData()->GetPixPos(meSplitPos)); // returns a negative Point
1885     aPoint.setX(-aPoint.getX());
1886     aPoint.setY(-aPoint.getY());
1887     aVisRect.SetPos(aPoint);
1888 
1889     ScGridWindow* pWin = static_cast<ScGridWindow*>(mpViewShell->GetWindowByPos(meSplitPos));
1890     if (pWin)
1891         aVisRect = pWin->PixelToLogic(aVisRect, pWin->GetDrawMapMode());
1892 
1893     return aVisRect;
1894 }
1895 
1896 Rectangle ScAccessibleDocument::GetVisibleArea() const
1897 {
1898     ScUnoGuard aGuard;
1899     IsObjectValid();
1900     return maVisArea;
1901 }
1902 
1903 Point ScAccessibleDocument::LogicToPixel (const Point& rPoint) const
1904 {
1905     ScUnoGuard aGuard;
1906     IsObjectValid();
1907     Point aPoint;
1908     ScGridWindow* pWin = static_cast<ScGridWindow*>(mpViewShell->GetWindowByPos(meSplitPos));
1909     if (pWin)
1910     {
1911         aPoint = pWin->LogicToPixel(rPoint, pWin->GetDrawMapMode());
1912         aPoint += pWin->GetWindowExtentsRelative(NULL).TopLeft();
1913     }
1914     return aPoint;
1915 }
1916 
1917 Size ScAccessibleDocument::LogicToPixel (const Size& rSize) const
1918 {
1919     ScUnoGuard aGuard;
1920     IsObjectValid();
1921     Size aSize;
1922     ScGridWindow* pWin = static_cast<ScGridWindow*>(mpViewShell->GetWindowByPos(meSplitPos));
1923     if (pWin)
1924         aSize = pWin->LogicToPixel(rSize, pWin->GetDrawMapMode());
1925     return aSize;
1926 }
1927 
1928 Point ScAccessibleDocument::PixelToLogic (const Point& rPoint) const
1929 {
1930     ScUnoGuard aGuard;
1931     IsObjectValid();
1932     Point aPoint;
1933     ScGridWindow* pWin = static_cast<ScGridWindow*>(mpViewShell->GetWindowByPos(meSplitPos));
1934     if (pWin)
1935     {
1936         aPoint -= pWin->GetWindowExtentsRelative(NULL).TopLeft();
1937         aPoint = pWin->PixelToLogic(rPoint, pWin->GetDrawMapMode());
1938     }
1939     return aPoint;
1940 }
1941 
1942 Size ScAccessibleDocument::PixelToLogic (const Size& rSize) const
1943 {
1944     ScUnoGuard aGuard;
1945     IsObjectValid();
1946     Size aSize;
1947     ScGridWindow* pWin = static_cast<ScGridWindow*>(mpViewShell->GetWindowByPos(meSplitPos));
1948     if (pWin)
1949         aSize = pWin->PixelToLogic(rSize, pWin->GetDrawMapMode());
1950     return aSize;
1951 }
1952 
1953     //=====  internal  ========================================================
1954 
1955 utl::AccessibleRelationSetHelper* ScAccessibleDocument::GetRelationSet(const ScAddress* pAddress) const
1956 {
1957     utl::AccessibleRelationSetHelper* pRelationSet = NULL;
1958     if (mpChildrenShapes)
1959         pRelationSet = mpChildrenShapes->GetRelationSet(pAddress);
1960     return pRelationSet;
1961 }
1962 
1963 ::rtl::OUString SAL_CALL
1964     ScAccessibleDocument::createAccessibleDescription(void)
1965     throw (uno::RuntimeException)
1966 {
1967     rtl::OUString sDescription = String(ScResId(STR_ACC_DOC_DESCR));
1968 	return sDescription;
1969 }
1970 
1971 ::rtl::OUString SAL_CALL
1972     ScAccessibleDocument::createAccessibleName(void)
1973     throw (uno::RuntimeException)
1974 {
1975 	ScUnoGuard aGuard;
1976     IsObjectValid();
1977 	rtl::OUString sName = String(ScResId(STR_ACC_DOC_NAME));
1978 	sal_Int32 nNumber(sal_Int32(meSplitPos) + 1);
1979 	sName += rtl::OUString::valueOf(nNumber);
1980 	return sName;
1981 }
1982 
1983 Rectangle ScAccessibleDocument::GetBoundingBoxOnScreen() const
1984 	throw (uno::RuntimeException)
1985 {
1986 	Rectangle aRect;
1987 	if (mpViewShell)
1988 	{
1989 		Window* pWindow = mpViewShell->GetWindowByPos(meSplitPos);
1990 		if (pWindow)
1991 			aRect = pWindow->GetWindowExtentsRelative(NULL);
1992 	}
1993 	return aRect;
1994 }
1995 
1996 Rectangle ScAccessibleDocument::GetBoundingBox() const
1997 	throw (uno::RuntimeException)
1998 {
1999 	Rectangle aRect;
2000 	if (mpViewShell)
2001 	{
2002 		Window* pWindow = mpViewShell->GetWindowByPos(meSplitPos);
2003 		if (pWindow)
2004 			aRect = pWindow->GetWindowExtentsRelative(pWindow->GetAccessibleParentWindow());
2005 	}
2006 	return aRect;
2007 }
2008 
2009 SCTAB ScAccessibleDocument::getVisibleTable() const
2010 {
2011 	SCTAB nVisibleTable(0);
2012 	if (mpViewShell && mpViewShell->GetViewData())
2013 		nVisibleTable = mpViewShell->GetViewData()->GetTabNo();
2014 	return nVisibleTable;
2015 }
2016 
2017 uno::Reference < XAccessible >
2018 	ScAccessibleDocument::GetAccessibleSpreadsheet()
2019 {
2020 	if (!mpAccessibleSpreadsheet && mpViewShell)
2021 	{
2022 		mpAccessibleSpreadsheet = new ScAccessibleSpreadsheet(this, mpViewShell, getVisibleTable(), meSplitPos);
2023 		mpAccessibleSpreadsheet->acquire();
2024 		mpAccessibleSpreadsheet->Init();
2025 		mbCompleteSheetSelected = IsTableSelected();
2026 	}
2027 	return mpAccessibleSpreadsheet;
2028 }
2029 
2030 void ScAccessibleDocument::FreeAccessibleSpreadsheet()
2031 {
2032 	if (mpAccessibleSpreadsheet)
2033 	{
2034 		mpAccessibleSpreadsheet->dispose();
2035 		mpAccessibleSpreadsheet->release();
2036 		mpAccessibleSpreadsheet = NULL;
2037 	}
2038 }
2039 
2040 sal_Bool ScAccessibleDocument::IsTableSelected() const
2041 {
2042 	sal_Bool bResult (sal_False);
2043 	if(mpViewShell)
2044 	{
2045 		SCTAB nTab(getVisibleTable());
2046         //#103800#; use a copy of MarkData
2047         ScMarkData aMarkData(mpViewShell->GetViewData()->GetMarkData());
2048 		aMarkData.MarkToMulti();
2049 		if (aMarkData.IsAllMarked(ScRange(ScAddress(0, 0, nTab),ScAddress(MAXCOL, MAXROW, nTab))))
2050 			bResult = sal_True;
2051 	}
2052 	return bResult;
2053 }
2054 
2055 sal_Bool ScAccessibleDocument::IsDefunc(
2056 	const uno::Reference<XAccessibleStateSet>& rxParentStates)
2057 {
2058 	return ScAccessibleContextBase::IsDefunc() || (mpViewShell == NULL) || !getAccessibleParent().is() ||
2059 		(rxParentStates.is() && rxParentStates->contains(AccessibleStateType::DEFUNC));
2060 }
2061 
2062 sal_Bool ScAccessibleDocument::IsEditable(
2063     const uno::Reference<XAccessibleStateSet>& /* rxParentStates */)
2064 {
2065 	// what is with document protection or readonly documents?
2066 	return sal_True;
2067 }
2068 
2069 void ScAccessibleDocument::AddChild(const uno::Reference<XAccessible>& xAcc, sal_Bool bFireEvent)
2070 {
2071     DBG_ASSERT(!mxTempAcc.is(), "this object should be removed before");
2072     if (xAcc.is())
2073     {
2074         mxTempAcc = xAcc;
2075 		if( bFireEvent )
2076 		{
2077 			AccessibleEventObject aEvent;
2078                         aEvent.Source = uno::Reference<XAccessibleContext>(this);
2079 			aEvent.EventId = AccessibleEventId::CHILD;
2080 			aEvent.NewValue <<= mxTempAcc;
2081 			CommitChange( aEvent );
2082 		}
2083     }
2084 }
2085 
2086 void ScAccessibleDocument::RemoveChild(const uno::Reference<XAccessible>& xAcc, sal_Bool bFireEvent)
2087 {
2088     DBG_ASSERT(mxTempAcc.is(), "this object should be added before");
2089     if (xAcc.is())
2090     {
2091         DBG_ASSERT(xAcc.get() == mxTempAcc.get(), "only the same object should be removed");
2092 		if( bFireEvent )
2093 		{
2094 			AccessibleEventObject aEvent;
2095                         aEvent.Source = uno::Reference<XAccessibleContext>(this);
2096 			aEvent.EventId = AccessibleEventId::CHILD;
2097 			aEvent.OldValue <<= mxTempAcc;
2098 			CommitChange( aEvent );
2099 		}
2100         mxTempAcc = NULL;
2101     }
2102 }
2103 
2104 rtl::OUString ScAccessibleDocument::GetCurrentCellName() const
2105 {
2106 	String sName( ScResId(STR_ACC_CELL_NAME) );
2107     if (mpViewShell)
2108     {
2109 	    String sAddress;
2110 	    // Document not needed, because only the cell address, but not the tablename is needed
2111 	    mpViewShell->GetViewData()->GetCurPos().Format( sAddress, SCA_VALID, NULL );
2112 	    sName.SearchAndReplaceAscii("%1", sAddress);
2113     }
2114     return rtl::OUString(sName);
2115 }
2116 
2117 rtl::OUString ScAccessibleDocument::GetCurrentCellDescription() const
2118 {
2119     return rtl::OUString();
2120 }
2121