xref: /trunk/main/sc/source/core/data/documen7.cxx (revision cf6516809c57e1bb0a940545cca99cdad54d4ce2)
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
10cdf0e10cSrcweir  *
11*b3f79822SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
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.
19cdf0e10cSrcweir  *
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 }
528