23#include <osl/diagnose.h>
25#include <document.hxx>
34#include <broadcast.hxx>
37 pUpdateChainNext(nullptr),
40 mbInUpdateChain(false),
41 mbGroupListening(false) {}
45 aTmpSeekBroadcastArea(
ScRange()),
48 mbInBroadcastIteration( false),
49 mbHasErasedArea(false)
77 OSL_ENSURE( pShell,
"Missing DocShell :-/" );
93 bool bNewArea =
false;
94 OSL_ENSURE(pListener,
"StartListeningArea: pListener Null");
104 ScBroadcastAreas::const_iterator aIter(
FindBroadcastArea( rRange, bGroupListening));
106 rpArea = (*aIter).mpArea;
118 OSL_FAIL(
"StartListeningArea: area not found and not inserted in slot?!?");
136 OSL_ENSURE( pArea,
"InsertListeningArea: pArea NULL");
148 OSL_ENSURE(pListener,
"EndListeningArea: pListener Null");
154 rpArea = (*aIter).mpArea;
158 if (rpArea->
GetRef() == 1)
170 OSL_ENSURE( (*aIter).mpArea == rpArea,
"EndListeningArea: area pointer mismatch");
171 if (rpArea->
GetRef() == 1)
179 const ScRange& rRange,
bool bGroupListening )
193 aHint.SetAddressTab(nTab);
196 aHint.SetAddressCol(nCol);
199 aHint.SetAddressRow(nRow);
215 bool bIsBroadcasted =
false;
241 broadcastRangeByCell(pArea->
GetBroadcaster(), aIntersection, nHint);
242 bIsBroadcasted =
true;
247 broadcastRangeByCell(pArea->
GetBroadcaster(), aIntersection, nHint);
248 bIsBroadcasted =
true;
259 return bIsBroadcasted;
269 bool bIsBroadcasted =
false;
293 bIsBroadcasted =
true;
299 bIsBroadcasted =
true;
311 return bIsBroadcasted;
321 const ScRange& rAreaRange = (*aIter).mpArea->GetRange();
344 SCCOL nCol1, nCol2, theCol1, theCol2;
345 SCROW nRow1, nRow2, theRow1, theRow2;
346 SCTAB nTab1, nTab2, theTab1, theTab2;
347 rRange.
GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
359 pArea->
GetRange().
GetVars( theCol1, theRow1, theTab1, theCol2, theRow2, theTab2);
361 nCol1,nRow1,nTab1, nCol2,nRow2,nTab2, nDx,nDy,nDz,
362 theCol1,theRow1,theTab1, theCol2,theRow2,theTab2 ))
387 if ((*aIter).mpArea != pArea)
388 OSL_FAIL(
"UpdateRemoveArea: area pointer mismatch");
398 ::std::pair< ScBroadcastAreas::iterator, bool > aPair =
406 if (pArea != pTarget)
410 for (
auto& pListener : rListeners)
423 (*rIter).mbErasure =
true;
441 const ScRange& rRange, std::vector<sc::AreaListener>& rListeners,
490 for (
const auto& pListener : rLst)
493 aEntry.
maArea = rAreaRange;
496 rListeners.push_back(aEntry);
505 const ScRange& rRange = rEntry.mpArea->GetRange();
507 auto& rLisStore = aRes.first->second;
509 for (
const SvtListener* pLis : rEntry.mpArea->GetBroadcaster().GetAllListeners())
511 if (
auto pFC =
dynamic_cast<const ScFormulaCell*
>(pLis); pFC)
513 rLisStore.emplace_back(pFC);
519 rLisStore.emplace_back(pFGL);
523 rLisStore.emplace_back(pLis);
536 : mnBcaSlots(nBcaSlots)
544 , ppSlots( std::move(rOther.ppSlots) )
576 sal_Int32 nCol2 = 1024;
578 while (nCol2 <= pDoc->GetMaxColCount())
581 SCROW nRow2 = 32*1024;
584 SCSIZE nSlotsStartCol = nSlots;
586 while (nRow2 <= pDoc->GetMaxRowCount())
588 maSlotDistribution.emplace_back(nRow1, nRow2, nSliceRow, nSlotsCol, nCol1, nCol2, nSliceCol, nSlotsStartCol);
589 nSlotsCol += (nRow2 - nRow1) / nSliceRow;
599 nSlots += (nCol2 - nCol1) / nSliceCol * nSlotsCol;
626 OSL_FAIL(
"Row/Col invalid, using first slot!" );
631 if (nRow < rSD.nStopRow && nCol < rSD.nStopCol)
633 assert(nRow >= rSD.nStartRow);
634 assert(nCol >= rSD.nStartCol);
635 SCSIZE slot = rSD.nCumulatedRow
636 +
static_cast<SCSIZE>(nRow - rSD.nStartRow) / rSD.nSliceRow
643 OSL_FAIL(
"No slot found, using last!" );
667 nStart += nBcaSlotsCol;
670 nBreak = nOff + nRowBreak;
686 constexpr SCSIZE nSliceRow = 128;
687 constexpr SCSIZE nSliceCol = 16;
727 SCSIZE nStart, nEnd, nRowBreak;
729 assert( nStart == 0 );
732 SCSIZE nBreak = nOff + nRowBreak;
736 while ( nOff <= nEnd )
740 compare( nOff, previous + 1, __LINE__ );
749 nBreak = nOff + nRowBreak;
750 ppSlots = slots.get();
752 while ( nOff <= nEnd )
779 !bDone && nTab <= rRange.
aEnd.
Tab(); ++nTab)
784 std::forward_as_tuple(nTab), std::forward_as_tuple(
mnBcaSlots) ).first;
786 SCSIZE nStart, nEnd, nRowBreak;
789 SCSIZE nBreak = nOff + nRowBreak;
791 while ( !bDone && nOff <= nEnd )
801 if (!(*pp)->StartListeningArea( rRange, bGroupListening, pListener, pArea))
805 (*pp)->InsertListeningArea( pArea);
833 SCSIZE nStart, nEnd, nRowBreak;
836 SCSIZE nBreak = nOff + nRowBreak;
848 }
while (++pp < pStop);
852 while ( nOff <= nEnd )
855 (*pp)->EndListeningArea( rRange, bGroupListening, pListener, pArea);
865 bool bBroadcasted =
false;
871 SCSIZE nStart, nEnd, nRowBreak;
874 SCSIZE nBreak = nOff + nRowBreak;
876 while ( nOff <= nEnd )
905 ScRange broadcastRange( rAddress,
907 bool bBroadcasted =
false;
909 SCSIZE nStart, nEnd, nRowBreak;
912 SCSIZE nBreak = nOff + nRowBreak;
914 while ( nOff <= nEnd )
932 SCSIZE nStart, nEnd, nRowBreak;
935 SCSIZE nBreak = nOff + nRowBreak;
946 }
while (++pp < pStop);
950 while ( nOff <= nEnd )
953 (*pp)->DelBroadcastAreasInRange( rRange );
971 SCSIZE nStart, nEnd, nRowBreak;
974 SCSIZE nBreak = nOff + nRowBreak;
984 (*pp)->
UpdateRemove( eUpdateRefMode, rRange, nDx, nDy, nDz );
985 }
while (++pp < pStop);
989 while ( nOff <= nEnd )
992 (*pp)->UpdateRemove( eUpdateRefMode, rRange, nDx, nDy, nDz );
1012 OSL_FAIL(
"UpdateBroadcastAreas: Where's the TableSlot?!?");
1016 SCSIZE nStart, nEnd, nRowBreak;
1019 SCSIZE nBreak = nOff + nRowBreak;
1021 while ( nOff <= nEnd && pArea->
GetRef() )
1039 while (iDel != iTab)
1046 SCTAB nTab = (*iTab).first + nDz;
1061 while (iTab != iStop)
1063 SCTAB nTab = (*iTab).first + nDz;
1070 SCTAB nTab = (*iTab).first + nDz;
1079 SCCOL nCol1, nCol2, theCol1, theCol2;
1080 SCROW nRow1, nRow2, theRow1, theRow2;
1081 SCTAB nTab1, nTab2, theTab1, theTab2;
1082 rRange.
GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
1090 aRange.
GetVars( theCol1, theRow1, theTab1, theCol2, theRow2, theTab2);
1092 nCol1,nRow1,nTab1, nCol2,nRow2,nTab2, nDx,nDy,nDz,
1093 theCol1,theRow1,theTab1, theCol2,theRow2,theTab2 ))
1095 aRange =
ScRange( theCol1,theRow1,theTab1, theCol2,theRow2,theTab2 );
1107 std::forward_as_tuple(nTab), std::forward_as_tuple(
mnBcaSlots) ).first;
1109 SCSIZE nStart, nEnd, nRowBreak;
1112 SCSIZE nBreak = nOff + nRowBreak;
1114 while ( nOff <= nEnd )
1118 (*pp)->UpdateInsert( pArea );
1152 else if (bBroadcasted)
1182 bool bBroadcasted =
false;
1191 SAL_WARN(
"sc.core",
"ScBroadcastAreaSlotMachine::BulkBroadcastGroupAreas - pArea has no listeners and should had been removed already");
1197 bBroadcasted =
true;
1203 return bBroadcasted;
1217 ScBroadcastAreas::iterator& rIter )
1225 "ScBroadcastAreaSlotMachine::FinallyEraseAreas: during iteration? NO!");
1235 if (rArea.first == pSlot)
1238 aCopy.push_back( rArea);
1246 std::vector<sc::AreaListener> aRet;
1250 iTab !=
aTableSlotsMap.end() && (*iTab).first <= nEndTab; ++iTab)
1253 SCSIZE nStart, nEnd, nRowBreak;
1256 SCSIZE nBreak = nOff + nRowBreak;
1258 while ( nOff <= nEnd )
1262 p->GetAllListeners(rRange, aRet,
eType, eGroup);
size_t SCSIZE
size_t typedef to be able to find places where code was changed from USHORT to size_t and is used to ...
#define BCA_LISTEN_ALWAYS
#define BCA_BRDCST_ALWAYS
static void ComputeNextSlot(SCSIZE &nOff, SCSIZE &nBreak, ScBroadcastAreaSlot **&pp, SCSIZE &nStart, ScBroadcastAreaSlot **const &ppSlots, SCSIZE nRowBreak, SCSIZE nBcaSlotsCol)
static void compare(SCSIZE value1, SCSIZE value2, int line)
std::unordered_set< const ScBroadcastArea *, ScBroadcastAreaBulkHash, ScBroadcastAreaBulkEqual > ScBroadcastAreasBulk
Slot offset arrangement of columns and rows, once per sheet.
TableSlots(SCSIZE nBcaSlots)
std::unique_ptr< ScBroadcastAreaSlot *[]> ppSlots
BroadcastAreaSlots and their management, once per document.
bool BulkBroadcastGroupAreas(SfxHintId nHintId)
ScBroadcastAreaSlotMachine(ScDocument *pDoc)
void ComputeAreaPoints(const ScRange &rRange, SCSIZE &nStart, SCSIZE &nEnd, SCSIZE &nRowBreak) const
BulkGroupAreasType m_BulkGroupAreas
AreasToBeErased maAreasToBeErased
void FinallyEraseAreas(ScBroadcastAreaSlot *pSlot)
void LeaveBulkBroadcast(SfxHintId nHintId)
ScBroadcastArea * GetEOUpdateChain() const
std::unique_ptr< SvtBroadcaster > pBCAlways
void SetEOUpdateChain(ScBroadcastArea *p)
std::vector< sc::AreaListener > GetAllListeners(const ScRange &rRange, sc::AreaOverlapType eType, sc::ListenerGroupType eGroup=sc::ListenerGroupType::Both)
TableSlotsMap aTableSlotsMap
bool IsInBulkBroadcast() const
ScSlotDistribution maSlotDistribution
void StartListeningArea(const ScRange &rRange, bool bGroupListening, SvtListener *pListener)
ScBroadcastAreasBulk aBulkBroadcastAreas
void UpdateBroadcastAreas(UpdateRefMode eUpdateRefMode, const ScRange &rRange, SCCOL nDx, SCROW nDy, SCTAB nDz)
void EndListeningArea(const ScRange &rRange, bool bGroupListening, SvtListener *pListener)
bool InsertBulkArea(const ScBroadcastArea *p)
size_t RemoveBulkArea(const ScBroadcastArea *p)
void CollectBroadcasterState(sc::BroadcasterState &rState) const
void DelBroadcastAreasInRange(const ScRange &rRange)
ScBroadcastArea * pEOUpdateChain
ScBroadcastArea * pUpdateChain
bool AreaBroadcast(const ScRange &rRange, SfxHintId nHint)
::std::vector< ::std::pair< ScBroadcastAreaSlot *, ScBroadcastAreas::iterator > > AreasToBeErased
void EnterBulkBroadcast()
sal_uInt32 nInBulkBroadcast
void RemoveBulkGroupArea(ScBroadcastArea *pArea)
void SetUpdateChain(ScBroadcastArea *p)
void PushAreaToBeErased(ScBroadcastAreaSlot *pSlot, ScBroadcastAreas::iterator &rIter)
void InsertBulkGroupArea(ScBroadcastArea *pArea, const ScRange &rRange)
SCSIZE ComputeSlotOffset(const ScAddress &rAddress) const
~ScBroadcastAreaSlotMachine()
Collection of BroadcastAreas.
ScBroadcastAreas::iterator FindBroadcastArea(const ScRange &rRange, bool bGroupListening)
bool IsInBroadcastIteration() const
void CollectBroadcasterState(sc::BroadcasterState &rState) const
void UpdateRemove(UpdateRefMode eUpdateRefMode, const ScRange &rRange, SCCOL nDx, SCROW nDy, SCTAB nDz)
bool mbInBroadcastIteration
ScBroadcastArea aTmpSeekBroadcastArea
ScBroadcastAreas aBroadcastAreaTbl
void FinallyEraseAreas()
Finally erase all areas pushed as to-be-erased.
bool AreaBroadcast(const ScRange &rRange, SfxHintId nHint)
static bool isMarkedErased(const ScBroadcastAreas::const_iterator &rIter)
void UpdateRemoveArea(ScBroadcastArea *pArea)
ScBroadcastAreaSlot(ScDocument *pDoc, ScBroadcastAreaSlotMachine *pBASM)
void DelBroadcastAreasInRange(const ScRange &rRange)
bool StartListeningArea(const ScRange &rRange, bool bGroupListening, SvtListener *pListener, ScBroadcastArea *&rpArea)
Only here new ScBroadcastArea objects are created, prevention of dupes.
void InsertListeningArea(ScBroadcastArea *pArea)
Insert a ScBroadcastArea obtained via StartListeningArea() to subsequent slots.
ScBroadcastAreaSlotMachine * pBASM
void EraseArea(ScBroadcastAreas::iterator &rIter)
Erase an area from set and delete it if last reference, or if mbInBroadcastIteration is set push it t...
ScDocument::HardRecalcState CheckHardRecalcStateCondition() const
More hypothetical (memory would probably be doomed anyway) check whether there would be an overflow w...
void UpdateInsert(ScBroadcastArea *pArea)
bool mbHasErasedArea
If true, the slot has at least one area broadcaster marked for removal.
void EndListeningArea(const ScRange &rRange, bool bGroupListening, SvtListener *pListener, ScBroadcastArea *&rpArea)
void GetAllListeners(const ScRange &rRange, std::vector< sc::AreaListener > &rListeners, sc::AreaOverlapType eType, sc::ListenerGroupType eGroup)
Used in a Unique Associative Container.
ScBroadcastArea * GetUpdateChainNext() const
const ScRange & GetRange() const
bool IsInUpdateChain() const
ScBroadcastArea(const ScBroadcastArea &)=delete
void SetGroupListening(bool b)
void UpdateRange(const ScRange &rNewRange)
void SetInUpdateChain(bool b)
void SetUpdateChainNext(ScBroadcastArea *p)
bool IsGroupListening() const
SvtBroadcaster & GetBroadcaster()
void TrackFormulas(SfxHintId nHintId=SfxHintId::ScDataChanged)
void FinalTrackFormulas(SfxHintId nHintId)
bool ValidRow(SCROW nRow) const
SC_DLLPUBLIC SCCOL MaxCol() const
SC_DLLPUBLIC SCROW GetMaxRowCount() const
HardRecalcState GetHardRecalcState() const
SC_DLLPUBLIC SCROW MaxRow() const
bool IsDelayedFormulaGrouping() const
@ ETERNAL
CalcAll() without broadcast/notify but setting up new listeners.
SfxObjectShell * GetDocumentShell() const
bool ValidCol(SCCOL nCol) const
SC_DLLPUBLIC void SetAutoCalc(bool bNewAutoCalc)
void SetHardRecalcState(HardRecalcState eVal)
SC_DLLPUBLIC SCCOL GetMaxColCount() const
bool IsTrackFormulasPending() const
SCROW GetRowCount() const
const ScAddress & GetStartAddress() const
ScRange Intersection(const ScRange &rOther) const
void GetVars(SCCOL &nCol1, SCROW &nRow1, SCTAB &nTab1, SCCOL &nCol2, SCROW &nRow2, SCTAB &nTab2) const
bool Intersects(const ScRange &rRange) const
bool Contains(const ScAddress &) const
is Address& fully in Range?
static ScRefUpdateRes Update(const ScDocument *pDoc, UpdateRefMode eUpdateRefMode, SCCOL nCol1, SCROW nRow1, SCTAB nTab1, SCCOL nCol2, SCROW nRow2, SCTAB nTab2, SCCOL nDx, SCROW nDy, SCTAB nDz, SCCOL &theCol1, SCROW &theRow1, SCTAB &theTab1, SCCOL &theCol2, SCROW &theRow2, SCTAB &theTab2)
void SetError(ErrCode rErr)
bool HasListeners() const
void Broadcast(const SfxHint &rHint)
std::vector< SvtListener * > ListenersType
ListenersType & GetAllListeners()
bool StartListening(SvtBroadcaster &rBroadcaster)
void EndListening(SvtBroadcaster &rBroadcaster)
void setSpans(const ColumnSpanSet *pSpans)
Structure that stores segments of boolean flags per column, and perform custom action on those segmen...
#define SAL_WARN_IF(condition, area, stream)
#define SAL_WARN(area, stream)
#define SCWARN_CORE_HARD_RECALC
std::map< ScRange, std::vector< AreaListener > > aAreaListenerStore