23 #include <osl/diagnose.h>
25 #include <document.hxx>
33 #if DEBUG_AREA_BROADCASTER
39 pUpdateChainNext(nullptr),
42 mbInUpdateChain(
false),
43 mbGroupListening(
false) {}
47 aTmpSeekBroadcastArea(
ScRange()),
50 mbInBroadcastIteration(
false),
51 mbHasErasedArea(
false)
79 OSL_ENSURE( pShell,
"Missing DocShell :-/" );
95 bool bNewArea =
false;
96 OSL_ENSURE(pListener,
"StartListeningArea: pListener Null");
106 ScBroadcastAreas::const_iterator aIter(
FindBroadcastArea( rRange, bGroupListening));
108 rpArea = (*aIter).mpArea;
120 OSL_FAIL(
"StartListeningArea: area not found and not inserted in slot?!?");
130 if (aBroadcastAreaTbl.insert( rpArea).second)
138 OSL_ENSURE( pArea,
"InsertListeningArea: pArea NULL");
150 OSL_ENSURE(pListener,
"EndListeningArea: pListener Null");
156 rpArea = (*aIter).mpArea;
160 if (rpArea->
GetRef() == 1)
172 OSL_ENSURE( (*aIter).mpArea == rpArea,
"EndListeningArea: area pointer mismatch");
173 if (rpArea->
GetRef() == 1)
181 const ScRange& rRange,
bool bGroupListening )
195 aHint.SetAddressTab(nTab);
198 aHint.SetAddressCol(nCol);
201 aHint.SetAddressRow(nRow);
217 bool bIsBroadcasted =
false;
243 broadcastRangeByCell(pArea->
GetBroadcaster(), aIntersection, nHint);
244 bIsBroadcasted =
true;
249 broadcastRangeByCell(pArea->
GetBroadcaster(), aIntersection, nHint);
250 bIsBroadcasted =
true;
261 return bIsBroadcasted;
271 bool bIsBroadcasted =
false;
295 bIsBroadcasted =
true;
301 bIsBroadcasted =
true;
313 return bIsBroadcasted;
323 const ScRange& rAreaRange = (*aIter).mpArea->GetRange();
346 SCCOL nCol1, nCol2, theCol1, theCol2;
347 SCROW nRow1, nRow2, theRow1, theRow2;
348 SCTAB nTab1, nTab2, theTab1, theTab2;
349 rRange.
GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
361 pArea->
GetRange().
GetVars( theCol1, theRow1, theTab1, theCol2, theRow2, theTab2);
363 nCol1,nRow1,nTab1, nCol2,nRow2,nTab2, nDx,nDy,nDz,
364 theCol1,theRow1,theTab1, theCol2,theRow2,theTab2 ))
389 if ((*aIter).mpArea != pArea)
390 OSL_FAIL(
"UpdateRemoveArea: area pointer mismatch");
400 ::std::pair< ScBroadcastAreas::iterator, bool > aPair =
408 if (pArea != pTarget)
412 for (
auto& pListener : rListeners)
425 (*rIter).mbErasure =
true;
443 const ScRange& rRange, std::vector<sc::AreaListener>& rListeners,
492 for (
const auto& pListener : rLst)
495 aEntry.
maArea = rAreaRange;
498 rListeners.push_back(aEntry);
503 #if DEBUG_AREA_BROADCASTER
504 void ScBroadcastAreaSlot::Dump()
const
511 size_t n = rListeners.size();
515 <<
", listener count: " << n <<
endl;
517 for (
size_t i = 0;
i < n; ++
i)
522 cout <<
" * listener: formula cell: "
531 cout <<
" * listener: formula group: (pos: "
533 <<
", length: " << pFGListener->getGroupLength()
538 cout <<
" * listener: unknown" << endl;
552 : mnBcaSlots(nBcaSlots)
585 sal_Int32 nCol2 = 1024;
587 while (nCol2 <= pDoc->GetMaxColCount())
590 SCROW nRow2 = 32*1024;
593 SCSIZE nSlotsStartCol = nSlots;
595 while (nRow2 <= pDoc->GetMaxRowCount())
597 maSlotDistribution.emplace_back(nRow1, nRow2, nSliceRow, nSlotsCol, nCol1, nCol2, nSliceCol, nSlotsStartCol);
598 nSlotsCol += (nRow2 - nRow1) / nSliceRow;
608 nSlots += (nCol2 - nCol1) / nSliceCol * nSlotsCol;
635 OSL_FAIL(
"Row/Col invalid, using first slot!" );
640 if (nRow < rSD.nStopRow && nCol < rSD.nStopCol)
642 assert(nRow >= rSD.nStartRow);
643 assert(nCol >= rSD.nStartCol);
644 SCSIZE slot = rSD.nCumulatedRow
645 +
static_cast<SCSIZE>(nRow - rSD.nStartRow) / rSD.nSliceRow
647 + static_cast<SCSIZE>(nCol - rSD.nStartCol) / rSD.nSliceCol *
mnBcaSlotsCol;
652 OSL_FAIL(
"No slot found, using last!" );
676 nStart += nBcaSlotsCol;
679 nBreak = nOff + nRowBreak;
687 SAL_WARN(
"sc",
"V1:" << value1 <<
" V2:" << value2 <<
" (" << line <<
")");
688 assert(value1 == value2);
695 constexpr
SCSIZE nSliceRow = 128;
696 constexpr
SCSIZE nSliceCol = 16;
736 SCSIZE nStart, nEnd, nRowBreak;
738 assert( nStart == 0 );
741 SCSIZE nBreak = nOff + nRowBreak;
745 while ( nOff <= nEnd )
749 compare( nOff, previous + 1, __LINE__ );
756 assert( nEnd == mnBcaSlots - 1 );
758 nBreak = nOff + nRowBreak;
759 ppSlots = slots.get();
761 while ( nOff <= nEnd )
788 !bDone && nTab <= rRange.
aEnd.
Tab(); ++nTab)
794 SCSIZE nStart, nEnd, nRowBreak;
797 SCSIZE nBreak = nOff + nRowBreak;
799 while ( !bDone && nOff <= nEnd )
809 if (!(*pp)->StartListeningArea( rRange, bGroupListening, pListener, pArea))
813 (*pp)->InsertListeningArea( pArea);
841 SCSIZE nStart, nEnd, nRowBreak;
844 SCSIZE nBreak = nOff + nRowBreak;
856 }
while (++pp < pStop);
860 while ( nOff <= nEnd )
863 (*pp)->EndListeningArea( rRange, bGroupListening, pListener, pArea);
873 bool bBroadcasted =
false;
879 SCSIZE nStart, nEnd, nRowBreak;
882 SCSIZE nBreak = nOff + nRowBreak;
884 while ( nOff <= nEnd )
913 ScRange broadcastRange( rAddress,
915 bool bBroadcasted =
false;
917 SCSIZE nStart, nEnd, nRowBreak;
920 SCSIZE nBreak = nOff + nRowBreak;
922 while ( nOff <= nEnd )
940 SCSIZE nStart, nEnd, nRowBreak;
943 SCSIZE nBreak = nOff + nRowBreak;
954 }
while (++pp < pStop);
958 while ( nOff <= nEnd )
961 (*pp)->DelBroadcastAreasInRange( rRange );
979 SCSIZE nStart, nEnd, nRowBreak;
982 SCSIZE nBreak = nOff + nRowBreak;
992 (*pp)->
UpdateRemove( eUpdateRefMode, rRange, nDx, nDy, nDz );
993 }
while (++pp < pStop);
997 while ( nOff <= nEnd )
1000 (*pp)->UpdateRemove( eUpdateRefMode, rRange, nDx, nDy, nDz );
1015 for (
SCTAB nTab = aRange.aStart.Tab(); nTab <= aRange.aEnd.Tab() && pArea->
GetRef(); ++nTab)
1020 OSL_FAIL(
"UpdateBroadcastAreas: Where's the TableSlot?!?");
1024 SCSIZE nStart, nEnd, nRowBreak;
1027 SCSIZE nBreak = nOff + nRowBreak;
1029 while ( nOff <= nEnd && pArea->
GetRef() )
1047 while (iDel != iTab)
1054 SCTAB nTab = (*iTab).first + nDz;
1069 while (iTab != iStop)
1071 SCTAB nTab = (*iTab).first + nDz;
1078 SCTAB nTab = (*iTab).first + nDz;
1087 SCCOL nCol1, nCol2, theCol1, theCol2;
1088 SCROW nRow1, nRow2, theRow1, theRow2;
1089 SCTAB nTab1, nTab2, theTab1, theTab2;
1090 rRange.
GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
1098 aRange.GetVars( theCol1, theRow1, theTab1, theCol2, theRow2, theTab2);
1100 nCol1,nRow1,nTab1, nCol2,nRow2,nTab2, nDx,nDy,nDz,
1101 theCol1,theRow1,theTab1, theCol2,theRow2,theTab2 ))
1103 aRange =
ScRange( theCol1,theRow1,theTab1, theCol2,theRow2,theTab2 );
1110 for (
SCTAB nTab = aRange.aStart.Tab(); nTab <= aRange.aEnd.Tab(); ++nTab)
1116 SCSIZE nStart, nEnd, nRowBreak;
1119 SCSIZE nBreak = nOff + nRowBreak;
1121 while ( nOff <= nEnd )
1125 (*pp)->UpdateInsert( pArea );
1159 else if (bBroadcasted)
1179 rSet.
set(*
pDoc, rRange,
true);
1189 bool bBroadcasted =
false;
1198 SAL_WARN(
"sc.core",
"ScBroadcastAreaSlotMachine::BulkBroadcastGroupAreas - pArea has no listeners and should had been removed already");
1204 bBroadcasted =
true;
1208 m_BulkGroupAreas.clear();
1210 return bBroadcasted;
1224 ScBroadcastAreas::iterator& rIter )
1232 "ScBroadcastAreaSlotMachine::FinallyEraseAreas: during iteration? NO!");
1242 if (rArea.first == pSlot)
1245 aCopy.push_back( rArea);
1247 maAreasToBeErased.swap( aCopy);
1253 std::vector<sc::AreaListener> aRet;
1257 iTab !=
aTableSlotsMap.end() && (*iTab).first <= nEndTab; ++iTab)
1260 SCSIZE nStart, nEnd, nRowBreak;
1263 SCSIZE nBreak = nOff + nRowBreak;
1265 while ( nOff <= nEnd )
1277 #if DEBUG_AREA_BROADCASTER
1278 void ScBroadcastAreaSlotMachine::Dump()
const
1280 cout <<
"slot distribution count: " << nBcaSlots << endl;
1283 cout <<
"-- sheet (index: " << rIndex <<
")" << endl;
1287 for (
SCSIZE i = 0;
i < nBcaSlots; ++
i)
1292 cout <<
"* slot " <<
i << endl;
bool IsInBulkBroadcast() const
SC_DLLPUBLIC void Format(OStringBuffer &r, ScRefFlags nFlags, const ScDocument *pDocument=nullptr, const Details &rDetails=detailsOOOa1) const
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)
#define BCA_LISTEN_ALWAYS
bool IsInBroadcastIteration() const
void EraseArea(ScBroadcastAreas::iterator &rIter)
Erase an area from set and delete it if last reference, or if mbInBroadcastIteration is set push it t...
void InsertListeningArea(ScBroadcastArea *pArea)
Insert a ScBroadcastArea obtained via StartListeningArea() to subsequent slots.
SC_DLLPUBLIC SCROW GetMaxRowCount() const
TableSlots(SCSIZE nBcaSlots)
bool IsGroupListening() const
size_t RemoveBulkArea(const ScBroadcastArea *p)
bool Intersects(const ScRange &rRange) const
bool mbInBroadcastIteration
ScBroadcastArea(const ScBroadcastArea &)=delete
ListenersType & GetAllListeners()
bool IsTrackFormulasPending() const
void EndListeningArea(const ScRange &rRange, bool bGroupListening, SvtListener *pListener, ScBroadcastArea *&rpArea)
SCROW GetRowCount() const
void UpdateRemove(UpdateRefMode eUpdateRefMode, const ScRange &rRange, SCCOL nDx, SCROW nDy, SCTAB nDz)
std::unordered_set< const ScBroadcastArea *, ScBroadcastAreaBulkHash, ScBroadcastAreaBulkEqual > ScBroadcastAreasBulk
ScBroadcastArea * GetEOUpdateChain() const
ScRange Intersection(const ScRange &rOther) const
void SetHardRecalcState(HardRecalcState eVal)
void LeaveBulkBroadcast(SfxHintId nHintId)
void StartListeningArea(const ScRange &rRange, bool bGroupListening, SvtListener *pListener)
ScBroadcastAreaSlot(ScDocument *pDoc, ScBroadcastAreaSlotMachine *pBASM)
void DelBroadcastAreasInRange(const ScRange &rRange)
Used in a Unique Associative Container.
#define SCWARN_CORE_HARD_RECALC
Collection of BroadcastAreas.
std::vector< SvtListener * > ListenersType
SC_DLLPUBLIC SCROW MaxRow() const
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 ...
ScDocument::HardRecalcState CheckHardRecalcStateCondition() const
More hypothetical (memory would probably be doomed anyway) check whether there would be an overflow w...
void setSpans(const ColumnSpanSet *pSpans)
bool IsInUpdateChain() const
~ScBroadcastAreaSlotMachine()
void set(const ScDocument &rDoc, SCTAB nTab, SCCOL nCol, SCROW nRow, bool bVal)
ScBroadcastArea aTmpSeekBroadcastArea
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
void EndListening(SvtBroadcaster &rBroadcaster)
bool AreaBroadcast(const ScRange &rRange, SfxHintId nHint)
void EndListeningArea(const ScRange &rRange, bool bGroupListening, SvtListener *pListener)
TableSlotsMap aTableSlotsMap
void FinalTrackFormulas(SfxHintId nHintId)
void UpdateInsert(ScBroadcastArea *pArea)
void PushAreaToBeErased(ScBroadcastAreaSlot *pSlot, ScBroadcastAreas::iterator &rIter)
SC_DLLPUBLIC SCCOL GetMaxColCount() const
bool BulkBroadcastGroupAreas(SfxHintId nHintId)
SC_DLLPUBLIC SCCOL MaxCol() const
std::unique_ptr< ScBroadcastAreaSlot *[]> ppSlots
void SetUpdateChain(ScBroadcastArea *p)
void Broadcast(const SfxHint &rHint)
void RemoveBulkGroupArea(ScBroadcastArea *pArea)
static void ComputeNextSlot(SCSIZE &nOff, SCSIZE &nBreak, ScBroadcastAreaSlot **&pp, SCSIZE &nStart, ScBroadcastAreaSlot **const &ppSlots, SCSIZE nRowBreak, SCSIZE nBcaSlotsCol)
bool ValidCol(SCCOL nCol) const
SC_DLLPUBLIC void SetAutoCalc(bool bNewAutoCalc)
void UpdateRange(const ScRange &rNewRange)
BulkGroupAreasType m_BulkGroupAreas
void SetGroupListening(bool b)
OUString Format(const ScDocument &rDocument, ScRefFlags nFlags=ScRefFlags::ZERO, const ScAddress::Details &rDetails=ScAddress::detailsOOOa1, bool bFullAddressNotation=false) const
Returns string with formatted cell range from aStart to aEnd, according to provided address conventio...
void DelBroadcastAreasInRange(const ScRange &rRange)
ScBroadcastAreaSlotMachine * pBASM
Structure that stores segments of boolean flags per column, and perform custom action on those segmen...
void FinallyEraseAreas(ScBroadcastAreaSlot *pSlot)
#define BCA_BRDCST_ALWAYS
ScBroadcastArea * GetUpdateChainNext() const
HardRecalcState GetHardRecalcState() const
SvtBroadcaster & GetBroadcaster()
void TrackFormulas(SfxHintId nHintId=SfxHintId::ScDataChanged)
BroadcastAreaSlots and their management, once per document.
SCSIZE ComputeSlotOffset(const ScAddress &rAddress) const
void SetUpdateChainNext(ScBroadcastArea *p)
sal_uInt32 nInBulkBroadcast
ScBroadcastAreas::iterator FindBroadcastArea(const ScRange &rRange, bool bGroupListening)
void GetVars(SCCOL &nCol1, SCROW &nRow1, SCTAB &nTab1, SCCOL &nCol2, SCROW &nRow2, SCTAB &nTab2) const
bool StartListening(SvtBroadcaster &rBroadcaster)
void UpdateBroadcastAreas(UpdateRefMode eUpdateRefMode, const ScRange &rRange, SCCOL nDx, SCROW nDy, SCTAB nDz)
::std::vector< ::std::pair< ScBroadcastAreaSlot *, ScBroadcastAreas::iterator > > AreasToBeErased
void GetAllListeners(const ScRange &rRange, std::vector< sc::AreaListener > &rListeners, sc::AreaOverlapType eType, sc::ListenerGroupType eGroup)
bool IsDelayedFormulaGrouping() const
ScBroadcastAreasBulk aBulkBroadcastAreas
bool ValidRow(SCROW nRow) const
ScBroadcastAreaSlotMachine(ScDocument *pDoc)
#define SAL_WARN_IF(condition, area, stream)
static void compare(SCSIZE value1, SCSIZE value2, int line)
void FinallyEraseAreas()
Finally erase all areas pushed as to-be-erased.
CalcAll() without broadcast/notify but setting up new listeners.
void SetEOUpdateChain(ScBroadcastArea *p)
SvStream & endl(SvStream &rStr)
bool InsertBulkArea(const ScBroadcastArea *p)
ScBroadcastAreas aBroadcastAreaTbl
bool Contains(const ScAddress &) const
is Address& fully in Range?
bool HasListeners() const
ScBroadcastArea * pEOUpdateChain
bool StartListeningArea(const ScRange &rRange, bool bGroupListening, SvtListener *pListener, ScBroadcastArea *&rpArea)
Only here new ScBroadcastArea objects are created, prevention of dupes.
bool mbHasErasedArea
If true, the slot has at least one area broadcaster marked for removal.
ScSlotDistribution maSlotDistribution
SfxObjectShell * GetDocumentShell() const
AreasToBeErased maAreasToBeErased
#define SAL_WARN(area, stream)
std::vector< sc::AreaListener > GetAllListeners(const ScRange &rRange, sc::AreaOverlapType eType, sc::ListenerGroupType eGroup=sc::ListenerGroupType::Both)
void ComputeAreaPoints(const ScRange &rRange, SCSIZE &nStart, SCSIZE &nEnd, SCSIZE &nRowBreak) const
void SetInUpdateChain(bool b)
bool AreaBroadcast(const ScRange &rRange, SfxHintId nHint)
void EnterBulkBroadcast()
void UpdateRemoveArea(ScBroadcastArea *pArea)
void SetError(ErrCode rErr)
const ScRange & GetRange() const
std::unique_ptr< SvtBroadcaster > pBCAlways
ScBroadcastArea * pUpdateChain
void InsertBulkGroupArea(ScBroadcastArea *pArea, const ScRange &rRange)
static bool isMarkedErased(const ScBroadcastAreas::const_iterator &rIter)
const ScAddress & GetStartAddress() const
bool m_bDetectedRangeSegmentation false