xref: /trunk/main/sc/source/ui/Accessibility/AccessibleSpreadsheet.cxx (revision 4d7c9de063a797b8b4f3d45e3561e82ad1f8ef1f)
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_sc.hxx"
26 
27 
28 #include "AccessibleSpreadsheet.hxx"
29 #include "AccessibilityHints.hxx"
30 #include "AccessibleCell.hxx"
31 #include "AccessibleDocument.hxx"
32 #include "tabvwsh.hxx"
33 #include "document.hxx"
34 #include "unoguard.hxx"
35 #include "hints.hxx"
36 #include "scmod.hxx"
37 
38 #ifndef _UTL_ACCESSIBLESTATESETHELPER_HXX
39 #include <unotools/accessiblestatesethelper.hxx>
40 #endif
41 #ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLEROLE_HPP_
42 #include <com/sun/star/accessibility/AccessibleRole.hpp>
43 #endif
44 #ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLESTATETYPE_HPP_
45 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
46 #endif
47 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
48 #include <com/sun/star/accessibility/AccessibleTableModelChangeType.hpp>
49 #include <rtl/uuid.h>
50 #include <tools/debug.hxx>
51 #include <tools/gen.hxx>
52 #include <svtools/colorcfg.hxx>
53 #include "scresid.hxx"
54 #include "sc.hrc"
55 #include <algorithm>
56 
57 using namespace ::com::sun::star;
58 using namespace ::com::sun::star::accessibility;
59 
60 bool CompMinCol(const std::pair<sal_uInt16,sal_uInt16> & pc1,const std::pair<sal_uInt16,sal_uInt16>  &pc2)
61 {
62     return pc1.first < pc2.first;
63 }
64 ScMyAddress ScAccessibleSpreadsheet::CalcScAddressFromRangeList(ScRangeList *pMarkedRanges,sal_Int32 nSelectedChildIndex)
65 {
66     if (pMarkedRanges->Count() <= 1)
67     {
68         ScRange* pRange = pMarkedRanges->First();
69         if (pRange)
70         {
71             // MT IA2: Not used.
72             // const int nRowNum = pRange->aEnd.Row() - pRange->aStart.Row() + 1;
73             const int nColNum = pRange->aEnd.Col() - pRange->aStart.Col() + 1;
74             const int nCurCol = nSelectedChildIndex % nColNum;
75             const int nCurRow = (nSelectedChildIndex - nCurCol)/nColNum;
76             return ScMyAddress(static_cast<SCCOL>(pRange->aStart.Col() + nCurCol), pRange->aStart.Row() + nCurRow, maActiveCell.Tab());
77         }
78     }
79     else
80     {
81         sal_Int32 nMinRow = MAXROW;
82         sal_Int32 nMaxRow = 0;
83         m_vecTempRange.clear();
84         ScRange* pRange = pMarkedRanges->First();
85         while (pRange)
86         {
87             if (pRange->aStart.Tab() != pRange->aEnd.Tab())
88             {
89                 if ((maActiveCell.Tab() >= pRange->aStart.Tab()) ||
90                     maActiveCell.Tab() <= pRange->aEnd.Tab())
91                 {
92                     m_vecTempRange.push_back(pRange);
93                     nMinRow = std::min(pRange->aStart.Row(),nMinRow);
94                     nMaxRow = std::max(pRange->aEnd.Row(),nMaxRow);
95                 }
96                 else
97                     DBG_ERROR("Range of wrong table");
98             }
99             else if(pRange->aStart.Tab() == maActiveCell.Tab())
100             {
101                 m_vecTempRange.push_back(pRange);
102                 nMinRow = std::min(pRange->aStart.Row(),nMinRow);
103                 nMaxRow = std::max(pRange->aEnd.Row(),nMaxRow);
104             }
105             else
106                 DBG_ERROR("Range of wrong table");
107             pRange = pMarkedRanges->Next();
108         }
109         int nCurrentIndex = 0 ;
110         for(sal_Int32 row = nMinRow ; row <= nMaxRow ; ++row)
111         {
112             m_vecTempCol.clear();
113             {
114                 VEC_RANGE::const_iterator vi = m_vecTempRange.begin();
115                 for (; vi < m_vecTempRange.end(); ++vi)
116                 {
117                     ScRange *p = *vi;
118                     if ( row >= p->aStart.Row() && row <= p->aEnd.Row())
119                     {
120                         m_vecTempCol.push_back(std::make_pair(p->aStart.Col(),p->aEnd.Col()));
121                     }
122                 }
123             }
124             std::sort(m_vecTempCol.begin(),m_vecTempCol.end(),CompMinCol);
125             {
126                 VEC_COL::const_iterator vic = m_vecTempCol.begin();
127                 for(; vic != m_vecTempCol.end(); ++vic)
128                 {
129                     const PAIR_COL &pariCol = *vic;
130                     sal_uInt16 nCol = pariCol.second - pariCol.first + 1;
131                     if (nCol + nCurrentIndex > nSelectedChildIndex)
132                     {
133                         return ScMyAddress(static_cast<SCCOL>(pariCol.first + nSelectedChildIndex - nCurrentIndex), row, maActiveCell.Tab());
134                     }
135                     nCurrentIndex += nCol;
136                 }
137             }
138         }
139     }
140     return ScMyAddress(0,0,maActiveCell.Tab());
141 }
142 sal_Bool ScAccessibleSpreadsheet::CalcScRangeDifferenceMax(ScRange *pSrc,ScRange *pDest,int nMax,VEC_MYADDR &vecRet,int &nSize)
143 {
144     //Src Must be :Src > Dest
145     if (pDest->In(*pSrc))
146     {//Here is Src In Dest,Src <= Dest
147         return sal_False;
148     }
149     if (!pDest->Intersects(*pSrc))
150     {
151         int nCellCount = sal_uInt32(pDest->aEnd.Col() - pDest->aStart.Col() + 1)
152             * sal_uInt32(pDest->aEnd.Row() - pDest->aStart.Row() + 1)
153             * sal_uInt32(pDest->aEnd.Tab() - pDest->aStart.Tab() + 1);
154         if (nCellCount + nSize > nMax)
155         {
156             return sal_True;
157         }
158         else if(nCellCount > 0)
159         {
160             nCellCount +=nSize;
161             for (sal_Int32 row = pDest->aStart.Row(); row <=  pDest->aEnd.Row();++row)
162             {
163                 for (sal_uInt16 col = pDest->aStart.Col(); col <=  pDest->aEnd.Col();++col)
164                 {
165                     vecRet.push_back(ScMyAddress(col,row,pDest->aStart.Tab()));
166                 }
167             }
168         }
169         return sal_False;
170     }
171     sal_Int32 nMinRow = pSrc->aStart.Row();
172     sal_Int32 nMaxRow = pSrc->aEnd.Row();
173     for (; nMinRow <= nMaxRow ; ++nMinRow,--nMaxRow)
174     {
175         for (sal_uInt16 col = pSrc->aStart.Col(); col <=  pSrc->aEnd.Col();++col)
176         {
177             if (nSize > nMax)
178             {
179                 return sal_True;
180             }
181             ScMyAddress cell(col,nMinRow,pSrc->aStart.Tab());
182             if(!pDest->In(cell))
183             {//In Src ,Not In Dest
184                 vecRet.push_back(cell);
185                 ++nSize;
186             }
187         }
188         if (nMinRow != nMaxRow)
189         {
190             for (sal_uInt16 col = pSrc->aStart.Col(); col <=  pSrc->aEnd.Col();++col)
191             {
192                 if (nSize > nMax)
193                 {
194                     return sal_True;
195                 }
196                 ScMyAddress cell(col,nMaxRow,pSrc->aStart.Tab());
197                 if(!pDest->In(cell))
198                 {//In Src ,Not In Dest
199                     vecRet.push_back(cell);
200                     ++nSize;
201                 }
202             }
203         }
204     }
205     return sal_False;
206 }
207 //In Src , Not in Dest
208 sal_Bool ScAccessibleSpreadsheet::CalcScRangeListDifferenceMax(ScRangeList *pSrc,ScRangeList *pDest,int nMax,VEC_MYADDR &vecRet)
209 {
210     if (pSrc == NULL || pDest == NULL)
211     {
212         return sal_False;
213     }
214     int nSize =0;
215     if (pDest->GetCellCount() == 0)//if the Dest Rang List is empty
216     {
217         if (pSrc->GetCellCount() > sal_uInt32(nMax))//if the Src Cell count is greater then  nMax
218         {
219             return sal_True;
220         }
221         //now the cell count is less then nMax
222         vecRet.reserve(10);
223         ScRange* pRange = pSrc->First();
224         while (pRange)
225         {
226             for (sal_Int32 row = pRange->aStart.Row(); row <=  pRange->aEnd.Row();++row)
227             {
228                 for (sal_uInt16 col = pRange->aStart.Col(); col <=  pRange->aEnd.Col();++col)
229                 {
230                     vecRet.push_back(ScMyAddress(col,row,pRange->aStart.Tab()));
231                 }
232             }
233             pRange = pSrc->Next();
234         }
235         return sal_False;
236     }
237     //the Dest Rang List is not empty
238     vecRet.reserve(10);
239     ScRange* pRange = pSrc->First();
240     while (pRange)
241     {
242         ScRange* pRangeDest = pDest->First();
243         while (pRangeDest)
244         {
245             if (CalcScRangeDifferenceMax(pRange,pRangeDest,nMax,vecRet,nSize))
246             {
247                 return sal_True;
248             }
249             pRangeDest = pDest->Next();
250         }
251         pRange = pSrc->Next();
252     }
253     return sal_False;
254 }
255 //=====  internal  ============================================================
256 
257 ScAccessibleSpreadsheet::ScAccessibleSpreadsheet(
258         ScAccessibleDocument* pAccDoc,
259         ScTabViewShell* pViewShell,
260         SCTAB nTab,
261         ScSplitPos eSplitPos)
262     :
263     ScAccessibleTableBase (pAccDoc, GetDocument(pViewShell),
264         ScRange(ScAddress(0, 0, nTab),ScAddress(MAXCOL, MAXROW, nTab))),
265     mbIsSpreadsheet( sal_True ),
266     m_bFormulaMode(sal_False),
267     m_bFormulaLastMode(sal_False),
268     m_pAccFormulaCell(NULL),
269     m_nMinX(0),m_nMaxX(0),m_nMinY(0),m_nMaxY(0)
270 {
271     ConstructScAccessibleSpreadsheet( pAccDoc, pViewShell, nTab, eSplitPos );
272 }
273 
274 ScAccessibleSpreadsheet::ScAccessibleSpreadsheet(
275         ScAccessibleSpreadsheet& rParent, const ScRange& rRange ) :
276     ScAccessibleTableBase( rParent.mpAccDoc, rParent.mpDoc, rRange),
277     mbIsSpreadsheet( sal_False )
278 {
279     ConstructScAccessibleSpreadsheet( rParent.mpAccDoc, rParent.mpViewShell, rParent.mnTab, rParent.meSplitPos );
280 }
281 
282 ScAccessibleSpreadsheet::~ScAccessibleSpreadsheet()
283 {
284     if (mpMarkedRanges)
285         delete mpMarkedRanges;
286     //if (mpSortedMarkedCells)
287     //  delete mpSortedMarkedCells;
288     if (mpViewShell)
289         mpViewShell->RemoveAccessibilityObject(*this);
290 }
291 
292 void ScAccessibleSpreadsheet::ConstructScAccessibleSpreadsheet(
293     ScAccessibleDocument* pAccDoc,
294     ScTabViewShell* pViewShell,
295     SCTAB nTab,
296     ScSplitPos eSplitPos)
297 {
298     mpViewShell = pViewShell;
299     mpMarkedRanges = 0;
300     mpSortedMarkedCells = 0;
301     mpAccDoc = pAccDoc;
302     mpAccCell = 0;
303     meSplitPos = eSplitPos;
304     mnTab = nTab;
305     mbHasSelection = sal_False;
306     mbDelIns = sal_False;
307     mbIsFocusSend = sal_False;
308     maVisCells = GetVisCells(GetVisArea(mpViewShell, meSplitPos));
309     if (mpViewShell)
310     {
311         mpViewShell->AddAccessibilityObject(*this);
312 
313         const ScViewData& rViewData = *mpViewShell->GetViewData();
314         const ScMarkData& rMarkData = rViewData.GetMarkData();
315         maActiveCell = rViewData.GetCurPos();
316         mbHasSelection = rMarkData.GetTableSelect(maActiveCell.Tab()) &&
317                     (rMarkData.IsMarked() || rMarkData.IsMultiMarked());
318         mpAccCell = GetAccessibleCellAt(maActiveCell.Row(), maActiveCell.Col());
319         mpAccCell->acquire();
320         mpAccCell->Init();
321         ScDocument* pScDoc= GetDocument(mpViewShell);
322         if (pScDoc)
323         {
324             pScDoc->GetName( maActiveCell.Tab(), m_strOldTabName );
325         }
326     }
327 }
328 
329 void SAL_CALL ScAccessibleSpreadsheet::disposing()
330 {
331     ScUnoGuard aGuard;
332     if (mpViewShell)
333     {
334         mpViewShell->RemoveAccessibilityObject(*this);
335         mpViewShell = NULL;
336     }
337     if (mpAccCell)
338     {
339         mpAccCell->release();
340         mpAccCell = NULL;
341     }
342 
343     ScAccessibleTableBase::disposing();
344 }
345 
346 void ScAccessibleSpreadsheet::CompleteSelectionChanged(sal_Bool bNewState)
347 {
348     if (IsFormulaMode())
349     {
350         return ;
351     }
352     if (mpMarkedRanges)
353         DELETEZ(mpMarkedRanges);
354     //if (mpSortedMarkedCells)
355     //  DELETEZ(mpSortedMarkedCells);
356     mbHasSelection = bNewState;
357 
358     AccessibleEventObject aEvent;
359     aEvent.EventId = AccessibleEventId::STATE_CHANGED;
360     if (bNewState)
361         aEvent.NewValue = uno::makeAny(AccessibleStateType::SELECTED);
362     else
363         aEvent.OldValue = uno::makeAny(AccessibleStateType::SELECTED);
364     aEvent.Source = uno::Reference< XAccessibleContext >(this);
365 
366     CommitChange(aEvent);
367 }
368 
369 void ScAccessibleSpreadsheet::LostFocus()
370 {
371     AccessibleEventObject aEvent;
372     aEvent.EventId = AccessibleEventId::ACTIVE_DESCENDANT_CHANGED;
373     aEvent.Source = uno::Reference< XAccessibleContext >(this);
374     uno::Reference< XAccessible > xOld = mpAccCell;
375     aEvent.OldValue <<= xOld;
376 
377     CommitChange(aEvent);
378 
379     CommitFocusLost();
380 }
381 
382 void ScAccessibleSpreadsheet::GotFocus()
383 {
384     //CommitFocusGained();
385     AccessibleEventObject aEvent;
386     aEvent.EventId = AccessibleEventId::ACTIVE_DESCENDANT_CHANGED;
387     aEvent.Source = uno::Reference< XAccessibleContext >(this);
388     //uno::Reference< XAccessible > xNew = mpAccCell;
389     uno::Reference< XAccessible > xNew;
390     if (IsFormulaMode())
391     {
392         if (!m_pAccFormulaCell || !m_bFormulaLastMode)
393         {
394             ScAddress aFormulaAddr;
395             if(!GetFormulaCurrentFocusCell(aFormulaAddr))
396             {
397                 return;
398             }
399             m_pAccFormulaCell = GetAccessibleCellAt(aFormulaAddr.Row(),aFormulaAddr.Col());
400 
401             m_pAccFormulaCell->acquire();
402             m_pAccFormulaCell->Init();
403 
404 
405         }
406         xNew = m_pAccFormulaCell;
407     }
408     else
409     {
410         if(mpAccCell->GetCellAddress() == maActiveCell)
411         {
412             xNew = mpAccCell;
413         }
414         else
415         {
416             CommitFocusCell(maActiveCell);
417             return ;
418         }
419     }
420     aEvent.NewValue <<= xNew;
421 
422     CommitChange(aEvent);
423 }
424 
425 void ScAccessibleSpreadsheet::BoundingBoxChanged()
426 {
427     AccessibleEventObject aEvent;
428     aEvent.EventId = AccessibleEventId::BOUNDRECT_CHANGED;
429     aEvent.Source = uno::Reference< XAccessibleContext >(this);
430 
431     CommitChange(aEvent);
432 }
433 
434 void ScAccessibleSpreadsheet::VisAreaChanged()
435 {
436     AccessibleEventObject aEvent;
437     aEvent.EventId = AccessibleEventId::VISIBLE_DATA_CHANGED;
438     aEvent.Source = uno::Reference< XAccessibleContext >(this);
439 
440     CommitChange(aEvent);
441 }
442 
443     //=====  SfxListener  =====================================================
444 
445 void ScAccessibleSpreadsheet::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
446 {
447     if (rHint.ISA( SfxSimpleHint ) )
448     {
449         const SfxSimpleHint& rRef = (const SfxSimpleHint&)rHint;
450         // only notify if child exist, otherwise it is not necessary
451         //if ((rRef.GetId() == SC_HINT_ACC_CURSORCHANGED))
452         //{
453         //  if (mpViewShell)
454         //  {
455         //      ScAddress aNewCell = mpViewShell->GetViewData()->GetCurPos();
456         //      sal_Bool bNewMarked(mpViewShell->GetViewData()->GetMarkData().GetTableSelect(aNewCell.Tab()) &&
457         //          (mpViewShell->GetViewData()->GetMarkData().IsMarked() ||
458         //          mpViewShell->GetViewData()->GetMarkData().IsMultiMarked()));
459         //      sal_Bool bNewCellSelected(isAccessibleSelected(aNewCell.Row(), aNewCell.Col()));
460         //      if ((bNewMarked != mbHasSelection) ||
461         //          (!bNewCellSelected && bNewMarked) ||
462         //          (bNewCellSelected && mbHasSelection))
463         //      {
464         //          if (mpMarkedRanges)
465         //              DELETEZ(mpMarkedRanges);
466         //          if (mpSortedMarkedCells)
467         //              DELETEZ(mpSortedMarkedCells);
468         //          AccessibleEventObject aEvent;
469         //          aEvent.EventId = AccessibleEventId::SELECTION_CHANGED;
470         //          aEvent.Source = uno::Reference< XAccessibleContext >(this);
471 
472         //          mbHasSelection = bNewMarked;
473 
474         //          CommitChange(aEvent);
475         //      }
476 
477   //              // active descendant changed event (new cell selected)
478   //              bool bFireActiveDescChanged = (aNewCell != maActiveCell) &&
479   //                  (aNewCell.Tab() == maActiveCell.Tab()) && IsFocused();
480 
481   //              /*  Remember old active cell and set new active cell.
482   //                  #i82409# always update the class members mpAccCell and
483   //                  maActiveCell, even if the sheet is not focused, e.g. when
484   //                  using the name box in the toolbar. */
485   //              uno::Reference< XAccessible > xOld = mpAccCell;
486   //              mpAccCell->release();
487   //              mpAccCell = GetAccessibleCellAt(aNewCell.Row(), aNewCell.Col());
488   //              mpAccCell->acquire();
489   //              mpAccCell->Init();
490   //              uno::Reference< XAccessible > xNew = mpAccCell;
491   //              maActiveCell = aNewCell;
492 
493   //              // #i14108# fire event only if sheet is focused
494   //              if( bFireActiveDescChanged )
495   //              {
496   //                  AccessibleEventObject aEvent;
497   //                  aEvent.EventId = AccessibleEventId::ACTIVE_DESCENDANT_CHANGED;
498   //                  aEvent.Source = uno::Reference< XAccessibleContext >(this);
499   //                  aEvent.OldValue <<= xOld;
500   //                  aEvent.NewValue <<= xNew;
501         //          CommitChange(aEvent);
502   //              }
503         //  }
504         //}
505         //else if ((rRef.GetId() == SC_HINT_DATACHANGED))
506         //{
507         //  if (!mbDelIns)
508         //      CommitTableModelChange(maRange.aStart.Row(), maRange.aStart.Col(), maRange.aEnd.Row(), maRange.aEnd.Col(), AccessibleTableModelChangeType::UPDATE);
509         //  else
510         //      mbDelIns = sal_False;
511         //}
512         if ((rRef.GetId() == SC_HINT_ACC_CURSORCHANGED))
513         {
514             if (mpViewShell)
515             {
516                 ScViewData *pViewData = mpViewShell->GetViewData();
517 
518                 m_bFormulaMode = pViewData->IsRefMode() || SC_MOD()->IsFormulaMode();
519                 if ( m_bFormulaMode )
520                 {
521                     NotifyRefMode();
522                     m_bFormulaLastMode = true;
523                     return ;
524                 }
525                 if (m_bFormulaLastMode)
526                 {//Last Notify Mode  Is Formula Mode.
527                     m_vecFormulaLastMyAddr.clear();
528                     RemoveFormulaSelection(sal_True);
529                     if(m_pAccFormulaCell)
530                     {
531                         m_pAccFormulaCell->release();
532                         m_pAccFormulaCell =NULL;
533                     }
534                     //Remove All Selection
535                 }
536                 m_bFormulaLastMode = m_bFormulaMode;
537 
538                 AccessibleEventObject aEvent;
539                 aEvent.Source = uno::Reference< XAccessible >(this);
540                 ScAddress aNewCell = pViewData->GetCurPos();
541                 if(aNewCell.Tab() != maActiveCell.Tab())
542                 {
543                     aEvent.EventId = AccessibleEventId::PAGE_CHANGED;
544                     ScAccessibleDocument *pAccDoc =
545                         static_cast<ScAccessibleDocument*>(getAccessibleParent().get());
546                     if(pAccDoc)
547                     {
548                         pAccDoc->CommitChange(aEvent);
549                     }
550                 }
551                 sal_Bool bNewPosCell = (aNewCell != maActiveCell);
552                 sal_Bool bNewPosCellFocus=sal_False;
553                 if ( bNewPosCell && IsFocused() && aNewCell.Tab() == maActiveCell.Tab() )
554                 {//single Focus
555                     bNewPosCellFocus=sal_True;
556                 }
557                 ScMarkData &refScMarkData = pViewData->GetMarkData();
558                 // MT IA2: Not used
559                 // int nSelCount = refScMarkData.GetSelectCount();
560                 sal_Bool bIsMark =refScMarkData.IsMarked();
561                 sal_Bool bIsMultMark = refScMarkData.IsMultiMarked();
562                 sal_Bool bNewMarked = refScMarkData.GetTableSelect(aNewCell.Tab()) && ( bIsMark || bIsMultMark );
563 //              sal_Bool bNewCellSelected = isAccessibleSelected(aNewCell.Row(), aNewCell.Col());
564                 sal_uInt16 nTab = pViewData->GetTabNo();
565                 ScRange aMarkRange;
566                 refScMarkData.GetMarkArea(aMarkRange);
567                 aEvent.OldValue <<= ::com::sun::star::uno::Any();
568                 //Mark All
569                 if ( !bNewPosCellFocus &&
570                     (bNewMarked || bIsMark || bIsMultMark ) &&
571                     aMarkRange == ScRange( 0,0,nTab, MAXCOL,MAXROW,nTab ) )
572                 {
573                     aEvent.EventId = AccessibleEventId::SELECTION_CHANGED_WITHIN;
574                     aEvent.NewValue <<= ::com::sun::star::uno::Any();
575                     CommitChange(aEvent);
576                     return ;
577                 }
578                 if (!mpMarkedRanges)
579                 {
580                     mpMarkedRanges = new ScRangeList();
581                 }
582                 refScMarkData.FillRangeListWithMarks(mpMarkedRanges, sal_True);
583 
584                 //For Whole Col Row
585                 sal_Bool bWholeRow = ::labs(aMarkRange.aStart.Row() - aMarkRange.aEnd.Row()) == MAXROW ;
586                 sal_Bool bWholeCol = ::abs(aMarkRange.aStart.Col() - aMarkRange.aEnd.Col()) == MAXCOL ;
587                 if ((bNewMarked || bIsMark || bIsMultMark ) && (bWholeCol || bWholeRow))
588                 {
589                     if ( aMarkRange != m_aLastWithInMarkRange )
590                     {
591                         RemoveSelection(refScMarkData);
592                         if(bNewPosCell)
593                         {
594                             CommitFocusCell(aNewCell);
595                         }
596                         sal_Bool bLastIsWholeColRow =
597                         ::labs(m_aLastWithInMarkRange.aStart.Row() - m_aLastWithInMarkRange.aEnd.Row()) == MAXROW && bWholeRow ||
598                         ::abs(m_aLastWithInMarkRange.aStart.Col() - m_aLastWithInMarkRange.aEnd.Col()) == MAXCOL && bWholeCol ;
599                         sal_Bool bSelSmaller=
600                             bLastIsWholeColRow &&
601                             !aMarkRange.In(m_aLastWithInMarkRange) &&
602                             aMarkRange.Intersects(m_aLastWithInMarkRange);
603                         if( !bSelSmaller )
604                         {
605                             aEvent.EventId = AccessibleEventId::SELECTION_CHANGED_WITHIN;
606                             aEvent.NewValue <<= ::com::sun::star::uno::Any();
607                             CommitChange(aEvent);
608                         }
609                         m_aLastWithInMarkRange = aMarkRange;
610                     }
611                     return ;
612                 }
613                 m_aLastWithInMarkRange = aMarkRange;
614                 int nNewMarkCount = mpMarkedRanges->GetCellCount();
615                 sal_Bool bSendSingle= (0 == nNewMarkCount) && bNewPosCell;
616                 if (bSendSingle)
617                 {
618                     RemoveSelection(refScMarkData);
619                     if(bNewPosCellFocus)
620                     {
621                         CommitFocusCell(aNewCell);
622                     }
623                     uno::Reference< XAccessible > xChild ;
624                     if (bNewPosCellFocus)
625                     {
626                         xChild = mpAccCell;
627                     }
628                     else
629                     {
630                         xChild = getAccessibleCellAt(aNewCell.Row(),aNewCell.Col());
631 
632                         maActiveCell = aNewCell;
633                         aEvent.EventId = AccessibleEventId::ACTIVE_DESCENDANT_CHANGED_NOFOCUS;
634                         aEvent.NewValue <<= xChild;
635                         aEvent.OldValue <<= uno::Reference< XAccessible >();
636                         CommitChange(aEvent);
637                     }
638                     aEvent.EventId = AccessibleEventId::SELECTION_CHANGED;
639                     aEvent.NewValue <<= xChild;
640                     CommitChange(aEvent);
641                     OSL_ASSERT(m_mapSelectionSend.count(aNewCell) == 0 );
642                     m_mapSelectionSend.insert(MAP_ADDR_XACC::value_type(aNewCell,xChild));
643 
644                 }
645                 else
646                 {
647                     ScRange aDelRange;
648                     sal_Bool bIsDel = pViewData->GetDelMark( aDelRange );
649                     if ( (!bIsDel || (bIsDel && aMarkRange != aDelRange)) &&
650                         bNewMarked &&
651                         nNewMarkCount > 0 &&
652                         !IsSameMarkCell() )
653                     {
654                         RemoveSelection(refScMarkData);
655                         if(bNewPosCellFocus)
656                         {
657                             CommitFocusCell(aNewCell);
658                         }
659                         VEC_MYADDR vecNew;
660                         if(CalcScRangeListDifferenceMax(mpMarkedRanges,&m_LastMarkedRanges,10,vecNew))
661                         {
662                             aEvent.EventId = AccessibleEventId::SELECTION_CHANGED_WITHIN;
663                             aEvent.NewValue <<= ::com::sun::star::uno::Any();
664                             CommitChange(aEvent);
665                         }
666                         else
667                         {
668                             VEC_MYADDR::iterator viAddr = vecNew.begin();
669                             for(; viAddr < vecNew.end() ; ++viAddr )
670                             {
671                                 uno::Reference< XAccessible > xChild = getAccessibleCellAt(viAddr->Row(),viAddr->Col());
672                                 if (!(bNewPosCellFocus && *viAddr == aNewCell) )
673                                 {
674                                     aEvent.EventId = AccessibleEventId::ACTIVE_DESCENDANT_CHANGED_NOFOCUS;
675                                     aEvent.NewValue <<= xChild;
676                                     CommitChange(aEvent);
677                                 }
678                                 aEvent.EventId = AccessibleEventId::SELECTION_CHANGED_ADD;
679                                 aEvent.NewValue <<= xChild;
680                                 CommitChange(aEvent);
681                                 m_mapSelectionSend.insert(MAP_ADDR_XACC::value_type(*viAddr,xChild));
682                             }
683                         }
684                     }
685                 }
686                 if (bNewPosCellFocus && maActiveCell != aNewCell)
687                 {
688                     CommitFocusCell(aNewCell);
689                 }
690                 m_LastMarkedRanges = *mpMarkedRanges;
691             }
692         }
693         else if ((rRef.GetId() == SC_HINT_DATACHANGED))
694         {
695             if (!mbDelIns)
696                 CommitTableModelChange(maRange.aStart.Row(), maRange.aStart.Col(), maRange.aEnd.Row(), maRange.aEnd.Col(), AccessibleTableModelChangeType::UPDATE);
697             else
698                 mbDelIns = sal_False;
699             ScViewData *pViewData = mpViewShell->GetViewData();
700             ScAddress aNewCell = pViewData->GetCurPos();
701             if( maActiveCell == aNewCell)
702             {
703                 ScDocument* pScDoc= GetDocument(mpViewShell);
704                 if (pScDoc)
705                 {
706                     String valStr;
707                     pScDoc->GetString(aNewCell.Col(),aNewCell.Row(),aNewCell.Tab(), valStr);
708                     if(m_strCurCellValue != valStr)
709                     {
710                         AccessibleEventObject aEvent;
711                         aEvent.EventId = AccessibleEventId::VALUE_CHANGED;
712                         mpAccCell->CommitChange(aEvent);
713                         m_strCurCellValue=valStr;
714                     }
715                     String tabName;
716                     pScDoc->GetName( maActiveCell.Tab(), tabName );
717                     if( m_strOldTabName != tabName )
718                     {
719                         AccessibleEventObject aEvent;
720                         aEvent.EventId = AccessibleEventId::NAME_CHANGED;
721                         String sOldName(ScResId(STR_ACC_TABLE_NAME));
722                         sOldName.SearchAndReplaceAscii("%1", m_strOldTabName);
723                         aEvent.OldValue <<= ::rtl::OUString( sOldName );
724                         String sNewName(ScResId(STR_ACC_TABLE_NAME));
725                         sNewName.SearchAndReplaceAscii("%1", tabName);
726                         aEvent.NewValue <<= ::rtl::OUString( sNewName );
727                         CommitChange( aEvent );
728                         m_strOldTabName = tabName;
729                     }
730                 }
731             }
732         }
733         // no longer needed, because the document calls the VisAreaChanged method
734 /*      else if (rRef.GetId() == SC_HINT_ACC_VISAREACHANGED)
735         {
736             AccessibleEventObject aEvent;
737             aEvent.EventId = AccessibleEventId::VISIBLE_DATA_CHANGED;
738             aEvent.Source = uno::Reference< XAccessibleContext >(this);
739 
740             CommitChange(aEvent);*/
741         // commented out, because to use a ModelChangeEvent is not the right way
742         // at the moment there is no way, but the Java/Gnome Api should be extended sometime
743 /*          if (mpViewShell)
744             {
745                 Rectangle aNewVisCells(GetVisCells(GetVisArea(mpViewShell, meSplitPos)));
746 
747                 Rectangle aNewPos(aNewVisCells);
748 
749                 if (aNewVisCells.IsOver(maVisCells))
750                     aNewPos.Union(maVisCells);
751                 else
752                     CommitTableModelChange(maVisCells.Top(), maVisCells.Left(), maVisCells.Bottom(), maVisCells.Right(), AccessibleTableModelChangeType::UPDATE);
753 
754                 maVisCells = aNewVisCells;
755 
756                 CommitTableModelChange(aNewPos.Top(), aNewPos.Left(), aNewPos.Bottom(), aNewPos.Right(), AccessibleTableModelChangeType::UPDATE);
757             }
758         }*/
759         // no longer needed, because the document calls the BoundingBoxChanged method
760 /*        else if (rRef.GetId() == SC_HINT_ACC_WINDOWRESIZED)
761         {
762             AccessibleEventObject aEvent;
763             aEvent.EventId = AccessibleEventId::BOUNDRECT_CHANGED;
764             aEvent.Source = uno::Reference< XAccessibleContext >(this);
765 
766             CommitChange(aEvent);
767         }*/
768     }
769     else if (rHint.ISA( ScUpdateRefHint ))
770     {
771         const ScUpdateRefHint& rRef = (const ScUpdateRefHint&)rHint;
772         if (rRef.GetMode() == URM_INSDEL && rRef.GetDz() == 0) //#107250# test whether table is inserted or deleted
773         {
774             if (((rRef.GetRange().aStart.Col() == maRange.aStart.Col()) &&
775                 (rRef.GetRange().aEnd.Col() == maRange.aEnd.Col())) ||
776                 ((rRef.GetRange().aStart.Row() == maRange.aStart.Row()) &&
777                 (rRef.GetRange().aEnd.Row() == maRange.aEnd.Row())))
778             {
779                 // ignore next SC_HINT_DATACHANGED notification
780                 mbDelIns = sal_True;
781 
782                 sal_Int16 nId(0);
783                 SCsCOL nX(rRef.GetDx());
784                 SCsROW nY(rRef.GetDy());
785                 ScRange aRange(rRef.GetRange());
786                 if ((nX < 0) || (nY < 0))
787                 {
788                     DBG_ASSERT(!((nX < 0) && (nY < 0)), "should not be possible to remove row and column at the same time");
789                     nId = AccessibleTableModelChangeType::DELETE;
790                     if (nX < 0)
791                     {
792                         nX = -nX;
793                         nY = aRange.aEnd.Row() - aRange.aStart.Row();
794                     }
795                     else
796                     {
797                         nY = -nY;
798                         nX = aRange.aEnd.Col() - aRange.aStart.Col();
799                     }
800                 }
801                 else if ((nX > 0) || (nY > 0))
802                 {
803                     DBG_ASSERT(!((nX > 0) && (nY > 0)), "should not be possible to add row and column at the same time");
804                     nId = AccessibleTableModelChangeType::INSERT;
805                     if (nX < 0)
806                         nY = aRange.aEnd.Row() - aRange.aStart.Row();
807                     else
808                         nX = aRange.aEnd.Col() - aRange.aStart.Col();
809                 }
810                 else
811                 {
812                     DBG_ERROR("is it a deletion or a insertion?");
813                 }
814 
815                 CommitTableModelChange(rRef.GetRange().aStart.Row(),
816                     rRef.GetRange().aStart.Col(),
817                     rRef.GetRange().aStart.Row() + nY,
818                     rRef.GetRange().aStart.Col() + nX, nId);
819 
820                 AccessibleEventObject aEvent;
821                 aEvent.EventId = AccessibleEventId::ACTIVE_DESCENDANT_CHANGED;
822                 aEvent.Source = uno::Reference< XAccessibleContext >(this);
823                 uno::Reference< XAccessible > xNew = mpAccCell;
824                 aEvent.NewValue <<= xNew;
825 
826                 CommitChange(aEvent);
827             }
828         }
829     }
830 
831     ScAccessibleTableBase::Notify(rBC, rHint);
832 }
833 void ScAccessibleSpreadsheet::RemoveSelection(ScMarkData &refScMarkData)
834 {
835     AccessibleEventObject aEvent;
836     aEvent.Source = uno::Reference< XAccessible >(this);
837     aEvent.OldValue <<= ::com::sun::star::uno::Any();
838     MAP_ADDR_XACC::iterator miRemove = m_mapSelectionSend.begin();
839     for(;  miRemove != m_mapSelectionSend.end() ;)
840     {
841         if (refScMarkData.IsCellMarked(miRemove->first.Col(),miRemove->first.Row(),sal_True) ||
842             refScMarkData.IsCellMarked(miRemove->first.Col(),miRemove->first.Row(),sal_False) )
843         {
844             ++miRemove;
845             continue;
846         }
847         aEvent.EventId = AccessibleEventId::SELECTION_CHANGED_REMOVE;
848         aEvent.NewValue <<= miRemove->second;
849         CommitChange(aEvent);
850         MAP_ADDR_XACC::iterator miNext = miRemove;
851         ++miNext;
852         m_mapSelectionSend.erase(miRemove);
853         miRemove = miNext;
854     }
855 }
856 void ScAccessibleSpreadsheet::CommitFocusCell(const ScAddress &aNewCell)
857 {
858     OSL_ASSERT(!IsFormulaMode());
859     if(IsFormulaMode())
860     {
861         return ;
862     }
863     AccessibleEventObject aEvent;
864     aEvent.EventId = AccessibleEventId::ACTIVE_DESCENDANT_CHANGED;
865     aEvent.Source = uno::Reference< XAccessible >(this);
866     uno::Reference< XAccessible > xOld = mpAccCell;
867     mpAccCell->release();
868     mpAccCell=NULL;
869     aEvent.OldValue <<= xOld;
870     mpAccCell = GetAccessibleCellAt(aNewCell.Row(), aNewCell.Col());
871     mpAccCell->acquire();
872     mpAccCell->Init();
873     uno::Reference< XAccessible > xNew = mpAccCell;
874     aEvent.NewValue <<= xNew;
875     maActiveCell = aNewCell;
876     ScDocument* pScDoc= GetDocument(mpViewShell);
877     if (pScDoc)
878     {
879         pScDoc->GetString(maActiveCell.Col(),maActiveCell.Row(),maActiveCell.Tab(), m_strCurCellValue);
880     }
881     CommitChange(aEvent);
882 }
883 sal_Bool ScAccessibleSpreadsheet::IsSameMarkCell()
884 {
885     return m_LastMarkedRanges == *mpMarkedRanges;
886 }
887     //=====  XAccessibleTable  ================================================
888 
889 uno::Reference< XAccessibleTable > SAL_CALL ScAccessibleSpreadsheet::getAccessibleRowHeaders(  )
890                     throw (uno::RuntimeException)
891 {
892     ScUnoGuard aGuard;
893     IsObjectValid();
894     uno::Reference< XAccessibleTable > xAccessibleTable;
895     if( mpDoc && mbIsSpreadsheet )
896     {
897         if( const ScRange* pRowRange = mpDoc->GetRepeatRowRange( mnTab ) )
898         {
899             SCROW nStart = pRowRange->aStart.Row();
900             SCROW nEnd = pRowRange->aEnd.Row();
901             if( (0 <= nStart) && (nStart <= nEnd) && (nEnd <= MAXROW) )
902                 xAccessibleTable.set( new ScAccessibleSpreadsheet( *this, ScRange( 0, nStart, mnTab, MAXCOL, nEnd, mnTab ) ) );
903         }
904     }
905     return xAccessibleTable;
906 }
907 
908 uno::Reference< XAccessibleTable > SAL_CALL ScAccessibleSpreadsheet::getAccessibleColumnHeaders(  )
909                     throw (uno::RuntimeException)
910 {
911     ScUnoGuard aGuard;
912     IsObjectValid();
913     uno::Reference< XAccessibleTable > xAccessibleTable;
914     if( mpDoc && mbIsSpreadsheet )
915     {
916         if( const ScRange* pColRange = mpDoc->GetRepeatColRange( mnTab ) )
917         {
918             SCCOL nStart = pColRange->aStart.Col();
919             SCCOL nEnd = pColRange->aEnd.Col();
920             if( (0 <= nStart) && (nStart <= nEnd) && (nEnd <= MAXCOL) )
921                 xAccessibleTable.set( new ScAccessibleSpreadsheet( *this, ScRange( nStart, 0, mnTab, nEnd, MAXROW, mnTab ) ) );
922         }
923     }
924     return xAccessibleTable;
925 }
926 
927 uno::Sequence< sal_Int32 > SAL_CALL ScAccessibleSpreadsheet::getSelectedAccessibleRows(  )
928                     throw (uno::RuntimeException)
929 {
930     ScUnoGuard aGuard;
931     IsObjectValid();
932     uno::Sequence<sal_Int32> aSequence;
933     if (IsFormulaMode())
934     {
935         return aSequence;
936     }
937     if (mpViewShell && mpViewShell->GetViewData())
938     {
939         aSequence.realloc(maRange.aEnd.Row() - maRange.aStart.Row() + 1);
940         const ScMarkData& rMarkdata = mpViewShell->GetViewData()->GetMarkData();
941         sal_Int32* pSequence = aSequence.getArray();
942         sal_Int32 nCount(0);
943         for (SCROW i = maRange.aStart.Row(); i <= maRange.aEnd.Row(); ++i)
944         {
945             if (rMarkdata.IsRowMarked(i))
946             {
947                 pSequence[nCount] = i;
948                 ++nCount;
949             }
950         }
951         aSequence.realloc(nCount);
952     }
953     else
954         aSequence.realloc(0);
955     return aSequence;
956 }
957 
958 uno::Sequence< sal_Int32 > SAL_CALL ScAccessibleSpreadsheet::getSelectedAccessibleColumns(  )
959                     throw (uno::RuntimeException)
960 {
961     ScUnoGuard aGuard;
962     IsObjectValid();
963     uno::Sequence<sal_Int32> aSequence;
964     if (IsFormulaMode())
965     {
966         return aSequence;
967     }
968     if (mpViewShell && mpViewShell->GetViewData())
969     {
970         aSequence.realloc(maRange.aEnd.Col() - maRange.aStart.Col() + 1);
971         const ScMarkData& rMarkdata = mpViewShell->GetViewData()->GetMarkData();
972         sal_Int32* pSequence = aSequence.getArray();
973         sal_Int32 nCount(0);
974         for (SCCOL i = maRange.aStart.Col(); i <= maRange.aEnd.Col(); ++i)
975         {
976             if (rMarkdata.IsColumnMarked(i))
977             {
978                 pSequence[nCount] = i;
979                 ++nCount;
980             }
981         }
982         aSequence.realloc(nCount);
983     }
984     else
985         aSequence.realloc(0);
986     return aSequence;
987 }
988 
989 sal_Bool SAL_CALL ScAccessibleSpreadsheet::isAccessibleRowSelected( sal_Int32 nRow )
990     throw (uno::RuntimeException, lang::IndexOutOfBoundsException)
991 {
992     ScUnoGuard aGuard;
993     IsObjectValid();
994     if (IsFormulaMode())
995     {
996         return sal_False;
997     }
998 
999     if ((nRow > (maRange.aEnd.Row() - maRange.aStart.Row())) || (nRow < 0))
1000         throw lang::IndexOutOfBoundsException();
1001 
1002     sal_Bool bResult(sal_False);
1003     if (mpViewShell && mpViewShell->GetViewData())
1004     {
1005         const ScMarkData& rMarkdata = mpViewShell->GetViewData()->GetMarkData();
1006         bResult = rMarkdata.IsRowMarked((SCROW)nRow);
1007     }
1008     return bResult;
1009 }
1010 
1011 sal_Bool SAL_CALL ScAccessibleSpreadsheet::isAccessibleColumnSelected( sal_Int32 nColumn )
1012     throw (uno::RuntimeException, lang::IndexOutOfBoundsException)
1013 {
1014     ScUnoGuard aGuard;
1015     IsObjectValid();
1016 
1017     if (IsFormulaMode())
1018     {
1019         return sal_False;
1020     }
1021     if ((nColumn > (maRange.aEnd.Col() - maRange.aStart.Col())) || (nColumn < 0))
1022         throw lang::IndexOutOfBoundsException();
1023 
1024     sal_Bool bResult(sal_False);
1025     if (mpViewShell && mpViewShell->GetViewData())
1026     {
1027         const ScMarkData& rMarkdata = mpViewShell->GetViewData()->GetMarkData();
1028         bResult = rMarkdata.IsColumnMarked((SCCOL)nColumn);
1029     }
1030     return bResult;
1031 }
1032 
1033 ScAccessibleCell* ScAccessibleSpreadsheet::GetAccessibleCellAt(sal_Int32 nRow, sal_Int32 nColumn)
1034 {
1035     ScAccessibleCell* pAccessibleCell = NULL;
1036     if (IsFormulaMode())
1037     {
1038         ScAddress aCellAddress(static_cast<SCCOL>(nColumn), nRow, mpViewShell->GetViewData()->GetTabNo());
1039         if ((aCellAddress == m_aFormulaActiveCell) && m_pAccFormulaCell)
1040         {
1041             pAccessibleCell = m_pAccFormulaCell;
1042         }
1043         else
1044             pAccessibleCell = new ScAccessibleCell(this, mpViewShell, aCellAddress, GetAccessibleIndexFormula(nRow, nColumn), meSplitPos, mpAccDoc);
1045     }
1046     else
1047     {
1048     ScAddress aCellAddress(static_cast<SCCOL>(maRange.aStart.Col() + nColumn),
1049         static_cast<SCROW>(maRange.aStart.Row() + nRow), maRange.aStart.Tab());
1050     if ((aCellAddress == maActiveCell) && mpAccCell)
1051     {
1052         pAccessibleCell = mpAccCell;
1053     }
1054     else
1055         pAccessibleCell = new ScAccessibleCell(this, mpViewShell, aCellAddress, getAccessibleIndex(nRow, nColumn), meSplitPos, mpAccDoc);
1056     }
1057 
1058     return pAccessibleCell;
1059 }
1060 
1061 uno::Reference< XAccessible > SAL_CALL ScAccessibleSpreadsheet::getAccessibleCellAt( sal_Int32 nRow, sal_Int32 nColumn )
1062                     throw (uno::RuntimeException, lang::IndexOutOfBoundsException)
1063 {
1064     ScUnoGuard aGuard;
1065     IsObjectValid();
1066     if (!IsFormulaMode())
1067     {
1068     if (nRow > (maRange.aEnd.Row() - maRange.aStart.Row()) ||
1069         nRow < 0 ||
1070         nColumn > (maRange.aEnd.Col() - maRange.aStart.Col()) ||
1071         nColumn < 0)
1072         throw lang::IndexOutOfBoundsException();
1073     }
1074     uno::Reference<XAccessible> xAccessible;
1075     ScAccessibleCell* pAccessibleCell = GetAccessibleCellAt(nRow, nColumn);
1076     xAccessible = pAccessibleCell;
1077     pAccessibleCell->Init();
1078     return xAccessible;
1079 }
1080 
1081 sal_Bool SAL_CALL ScAccessibleSpreadsheet::isAccessibleSelected( sal_Int32 nRow, sal_Int32 nColumn )
1082     throw (uno::RuntimeException, lang::IndexOutOfBoundsException)
1083 {
1084     ScUnoGuard aGuard;
1085     IsObjectValid();
1086 
1087     if (IsFormulaMode())
1088     {
1089         ScAddress addr(static_cast<SCCOL>(nColumn), nRow, 0);
1090         return IsScAddrFormulaSel(addr);
1091     }
1092     if ((nColumn > (maRange.aEnd.Col() - maRange.aStart.Col())) || (nColumn < 0) ||
1093         (nRow > (maRange.aEnd.Row() - maRange.aStart.Row())) || (nRow < 0))
1094         throw lang::IndexOutOfBoundsException();
1095 
1096     sal_Bool bResult(sal_False);
1097     if (mpViewShell)
1098     {
1099         const ScMarkData& rMarkdata = mpViewShell->GetViewData()->GetMarkData();
1100         bResult = rMarkdata.IsCellMarked(static_cast<SCCOL>(nColumn), static_cast<SCROW>(nRow));
1101     }
1102     return bResult;
1103 }
1104 
1105     //=====  XAccessibleComponent  ============================================
1106 
1107 uno::Reference< XAccessible > SAL_CALL ScAccessibleSpreadsheet::getAccessibleAtPoint(
1108     const awt::Point& rPoint )
1109         throw (uno::RuntimeException)
1110 {
1111     uno::Reference< XAccessible > xAccessible;
1112     if (containsPoint(rPoint))
1113     {
1114         ScUnoGuard aGuard;
1115         IsObjectValid();
1116         if (mpViewShell)
1117         {
1118             SCsCOL nX;
1119             SCsROW nY;
1120             mpViewShell->GetViewData()->GetPosFromPixel( rPoint.X, rPoint.Y, meSplitPos, nX, nY);
1121             try{
1122             xAccessible = getAccessibleCellAt(nY, nX);
1123             }
1124             catch( ::com::sun::star::lang::IndexOutOfBoundsException e)
1125             {
1126                 return NULL;
1127             }
1128         }
1129     }
1130     return xAccessible;
1131 }
1132 
1133 void SAL_CALL ScAccessibleSpreadsheet::grabFocus(  )
1134         throw (uno::RuntimeException)
1135 {
1136     if (getAccessibleParent().is())
1137     {
1138         uno::Reference<XAccessibleComponent> xAccessibleComponent(getAccessibleParent()->getAccessibleContext(), uno::UNO_QUERY);
1139         if (xAccessibleComponent.is())
1140             xAccessibleComponent->grabFocus();
1141     }
1142 }
1143 
1144 sal_Int32 SAL_CALL ScAccessibleSpreadsheet::getForeground(  )
1145         throw (uno::RuntimeException)
1146 {
1147     return COL_BLACK;
1148 }
1149 
1150 sal_Int32 SAL_CALL ScAccessibleSpreadsheet::getBackground(  )
1151         throw (uno::RuntimeException)
1152 {
1153     ScUnoGuard aGuard;
1154     IsObjectValid();
1155     return SC_MOD()->GetColorConfig().GetColorValue( ::svtools::DOCCOLOR ).nColor;
1156 }
1157 
1158     //=====  XAccessibleContext  ==============================================
1159 
1160 uno::Reference<XAccessibleRelationSet> SAL_CALL ScAccessibleSpreadsheet::getAccessibleRelationSet(void)
1161         throw (::com::sun::star::uno::RuntimeException)
1162 {
1163     utl::AccessibleRelationSetHelper* pRelationSet = NULL;
1164     if(mpAccDoc)
1165         pRelationSet = mpAccDoc->GetRelationSet(NULL);
1166     if (!pRelationSet)
1167         pRelationSet = new utl::AccessibleRelationSetHelper();
1168     return pRelationSet;
1169 }
1170 
1171 uno::Reference<XAccessibleStateSet> SAL_CALL
1172     ScAccessibleSpreadsheet::getAccessibleStateSet(void)
1173     throw (uno::RuntimeException)
1174 {
1175     ScUnoGuard aGuard;
1176     uno::Reference<XAccessibleStateSet> xParentStates;
1177     if (getAccessibleParent().is())
1178     {
1179         uno::Reference<XAccessibleContext> xParentContext = getAccessibleParent()->getAccessibleContext();
1180         xParentStates = xParentContext->getAccessibleStateSet();
1181     }
1182     utl::AccessibleStateSetHelper* pStateSet = new utl::AccessibleStateSetHelper();
1183     if (IsDefunc(xParentStates))
1184         pStateSet->AddState(AccessibleStateType::DEFUNC);
1185     else
1186     {
1187         pStateSet->AddState(AccessibleStateType::MANAGES_DESCENDANTS);
1188         if (IsEditable(xParentStates))
1189             pStateSet->AddState(AccessibleStateType::EDITABLE);
1190         pStateSet->AddState(AccessibleStateType::ENABLED);
1191         pStateSet->AddState(AccessibleStateType::FOCUSABLE);
1192         if (IsFocused())
1193             pStateSet->AddState(AccessibleStateType::FOCUSED);
1194         pStateSet->AddState(AccessibleStateType::MULTI_SELECTABLE);
1195         pStateSet->AddState(AccessibleStateType::OPAQUE);
1196         pStateSet->AddState(AccessibleStateType::SELECTABLE);
1197         if (IsCompleteSheetSelected())
1198             pStateSet->AddState(AccessibleStateType::SELECTED);
1199         if (isShowing())
1200             pStateSet->AddState(AccessibleStateType::SHOWING);
1201         if (isVisible())
1202             pStateSet->AddState(AccessibleStateType::VISIBLE);
1203     }
1204     return pStateSet;
1205 }
1206 
1207     ///=====  XAccessibleSelection  ===========================================
1208 
1209 void SAL_CALL
1210         ScAccessibleSpreadsheet::selectAccessibleChild( sal_Int32 nChildIndex )
1211         throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
1212 {
1213     ScUnoGuard aGuard;
1214     IsObjectValid();
1215     if (nChildIndex < 0 || nChildIndex >= getAccessibleChildCount())
1216         throw lang::IndexOutOfBoundsException();
1217 
1218     if (mpViewShell)
1219     {
1220         sal_Int32 nCol(getAccessibleColumn(nChildIndex));
1221         sal_Int32 nRow(getAccessibleRow(nChildIndex));
1222 
1223         SelectCell(nRow, nCol, sal_False);
1224     }
1225 }
1226 
1227 void SAL_CALL
1228         ScAccessibleSpreadsheet::clearAccessibleSelection(  )
1229         throw (uno::RuntimeException)
1230 {
1231     ScUnoGuard aGuard;
1232     IsObjectValid();
1233     if (mpViewShell)
1234     {
1235         if (!IsFormulaMode())
1236         mpViewShell->Unmark();
1237     }
1238 }
1239 
1240 void SAL_CALL
1241         ScAccessibleSpreadsheet::selectAllAccessibleChildren(  )
1242         throw (uno::RuntimeException)
1243 {
1244     ScUnoGuard aGuard;
1245     IsObjectValid();
1246     if (mpViewShell)
1247     {
1248         if (IsFormulaMode())
1249         {
1250             ScViewData *pViewData = mpViewShell->GetViewData();
1251             mpViewShell->InitRefMode( 0, 0, pViewData->GetTabNo(), SC_REFTYPE_REF );
1252             pViewData->SetRefStart(0,0,pViewData->GetTabNo());
1253             pViewData->SetRefStart(MAXCOL,MAXROW,pViewData->GetTabNo());
1254             mpViewShell->UpdateRef(MAXCOL, MAXROW, pViewData->GetTabNo());
1255         }
1256         else
1257         mpViewShell->SelectAll();
1258     }
1259 }
1260 
1261 sal_Int32 SAL_CALL
1262         ScAccessibleSpreadsheet::getSelectedAccessibleChildCount(  )
1263         throw (uno::RuntimeException)
1264 {
1265     ScUnoGuard aGuard;
1266     IsObjectValid();
1267     sal_Int32 nResult(0);
1268     if (mpViewShell)
1269     {
1270         if (IsFormulaMode())
1271         {
1272             nResult =  GetRowAll() * GetColAll() ;
1273         }
1274         else
1275         {
1276         if (!mpMarkedRanges)
1277         {
1278             mpMarkedRanges = new ScRangeList();
1279             ScMarkData aMarkData(mpViewShell->GetViewData()->GetMarkData());
1280             //aMarkData.MarkToMulti();
1281             aMarkData.FillRangeListWithMarks(mpMarkedRanges, sal_False);
1282         }
1283         // is possible, because there shouldn't be overlapped ranges in it
1284         if (mpMarkedRanges)
1285             nResult = mpMarkedRanges->GetCellCount();
1286         }
1287     }
1288     return nResult;
1289 }
1290 
1291 uno::Reference<XAccessible > SAL_CALL
1292         ScAccessibleSpreadsheet::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex )
1293         throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
1294 {
1295     ScUnoGuard aGuard;
1296     IsObjectValid();
1297     uno::Reference < XAccessible > xAccessible;
1298     if (IsFormulaMode())
1299     {
1300         if(CheckChildIndex(nSelectedChildIndex))
1301         {
1302             ScAddress addr = GetChildIndexAddress(nSelectedChildIndex);
1303             xAccessible = getAccessibleCellAt(addr.Row(), addr.Col());
1304         }
1305         return xAccessible;
1306     }
1307     if (mpViewShell)
1308     {
1309         if (!mpMarkedRanges)
1310         {
1311             mpMarkedRanges = new ScRangeList();
1312             mpViewShell->GetViewData()->GetMarkData().FillRangeListWithMarks(mpMarkedRanges, sal_False);
1313         }
1314         if (mpMarkedRanges)
1315         {
1316             //if (!mpSortedMarkedCells)
1317             //  CreateSortedMarkedCells();
1318             //if (mpSortedMarkedCells)
1319             //{
1320             //  if ((nSelectedChildIndex < 0) ||
1321             //      (mpSortedMarkedCells->size() <= static_cast<sal_uInt32>(nSelectedChildIndex)))
1322             //      throw lang::IndexOutOfBoundsException();
1323             //  else
1324             //      xAccessible = getAccessibleCellAt((*mpSortedMarkedCells)[nSelectedChildIndex].Row(), (*mpSortedMarkedCells)[nSelectedChildIndex].Col());
1325             if ((nSelectedChildIndex < 0) ||
1326                     (mpMarkedRanges->GetCellCount() <= static_cast<sal_uInt32>(nSelectedChildIndex)))
1327             {
1328                 throw lang::IndexOutOfBoundsException();
1329             }
1330             ScMyAddress addr = CalcScAddressFromRangeList(mpMarkedRanges,nSelectedChildIndex);
1331             if( m_mapSelectionSend.find(addr) != m_mapSelectionSend.end() )
1332                 xAccessible = m_mapSelectionSend[addr];
1333             else
1334                 xAccessible = getAccessibleCellAt(addr.Row(), addr.Col());
1335         }
1336     }
1337     return xAccessible;
1338 }
1339 
1340 void SAL_CALL
1341         ScAccessibleSpreadsheet::deselectAccessibleChild( sal_Int32 nChildIndex )
1342         throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
1343 {
1344     ScUnoGuard aGuard;
1345     IsObjectValid();
1346 
1347     if (nChildIndex < 0 || nChildIndex >= getAccessibleChildCount())
1348         throw lang::IndexOutOfBoundsException();
1349 
1350     if (mpViewShell)
1351     {
1352         sal_Int32 nCol(getAccessibleColumn(nChildIndex));
1353         sal_Int32 nRow(getAccessibleRow(nChildIndex));
1354 
1355         if (IsFormulaMode())
1356         {
1357             if(IsScAddrFormulaSel(
1358                 ScAddress(static_cast<SCCOL>(nCol), nRow,mpViewShell->GetViewData()->GetTabNo()))
1359                 )
1360             {
1361                 SelectCell(nRow, nCol, sal_True);
1362             }
1363             return ;
1364         }
1365         if (mpViewShell->GetViewData()->GetMarkData().IsCellMarked(static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow)))
1366             SelectCell(nRow, nCol, sal_True);
1367     }
1368 }
1369 
1370 void ScAccessibleSpreadsheet::SelectCell(sal_Int32 nRow, sal_Int32 nCol, sal_Bool bDeselect)
1371 {
1372     if (IsFormulaMode())
1373     {
1374         if (bDeselect)
1375         {//??
1376             return ;
1377         }
1378         else
1379         {
1380             ScViewData *pViewData = mpViewShell->GetViewData();
1381 
1382             mpViewShell->InitRefMode( static_cast<SCCOL>(nCol), nRow, pViewData->GetTabNo(), SC_REFTYPE_REF );
1383             mpViewShell->UpdateRef(static_cast<SCCOL>(nCol), nRow, pViewData->GetTabNo());
1384         }
1385         return ;
1386     }
1387     mpViewShell->SetTabNo( maRange.aStart.Tab() );
1388 
1389     mpViewShell->DoneBlockMode( sal_True ); // continue selecting
1390     mpViewShell->InitBlockMode( static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), maRange.aStart.Tab(), bDeselect, sal_False, sal_False );
1391 
1392     mpViewShell->SelectionChanged();
1393 }
1394 //void ScAccessibleSpreadsheet::CreateSortedMarkedCells()
1395 //{
1396 //  mpSortedMarkedCells = new std::vector<ScMyAddress>();
1397 //  mpSortedMarkedCells->reserve(mpMarkedRanges->GetCellCount());
1398 //  ScRange* pRange = mpMarkedRanges->First();
1399 //  while (pRange)
1400 //  {
1401 //      if (pRange->aStart.Tab() != pRange->aEnd.Tab())
1402 //      {
1403 //          if ((maActiveCell.Tab() >= pRange->aStart.Tab()) ||
1404 //              maActiveCell.Tab() <= pRange->aEnd.Tab())
1405 //          {
1406 //              ScRange aRange(*pRange);
1407 //              aRange.aStart.SetTab(maActiveCell.Tab());
1408 //              aRange.aEnd.SetTab(maActiveCell.Tab());
1409 //              AddMarkedRange(aRange);
1410 //          }
1411 //          else
1412 //          {
1413 //              DBG_ERROR("Range of wrong table");
1414 //          }
1415 //      }
1416 //      else if(pRange->aStart.Tab() == maActiveCell.Tab())
1417 //          AddMarkedRange(*pRange);
1418 //      else
1419 //      {
1420 //          DBG_ERROR("Range of wrong table");
1421 //      }
1422 //      pRange = mpMarkedRanges->Next();
1423 //  }
1424 //  std::sort(mpSortedMarkedCells->begin(), mpSortedMarkedCells->end());
1425 //}
1426 
1427 /*void ScAccessibleSpreadsheet::AddMarkedRange(const ScRange& rRange)
1428 {
1429     for (SCROW nRow = rRange.aStart.Row(); nRow <= rRange.aEnd.Row(); ++nRow)
1430     {
1431         for (SCCOL nCol = rRange.aStart.Col(); nCol <= rRange.aEnd.Col(); ++nCol)
1432         {
1433             ScMyAddress aCell(nCol, nRow, maActiveCell.Tab());
1434             mpSortedMarkedCells->push_back(aCell);
1435         }
1436     }
1437 }*/
1438 
1439     //=====  XServiceInfo  ====================================================
1440 
1441 ::rtl::OUString SAL_CALL ScAccessibleSpreadsheet::getImplementationName(void)
1442         throw (uno::RuntimeException)
1443 {
1444     return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM ("ScAccessibleSpreadsheet"));
1445 }
1446 
1447 uno::Sequence< ::rtl::OUString> SAL_CALL
1448     ScAccessibleSpreadsheet::getSupportedServiceNames (void)
1449         throw (uno::RuntimeException)
1450 {
1451     uno::Sequence< ::rtl::OUString > aSequence = ScAccessibleTableBase::getSupportedServiceNames();
1452     sal_Int32 nOldSize(aSequence.getLength());
1453     aSequence.realloc(nOldSize + 1);
1454     ::rtl::OUString* pNames = aSequence.getArray();
1455 
1456     pNames[nOldSize] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.AccessibleSpreadsheet"));
1457 
1458     return aSequence;
1459 }
1460 
1461 //=====  XTypeProvider  =======================================================
1462 
1463 uno::Sequence<sal_Int8> SAL_CALL
1464     ScAccessibleSpreadsheet::getImplementationId(void)
1465     throw (uno::RuntimeException)
1466 {
1467     ScUnoGuard aGuard;
1468     IsObjectValid();
1469     static uno::Sequence<sal_Int8> aId;
1470     if (aId.getLength() == 0)
1471     {
1472         aId.realloc (16);
1473         rtl_createUuid (reinterpret_cast<sal_uInt8 *>(aId.getArray()), 0, sal_True);
1474     }
1475     return aId;
1476 }
1477 
1478 ///=====  XAccessibleEventBroadcaster  =====================================
1479 
1480 void SAL_CALL ScAccessibleSpreadsheet::addEventListener(const uno::Reference<XAccessibleEventListener>& xListener)
1481         throw (uno::RuntimeException)
1482 {
1483     ScUnoGuard aGuard;
1484     IsObjectValid();
1485     ScAccessibleTableBase::addEventListener(xListener);
1486 
1487 /*    if (!mbIsFocusSend)
1488     {
1489         mbIsFocusSend = sal_True;
1490         CommitFocusGained();
1491 
1492         AccessibleEventObject aEvent;
1493         aEvent.EventId = AccessibleEventId::ACTIVE_DESCENDANT_CHANGED;
1494         aEvent.Source = uno::Reference< XAccessibleContext >(this);
1495         aEvent.NewValue <<= getAccessibleCellAt(maActiveCell.Row(), maActiveCell.Col());
1496 
1497         CommitChange(aEvent);
1498     }
1499 */
1500 }
1501 
1502     //====  internal  =========================================================
1503 
1504 Rectangle ScAccessibleSpreadsheet::GetBoundingBoxOnScreen() const
1505     throw (uno::RuntimeException)
1506 {
1507     Rectangle aRect;
1508     if (mpViewShell)
1509     {
1510         Window* pWindow = mpViewShell->GetWindowByPos(meSplitPos);
1511         if (pWindow)
1512             aRect = pWindow->GetWindowExtentsRelative(NULL);
1513     }
1514     return aRect;
1515 }
1516 
1517 Rectangle ScAccessibleSpreadsheet::GetBoundingBox() const
1518     throw (uno::RuntimeException)
1519 {
1520     Rectangle aRect;
1521     if (mpViewShell)
1522     {
1523         Window* pWindow = mpViewShell->GetWindowByPos(meSplitPos);
1524         if (pWindow)
1525             //#101986#; extends to the same window, because the parent is the document and it has the same window
1526             aRect = pWindow->GetWindowExtentsRelative(pWindow);
1527     }
1528     return aRect;
1529 }
1530 
1531 sal_Bool ScAccessibleSpreadsheet::IsDefunc(
1532     const uno::Reference<XAccessibleStateSet>& rxParentStates)
1533 {
1534     return ScAccessibleContextBase::IsDefunc() || (mpViewShell == NULL) || !getAccessibleParent().is() ||
1535         (rxParentStates.is() && rxParentStates->contains(AccessibleStateType::DEFUNC));
1536 }
1537 
1538 sal_Bool ScAccessibleSpreadsheet::IsEditable(
1539     const uno::Reference<XAccessibleStateSet>& /* rxParentStates */)
1540 {
1541     if (IsFormulaMode())
1542     {
1543         return sal_False;
1544     }
1545     sal_Bool bProtected(sal_False);
1546     if (mpDoc && mpDoc->IsTabProtected(maRange.aStart.Tab()))
1547         bProtected = sal_True;
1548     return !bProtected;
1549 }
1550 
1551 sal_Bool ScAccessibleSpreadsheet::IsFocused()
1552 {
1553     sal_Bool bFocused(sal_False);
1554     if (mpViewShell)
1555     {
1556         if (mpViewShell->GetViewData()->GetActivePart() == meSplitPos)
1557             bFocused = mpViewShell->GetActiveWin()->HasFocus();
1558     }
1559     return bFocused;
1560 }
1561 
1562 sal_Bool ScAccessibleSpreadsheet::IsCompleteSheetSelected()
1563 {
1564     if (IsFormulaMode())
1565     {
1566         return sal_False;
1567     }
1568     sal_Bool bResult(sal_False);
1569     if(mpViewShell)
1570     {
1571         //#103800#; use a copy of MarkData
1572         ScMarkData aMarkData(mpViewShell->GetViewData()->GetMarkData());
1573         aMarkData.MarkToMulti();
1574         if (aMarkData.IsAllMarked(maRange))
1575             bResult = sal_True;
1576     }
1577     return bResult;
1578 }
1579 
1580 ScDocument* ScAccessibleSpreadsheet::GetDocument(ScTabViewShell* pViewShell)
1581 {
1582     ScDocument* pDoc = NULL;
1583     if (pViewShell)
1584         pDoc = pViewShell->GetViewData()->GetDocument();
1585     return pDoc;
1586 }
1587 
1588 Rectangle ScAccessibleSpreadsheet::GetVisArea(ScTabViewShell* pViewShell, ScSplitPos eSplitPos)
1589 {
1590     Rectangle aVisArea;
1591     if (pViewShell)
1592     {
1593         Window* pWindow = pViewShell->GetWindowByPos(eSplitPos);
1594         if (pWindow)
1595         {
1596             aVisArea.SetPos(pViewShell->GetViewData()->GetPixPos(eSplitPos));
1597             aVisArea.SetSize(pWindow->GetSizePixel());
1598         }
1599     }
1600     return aVisArea;
1601 }
1602 
1603 Rectangle ScAccessibleSpreadsheet::GetVisCells(const Rectangle& rVisArea)
1604 {
1605     if (mpViewShell)
1606     {
1607         SCsCOL nStartX, nEndX;
1608         SCsROW nStartY, nEndY;
1609 
1610         mpViewShell->GetViewData()->GetPosFromPixel( 1, 1, meSplitPos, nStartX, nStartY);
1611         mpViewShell->GetViewData()->GetPosFromPixel( rVisArea.GetWidth(), rVisArea.GetHeight(), meSplitPos, nEndX, nEndY);
1612 
1613         return Rectangle(nStartX, nStartY, nEndX, nEndY);
1614     }
1615     else
1616         return Rectangle();
1617 }
1618 sal_Bool SAL_CALL ScAccessibleSpreadsheet::selectRow( sal_Int32 row )
1619 throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
1620 {
1621     if (IsFormulaMode())
1622     {
1623         return sal_False;
1624     }
1625 
1626     mpViewShell->SetTabNo( maRange.aStart.Tab() );
1627     mpViewShell->DoneBlockMode( sal_True ); // continue selecting
1628     mpViewShell->InitBlockMode( 0, row, maRange.aStart.Tab(), sal_False, sal_False, sal_True );
1629     mpViewShell->MarkCursor( MAXCOL, row, maRange.aStart.Tab(), sal_False, sal_True );
1630     mpViewShell->SelectionChanged();
1631     return sal_True;
1632 }
1633 
1634 sal_Bool SAL_CALL ScAccessibleSpreadsheet::selectColumn( sal_Int32 column )
1635         throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
1636 {
1637     if (IsFormulaMode())
1638     {
1639         return sal_False;
1640     }
1641 
1642     mpViewShell->SetTabNo( maRange.aStart.Tab() );
1643     mpViewShell->DoneBlockMode( sal_True ); // continue selecting
1644     mpViewShell->InitBlockMode( static_cast<SCCOL>(column), 0, maRange.aStart.Tab(), sal_False, sal_True, sal_False );
1645     mpViewShell->MarkCursor( static_cast<SCCOL>(column), MAXROW, maRange.aStart.Tab(), sal_True, sal_False );
1646     mpViewShell->SelectionChanged();
1647     return sal_True;
1648 }
1649 
1650 sal_Bool SAL_CALL ScAccessibleSpreadsheet::unselectRow( sal_Int32 row )
1651         throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
1652 {
1653     if (IsFormulaMode())
1654     {
1655         return sal_False;
1656     }
1657 
1658     mpViewShell->SetTabNo( maRange.aStart.Tab() );
1659     mpViewShell->DoneBlockMode( sal_True ); // continue selecting
1660     mpViewShell->InitBlockMode( 0, row, maRange.aStart.Tab(), sal_False, sal_False, sal_True, sal_True );
1661     mpViewShell->MarkCursor( MAXCOL, row, maRange.aStart.Tab(), sal_False, sal_True );
1662     mpViewShell->SelectionChanged();
1663     mpViewShell->DoneBlockMode( sal_True );
1664     return sal_True;
1665 }
1666 
1667 sal_Bool SAL_CALL ScAccessibleSpreadsheet::unselectColumn( sal_Int32 column )
1668         throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
1669 {
1670     if (IsFormulaMode())
1671     {
1672         return sal_False;
1673     }
1674 
1675     mpViewShell->SetTabNo( maRange.aStart.Tab() );
1676     mpViewShell->DoneBlockMode( sal_True ); // continue selecting
1677     mpViewShell->InitBlockMode( static_cast<SCCOL>(column), 0, maRange.aStart.Tab(), sal_False, sal_True, sal_False, sal_True );
1678     mpViewShell->MarkCursor( static_cast<SCCOL>(column), MAXROW, maRange.aStart.Tab(), sal_True, sal_False );
1679     mpViewShell->SelectionChanged();
1680     mpViewShell->DoneBlockMode( sal_True );
1681     return sal_True;
1682 }
1683 
1684 void ScAccessibleSpreadsheet::FireFirstCellFocus()
1685 {
1686     if (IsFormulaMode())
1687     {
1688         return ;
1689     }
1690     if (mbIsFocusSend)
1691     {
1692         return ;
1693     }
1694     mbIsFocusSend = sal_True;
1695     AccessibleEventObject aEvent;
1696     aEvent.EventId = AccessibleEventId::ACTIVE_DESCENDANT_CHANGED;
1697     aEvent.Source = uno::Reference< XAccessible >(this);
1698     aEvent.NewValue <<= getAccessibleCellAt(maActiveCell.Row(), maActiveCell.Col());
1699     CommitChange(aEvent);
1700 }
1701 void ScAccessibleSpreadsheet::NotifyRefMode()
1702 {
1703     ScViewData *pViewData = mpViewShell->GetViewData();
1704     sal_uInt16 nRefStartX =pViewData->GetRefStartX();
1705     sal_Int32 nRefStartY=pViewData->GetRefStartY();
1706     sal_uInt16 nRefEndX=pViewData->GetRefEndX();
1707     sal_Int32 nRefEndY=pViewData->GetRefEndY();
1708     ScAddress aFormulaAddr;
1709     if(!GetFormulaCurrentFocusCell(aFormulaAddr))
1710     {
1711         return ;
1712     }
1713     if (m_aFormulaActiveCell != aFormulaAddr)
1714     {//New Focus
1715         m_nMinX =std::min(nRefStartX,nRefEndX);
1716         m_nMaxX =std::max(nRefStartX,nRefEndX);
1717         m_nMinY = std::min(nRefStartY,nRefEndY);
1718         m_nMaxY = std::max(nRefStartY,nRefEndY);
1719         RemoveFormulaSelection();
1720         AccessibleEventObject aEvent;
1721         aEvent.Source = uno::Reference< XAccessible >(this);
1722         aEvent.EventId = AccessibleEventId::ACTIVE_DESCENDANT_CHANGED;
1723         aEvent.Source = uno::Reference< XAccessible >(this);
1724         uno::Reference< XAccessible > xOld = m_pAccFormulaCell;
1725         aEvent.OldValue <<= xOld;
1726         m_pAccFormulaCell = GetAccessibleCellAt(aFormulaAddr.Row(), aFormulaAddr.Col());
1727         m_pAccFormulaCell->acquire();
1728         m_pAccFormulaCell->Init();
1729         uno::Reference< XAccessible > xNew = m_pAccFormulaCell;
1730         aEvent.NewValue <<= xNew;
1731         CommitChange(aEvent);
1732         if (nRefStartX == nRefEndX && nRefStartY == nRefEndY)
1733         {//Selection Single
1734             aEvent.EventId = AccessibleEventId::SELECTION_CHANGED;
1735             aEvent.NewValue <<= xNew;
1736             CommitChange(aEvent);
1737             m_mapFormulaSelectionSend.insert(MAP_ADDR_XACC::value_type(aFormulaAddr,xNew));
1738             m_vecFormulaLastMyAddr.clear();
1739             m_vecFormulaLastMyAddr.push_back(aFormulaAddr);
1740         }
1741         else
1742         {
1743             VEC_MYADDR vecCurSel;
1744             int nCurSize =  (m_nMaxX - m_nMinX +1)*(m_nMaxY - m_nMinY +1) ;
1745             vecCurSel.reserve(nCurSize);
1746             for (sal_uInt16 x = m_nMinX ; x <= m_nMaxX ; ++x)
1747             {
1748                 for (sal_Int32 y = m_nMinY ; y <= m_nMaxY ; ++y)
1749                 {
1750                     ScMyAddress aAddr(x,y,0);
1751                     vecCurSel.push_back(aAddr);
1752                 }
1753             }
1754             std::sort(vecCurSel.begin(), vecCurSel.end());
1755             VEC_MYADDR vecNew;
1756             std::set_difference(vecCurSel.begin(),vecCurSel.end(),
1757                 m_vecFormulaLastMyAddr.begin(),m_vecFormulaLastMyAddr.end(),
1758                 std::back_insert_iterator<VEC_MYADDR>(vecNew));
1759             int nNewSize = vecNew.size();
1760             if ( nNewSize > 10 )
1761             {
1762                 aEvent.EventId = AccessibleEventId::SELECTION_CHANGED_WITHIN;
1763                 aEvent.NewValue <<= ::com::sun::star::uno::Any();
1764                 CommitChange(aEvent);
1765             }
1766             else
1767             {
1768                 VEC_MYADDR::iterator viAddr = vecNew.begin();
1769                 for(; viAddr != vecNew.end() ; ++viAddr )
1770                 {
1771                     uno::Reference< XAccessible > xChild;
1772                     if (*viAddr == aFormulaAddr)
1773                     {
1774                         xChild = m_pAccFormulaCell;
1775                     }
1776                     else
1777                     {
1778                         xChild = getAccessibleCellAt(viAddr->Row(),viAddr->Col());
1779                         aEvent.EventId = AccessibleEventId::ACTIVE_DESCENDANT_CHANGED_NOFOCUS;
1780                         aEvent.NewValue <<= xChild;
1781                         CommitChange(aEvent);
1782                     }
1783                     aEvent.EventId = AccessibleEventId::SELECTION_CHANGED_ADD;
1784                     aEvent.NewValue <<= xChild;
1785                     CommitChange(aEvent);
1786                     m_mapFormulaSelectionSend.insert(MAP_ADDR_XACC::value_type(*viAddr,xChild));
1787                 }
1788             }
1789             m_vecFormulaLastMyAddr.swap(vecCurSel);
1790         }
1791     }
1792     m_aFormulaActiveCell = aFormulaAddr;
1793 }
1794 void ScAccessibleSpreadsheet::RemoveFormulaSelection(sal_Bool bRemoveAll )
1795 {
1796     AccessibleEventObject aEvent;
1797     aEvent.Source = uno::Reference< XAccessible >(this);
1798     aEvent.OldValue <<= ::com::sun::star::uno::Any();
1799     MAP_ADDR_XACC::iterator miRemove = m_mapFormulaSelectionSend.begin();
1800     for(;  miRemove != m_mapFormulaSelectionSend.end() ;)
1801     {
1802         if( !bRemoveAll && IsScAddrFormulaSel(miRemove->first) )
1803         {
1804             ++miRemove;
1805             continue;
1806         }
1807         aEvent.EventId = AccessibleEventId::SELECTION_CHANGED_REMOVE;
1808         aEvent.NewValue <<= miRemove->second;
1809         CommitChange(aEvent);
1810         MAP_ADDR_XACC::iterator miNext = miRemove;
1811         ++miNext;
1812         m_mapFormulaSelectionSend.erase(miRemove);
1813         miRemove = miNext;
1814     }
1815 }
1816 sal_Bool ScAccessibleSpreadsheet::IsScAddrFormulaSel(const ScAddress &addr) const
1817 {
1818     if( addr.Col() >= m_nMinX && addr.Col() <= m_nMaxX &&
1819         addr.Row() >= m_nMinY && addr.Row() <= m_nMaxY &&
1820         addr.Tab() == mpViewShell->GetViewData()->GetTabNo() )
1821     {
1822         return sal_True;
1823     }
1824     return sal_False;
1825 }
1826 sal_Bool ScAccessibleSpreadsheet::CheckChildIndex(sal_Int32 nIndex) const
1827 {
1828     sal_Int32 nMaxIndex = (m_nMaxX - m_nMinX +1)*(m_nMaxY - m_nMinY +1) -1 ;
1829     return nIndex <= nMaxIndex && nIndex >= 0 ;
1830 }
1831 ScAddress ScAccessibleSpreadsheet::GetChildIndexAddress(sal_Int32 nIndex) const
1832 {
1833     sal_Int32 nRowAll = GetRowAll();
1834     sal_uInt16  nColAll = GetColAll();
1835     if (nIndex < 0 || nIndex >=  nRowAll * nColAll )
1836     {
1837         return ScAddress();
1838     }
1839     return ScAddress(
1840         static_cast<SCCOL>((nIndex - nIndex % nRowAll) / nRowAll +  + m_nMinX),
1841         nIndex % nRowAll + m_nMinY,
1842         mpViewShell->GetViewData()->GetTabNo()
1843         );
1844 }
1845 sal_Int32 ScAccessibleSpreadsheet::GetAccessibleIndexFormula( sal_Int32 nRow, sal_Int32 nColumn )
1846 {
1847     sal_uInt16 nColRelative = sal_uInt16(nColumn) - GetColAll();
1848     sal_Int32 nRowRelative = nRow - GetRowAll();
1849     if (nRow < 0 || nColumn < 0  || nRowRelative >= GetRowAll() || nColRelative >= GetColAll() )
1850     {
1851         return -1;
1852     }
1853     return GetRowAll() * nRowRelative + nColRelative;
1854 }
1855 sal_Bool ScAccessibleSpreadsheet::IsFormulaMode()
1856 {
1857     ScViewData *pViewData = mpViewShell->GetViewData();
1858     m_bFormulaMode = pViewData->IsRefMode() || SC_MOD()->IsFormulaMode();
1859     return m_bFormulaMode ;
1860 }
1861 sal_Bool ScAccessibleSpreadsheet::GetFormulaCurrentFocusCell(ScAddress &addr)
1862 {
1863     ScViewData *pViewData = mpViewShell->GetViewData();
1864     sal_uInt16 nRefX=0;
1865     sal_Int32 nRefY=0;
1866     if(m_bFormulaLastMode)
1867     {
1868         nRefX=pViewData->GetRefEndX();
1869         nRefY=pViewData->GetRefEndY();
1870     }
1871     else
1872     {
1873         nRefX=pViewData->GetRefStartX();
1874         nRefY=pViewData->GetRefStartY();
1875     }
1876     if( /* Always true: nRefX >= 0 && */ nRefX <= MAXCOL && nRefY >= 0 && nRefY <= MAXROW)
1877     {
1878         addr = ScAddress(nRefX,nRefY,pViewData->GetTabNo());
1879         return sal_True;
1880     }
1881     return sal_False;
1882 }
1883 uno::Reference < XAccessible > ScAccessibleSpreadsheet::GetActiveCell()
1884 {
1885     if( m_mapSelectionSend.find( maActiveCell ) != m_mapSelectionSend.end() )
1886             return m_mapSelectionSend[maActiveCell];
1887         else
1888             return getAccessibleCellAt(maActiveCell.Row(), maActiveCell .Col());
1889 }
1890