1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: bcaslot.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
36 #include <sfx2/objsh.hxx>
37 #include <svtools/listener.hxx>
38 #include <svtools/listeneriter.hxx>
40 #include "document.hxx"
42 #include "bcaslot.hxx"
43 #include "scerrors.hxx"
44 #include "docoptio.hxx"
45 #include "refupdat.hxx"
48 // Number of slots per dimension
49 // must be integer divisors of MAXCOLCOUNT respectively MAXROWCOUNT
50 #define BCA_SLOTS_COL ((MAXCOLCOUNT_DEFINE) / 16)
51 #if MAXROWCOUNT_DEFINE == 32000
52 #define BCA_SLOTS_ROW 256
54 #define BCA_SLOTS_ROW ((MAXROWCOUNT_DEFINE) / 128)
56 #define BCA_SLOT_COLS ((MAXCOLCOUNT_DEFINE) / BCA_SLOTS_COL)
57 #define BCA_SLOT_ROWS ((MAXROWCOUNT_DEFINE) / BCA_SLOTS_ROW)
59 #if (BCA_SLOT_COLS * BCA_SLOTS_COL) != (MAXCOLCOUNT_DEFINE)
60 #error bad BCA_SLOTS_COL value!
62 #if (BCA_SLOT_ROWS * BCA_SLOTS_ROW) != (MAXROWCOUNT_DEFINE)
63 #error bad BCA_SLOTS_ROW value!
66 #define BCA_SLOTS_DEFINE (BCA_SLOTS_COL * BCA_SLOTS_ROW)
67 // Arbitrary 2**31/8, assuming size_t can hold at least 2^31 values and
68 // sizeof_ptr is at most 8 bytes. You'd probably doom your machine's memory
69 // anyway, once you reached these values..
70 #if BCA_SLOTS_DEFINE > 268435456
71 #error BCA_SLOTS_DEFINE DOOMed!
74 const SCSIZE BCA_SLOTS
= BCA_SLOTS_DEFINE
;
76 // STATIC DATA -----------------------------------------------------------
78 TYPEINIT1( ScHint
, SfxSimpleHint
);
79 TYPEINIT1( ScAreaChangedHint
, SfxHint
);
82 ScBroadcastAreaSlot::ScBroadcastAreaSlot( ScDocument
* pDocument
,
83 ScBroadcastAreaSlotMachine
* pBASMa
) :
84 aTmpSeekBroadcastArea( ScRange()),
91 ScBroadcastAreaSlot::~ScBroadcastAreaSlot()
93 for ( ScBroadcastAreas::iterator
aIter( aBroadcastAreaTbl
.begin());
94 aIter
!= aBroadcastAreaTbl
.end(); ++aIter
)
96 if (!(*aIter
)->DecRef())
102 bool ScBroadcastAreaSlot::CheckHardRecalcStateCondition() const
104 if ( pDoc
->GetHardRecalcState() )
106 if (aBroadcastAreaTbl
.size() >= aBroadcastAreaTbl
.max_size())
107 { // this is more hypothetical now, check existed for old SV_PTRARR_SORT
108 if ( !pDoc
->GetHardRecalcState() )
110 pDoc
->SetHardRecalcState( 1 );
112 SfxObjectShell
* pShell
= pDoc
->GetDocumentShell();
113 DBG_ASSERT( pShell
, "Missing DocShell :-/" );
116 pShell
->SetError( SCWARN_CORE_HARD_RECALC
, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ) );
118 pDoc
->SetAutoCalc( FALSE
);
119 pDoc
->SetHardRecalcState( 2 );
127 bool ScBroadcastAreaSlot::StartListeningArea( const ScRange
& rRange
,
128 SvtListener
* pListener
, ScBroadcastArea
*& rpArea
)
130 bool bNewArea
= false;
131 DBG_ASSERT(pListener
, "StartListeningArea: pListener Null");
132 if (CheckHardRecalcStateCondition())
136 // Even if most times the area doesn't exist yet and immediately trying
137 // to new and insert it would save an attempt to find it, on mass
138 // operations like identical large [HV]LOOKUP() areas the new/delete
139 // would add quite some penalty for all but the first formula cell.
140 ScBroadcastAreas::const_iterator
aIter( FindBroadcastArea( rRange
));
141 if (aIter
!= aBroadcastAreaTbl
.end())
145 rpArea
= new ScBroadcastArea( rRange
);
146 if (aBroadcastAreaTbl
.insert( rpArea
).second
)
153 DBG_ERRORFILE("StartListeningArea: area not found and not inserted in slot?!?");
159 pListener
->StartListening( rpArea
->GetBroadcaster());
163 if (aBroadcastAreaTbl
.insert( rpArea
).second
)
170 void ScBroadcastAreaSlot::InsertListeningArea( ScBroadcastArea
* pArea
)
172 DBG_ASSERT( pArea
, "InsertListeningArea: pArea NULL");
173 if (CheckHardRecalcStateCondition())
175 if (aBroadcastAreaTbl
.insert( pArea
).second
)
180 // If rpArea != NULL then no listeners are stopped, only the area is removed
181 // and the reference count decremented.
182 void ScBroadcastAreaSlot::EndListeningArea( const ScRange
& rRange
,
183 SvtListener
* pListener
, ScBroadcastArea
*& rpArea
)
185 DBG_ASSERT(pListener
, "EndListeningArea: pListener Null");
188 ScBroadcastAreas::iterator
aIter( FindBroadcastArea( rRange
));
189 if (aIter
== aBroadcastAreaTbl
.end())
192 pListener
->EndListening( rpArea
->GetBroadcaster() );
193 if ( !rpArea
->GetBroadcaster().HasListeners() )
194 { // if nobody is listening we can dispose it
195 aBroadcastAreaTbl
.erase( aIter
);
196 if ( !rpArea
->DecRef() )
205 if ( !rpArea
->GetBroadcaster().HasListeners() )
207 ScBroadcastAreas::iterator
aIter( FindBroadcastArea( rRange
));
208 if (aIter
== aBroadcastAreaTbl
.end())
210 DBG_ASSERT( *aIter
== rpArea
, "EndListeningArea: area pointer mismatch");
211 aBroadcastAreaTbl
.erase( aIter
);
212 if ( !rpArea
->DecRef() )
222 ScBroadcastAreas::iterator
ScBroadcastAreaSlot::FindBroadcastArea(
223 const ScRange
& rRange
) const
225 aTmpSeekBroadcastArea
.UpdateRange( rRange
);
226 return aBroadcastAreaTbl
.find( &aTmpSeekBroadcastArea
);
230 BOOL
ScBroadcastAreaSlot::AreaBroadcast( const ScHint
& rHint
) const
232 if (aBroadcastAreaTbl
.empty())
234 BOOL bIsBroadcasted
= FALSE
;
235 const ScAddress
& rAddress
= rHint
.GetAddress();
236 for (ScBroadcastAreas::const_iterator
aIter( aBroadcastAreaTbl
.begin());
237 aIter
!= aBroadcastAreaTbl
.end(); /* increment in body */ )
239 ScBroadcastArea
* pArea
= *aIter
;
240 // A Notify() during broadcast may call EndListeningArea() and thus
241 // dispose this area if it was the last listener, which would
242 // invalidate the iterator, hence increment before call.
244 const ScRange
& rAreaRange
= pArea
->GetRange();
245 if (rAreaRange
.In( rAddress
))
247 if (!pBASM
->IsInBulkBroadcast() || pBASM
->InsertBulkArea( pArea
))
249 pArea
->GetBroadcaster().Broadcast( rHint
);
250 bIsBroadcasted
= TRUE
;
254 return bIsBroadcasted
;
258 BOOL
ScBroadcastAreaSlot::AreaBroadcastInRange( const ScRange
& rRange
,
259 const ScHint
& rHint
) const
261 if (aBroadcastAreaTbl
.empty())
263 BOOL bIsBroadcasted
= FALSE
;
264 for (ScBroadcastAreas::const_iterator
aIter( aBroadcastAreaTbl
.begin());
265 aIter
!= aBroadcastAreaTbl
.end(); /* increment in body */ )
267 ScBroadcastArea
* pArea
= *aIter
;
268 // A Notify() during broadcast may call EndListeningArea() and thus
269 // dispose this area if it was the last listener, which would
270 // invalidate the iterator, hence increment before call.
272 const ScRange
& rAreaRange
= pArea
->GetRange();
273 if (rAreaRange
.Intersects( rRange
))
275 if (!pBASM
->IsInBulkBroadcast() || pBASM
->InsertBulkArea( pArea
))
277 pArea
->GetBroadcaster().Broadcast( rHint
);
278 bIsBroadcasted
= TRUE
;
282 return bIsBroadcasted
;
286 void ScBroadcastAreaSlot::DelBroadcastAreasInRange( const ScRange
& rRange
)
288 if (aBroadcastAreaTbl
.empty())
290 for (ScBroadcastAreas::iterator
aIter( aBroadcastAreaTbl
.begin());
291 aIter
!= aBroadcastAreaTbl
.end(); /* increment in body */ )
293 const ScRange
& rAreaRange
= (*aIter
)->GetRange();
294 if (rRange
.In( rAreaRange
))
296 ScBroadcastArea
* pArea
= *aIter
;
297 aBroadcastAreaTbl
.erase( aIter
++); // erase before modifying
298 if (!pArea
->DecRef())
300 if (pBASM
->IsInBulkBroadcast())
301 pBASM
->RemoveBulkArea( pArea
);
311 void ScBroadcastAreaSlot::UpdateRemove( UpdateRefMode eUpdateRefMode
,
312 const ScRange
& rRange
, SCsCOL nDx
, SCsROW nDy
, SCsTAB nDz
)
314 if (aBroadcastAreaTbl
.empty())
317 SCCOL nCol1
, nCol2
, theCol1
, theCol2
;
318 SCROW nRow1
, nRow2
, theRow1
, theRow2
;
319 SCTAB nTab1
, nTab2
, theTab1
, theTab2
;
320 rRange
.GetVars( nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
);
321 for ( ScBroadcastAreas::iterator
aIter( aBroadcastAreaTbl
.begin());
322 aIter
!= aBroadcastAreaTbl
.end(); /* increment in body */ )
324 ScBroadcastArea
* pArea
= *aIter
;
325 if ( pArea
->IsInUpdateChain() )
327 aBroadcastAreaTbl
.erase( aIter
++);
332 pArea
->GetRange().GetVars( theCol1
, theRow1
, theTab1
, theCol2
, theRow2
, theTab2
);
333 if ( ScRefUpdate::Update( pDoc
, eUpdateRefMode
,
334 nCol1
,nRow1
,nTab1
, nCol2
,nRow2
,nTab2
, nDx
,nDy
,nDz
,
335 theCol1
,theRow1
,theTab1
, theCol2
,theRow2
,theTab2
))
337 aBroadcastAreaTbl
.erase( aIter
++);
339 if (pBASM
->IsInBulkBroadcast())
340 pBASM
->RemoveBulkArea( pArea
);
341 pArea
->SetInUpdateChain( TRUE
);
342 ScBroadcastArea
* pUC
= pBASM
->GetEOUpdateChain();
344 pUC
->SetUpdateChainNext( pArea
);
345 else // no tail => no head
346 pBASM
->SetUpdateChain( pArea
);
347 pBASM
->SetEOUpdateChain( pArea
);
356 void ScBroadcastAreaSlot::UpdateInsert( ScBroadcastArea
* pArea
)
358 ::std::pair
< ScBroadcastAreas::iterator
, bool > aPair
=
359 aBroadcastAreaTbl
.insert( pArea
);
364 // Identical area already exists, add listeners.
365 ScBroadcastArea
* pTarget
= *(aPair
.first
);
366 if (pArea
!= pTarget
)
368 SvtBroadcaster
& rTarget
= pTarget
->GetBroadcaster();
369 SvtListenerIter
it( pArea
->GetBroadcaster());
370 for (SvtListener
* pListener
= it
.GetCurr(); pListener
;
371 pListener
= it
.GoNext())
373 pListener
->StartListening( rTarget
);
380 // --- ScBroadcastAreaSlotMachine -------------------------------------
382 ScBroadcastAreaSlotMachine::TableSlots::TableSlots()
384 ppSlots
= new ScBroadcastAreaSlot
* [ BCA_SLOTS
];
385 memset( ppSlots
, 0 , sizeof( ScBroadcastAreaSlot
* ) * BCA_SLOTS
);
389 ScBroadcastAreaSlotMachine::TableSlots::~TableSlots()
391 for ( ScBroadcastAreaSlot
** pp
= ppSlots
+ BCA_SLOTS
; --pp
>= ppSlots
; /* nothing */ )
400 ScBroadcastAreaSlotMachine::ScBroadcastAreaSlotMachine(
401 ScDocument
* pDocument
) :
404 pUpdateChain( NULL
),
405 pEOUpdateChain( NULL
),
406 nInBulkBroadcast( 0 )
408 for (TableSlotsMap::iterator
iTab( aTableSlotsMap
.begin());
409 iTab
!= aTableSlotsMap
.end(); ++iTab
)
411 delete (*iTab
).second
;
416 ScBroadcastAreaSlotMachine::~ScBroadcastAreaSlotMachine()
422 inline SCSIZE
ScBroadcastAreaSlotMachine::ComputeSlotOffset(
423 const ScAddress
& rAddress
) const
425 SCROW nRow
= rAddress
.Row();
426 SCCOL nCol
= rAddress
.Col();
427 if ( !ValidRow(nRow
) || !ValidCol(nCol
) )
429 DBG_ASSERT( FALSE
, "Row/Col ungueltig!" );
434 static_cast<SCSIZE
>(nRow
) / BCA_SLOT_ROWS
+
435 static_cast<SCSIZE
>(nCol
) / BCA_SLOT_COLS
* BCA_SLOTS_ROW
;
439 void ScBroadcastAreaSlotMachine::ComputeAreaPoints( const ScRange
& rRange
,
440 SCSIZE
& rStart
, SCSIZE
& rEnd
, SCSIZE
& rRowBreak
) const
442 rStart
= ComputeSlotOffset( rRange
.aStart
);
443 rEnd
= ComputeSlotOffset( rRange
.aEnd
);
444 // count of row slots per column minus one
445 rRowBreak
= ComputeSlotOffset(
446 ScAddress( rRange
.aStart
.Col(), rRange
.aEnd
.Row(), 0 ) ) - rStart
;
450 void ScBroadcastAreaSlotMachine::StartListeningArea( const ScRange
& rRange
,
451 SvtListener
* pListener
)
453 if ( rRange
== BCA_LISTEN_ALWAYS
)
456 pBCAlways
= new SvtBroadcaster
;
457 pListener
->StartListening( *pBCAlways
);
462 for (SCTAB nTab
= rRange
.aStart
.Tab();
463 !bDone
&& nTab
<= rRange
.aEnd
.Tab(); ++nTab
)
465 TableSlotsMap::iterator
iTab( aTableSlotsMap
.find( nTab
));
466 if (iTab
== aTableSlotsMap
.end())
467 iTab
= aTableSlotsMap
.insert( TableSlotsMap::value_type(
468 nTab
, new TableSlots
)).first
;
469 ScBroadcastAreaSlot
** ppSlots
= (*iTab
).second
->getSlots();
470 SCSIZE nStart
, nEnd
, nRowBreak
;
471 ComputeAreaPoints( rRange
, nStart
, nEnd
, nRowBreak
);
472 SCSIZE nOff
= nStart
;
473 SCSIZE nBreak
= nOff
+ nRowBreak
;
474 ScBroadcastAreaSlot
** pp
= ppSlots
+ nOff
;
475 ScBroadcastArea
* pArea
= NULL
;
476 while ( !bDone
&& nOff
<= nEnd
)
479 *pp
= new ScBroadcastAreaSlot( pDoc
, this );
482 // If the call to StartListeningArea didn't create the
483 // ScBroadcastArea, listeners were added to an already
484 // existing identical area that doesn't need to be inserted
486 if (!(*pp
)->StartListeningArea( rRange
, pListener
, pArea
))
490 (*pp
)->InsertListeningArea( pArea
);
498 nStart
+= BCA_SLOTS_ROW
;
501 nBreak
= nOff
+ nRowBreak
;
509 void ScBroadcastAreaSlotMachine::EndListeningArea( const ScRange
& rRange
,
510 SvtListener
* pListener
)
512 if ( rRange
== BCA_LISTEN_ALWAYS
)
514 DBG_ASSERT( pBCAlways
, "ScBroadcastAreaSlotMachine::EndListeningArea: BCA_LISTEN_ALWAYS but none established");
517 pListener
->EndListening( *pBCAlways
);
518 if (!pBCAlways
->HasListeners())
527 SCTAB nEndTab
= rRange
.aEnd
.Tab();
528 for (TableSlotsMap::iterator
iTab( aTableSlotsMap
.lower_bound( rRange
.aStart
.Tab()));
529 iTab
!= aTableSlotsMap
.end() && (*iTab
).first
<= nEndTab
; ++iTab
)
531 ScBroadcastAreaSlot
** ppSlots
= (*iTab
).second
->getSlots();
532 SCSIZE nStart
, nEnd
, nRowBreak
;
533 ComputeAreaPoints( rRange
, nStart
, nEnd
, nRowBreak
);
534 SCSIZE nOff
= nStart
;
535 SCSIZE nBreak
= nOff
+ nRowBreak
;
536 ScBroadcastAreaSlot
** pp
= ppSlots
+ nOff
;
537 ScBroadcastArea
* pArea
= NULL
;
538 if (nOff
== 0 && nEnd
== BCA_SLOTS
-1)
540 // Slightly optimized for 0,0,MAXCOL,MAXROW calls as they
541 // happen for insertion and deletion of sheets.
542 ScBroadcastAreaSlot
** const pStop
= ppSlots
+ nEnd
;
546 (*pp
)->EndListeningArea( rRange
, pListener
, pArea
);
547 } while (++pp
< pStop
);
551 while ( nOff
<= nEnd
)
554 (*pp
)->EndListeningArea( rRange
, pListener
, pArea
);
562 nStart
+= BCA_SLOTS_ROW
;
565 nBreak
= nOff
+ nRowBreak
;
574 BOOL
ScBroadcastAreaSlotMachine::AreaBroadcast( const ScHint
& rHint
) const
576 const ScAddress
& rAddress
= rHint
.GetAddress();
577 if ( rAddress
== BCA_BRDCST_ALWAYS
)
581 pBCAlways
->Broadcast( rHint
);
589 TableSlotsMap::const_iterator
iTab( aTableSlotsMap
.find( rAddress
.Tab()));
590 if (iTab
== aTableSlotsMap
.end())
592 ScBroadcastAreaSlot
* pSlot
= (*iTab
).second
->getAreaSlot(
593 ComputeSlotOffset( rAddress
));
595 return pSlot
->AreaBroadcast( rHint
);
602 BOOL
ScBroadcastAreaSlotMachine::AreaBroadcastInRange( const ScRange
& rRange
,
603 const ScHint
& rHint
) const
605 BOOL bBroadcasted
= FALSE
;
606 SCTAB nEndTab
= rRange
.aEnd
.Tab();
607 for (TableSlotsMap::const_iterator
iTab( aTableSlotsMap
.lower_bound( rRange
.aStart
.Tab()));
608 iTab
!= aTableSlotsMap
.end() && (*iTab
).first
<= nEndTab
; ++iTab
)
610 ScBroadcastAreaSlot
** ppSlots
= (*iTab
).second
->getSlots();
611 SCSIZE nStart
, nEnd
, nRowBreak
;
612 ComputeAreaPoints( rRange
, nStart
, nEnd
, nRowBreak
);
613 SCSIZE nOff
= nStart
;
614 SCSIZE nBreak
= nOff
+ nRowBreak
;
615 ScBroadcastAreaSlot
** pp
= ppSlots
+ nOff
;
616 while ( nOff
<= nEnd
)
619 bBroadcasted
|= (*pp
)->AreaBroadcastInRange( rRange
, rHint
);
627 nStart
+= BCA_SLOTS_ROW
;
630 nBreak
= nOff
+ nRowBreak
;
638 void ScBroadcastAreaSlotMachine::DelBroadcastAreasInRange(
639 const ScRange
& rRange
)
641 SCTAB nEndTab
= rRange
.aEnd
.Tab();
642 for (TableSlotsMap::iterator
iTab( aTableSlotsMap
.lower_bound( rRange
.aStart
.Tab()));
643 iTab
!= aTableSlotsMap
.end() && (*iTab
).first
<= nEndTab
; ++iTab
)
645 ScBroadcastAreaSlot
** ppSlots
= (*iTab
).second
->getSlots();
646 SCSIZE nStart
, nEnd
, nRowBreak
;
647 ComputeAreaPoints( rRange
, nStart
, nEnd
, nRowBreak
);
648 SCSIZE nOff
= nStart
;
649 SCSIZE nBreak
= nOff
+ nRowBreak
;
650 ScBroadcastAreaSlot
** pp
= ppSlots
+ nOff
;
651 if (nOff
== 0 && nEnd
== BCA_SLOTS
-1)
653 // Slightly optimized for 0,0,MAXCOL,MAXROW calls as they
654 // happen for insertion and deletion of sheets.
655 ScBroadcastAreaSlot
** const pStop
= ppSlots
+ nEnd
;
659 (*pp
)->DelBroadcastAreasInRange( rRange
);
660 } while (++pp
< pStop
);
664 while ( nOff
<= nEnd
)
667 (*pp
)->DelBroadcastAreasInRange( rRange
);
675 nStart
+= BCA_SLOTS_ROW
;
678 nBreak
= nOff
+ nRowBreak
;
686 // for all affected: remove, chain, update range, insert, and maybe delete
687 void ScBroadcastAreaSlotMachine::UpdateBroadcastAreas(
688 UpdateRefMode eUpdateRefMode
,
689 const ScRange
& rRange
, SCsCOL nDx
, SCsROW nDy
, SCsTAB nDz
)
691 // remove affected and put in chain
692 SCTAB nEndTab
= rRange
.aEnd
.Tab();
693 for (TableSlotsMap::iterator
iTab( aTableSlotsMap
.lower_bound( rRange
.aStart
.Tab()));
694 iTab
!= aTableSlotsMap
.end() && (*iTab
).first
<= nEndTab
; ++iTab
)
696 ScBroadcastAreaSlot
** ppSlots
= (*iTab
).second
->getSlots();
697 SCSIZE nStart
, nEnd
, nRowBreak
;
698 ComputeAreaPoints( rRange
, nStart
, nEnd
, nRowBreak
);
699 SCSIZE nOff
= nStart
;
700 SCSIZE nBreak
= nOff
+ nRowBreak
;
701 ScBroadcastAreaSlot
** pp
= ppSlots
+ nOff
;
702 if (nOff
== 0 && nEnd
== BCA_SLOTS
-1)
704 // Slightly optimized for 0,0,MAXCOL,MAXROW calls as they
705 // happen for insertion and deletion of sheets.
706 ScBroadcastAreaSlot
** const pStop
= ppSlots
+ nEnd
;
710 (*pp
)->UpdateRemove( eUpdateRefMode
, rRange
, nDx
, nDy
, nDz
);
711 } while (++pp
< pStop
);
715 while ( nOff
<= nEnd
)
718 (*pp
)->UpdateRemove( eUpdateRefMode
, rRange
, nDx
, nDy
, nDz
);
726 nStart
+= BCA_SLOTS_ROW
;
729 nBreak
= nOff
+ nRowBreak
;
740 TableSlotsMap::iterator
iDel( aTableSlotsMap
.lower_bound( rRange
.aStart
.Tab()));
741 TableSlotsMap::iterator
iTab( aTableSlotsMap
.lower_bound( rRange
.aStart
.Tab() - nDz
));
742 // Remove sheets, if any, iDel or/and iTab may as well point to end().
745 delete (*iDel
).second
;
746 aTableSlotsMap
.erase( iDel
++);
748 // shift remaining down
749 while (iTab
!= aTableSlotsMap
.end())
751 SCTAB nTab
= (*iTab
).first
+ nDz
;
752 aTableSlotsMap
[nTab
] = (*iTab
).second
;
753 aTableSlotsMap
.erase( iTab
++);
758 TableSlotsMap::iterator
iStop( aTableSlotsMap
.lower_bound( rRange
.aStart
.Tab()));
759 if (iStop
!= aTableSlotsMap
.end())
761 bool bStopIsBegin
= (iStop
== aTableSlotsMap
.begin());
764 TableSlotsMap::iterator
iTab( aTableSlotsMap
.end());
766 while (iTab
!= iStop
)
768 SCTAB nTab
= (*iTab
).first
+ nDz
;
769 aTableSlotsMap
[nTab
] = (*iTab
).second
;
770 aTableSlotsMap
.erase( iTab
--);
772 // Shift the very first, iTab==iStop in this case.
775 SCTAB nTab
= (*iTab
).first
+ nDz
;
776 aTableSlotsMap
[nTab
] = (*iTab
).second
;
777 aTableSlotsMap
.erase( iStop
);
784 SCCOL nCol1
, nCol2
, theCol1
, theCol2
;
785 SCROW nRow1
, nRow2
, theRow1
, theRow2
;
786 SCTAB nTab1
, nTab2
, theTab1
, theTab2
;
787 rRange
.GetVars( nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
);
788 while ( pUpdateChain
)
790 ScBroadcastArea
* pArea
= pUpdateChain
;
791 ScRange
aRange( pArea
->GetRange());
792 pUpdateChain
= pArea
->GetUpdateChainNext();
795 aRange
.GetVars( theCol1
, theRow1
, theTab1
, theCol2
, theRow2
, theTab2
);
796 if ( ScRefUpdate::Update( pDoc
, eUpdateRefMode
,
797 nCol1
,nRow1
,nTab1
, nCol2
,nRow2
,nTab2
, nDx
,nDy
,nDz
,
798 theCol1
,theRow1
,theTab1
, theCol2
,theRow2
,theTab2
))
800 aRange
= ScRange( theCol1
,theRow1
,theTab1
, theCol2
,theRow2
,theTab2
);
801 pArea
->UpdateRange( aRange
);
802 pArea
->GetBroadcaster().Broadcast( ScAreaChangedHint( aRange
) ); // for DDE
806 for (SCTAB nTab
= aRange
.aStart
.Tab(); nTab
<= aRange
.aEnd
.Tab(); ++nTab
)
808 TableSlotsMap::iterator
iTab( aTableSlotsMap
.find( nTab
));
809 if (iTab
== aTableSlotsMap
.end())
810 iTab
= aTableSlotsMap
.insert( TableSlotsMap::value_type(
811 nTab
, new TableSlots
)).first
;
812 ScBroadcastAreaSlot
** ppSlots
= (*iTab
).second
->getSlots();
813 SCSIZE nStart
, nEnd
, nRowBreak
;
814 ComputeAreaPoints( aRange
, nStart
, nEnd
, nRowBreak
);
815 SCSIZE nOff
= nStart
;
816 SCSIZE nBreak
= nOff
+ nRowBreak
;
817 ScBroadcastAreaSlot
** pp
= ppSlots
+ nOff
;
818 while ( nOff
<= nEnd
)
821 *pp
= new ScBroadcastAreaSlot( pDoc
, this );
822 (*pp
)->UpdateInsert( pArea
);
830 nStart
+= BCA_SLOTS_ROW
;
833 nBreak
= nOff
+ nRowBreak
;
839 pArea
->SetUpdateChainNext( NULL
);
840 pArea
->SetInUpdateChain( FALSE
);
842 // Delete if not inserted to any slot. RemoveBulkArea(pArea) was
843 // already executed in UpdateRemove().
844 if (!pArea
->GetRef())
847 pEOUpdateChain
= NULL
;
851 void ScBroadcastAreaSlotMachine::EnterBulkBroadcast()
857 void ScBroadcastAreaSlotMachine::LeaveBulkBroadcast()
859 if (nInBulkBroadcast
> 0)
861 if (--nInBulkBroadcast
== 0)
862 ScBroadcastAreasBulk().swap( aBulkBroadcastAreas
);
867 bool ScBroadcastAreaSlotMachine::InsertBulkArea( const ScBroadcastArea
* pArea
)
869 return aBulkBroadcastAreas
.insert( pArea
).second
;
873 size_t ScBroadcastAreaSlotMachine::RemoveBulkArea( const ScBroadcastArea
* pArea
)
875 return aBulkBroadcastAreas
.erase( pArea
);