xref: /trunk/main/sc/source/core/data/documen7.cxx (revision b3f79822)
1*b3f79822SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*b3f79822SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*b3f79822SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*b3f79822SAndrew Rist  * distributed with this work for additional information
6*b3f79822SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*b3f79822SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*b3f79822SAndrew Rist  * "License"); you may not use this file except in compliance
9*b3f79822SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*b3f79822SAndrew Rist  *
11*b3f79822SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*b3f79822SAndrew Rist  *
13*b3f79822SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*b3f79822SAndrew Rist  * software distributed under the License is distributed on an
15*b3f79822SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b3f79822SAndrew Rist  * KIND, either express or implied.  See the License for the
17*b3f79822SAndrew Rist  * specific language governing permissions and limitations
18*b3f79822SAndrew Rist  * under the License.
19*b3f79822SAndrew Rist  *
20*b3f79822SAndrew Rist  *************************************************************/
21*b3f79822SAndrew Rist 
22*b3f79822SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_sc.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir // INCLUDE ---------------------------------------------------------------
28cdf0e10cSrcweir 
29cdf0e10cSrcweir #include <vcl/svapp.hxx>
30cdf0e10cSrcweir 
31cdf0e10cSrcweir #if defined( WNT ) && defined( erBEEP )
32cdf0e10cSrcweir #include <svwin.h>
33cdf0e10cSrcweir #define erBEEPER() Beep( 666, 66 )
34cdf0e10cSrcweir #else
35cdf0e10cSrcweir #define erBEEPER()
36cdf0e10cSrcweir #endif
37cdf0e10cSrcweir 
38cdf0e10cSrcweir #include "document.hxx"
39cdf0e10cSrcweir #include "brdcst.hxx"
40cdf0e10cSrcweir #include "bcaslot.hxx"
41cdf0e10cSrcweir #include "cell.hxx"
42cdf0e10cSrcweir #include "formula/errorcodes.hxx"		// errCircularReference
43cdf0e10cSrcweir #include "scerrors.hxx"
44cdf0e10cSrcweir #include "docoptio.hxx"
45cdf0e10cSrcweir #include "refupdat.hxx"
46cdf0e10cSrcweir #include "table.hxx"
47cdf0e10cSrcweir #include "progress.hxx"
48cdf0e10cSrcweir #include "scmod.hxx"   		// SC_MOD
49cdf0e10cSrcweir #include "inputopt.hxx" 	// GetExpandRefs
50cdf0e10cSrcweir #include "conditio.hxx"
51cdf0e10cSrcweir #include "sheetevents.hxx"
52cdf0e10cSrcweir #include <tools/shl.hxx>
53cdf0e10cSrcweir 
54cdf0e10cSrcweir 
55cdf0e10cSrcweir #include "globstr.hrc"
56cdf0e10cSrcweir 
57cdf0e10cSrcweir extern const ScFormulaCell* pLastFormulaTreeTop;	// cellform.cxx Err527 WorkAround
58cdf0e10cSrcweir 
59cdf0e10cSrcweir // STATIC DATA -----------------------------------------------------------
60cdf0e10cSrcweir 
61cdf0e10cSrcweir #ifdef erDEBUG
62cdf0e10cSrcweir sal_uLong erCountBCAInserts = 0;
63cdf0e10cSrcweir sal_uLong erCountBCAFinds = 0;
64cdf0e10cSrcweir #endif
65cdf0e10cSrcweir 
66cdf0e10cSrcweir // -----------------------------------------------------------------------
67cdf0e10cSrcweir 
StartListeningArea(const ScRange & rRange,SvtListener * pListener)68cdf0e10cSrcweir void ScDocument::StartListeningArea( const ScRange& rRange,
69cdf0e10cSrcweir 		SvtListener* pListener
70cdf0e10cSrcweir 	)
71cdf0e10cSrcweir {
72cdf0e10cSrcweir 	if ( pBASM )
73cdf0e10cSrcweir 		pBASM->StartListeningArea( rRange, pListener );
74cdf0e10cSrcweir }
75cdf0e10cSrcweir 
76cdf0e10cSrcweir 
EndListeningArea(const ScRange & rRange,SvtListener * pListener)77cdf0e10cSrcweir void ScDocument::EndListeningArea( const ScRange& rRange,
78cdf0e10cSrcweir 		SvtListener* pListener
79cdf0e10cSrcweir 	)
80cdf0e10cSrcweir {
81cdf0e10cSrcweir 	if ( pBASM )
82cdf0e10cSrcweir 		pBASM->EndListeningArea( rRange, pListener );
83cdf0e10cSrcweir }
84cdf0e10cSrcweir 
85cdf0e10cSrcweir 
Broadcast(sal_uLong nHint,const ScAddress & rAddr,ScBaseCell * pCell)86cdf0e10cSrcweir void ScDocument::Broadcast( sal_uLong nHint, const ScAddress& rAddr,
87cdf0e10cSrcweir 		ScBaseCell* pCell
88cdf0e10cSrcweir 	)
89cdf0e10cSrcweir {
90cdf0e10cSrcweir 	if ( !pBASM )
91cdf0e10cSrcweir 		return ;	// Clipboard or Undo
92cdf0e10cSrcweir     ScHint aHint( nHint, rAddr, pCell );
93cdf0e10cSrcweir     Broadcast( aHint );
94cdf0e10cSrcweir }
95cdf0e10cSrcweir 
96cdf0e10cSrcweir 
Broadcast(const ScHint & rHint)97cdf0e10cSrcweir void ScDocument::Broadcast( const ScHint& rHint )
98cdf0e10cSrcweir {
99cdf0e10cSrcweir 	if ( !pBASM )
100cdf0e10cSrcweir 		return ;	// Clipboard or Undo
101cdf0e10cSrcweir 	if ( !nHardRecalcState )
102cdf0e10cSrcweir 	{
103cdf0e10cSrcweir         ScBulkBroadcast aBulkBroadcast( pBASM);     // scoped bulk broadcast
104cdf0e10cSrcweir 		sal_Bool bIsBroadcasted = sal_False;
105cdf0e10cSrcweir         ScBaseCell* pCell = rHint.GetCell();
106cdf0e10cSrcweir 		if ( pCell )
107cdf0e10cSrcweir 		{
108cdf0e10cSrcweir 			SvtBroadcaster* pBC = pCell->GetBroadcaster();
109cdf0e10cSrcweir 			if ( pBC )
110cdf0e10cSrcweir 			{
111cdf0e10cSrcweir 				pBC->Broadcast( rHint );
112cdf0e10cSrcweir 				bIsBroadcasted = sal_True;
113cdf0e10cSrcweir 			}
114cdf0e10cSrcweir 		}
115cdf0e10cSrcweir 		if ( pBASM->AreaBroadcast( rHint ) || bIsBroadcasted )
116cdf0e10cSrcweir 			TrackFormulas( rHint.GetId() );
117cdf0e10cSrcweir 	}
118cdf0e10cSrcweir 
119cdf0e10cSrcweir 	//	Repaint fuer bedingte Formate mit relativen Referenzen:
120cdf0e10cSrcweir 	if ( pCondFormList && rHint.GetAddress() != BCA_BRDCST_ALWAYS )
121cdf0e10cSrcweir 		pCondFormList->SourceChanged( rHint.GetAddress() );
122cdf0e10cSrcweir 
123cdf0e10cSrcweir     if ( rHint.GetAddress() != BCA_BRDCST_ALWAYS )
124cdf0e10cSrcweir     {
125cdf0e10cSrcweir         SCTAB nTab = rHint.GetAddress().Tab();
126cdf0e10cSrcweir         if (pTab[nTab] && pTab[nTab]->IsStreamValid())
127cdf0e10cSrcweir             pTab[nTab]->SetStreamValid(sal_False);
128cdf0e10cSrcweir     }
129cdf0e10cSrcweir }
130cdf0e10cSrcweir 
131cdf0e10cSrcweir 
AreaBroadcast(const ScHint & rHint)132cdf0e10cSrcweir void ScDocument::AreaBroadcast( const ScHint& rHint )
133cdf0e10cSrcweir {
134cdf0e10cSrcweir 	if ( !pBASM )
135cdf0e10cSrcweir 		return ;	// Clipboard or Undo
136cdf0e10cSrcweir 	if ( !nHardRecalcState )
137cdf0e10cSrcweir 	{
138cdf0e10cSrcweir         ScBulkBroadcast aBulkBroadcast( pBASM);     // scoped bulk broadcast
139cdf0e10cSrcweir 		if ( pBASM->AreaBroadcast( rHint ) )
140cdf0e10cSrcweir 			TrackFormulas( rHint.GetId() );
141cdf0e10cSrcweir 	}
142cdf0e10cSrcweir 
143cdf0e10cSrcweir 	//	Repaint fuer bedingte Formate mit relativen Referenzen:
144cdf0e10cSrcweir 	if ( pCondFormList && rHint.GetAddress() != BCA_BRDCST_ALWAYS )
145cdf0e10cSrcweir 		pCondFormList->SourceChanged( rHint.GetAddress() );
146cdf0e10cSrcweir }
147cdf0e10cSrcweir 
148cdf0e10cSrcweir 
AreaBroadcastInRange(const ScRange & rRange,const ScHint & rHint)149cdf0e10cSrcweir void ScDocument::AreaBroadcastInRange( const ScRange& rRange, const ScHint& rHint )
150cdf0e10cSrcweir {
151cdf0e10cSrcweir     if ( !pBASM )
152cdf0e10cSrcweir         return ;    // Clipboard or Undo
153cdf0e10cSrcweir     if ( !nHardRecalcState )
154cdf0e10cSrcweir     {
155cdf0e10cSrcweir         ScBulkBroadcast aBulkBroadcast( pBASM);     // scoped bulk broadcast
156cdf0e10cSrcweir         if ( pBASM->AreaBroadcastInRange( rRange, rHint ) )
157cdf0e10cSrcweir             TrackFormulas( rHint.GetId() );
158cdf0e10cSrcweir     }
159cdf0e10cSrcweir 
160cdf0e10cSrcweir     // Repaint for conditional formats containing relative references.
161cdf0e10cSrcweir     //! This is _THE_ bottle neck!
162cdf0e10cSrcweir     if ( pCondFormList )
163cdf0e10cSrcweir     {
164cdf0e10cSrcweir         SCCOL nCol;
165cdf0e10cSrcweir         SCROW nRow;
166cdf0e10cSrcweir         SCTAB nTab;
167cdf0e10cSrcweir         SCCOL nCol1;
168cdf0e10cSrcweir         SCROW nRow1;
169cdf0e10cSrcweir         SCTAB nTab1;
170cdf0e10cSrcweir         SCCOL nCol2;
171cdf0e10cSrcweir         SCROW nRow2;
172cdf0e10cSrcweir         SCTAB nTab2;
173cdf0e10cSrcweir         rRange.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
174cdf0e10cSrcweir         ScAddress aAddress( rRange.aStart );
175cdf0e10cSrcweir         for ( nTab = nTab1; nTab <= nTab2; ++nTab )
176cdf0e10cSrcweir         {
177cdf0e10cSrcweir             aAddress.SetTab( nTab );
178cdf0e10cSrcweir             for ( nCol = nCol1; nCol <= nCol2; ++nCol )
179cdf0e10cSrcweir             {
180cdf0e10cSrcweir                 aAddress.SetCol( nCol );
181cdf0e10cSrcweir                 for ( nRow = nRow1; nRow <= nRow2; ++nRow )
182cdf0e10cSrcweir                 {
183cdf0e10cSrcweir                     aAddress.SetRow( nRow );
184cdf0e10cSrcweir                     pCondFormList->SourceChanged( aAddress );
185cdf0e10cSrcweir                 }
186cdf0e10cSrcweir             }
187cdf0e10cSrcweir         }
188cdf0e10cSrcweir     }
189cdf0e10cSrcweir }
190cdf0e10cSrcweir 
191cdf0e10cSrcweir 
DelBroadcastAreasInRange(const ScRange & rRange)192cdf0e10cSrcweir void ScDocument::DelBroadcastAreasInRange( const ScRange& rRange )
193cdf0e10cSrcweir {
194cdf0e10cSrcweir 	if ( pBASM )
195cdf0e10cSrcweir 		pBASM->DelBroadcastAreasInRange( rRange );
196cdf0e10cSrcweir }
197cdf0e10cSrcweir 
StartListeningCell(const ScAddress & rAddress,SvtListener * pListener)198cdf0e10cSrcweir void ScDocument::StartListeningCell( const ScAddress& rAddress,
199cdf0e10cSrcweir 											SvtListener* pListener )
200cdf0e10cSrcweir {
201cdf0e10cSrcweir 	DBG_ASSERT(pListener, "StartListeningCell: pListener Null");
202cdf0e10cSrcweir 	SCTAB nTab = rAddress.Tab();
203cdf0e10cSrcweir 	if (pTab[nTab])
204cdf0e10cSrcweir 		pTab[nTab]->StartListening( rAddress, pListener );
205cdf0e10cSrcweir }
206cdf0e10cSrcweir 
EndListeningCell(const ScAddress & rAddress,SvtListener * pListener)207cdf0e10cSrcweir void ScDocument::EndListeningCell( const ScAddress& rAddress,
208cdf0e10cSrcweir 											SvtListener* pListener )
209cdf0e10cSrcweir {
210cdf0e10cSrcweir 	DBG_ASSERT(pListener, "EndListeningCell: pListener Null");
211cdf0e10cSrcweir 	SCTAB nTab = rAddress.Tab();
212cdf0e10cSrcweir 	if (pTab[nTab])
213cdf0e10cSrcweir 		pTab[nTab]->EndListening( rAddress, pListener );
214cdf0e10cSrcweir }
215cdf0e10cSrcweir 
216cdf0e10cSrcweir 
PutInFormulaTree(ScFormulaCell * pCell)217cdf0e10cSrcweir void ScDocument::PutInFormulaTree( ScFormulaCell* pCell )
218cdf0e10cSrcweir {
219cdf0e10cSrcweir 	DBG_ASSERT( pCell, "PutInFormulaTree: pCell Null" );
220cdf0e10cSrcweir 	RemoveFromFormulaTree( pCell );
221cdf0e10cSrcweir 	// anhaengen
222cdf0e10cSrcweir 	if ( pEOFormulaTree )
223cdf0e10cSrcweir 		pEOFormulaTree->SetNext( pCell );
224cdf0e10cSrcweir 	else
225cdf0e10cSrcweir 		pFormulaTree = pCell;				// kein Ende, kein Anfang..
226cdf0e10cSrcweir 	pCell->SetPrevious( pEOFormulaTree );
227cdf0e10cSrcweir 	pCell->SetNext( 0 );
228cdf0e10cSrcweir 	pEOFormulaTree = pCell;
229cdf0e10cSrcweir 	nFormulaCodeInTree += pCell->GetCode()->GetCodeLen();
230cdf0e10cSrcweir }
231cdf0e10cSrcweir 
232cdf0e10cSrcweir 
RemoveFromFormulaTree(ScFormulaCell * pCell)233cdf0e10cSrcweir void ScDocument::RemoveFromFormulaTree( ScFormulaCell* pCell )
234cdf0e10cSrcweir {
235cdf0e10cSrcweir 	DBG_ASSERT( pCell, "RemoveFromFormulaTree: pCell Null" );
236cdf0e10cSrcweir 	ScFormulaCell* pPrev = pCell->GetPrevious();
237cdf0e10cSrcweir 	// wenn die Zelle die erste oder sonstwo ist
238cdf0e10cSrcweir 	if ( pPrev || pFormulaTree == pCell )
239cdf0e10cSrcweir 	{
240cdf0e10cSrcweir 		ScFormulaCell* pNext = pCell->GetNext();
241cdf0e10cSrcweir 		if ( pPrev )
242cdf0e10cSrcweir 			pPrev->SetNext( pNext );		// gibt Vorlaeufer
243cdf0e10cSrcweir 		else
244cdf0e10cSrcweir 			pFormulaTree = pNext;			// ist erste Zelle
245cdf0e10cSrcweir 		if ( pNext )
246cdf0e10cSrcweir 			pNext->SetPrevious( pPrev );	// gibt Nachfolger
247cdf0e10cSrcweir 		else
248cdf0e10cSrcweir 			pEOFormulaTree = pPrev;			// ist letzte Zelle
249cdf0e10cSrcweir 		pCell->SetPrevious( 0 );
250cdf0e10cSrcweir 		pCell->SetNext( 0 );
251cdf0e10cSrcweir 		sal_uInt16 nRPN = pCell->GetCode()->GetCodeLen();
252cdf0e10cSrcweir 		if ( nFormulaCodeInTree >= nRPN )
253cdf0e10cSrcweir 			nFormulaCodeInTree -= nRPN;
254cdf0e10cSrcweir 		else
255cdf0e10cSrcweir 		{
256cdf0e10cSrcweir 			DBG_ERRORFILE( "RemoveFromFormulaTree: nFormulaCodeInTree < nRPN" );
257cdf0e10cSrcweir 			nFormulaCodeInTree = 0;
258cdf0e10cSrcweir 		}
259cdf0e10cSrcweir 	}
260cdf0e10cSrcweir 	else if ( !pFormulaTree && nFormulaCodeInTree )
261cdf0e10cSrcweir 	{
262cdf0e10cSrcweir 		DBG_ERRORFILE( "!pFormulaTree && nFormulaCodeInTree != 0" );
263cdf0e10cSrcweir 		nFormulaCodeInTree = 0;
264cdf0e10cSrcweir 	}
265cdf0e10cSrcweir }
266cdf0e10cSrcweir 
267cdf0e10cSrcweir 
IsInFormulaTree(ScFormulaCell * pCell) const268cdf0e10cSrcweir sal_Bool ScDocument::IsInFormulaTree( ScFormulaCell* pCell ) const
269cdf0e10cSrcweir {
270cdf0e10cSrcweir 	return pCell->GetPrevious() || pFormulaTree == pCell;
271cdf0e10cSrcweir }
272cdf0e10cSrcweir 
273cdf0e10cSrcweir 
CalcFormulaTree(sal_Bool bOnlyForced,sal_Bool bNoProgress)274cdf0e10cSrcweir void ScDocument::CalcFormulaTree( sal_Bool bOnlyForced, sal_Bool bNoProgress )
275cdf0e10cSrcweir {
276cdf0e10cSrcweir 	DBG_ASSERT( !IsCalculatingFormulaTree(), "CalcFormulaTree recursion" );
277cdf0e10cSrcweir 	// never ever recurse into this, might end up lost in infinity
278cdf0e10cSrcweir 	if ( IsCalculatingFormulaTree() )
279cdf0e10cSrcweir 		return ;
280cdf0e10cSrcweir 	bCalculatingFormulaTree = sal_True;
281cdf0e10cSrcweir 
282cdf0e10cSrcweir 	SetForcedFormulaPending( sal_False );
283cdf0e10cSrcweir 	sal_Bool bOldIdleDisabled = IsIdleDisabled();
284cdf0e10cSrcweir 	DisableIdle( sal_True );
285cdf0e10cSrcweir 	sal_Bool bOldAutoCalc = GetAutoCalc();
286cdf0e10cSrcweir 	//! _nicht_ SetAutoCalc( sal_True ) weil das evtl. CalcFormulaTree( sal_True )
287cdf0e10cSrcweir 	//! aufruft, wenn vorher disabled war und bHasForcedFormulas gesetzt ist
288cdf0e10cSrcweir 	bAutoCalc = sal_True;
289cdf0e10cSrcweir 	if ( nHardRecalcState )
290cdf0e10cSrcweir 		CalcAll();
291cdf0e10cSrcweir 	else
292cdf0e10cSrcweir 	{
293cdf0e10cSrcweir 		ScFormulaCell* pCell = pFormulaTree;
294cdf0e10cSrcweir 		while ( pCell )
295cdf0e10cSrcweir 		{
296cdf0e10cSrcweir 			if ( pCell->GetDirty() )
297cdf0e10cSrcweir 				pCell = pCell->GetNext();		// alles klar
298cdf0e10cSrcweir 			else
299cdf0e10cSrcweir 			{
300cdf0e10cSrcweir 				if ( pCell->GetCode()->IsRecalcModeAlways() )
301cdf0e10cSrcweir 				{
302cdf0e10cSrcweir 					// pCell wird im SetDirty neu angehaengt!
303cdf0e10cSrcweir 					ScFormulaCell* pNext = pCell->GetNext();
304cdf0e10cSrcweir 					pCell->SetDirty();
305cdf0e10cSrcweir 					// falls pNext==0 und neue abhaengige hinten angehaengt
306cdf0e10cSrcweir 					// wurden, so macht das nichts, da die alle bDirty sind
307cdf0e10cSrcweir 					pCell = pNext;
308cdf0e10cSrcweir 				}
309cdf0e10cSrcweir 				else
310cdf0e10cSrcweir 				{	// andere simpel berechnen
311cdf0e10cSrcweir 					pCell->SetDirtyVar();
312cdf0e10cSrcweir 					pCell = pCell->GetNext();
313cdf0e10cSrcweir 				}
314cdf0e10cSrcweir 			}
315cdf0e10cSrcweir 		}
316cdf0e10cSrcweir 		sal_Bool bProgress = !bOnlyForced && nFormulaCodeInTree && !bNoProgress;
317cdf0e10cSrcweir 		if ( bProgress )
318cdf0e10cSrcweir 			ScProgress::CreateInterpretProgress( this, sal_True );
319cdf0e10cSrcweir 
320cdf0e10cSrcweir         pCell = pFormulaTree;
321cdf0e10cSrcweir         ScFormulaCell* pLastNoGood = 0;
322cdf0e10cSrcweir         while ( pCell )
323cdf0e10cSrcweir         {
324cdf0e10cSrcweir             // Interpret setzt bDirty zurueck und callt Remove, auch der referierten!
325cdf0e10cSrcweir             // bei RECALCMODE_ALWAYS bleibt die Zelle
326cdf0e10cSrcweir             if ( bOnlyForced )
327cdf0e10cSrcweir             {
328cdf0e10cSrcweir                 if ( pCell->GetCode()->IsRecalcModeForced() )
329cdf0e10cSrcweir                     pCell->Interpret();
330cdf0e10cSrcweir             }
331cdf0e10cSrcweir             else
332cdf0e10cSrcweir             {
333cdf0e10cSrcweir                 pCell->Interpret();
334cdf0e10cSrcweir             }
335cdf0e10cSrcweir             if ( pCell->GetPrevious() || pCell == pFormulaTree )
336cdf0e10cSrcweir             {   // (IsInFormulaTree(pCell)) kein Remove gewesen => next
337cdf0e10cSrcweir                 pLastNoGood = pCell;
338cdf0e10cSrcweir                 pCell = pCell->GetNext();
339cdf0e10cSrcweir             }
340cdf0e10cSrcweir             else
341cdf0e10cSrcweir             {
342cdf0e10cSrcweir                 if ( pFormulaTree )
343cdf0e10cSrcweir                 {
344cdf0e10cSrcweir                     if ( pFormulaTree->GetDirty() && !bOnlyForced )
345cdf0e10cSrcweir                     {
346cdf0e10cSrcweir                         pCell = pFormulaTree;
347cdf0e10cSrcweir                         pLastNoGood = 0;
348cdf0e10cSrcweir                     }
349cdf0e10cSrcweir                     else
350cdf0e10cSrcweir                     {
351cdf0e10cSrcweir                         // IsInFormulaTree(pLastNoGood)
352cdf0e10cSrcweir                         if ( pLastNoGood && (pLastNoGood->GetPrevious() ||
353cdf0e10cSrcweir                                 pLastNoGood == pFormulaTree) )
354cdf0e10cSrcweir                             pCell = pLastNoGood->GetNext();
355cdf0e10cSrcweir                         else
356cdf0e10cSrcweir                         {
357cdf0e10cSrcweir                             pCell = pFormulaTree;
358cdf0e10cSrcweir                             while ( pCell && !pCell->GetDirty() )
359cdf0e10cSrcweir                                 pCell = pCell->GetNext();
360cdf0e10cSrcweir                             if ( pCell )
361cdf0e10cSrcweir                                 pLastNoGood = pCell->GetPrevious();
362cdf0e10cSrcweir                         }
363cdf0e10cSrcweir                     }
364cdf0e10cSrcweir                 }
365cdf0e10cSrcweir                 else
366cdf0e10cSrcweir                     pCell = 0;
367cdf0e10cSrcweir             }
368cdf0e10cSrcweir             if ( ScProgress::IsUserBreak() )
369cdf0e10cSrcweir                 pCell = 0;
370cdf0e10cSrcweir         }
371cdf0e10cSrcweir 		if ( bProgress )
372cdf0e10cSrcweir 			ScProgress::DeleteInterpretProgress();
373cdf0e10cSrcweir 	}
374cdf0e10cSrcweir 	bAutoCalc = bOldAutoCalc;
375cdf0e10cSrcweir 	DisableIdle( bOldIdleDisabled );
376cdf0e10cSrcweir 	bCalculatingFormulaTree = sal_False;
377cdf0e10cSrcweir }
378cdf0e10cSrcweir 
379cdf0e10cSrcweir 
ClearFormulaTree()380cdf0e10cSrcweir void ScDocument::ClearFormulaTree()
381cdf0e10cSrcweir {
382cdf0e10cSrcweir 	ScFormulaCell* pCell;
383cdf0e10cSrcweir 	ScFormulaCell* pTree = pFormulaTree;
384cdf0e10cSrcweir 	while ( pTree )
385cdf0e10cSrcweir 	{
386cdf0e10cSrcweir 		pCell = pTree;
387cdf0e10cSrcweir 		pTree = pCell->GetNext();
388cdf0e10cSrcweir 		if ( !pCell->GetCode()->IsRecalcModeAlways() )
389cdf0e10cSrcweir 			RemoveFromFormulaTree( pCell );
390cdf0e10cSrcweir 	}
391cdf0e10cSrcweir }
392cdf0e10cSrcweir 
393cdf0e10cSrcweir 
AppendToFormulaTrack(ScFormulaCell * pCell)394cdf0e10cSrcweir void ScDocument::AppendToFormulaTrack( ScFormulaCell* pCell )
395cdf0e10cSrcweir {
396cdf0e10cSrcweir 	DBG_ASSERT( pCell, "AppendToFormulaTrack: pCell Null" );
397cdf0e10cSrcweir 	// Zelle kann nicht in beiden Listen gleichzeitig sein
398cdf0e10cSrcweir 	RemoveFromFormulaTrack( pCell );
399cdf0e10cSrcweir 	RemoveFromFormulaTree( pCell );
400cdf0e10cSrcweir 	if ( pEOFormulaTrack )
401cdf0e10cSrcweir 		pEOFormulaTrack->SetNextTrack( pCell );
402cdf0e10cSrcweir 	else
403cdf0e10cSrcweir 		pFormulaTrack = pCell;				// kein Ende, kein Anfang..
404cdf0e10cSrcweir 	pCell->SetPreviousTrack( pEOFormulaTrack );
405cdf0e10cSrcweir 	pCell->SetNextTrack( 0 );
406cdf0e10cSrcweir 	pEOFormulaTrack = pCell;
407cdf0e10cSrcweir 	++nFormulaTrackCount;
408cdf0e10cSrcweir }
409cdf0e10cSrcweir 
410cdf0e10cSrcweir 
RemoveFromFormulaTrack(ScFormulaCell * pCell)411cdf0e10cSrcweir void ScDocument::RemoveFromFormulaTrack( ScFormulaCell* pCell )
412cdf0e10cSrcweir {
413cdf0e10cSrcweir 	DBG_ASSERT( pCell, "RemoveFromFormulaTrack: pCell Null" );
414cdf0e10cSrcweir 	ScFormulaCell* pPrev = pCell->GetPreviousTrack();
415cdf0e10cSrcweir 	// wenn die Zelle die erste oder sonstwo ist
416cdf0e10cSrcweir 	if ( pPrev || pFormulaTrack == pCell )
417cdf0e10cSrcweir 	{
418cdf0e10cSrcweir 		ScFormulaCell* pNext = pCell->GetNextTrack();
419cdf0e10cSrcweir 		if ( pPrev )
420cdf0e10cSrcweir 			pPrev->SetNextTrack( pNext );		// gibt Vorlaeufer
421cdf0e10cSrcweir 		else
422cdf0e10cSrcweir 			pFormulaTrack = pNext;				// ist erste Zelle
423cdf0e10cSrcweir 		if ( pNext )
424cdf0e10cSrcweir 			pNext->SetPreviousTrack( pPrev );	// gibt Nachfolger
425cdf0e10cSrcweir 		else
426cdf0e10cSrcweir 			pEOFormulaTrack = pPrev;  			// ist letzte Zelle
427cdf0e10cSrcweir 		pCell->SetPreviousTrack( 0 );
428cdf0e10cSrcweir 		pCell->SetNextTrack( 0 );
429cdf0e10cSrcweir 		--nFormulaTrackCount;
430cdf0e10cSrcweir 	}
431cdf0e10cSrcweir }
432cdf0e10cSrcweir 
433cdf0e10cSrcweir 
IsInFormulaTrack(ScFormulaCell * pCell) const434cdf0e10cSrcweir sal_Bool ScDocument::IsInFormulaTrack( ScFormulaCell* pCell ) const
435cdf0e10cSrcweir {
436cdf0e10cSrcweir 	return pCell->GetPreviousTrack() || pFormulaTrack == pCell;
437cdf0e10cSrcweir }
438cdf0e10cSrcweir 
439cdf0e10cSrcweir 
440cdf0e10cSrcweir /*
441cdf0e10cSrcweir 	Der erste wird gebroadcastet,
442cdf0e10cSrcweir 	die dadurch entstehenden werden durch das Notify an den Track gehaengt.
443cdf0e10cSrcweir 	Der nachfolgende broadcastet wieder usw.
444cdf0e10cSrcweir 	View stoesst Interpret an.
445cdf0e10cSrcweir  */
TrackFormulas(sal_uLong nHintId)446cdf0e10cSrcweir void ScDocument::TrackFormulas( sal_uLong nHintId )
447cdf0e10cSrcweir {
448cdf0e10cSrcweir 
449cdf0e10cSrcweir 	if ( pFormulaTrack )
450cdf0e10cSrcweir 	{
451cdf0e10cSrcweir 		erBEEPER();
452cdf0e10cSrcweir         // outside the loop, check if any sheet has a "calculate" event script
453cdf0e10cSrcweir         bool bCalcEvent = HasAnySheetEventScript( SC_SHEETEVENT_CALCULATE, true );
454cdf0e10cSrcweir 		SvtBroadcaster* pBC;
455cdf0e10cSrcweir 		ScFormulaCell* pTrack;
456cdf0e10cSrcweir 		ScFormulaCell* pNext;
457cdf0e10cSrcweir 		pTrack = pFormulaTrack;
458cdf0e10cSrcweir 		do
459cdf0e10cSrcweir 		{
460cdf0e10cSrcweir 			ScHint aHint( nHintId, pTrack->aPos, pTrack );
461cdf0e10cSrcweir             if ( ( pBC = pTrack->GetBroadcaster() ) != NULL )
462cdf0e10cSrcweir 				pBC->Broadcast( aHint );
463cdf0e10cSrcweir 			pBASM->AreaBroadcast( aHint );
464cdf0e10cSrcweir 			//	Repaint fuer bedingte Formate mit relativen Referenzen:
465cdf0e10cSrcweir 			if ( pCondFormList )
466cdf0e10cSrcweir 				pCondFormList->SourceChanged( pTrack->aPos );
467cdf0e10cSrcweir             // for "calculate" event, keep track of which sheets are affected by tracked formulas
468cdf0e10cSrcweir             if ( bCalcEvent )
469cdf0e10cSrcweir                 SetCalcNotification( pTrack->aPos.Tab() );
470cdf0e10cSrcweir 			pTrack = pTrack->GetNextTrack();
471cdf0e10cSrcweir 		} while ( pTrack );
472cdf0e10cSrcweir 		pTrack = pFormulaTrack;
473cdf0e10cSrcweir 		sal_Bool bHaveForced = sal_False;
474cdf0e10cSrcweir 		do
475cdf0e10cSrcweir 		{
476cdf0e10cSrcweir 			pNext = pTrack->GetNextTrack();
477cdf0e10cSrcweir 			RemoveFromFormulaTrack( pTrack );
478cdf0e10cSrcweir 			PutInFormulaTree( pTrack );
479cdf0e10cSrcweir 			if ( pTrack->GetCode()->IsRecalcModeForced() )
480cdf0e10cSrcweir 				bHaveForced = sal_True;
481cdf0e10cSrcweir 			pTrack = pNext;
482cdf0e10cSrcweir 		} while ( pTrack );
483cdf0e10cSrcweir 		if ( bHaveForced )
484cdf0e10cSrcweir 		{
485cdf0e10cSrcweir 			SetForcedFormulas( sal_True );
486cdf0e10cSrcweir 			if ( bAutoCalc && !IsAutoCalcShellDisabled() && !IsInInterpreter()
487cdf0e10cSrcweir 					&& !IsCalculatingFormulaTree() )
488cdf0e10cSrcweir 				CalcFormulaTree( sal_True );
489cdf0e10cSrcweir 			else
490cdf0e10cSrcweir 				SetForcedFormulaPending( sal_True );
491cdf0e10cSrcweir 		}
492cdf0e10cSrcweir 	}
493cdf0e10cSrcweir 	DBG_ASSERT( nFormulaTrackCount==0, "TrackFormulas: nFormulaTrackCount!=0" );
494cdf0e10cSrcweir }
495cdf0e10cSrcweir 
496cdf0e10cSrcweir 
StartAllListeners()497cdf0e10cSrcweir void ScDocument::StartAllListeners()
498cdf0e10cSrcweir {
499cdf0e10cSrcweir 	for ( SCTAB i = 0; i <= MAXTAB; ++i )
500cdf0e10cSrcweir 		if ( pTab[i] )
501cdf0e10cSrcweir 			pTab[i]->StartAllListeners();
502cdf0e10cSrcweir }
503cdf0e10cSrcweir 
UpdateBroadcastAreas(UpdateRefMode eUpdateRefMode,const ScRange & rRange,SCsCOL nDx,SCsROW nDy,SCsTAB nDz)504cdf0e10cSrcweir void ScDocument::UpdateBroadcastAreas( UpdateRefMode eUpdateRefMode,
505cdf0e10cSrcweir 		const ScRange& rRange, SCsCOL nDx, SCsROW nDy, SCsTAB nDz
506cdf0e10cSrcweir 	)
507cdf0e10cSrcweir {
508cdf0e10cSrcweir 	sal_Bool bExpandRefsOld = IsExpandRefs();
509cdf0e10cSrcweir 	if ( eUpdateRefMode == URM_INSDEL && (nDx > 0 || nDy > 0 || nDz > 0) )
510cdf0e10cSrcweir 		SetExpandRefs( SC_MOD()->GetInputOptions().GetExpandRefs() );
511cdf0e10cSrcweir 	if ( pBASM )
512cdf0e10cSrcweir 		pBASM->UpdateBroadcastAreas( eUpdateRefMode, rRange, nDx, nDy, nDz );
513cdf0e10cSrcweir 	SetExpandRefs( bExpandRefsOld );
514cdf0e10cSrcweir }
515cdf0e10cSrcweir 
SetAutoCalc(sal_Bool bNewAutoCalc)516cdf0e10cSrcweir void ScDocument::SetAutoCalc( sal_Bool bNewAutoCalc )
517cdf0e10cSrcweir {
518cdf0e10cSrcweir 	sal_Bool bOld = bAutoCalc;
519cdf0e10cSrcweir 	bAutoCalc = bNewAutoCalc;
520cdf0e10cSrcweir 	if ( !bOld && bNewAutoCalc && bHasForcedFormulas )
521cdf0e10cSrcweir 	{
522cdf0e10cSrcweir 		if ( IsAutoCalcShellDisabled() )
523cdf0e10cSrcweir 			SetForcedFormulaPending( sal_True );
524cdf0e10cSrcweir 		else if ( !IsInInterpreter() )
525cdf0e10cSrcweir 			CalcFormulaTree( sal_True );
526cdf0e10cSrcweir 	}
527cdf0e10cSrcweir }
528cdf0e10cSrcweir 
529cdf0e10cSrcweir 
530cdf0e10cSrcweir 
531