xref: /aoo42x/main/sc/source/core/data/cell.cxx (revision 7a980842)
1b3f79822SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3b3f79822SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4b3f79822SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5b3f79822SAndrew Rist  * distributed with this work for additional information
6b3f79822SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7b3f79822SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8b3f79822SAndrew Rist  * "License"); you may not use this file except in compliance
9b3f79822SAndrew Rist  * with the License.  You may obtain a copy of the License at
10b3f79822SAndrew Rist  *
11b3f79822SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12b3f79822SAndrew Rist  *
13b3f79822SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14b3f79822SAndrew Rist  * software distributed under the License is distributed on an
15b3f79822SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16b3f79822SAndrew Rist  * KIND, either express or implied.  See the License for the
17b3f79822SAndrew Rist  * specific language governing permissions and limitations
18b3f79822SAndrew Rist  * under the License.
19b3f79822SAndrew Rist  *
20b3f79822SAndrew Rist  *************************************************************/
21b3f79822SAndrew Rist 
22cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
23cdf0e10cSrcweir #include "precompiled_sc.hxx"
24cdf0e10cSrcweir 
25cdf0e10cSrcweir // INCLUDE ---------------------------------------------------------------
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include <svl/zforlist.hxx>
28cdf0e10cSrcweir 
29cdf0e10cSrcweir #include "scitems.hxx"
30cdf0e10cSrcweir #include "attrib.hxx"
31cdf0e10cSrcweir #include "cell.hxx"
32cdf0e10cSrcweir #include "compiler.hxx"
33cdf0e10cSrcweir #include "interpre.hxx"
34cdf0e10cSrcweir #include "document.hxx"
35cdf0e10cSrcweir #include "scmatrix.hxx"
36cdf0e10cSrcweir #include "dociter.hxx"
37cdf0e10cSrcweir #include "docoptio.hxx"
38cdf0e10cSrcweir #include "rechead.hxx"
39cdf0e10cSrcweir #include "rangenam.hxx"
40cdf0e10cSrcweir #include "brdcst.hxx"
41cdf0e10cSrcweir #include "ddelink.hxx"
42cdf0e10cSrcweir #include "validat.hxx"
43cdf0e10cSrcweir #include "progress.hxx"
44cdf0e10cSrcweir #include "editutil.hxx"
45cdf0e10cSrcweir #include "recursionhelper.hxx"
46cdf0e10cSrcweir #include "postit.hxx"
47cdf0e10cSrcweir #include "externalrefmgr.hxx"
48cdf0e10cSrcweir #include <editeng/editobj.hxx>
49cdf0e10cSrcweir #include <svl/intitem.hxx>
50cdf0e10cSrcweir #include <editeng/flditem.hxx>
51cdf0e10cSrcweir #include <svl/broadcast.hxx>
52cdf0e10cSrcweir 
53cdf0e10cSrcweir using namespace formula;
54cdf0e10cSrcweir // More or less arbitrary, of course all recursions must fit into available
55cdf0e10cSrcweir // stack space (which is what on all systems we don't know yet?). Choosing a
56cdf0e10cSrcweir // lower value may be better than trying a much higher value that also isn't
57cdf0e10cSrcweir // sufficient but temporarily leads to high memory consumption. On the other
58cdf0e10cSrcweir // hand, if the value fits all recursions, execution is quicker as no resumes
59cdf0e10cSrcweir // are necessary. Could be made a configurable option.
60cdf0e10cSrcweir // Allow for a year's calendar (366).
61cdf0e10cSrcweir const sal_uInt16 MAXRECURSION = 400;
62cdf0e10cSrcweir 
63cdf0e10cSrcweir // STATIC DATA -----------------------------------------------------------
64cdf0e10cSrcweir 
65cdf0e10cSrcweir #ifdef USE_MEMPOOL
66cdf0e10cSrcweir // MemPools auf 4k Boundaries  - 64 Bytes ausrichten
67cdf0e10cSrcweir const sal_uInt16 nMemPoolValueCell = (0x8000 - 64) / sizeof(ScValueCell);
68cdf0e10cSrcweir const sal_uInt16 nMemPoolFormulaCell = (0x8000 - 64) / sizeof(ScFormulaCell);
69cdf0e10cSrcweir const sal_uInt16 nMemPoolStringCell = (0x4000 - 64) / sizeof(ScStringCell);
70cdf0e10cSrcweir const sal_uInt16 nMemPoolNoteCell = (0x1000 - 64) / sizeof(ScNoteCell);
IMPL_FIXEDMEMPOOL_NEWDEL(ScValueCell,nMemPoolValueCell,nMemPoolValueCell)71cdf0e10cSrcweir IMPL_FIXEDMEMPOOL_NEWDEL( ScValueCell,   nMemPoolValueCell, nMemPoolValueCell )
72cdf0e10cSrcweir IMPL_FIXEDMEMPOOL_NEWDEL( ScFormulaCell, nMemPoolFormulaCell, nMemPoolFormulaCell )
73cdf0e10cSrcweir IMPL_FIXEDMEMPOOL_NEWDEL( ScStringCell,  nMemPoolStringCell, nMemPoolStringCell )
74cdf0e10cSrcweir IMPL_FIXEDMEMPOOL_NEWDEL( ScNoteCell,	 nMemPoolNoteCell, nMemPoolNoteCell )
75cdf0e10cSrcweir #endif
76cdf0e10cSrcweir 
77cdf0e10cSrcweir // ============================================================================
78cdf0e10cSrcweir 
79cdf0e10cSrcweir ScBaseCell::ScBaseCell( CellType eNewType ) :
80cdf0e10cSrcweir     mpNote( 0 ),
81cdf0e10cSrcweir     mpBroadcaster( 0 ),
82cdf0e10cSrcweir     nTextWidth( TEXTWIDTH_DIRTY ),
83cdf0e10cSrcweir     eCellType( sal::static_int_cast<sal_uInt8>(eNewType) ),
84cdf0e10cSrcweir     nScriptType( SC_SCRIPTTYPE_UNKNOWN )
85cdf0e10cSrcweir {
86cdf0e10cSrcweir }
87cdf0e10cSrcweir 
ScBaseCell(const ScBaseCell & rCell)88cdf0e10cSrcweir ScBaseCell::ScBaseCell( const ScBaseCell& rCell ) :
89cdf0e10cSrcweir     mpNote( 0 ),
90cdf0e10cSrcweir     mpBroadcaster( 0 ),
91cdf0e10cSrcweir     nTextWidth( rCell.nTextWidth ),
92cdf0e10cSrcweir     eCellType( rCell.eCellType ),
93cdf0e10cSrcweir     nScriptType( SC_SCRIPTTYPE_UNKNOWN )
94cdf0e10cSrcweir {
95cdf0e10cSrcweir }
96cdf0e10cSrcweir 
~ScBaseCell()97cdf0e10cSrcweir ScBaseCell::~ScBaseCell()
98cdf0e10cSrcweir {
99cdf0e10cSrcweir     delete mpNote;
100cdf0e10cSrcweir     delete mpBroadcaster;
101cdf0e10cSrcweir     DBG_ASSERT( eCellType == CELLTYPE_DESTROYED, "BaseCell Destructor" );
102cdf0e10cSrcweir }
103cdf0e10cSrcweir 
104cdf0e10cSrcweir namespace {
105cdf0e10cSrcweir 
lclCloneCell(const ScBaseCell & rSrcCell,ScDocument & rDestDoc,const ScAddress & rDestPos,int nCloneFlags)106cdf0e10cSrcweir ScBaseCell* lclCloneCell( const ScBaseCell& rSrcCell, ScDocument& rDestDoc, const ScAddress& rDestPos, int nCloneFlags )
107cdf0e10cSrcweir {
108cdf0e10cSrcweir     switch( rSrcCell.GetCellType() )
109cdf0e10cSrcweir     {
110cdf0e10cSrcweir         case CELLTYPE_VALUE:
111cdf0e10cSrcweir             return new ScValueCell( static_cast< const ScValueCell& >( rSrcCell ) );
112cdf0e10cSrcweir         case CELLTYPE_STRING:
113cdf0e10cSrcweir             return new ScStringCell( static_cast< const ScStringCell& >( rSrcCell ) );
114cdf0e10cSrcweir         case CELLTYPE_EDIT:
115cdf0e10cSrcweir             return new ScEditCell( static_cast< const ScEditCell& >( rSrcCell ), rDestDoc );
116cdf0e10cSrcweir         case CELLTYPE_FORMULA:
117cdf0e10cSrcweir             return new ScFormulaCell( static_cast< const ScFormulaCell& >( rSrcCell ), rDestDoc, rDestPos, nCloneFlags );
118cdf0e10cSrcweir         case CELLTYPE_NOTE:
119cdf0e10cSrcweir             return new ScNoteCell;
120cdf0e10cSrcweir         default:;
121cdf0e10cSrcweir     }
122cdf0e10cSrcweir     DBG_ERROR( "lclCloneCell - unknown cell type" );
123cdf0e10cSrcweir     return 0;
124cdf0e10cSrcweir }
125cdf0e10cSrcweir 
126cdf0e10cSrcweir } // namespace
127cdf0e10cSrcweir 
CloneWithoutNote(ScDocument & rDestDoc,int nCloneFlags) const128cdf0e10cSrcweir ScBaseCell* ScBaseCell::CloneWithoutNote( ScDocument& rDestDoc, int nCloneFlags ) const
129cdf0e10cSrcweir {
130cdf0e10cSrcweir     // notes will not be cloned -> cell address only needed for formula cells
131cdf0e10cSrcweir     ScAddress aDestPos;
132cdf0e10cSrcweir     if( eCellType == CELLTYPE_FORMULA )
133cdf0e10cSrcweir         aDestPos = static_cast< const ScFormulaCell* >( this )->aPos;
134cdf0e10cSrcweir     return lclCloneCell( *this, rDestDoc, aDestPos, nCloneFlags );
135cdf0e10cSrcweir }
136cdf0e10cSrcweir 
CloneWithoutNote(ScDocument & rDestDoc,const ScAddress & rDestPos,int nCloneFlags) const137cdf0e10cSrcweir ScBaseCell* ScBaseCell::CloneWithoutNote( ScDocument& rDestDoc, const ScAddress& rDestPos, int nCloneFlags ) const
138cdf0e10cSrcweir {
139cdf0e10cSrcweir     return lclCloneCell( *this, rDestDoc, rDestPos, nCloneFlags );
140cdf0e10cSrcweir }
141cdf0e10cSrcweir 
CloneWithNote(const ScAddress & rOwnPos,ScDocument & rDestDoc,const ScAddress & rDestPos,int nCloneFlags) const142cdf0e10cSrcweir ScBaseCell* ScBaseCell::CloneWithNote( const ScAddress& rOwnPos, ScDocument& rDestDoc, const ScAddress& rDestPos, int nCloneFlags ) const
143cdf0e10cSrcweir {
144cdf0e10cSrcweir     ScBaseCell* pNewCell = lclCloneCell( *this, rDestDoc, rDestPos, nCloneFlags );
145cdf0e10cSrcweir     if( mpNote )
146cdf0e10cSrcweir     {
147cdf0e10cSrcweir         if( !pNewCell )
148cdf0e10cSrcweir             pNewCell = new ScNoteCell;
149cdf0e10cSrcweir         bool bCloneCaption = (nCloneFlags & SC_CLONECELL_NOCAPTION) == 0;
150cdf0e10cSrcweir         pNewCell->TakeNote( mpNote->Clone( rOwnPos, rDestDoc, rDestPos, bCloneCaption ) );
151cdf0e10cSrcweir     }
152cdf0e10cSrcweir     return pNewCell;
153cdf0e10cSrcweir }
154cdf0e10cSrcweir 
Delete()155cdf0e10cSrcweir void ScBaseCell::Delete()
156cdf0e10cSrcweir {
157cdf0e10cSrcweir 	DeleteNote();
158cdf0e10cSrcweir 	switch (eCellType)
159cdf0e10cSrcweir 	{
160cdf0e10cSrcweir 		case CELLTYPE_VALUE:
161cdf0e10cSrcweir 			delete (ScValueCell*) this;
162cdf0e10cSrcweir 			break;
163cdf0e10cSrcweir 		case CELLTYPE_STRING:
164cdf0e10cSrcweir 			delete (ScStringCell*) this;
165cdf0e10cSrcweir 			break;
166cdf0e10cSrcweir 		case CELLTYPE_EDIT:
167cdf0e10cSrcweir 			delete (ScEditCell*) this;
168cdf0e10cSrcweir 			break;
169cdf0e10cSrcweir 		case CELLTYPE_FORMULA:
170cdf0e10cSrcweir 			delete (ScFormulaCell*) this;
171cdf0e10cSrcweir 			break;
172cdf0e10cSrcweir 		case CELLTYPE_NOTE:
173cdf0e10cSrcweir 			delete (ScNoteCell*) this;
174cdf0e10cSrcweir 			break;
175cdf0e10cSrcweir 		default:
176cdf0e10cSrcweir 			DBG_ERROR("Unbekannter Zellentyp");
177cdf0e10cSrcweir 			break;
178cdf0e10cSrcweir 	}
179cdf0e10cSrcweir }
180cdf0e10cSrcweir 
IsBlank(bool bIgnoreNotes) const181cdf0e10cSrcweir bool ScBaseCell::IsBlank( bool bIgnoreNotes ) const
182cdf0e10cSrcweir {
183cdf0e10cSrcweir     return (eCellType == CELLTYPE_NOTE) && (bIgnoreNotes || !mpNote);
184cdf0e10cSrcweir }
185cdf0e10cSrcweir 
TakeNote(ScPostIt * pNote)186cdf0e10cSrcweir void ScBaseCell::TakeNote( ScPostIt* pNote )
187cdf0e10cSrcweir {
188cdf0e10cSrcweir     delete mpNote;
189cdf0e10cSrcweir     mpNote = pNote;
190cdf0e10cSrcweir }
191cdf0e10cSrcweir 
ReleaseNote()192cdf0e10cSrcweir ScPostIt* ScBaseCell::ReleaseNote()
193cdf0e10cSrcweir {
194cdf0e10cSrcweir     ScPostIt* pNote = mpNote;
195cdf0e10cSrcweir     mpNote = 0;
196cdf0e10cSrcweir     return pNote;
197cdf0e10cSrcweir }
198cdf0e10cSrcweir 
DeleteNote()199cdf0e10cSrcweir void ScBaseCell::DeleteNote()
200cdf0e10cSrcweir {
201cdf0e10cSrcweir     DELETEZ( mpNote );
202cdf0e10cSrcweir }
203cdf0e10cSrcweir 
TakeBroadcaster(SvtBroadcaster * pBroadcaster)204cdf0e10cSrcweir void ScBaseCell::TakeBroadcaster( SvtBroadcaster* pBroadcaster )
205cdf0e10cSrcweir {
206cdf0e10cSrcweir     delete mpBroadcaster;
207cdf0e10cSrcweir     mpBroadcaster = pBroadcaster;
208cdf0e10cSrcweir }
209cdf0e10cSrcweir 
ReleaseBroadcaster()210cdf0e10cSrcweir SvtBroadcaster* ScBaseCell::ReleaseBroadcaster()
211cdf0e10cSrcweir {
212cdf0e10cSrcweir     SvtBroadcaster* pBroadcaster = mpBroadcaster;
213cdf0e10cSrcweir     mpBroadcaster = 0;
214cdf0e10cSrcweir     return pBroadcaster;
215cdf0e10cSrcweir }
216cdf0e10cSrcweir 
DeleteBroadcaster()217cdf0e10cSrcweir void ScBaseCell::DeleteBroadcaster()
218cdf0e10cSrcweir {
219cdf0e10cSrcweir     DELETEZ( mpBroadcaster );
220cdf0e10cSrcweir }
221cdf0e10cSrcweir 
CreateTextCell(const String & rString,ScDocument * pDoc)222cdf0e10cSrcweir ScBaseCell* ScBaseCell::CreateTextCell( const String& rString, ScDocument* pDoc )
223cdf0e10cSrcweir {
224cdf0e10cSrcweir 	if ( rString.Search('\n') != STRING_NOTFOUND || rString.Search(CHAR_CR) != STRING_NOTFOUND )
225cdf0e10cSrcweir 		return new ScEditCell( rString, pDoc );
226cdf0e10cSrcweir 	else
227cdf0e10cSrcweir 		return new ScStringCell( rString );
228cdf0e10cSrcweir }
229cdf0e10cSrcweir 
StartListeningTo(ScDocument * pDoc)230cdf0e10cSrcweir void ScBaseCell::StartListeningTo( ScDocument* pDoc )
231cdf0e10cSrcweir {
232cdf0e10cSrcweir 	if ( eCellType == CELLTYPE_FORMULA && !pDoc->IsClipOrUndo()
233cdf0e10cSrcweir 			&& !pDoc->GetNoListening()
234cdf0e10cSrcweir 			&& !((ScFormulaCell*)this)->IsInChangeTrack()
235cdf0e10cSrcweir 		)
236cdf0e10cSrcweir 	{
237cdf0e10cSrcweir 		pDoc->SetDetectiveDirty(sal_True);	// es hat sich was geaendert...
238cdf0e10cSrcweir 
239cdf0e10cSrcweir 		ScFormulaCell* pFormCell = (ScFormulaCell*)this;
240cdf0e10cSrcweir         ScTokenArray* pArr = pFormCell->GetCode();
241cdf0e10cSrcweir 		if( pArr->IsRecalcModeAlways() )
242cdf0e10cSrcweir 			pDoc->StartListeningArea( BCA_LISTEN_ALWAYS, pFormCell );
243cdf0e10cSrcweir 		else
244cdf0e10cSrcweir 		{
245cdf0e10cSrcweir 			pArr->Reset();
246cdf0e10cSrcweir             ScToken* t;
247cdf0e10cSrcweir             while ( ( t = static_cast<ScToken*>(pArr->GetNextReferenceRPN()) ) != NULL )
248cdf0e10cSrcweir 			{
249cdf0e10cSrcweir 				StackVar eType = t->GetType();
250cdf0e10cSrcweir 				ScSingleRefData& rRef1 = t->GetSingleRef();
251cdf0e10cSrcweir 				ScSingleRefData& rRef2 = (eType == svDoubleRef ?
252cdf0e10cSrcweir 					t->GetDoubleRef().Ref2 : rRef1);
253cdf0e10cSrcweir                 switch( eType )
254cdf0e10cSrcweir                 {
255cdf0e10cSrcweir                     case svSingleRef:
256cdf0e10cSrcweir                         rRef1.CalcAbsIfRel( pFormCell->aPos );
257cdf0e10cSrcweir                         if ( rRef1.Valid() )
258cdf0e10cSrcweir                         {
259cdf0e10cSrcweir                             pDoc->StartListeningCell(
260cdf0e10cSrcweir                                 ScAddress( rRef1.nCol,
261cdf0e10cSrcweir                                            rRef1.nRow,
262cdf0e10cSrcweir                                            rRef1.nTab ), pFormCell );
263cdf0e10cSrcweir                         }
264cdf0e10cSrcweir                     break;
265cdf0e10cSrcweir                     case svDoubleRef:
266cdf0e10cSrcweir                         t->CalcAbsIfRel( pFormCell->aPos );
267cdf0e10cSrcweir                         if ( rRef1.Valid() && rRef2.Valid() )
268cdf0e10cSrcweir                         {
269cdf0e10cSrcweir                             if ( t->GetOpCode() == ocColRowNameAuto )
270cdf0e10cSrcweir                             {	// automagically
271cdf0e10cSrcweir                                 if ( rRef1.IsColRel() )
272cdf0e10cSrcweir                                 {	// ColName
273cdf0e10cSrcweir                                     pDoc->StartListeningArea( ScRange (
274cdf0e10cSrcweir                                         rRef1.nCol,
275cdf0e10cSrcweir                                         rRef1.nRow,
276cdf0e10cSrcweir                                         rRef1.nTab,
277cdf0e10cSrcweir                                         rRef2.nCol,
278cdf0e10cSrcweir                                         MAXROW,
279cdf0e10cSrcweir                                         rRef2.nTab ), pFormCell );
280cdf0e10cSrcweir                                 }
281cdf0e10cSrcweir                                 else
282cdf0e10cSrcweir                                 {	// RowName
283cdf0e10cSrcweir                                     pDoc->StartListeningArea( ScRange (
284cdf0e10cSrcweir                                         rRef1.nCol,
285cdf0e10cSrcweir                                         rRef1.nRow,
286cdf0e10cSrcweir                                         rRef1.nTab,
287cdf0e10cSrcweir                                         MAXCOL,
288cdf0e10cSrcweir                                         rRef2.nRow,
289cdf0e10cSrcweir                                         rRef2.nTab ), pFormCell );
290cdf0e10cSrcweir                                 }
291cdf0e10cSrcweir                             }
292cdf0e10cSrcweir                             else
293cdf0e10cSrcweir                             {
294cdf0e10cSrcweir                                 pDoc->StartListeningArea( ScRange (
295cdf0e10cSrcweir                                     rRef1.nCol,
296cdf0e10cSrcweir                                     rRef1.nRow,
297cdf0e10cSrcweir                                     rRef1.nTab,
298cdf0e10cSrcweir                                     rRef2.nCol,
299cdf0e10cSrcweir                                     rRef2.nRow,
300cdf0e10cSrcweir                                     rRef2.nTab ), pFormCell );
301cdf0e10cSrcweir                             }
302cdf0e10cSrcweir                         }
303cdf0e10cSrcweir                     break;
304cdf0e10cSrcweir                     default:
305cdf0e10cSrcweir                         ;   // nothing
306cdf0e10cSrcweir                 }
307cdf0e10cSrcweir 			}
308cdf0e10cSrcweir 		}
309cdf0e10cSrcweir         pFormCell->SetNeedsListening( sal_False);
310cdf0e10cSrcweir 	}
311cdf0e10cSrcweir }
312cdf0e10cSrcweir 
313cdf0e10cSrcweir //	pArr gesetzt -> Referenzen von anderer Zelle nehmen
314cdf0e10cSrcweir // dann muss auch aPos uebergeben werden!
315cdf0e10cSrcweir 
EndListeningTo(ScDocument * pDoc,ScTokenArray * pArr,ScAddress aPos)316cdf0e10cSrcweir void ScBaseCell::EndListeningTo( ScDocument* pDoc, ScTokenArray* pArr,
317cdf0e10cSrcweir         ScAddress aPos )
318cdf0e10cSrcweir {
319cdf0e10cSrcweir 	if ( eCellType == CELLTYPE_FORMULA && !pDoc->IsClipOrUndo()
320cdf0e10cSrcweir 			&& !((ScFormulaCell*)this)->IsInChangeTrack()
321cdf0e10cSrcweir 		)
322cdf0e10cSrcweir 	{
323cdf0e10cSrcweir 		pDoc->SetDetectiveDirty(sal_True);	// es hat sich was geaendert...
324cdf0e10cSrcweir 
325cdf0e10cSrcweir 		ScFormulaCell* pFormCell = (ScFormulaCell*)this;
326cdf0e10cSrcweir 		if( pFormCell->GetCode()->IsRecalcModeAlways() )
327cdf0e10cSrcweir 			pDoc->EndListeningArea( BCA_LISTEN_ALWAYS, pFormCell );
328cdf0e10cSrcweir 		else
329cdf0e10cSrcweir 		{
330cdf0e10cSrcweir 			if (!pArr)
331cdf0e10cSrcweir 			{
332cdf0e10cSrcweir 				pArr = pFormCell->GetCode();
333cdf0e10cSrcweir 				aPos = pFormCell->aPos;
334cdf0e10cSrcweir 			}
335cdf0e10cSrcweir 			pArr->Reset();
336cdf0e10cSrcweir 			ScToken* t;
337cdf0e10cSrcweir             while ( ( t = static_cast<ScToken*>(pArr->GetNextReferenceRPN()) ) != NULL )
338cdf0e10cSrcweir 			{
339cdf0e10cSrcweir 				StackVar eType = t->GetType();
340cdf0e10cSrcweir 				ScSingleRefData& rRef1 = t->GetSingleRef();
341cdf0e10cSrcweir 				ScSingleRefData& rRef2 = (eType == svDoubleRef ?
342cdf0e10cSrcweir 					t->GetDoubleRef().Ref2 : rRef1);
343cdf0e10cSrcweir                 switch( eType )
344cdf0e10cSrcweir                 {
345cdf0e10cSrcweir                     case svSingleRef:
346cdf0e10cSrcweir                         rRef1.CalcAbsIfRel( aPos );
347cdf0e10cSrcweir                         if ( rRef1.Valid() )
348cdf0e10cSrcweir                         {
349cdf0e10cSrcweir                             pDoc->EndListeningCell(
350cdf0e10cSrcweir                                 ScAddress( rRef1.nCol,
351cdf0e10cSrcweir                                            rRef1.nRow,
352cdf0e10cSrcweir                                            rRef1.nTab ), pFormCell );
353cdf0e10cSrcweir                         }
354cdf0e10cSrcweir                     break;
355cdf0e10cSrcweir                     case svDoubleRef:
356cdf0e10cSrcweir                         t->CalcAbsIfRel( aPos );
357cdf0e10cSrcweir                         if ( rRef1.Valid() && rRef2.Valid() )
358cdf0e10cSrcweir                         {
359cdf0e10cSrcweir                             if ( t->GetOpCode() == ocColRowNameAuto )
360cdf0e10cSrcweir                             {	// automagically
361cdf0e10cSrcweir                                 if ( rRef1.IsColRel() )
362cdf0e10cSrcweir                                 {	// ColName
363cdf0e10cSrcweir                                     pDoc->EndListeningArea( ScRange (
364cdf0e10cSrcweir                                         rRef1.nCol,
365cdf0e10cSrcweir                                         rRef1.nRow,
366cdf0e10cSrcweir                                         rRef1.nTab,
367cdf0e10cSrcweir                                         rRef2.nCol,
368cdf0e10cSrcweir                                         MAXROW,
369cdf0e10cSrcweir                                         rRef2.nTab ), pFormCell );
370cdf0e10cSrcweir                                 }
371cdf0e10cSrcweir                                 else
372cdf0e10cSrcweir                                 {	// RowName
373cdf0e10cSrcweir                                     pDoc->EndListeningArea( ScRange (
374cdf0e10cSrcweir                                         rRef1.nCol,
375cdf0e10cSrcweir                                         rRef1.nRow,
376cdf0e10cSrcweir                                         rRef1.nTab,
377cdf0e10cSrcweir                                         MAXCOL,
378cdf0e10cSrcweir                                         rRef2.nRow,
379cdf0e10cSrcweir                                         rRef2.nTab ), pFormCell );
380cdf0e10cSrcweir                                 }
381cdf0e10cSrcweir                             }
382cdf0e10cSrcweir                             else
383cdf0e10cSrcweir                             {
384cdf0e10cSrcweir                                 pDoc->EndListeningArea( ScRange (
385cdf0e10cSrcweir                                     rRef1.nCol,
386cdf0e10cSrcweir                                     rRef1.nRow,
387cdf0e10cSrcweir                                     rRef1.nTab,
388cdf0e10cSrcweir                                     rRef2.nCol,
389cdf0e10cSrcweir                                     rRef2.nRow,
390cdf0e10cSrcweir                                     rRef2.nTab ), pFormCell );
391cdf0e10cSrcweir                             }
392cdf0e10cSrcweir                         }
393cdf0e10cSrcweir                     break;
394cdf0e10cSrcweir                     default:
395cdf0e10cSrcweir                         ;   // nothing
396cdf0e10cSrcweir                 }
397cdf0e10cSrcweir 			}
398cdf0e10cSrcweir 		}
399cdf0e10cSrcweir 	}
400cdf0e10cSrcweir }
401cdf0e10cSrcweir 
402cdf0e10cSrcweir 
GetErrorCode() const403cdf0e10cSrcweir sal_uInt16 ScBaseCell::GetErrorCode() const
404cdf0e10cSrcweir {
405cdf0e10cSrcweir 	switch ( eCellType )
406cdf0e10cSrcweir 	{
407cdf0e10cSrcweir 		case CELLTYPE_FORMULA :
408cdf0e10cSrcweir 			return ((ScFormulaCell*)this)->GetErrCode();
409cdf0e10cSrcweir 		default:
410cdf0e10cSrcweir 			return 0;
411cdf0e10cSrcweir 	}
412cdf0e10cSrcweir }
413cdf0e10cSrcweir 
414cdf0e10cSrcweir 
HasEmptyData() const415cdf0e10cSrcweir sal_Bool ScBaseCell::HasEmptyData() const
416cdf0e10cSrcweir {
417cdf0e10cSrcweir 	switch ( eCellType )
418cdf0e10cSrcweir 	{
419cdf0e10cSrcweir 		case CELLTYPE_NOTE :
420cdf0e10cSrcweir 			return sal_True;
421cdf0e10cSrcweir 		case CELLTYPE_FORMULA :
422cdf0e10cSrcweir 			return ((ScFormulaCell*)this)->IsEmpty();
423cdf0e10cSrcweir 		default:
424cdf0e10cSrcweir 			return sal_False;
425cdf0e10cSrcweir 	}
426cdf0e10cSrcweir }
427cdf0e10cSrcweir 
428cdf0e10cSrcweir 
HasValueData() const429cdf0e10cSrcweir sal_Bool ScBaseCell::HasValueData() const
430cdf0e10cSrcweir {
431cdf0e10cSrcweir 	switch ( eCellType )
432cdf0e10cSrcweir 	{
433cdf0e10cSrcweir 		case CELLTYPE_VALUE :
434cdf0e10cSrcweir 			return sal_True;
435cdf0e10cSrcweir 		case CELLTYPE_FORMULA :
436cdf0e10cSrcweir 			return ((ScFormulaCell*)this)->IsValue();
437cdf0e10cSrcweir 		default:
438cdf0e10cSrcweir 			return sal_False;
439cdf0e10cSrcweir 	}
440cdf0e10cSrcweir }
441cdf0e10cSrcweir 
442cdf0e10cSrcweir 
HasStringData() const443cdf0e10cSrcweir sal_Bool ScBaseCell::HasStringData() const
444cdf0e10cSrcweir {
445cdf0e10cSrcweir 	switch ( eCellType )
446cdf0e10cSrcweir 	{
447cdf0e10cSrcweir 		case CELLTYPE_STRING :
448cdf0e10cSrcweir 		case CELLTYPE_EDIT :
449cdf0e10cSrcweir 			return sal_True;
450cdf0e10cSrcweir 		case CELLTYPE_FORMULA :
451cdf0e10cSrcweir 			return !((ScFormulaCell*)this)->IsValue();
452cdf0e10cSrcweir 		default:
453cdf0e10cSrcweir 			return sal_False;
454cdf0e10cSrcweir 	}
455cdf0e10cSrcweir }
456cdf0e10cSrcweir 
GetStringData() const457cdf0e10cSrcweir String ScBaseCell::GetStringData() const
458cdf0e10cSrcweir {
459cdf0e10cSrcweir 	String aStr;
460cdf0e10cSrcweir 	switch ( eCellType )
461cdf0e10cSrcweir 	{
462cdf0e10cSrcweir 		case CELLTYPE_STRING:
463cdf0e10cSrcweir 			((const ScStringCell*)this)->GetString( aStr );
464cdf0e10cSrcweir 			break;
465cdf0e10cSrcweir 		case CELLTYPE_EDIT:
466cdf0e10cSrcweir 			((const ScEditCell*)this)->GetString( aStr );
467cdf0e10cSrcweir 			break;
468cdf0e10cSrcweir 		case CELLTYPE_FORMULA:
469cdf0e10cSrcweir 			((ScFormulaCell*)this)->GetString( aStr );		// an der Formelzelle nicht-const
470cdf0e10cSrcweir 			break;
471cdf0e10cSrcweir 	}
472cdf0e10cSrcweir 	return aStr;
473cdf0e10cSrcweir }
474cdf0e10cSrcweir 
475cdf0e10cSrcweir //	static
CellEqual(const ScBaseCell * pCell1,const ScBaseCell * pCell2)476cdf0e10cSrcweir sal_Bool ScBaseCell::CellEqual( const ScBaseCell* pCell1, const ScBaseCell* pCell2 )
477cdf0e10cSrcweir {
478cdf0e10cSrcweir 	CellType eType1 = CELLTYPE_NONE;
479cdf0e10cSrcweir 	CellType eType2 = CELLTYPE_NONE;
480cdf0e10cSrcweir 	if ( pCell1 )
481cdf0e10cSrcweir 	{
482cdf0e10cSrcweir 		eType1 = pCell1->GetCellType();
483cdf0e10cSrcweir 		if (eType1 == CELLTYPE_EDIT)
484cdf0e10cSrcweir 			eType1 = CELLTYPE_STRING;
485cdf0e10cSrcweir 		else if (eType1 == CELLTYPE_NOTE)
486cdf0e10cSrcweir 			eType1 = CELLTYPE_NONE;
487cdf0e10cSrcweir 	}
488cdf0e10cSrcweir 	if ( pCell2 )
489cdf0e10cSrcweir 	{
490cdf0e10cSrcweir 		eType2 = pCell2->GetCellType();
491cdf0e10cSrcweir 		if (eType2 == CELLTYPE_EDIT)
492cdf0e10cSrcweir 			eType2 = CELLTYPE_STRING;
493cdf0e10cSrcweir 		else if (eType2 == CELLTYPE_NOTE)
494cdf0e10cSrcweir 			eType2 = CELLTYPE_NONE;
495cdf0e10cSrcweir 	}
496cdf0e10cSrcweir 	if ( eType1 != eType2 )
497cdf0e10cSrcweir 		return sal_False;
498cdf0e10cSrcweir 
499cdf0e10cSrcweir 	switch ( eType1 )				// beide Typen gleich
500cdf0e10cSrcweir 	{
501cdf0e10cSrcweir 		case CELLTYPE_NONE:			// beide leer
502cdf0e10cSrcweir 			return sal_True;
503cdf0e10cSrcweir 		case CELLTYPE_VALUE:		// wirklich Value-Zellen
504cdf0e10cSrcweir 			return ( ((const ScValueCell*)pCell1)->GetValue() ==
505cdf0e10cSrcweir 					 ((const ScValueCell*)pCell2)->GetValue() );
506cdf0e10cSrcweir 		case CELLTYPE_STRING:		// String oder Edit
507cdf0e10cSrcweir 			{
508cdf0e10cSrcweir 				String aText1;
509cdf0e10cSrcweir 				if ( pCell1->GetCellType() == CELLTYPE_STRING )
510cdf0e10cSrcweir 					((const ScStringCell*)pCell1)->GetString(aText1);
511cdf0e10cSrcweir 				else
512cdf0e10cSrcweir 					((const ScEditCell*)pCell1)->GetString(aText1);
513cdf0e10cSrcweir 				String aText2;
514cdf0e10cSrcweir 				if ( pCell2->GetCellType() == CELLTYPE_STRING )
515cdf0e10cSrcweir 					((const ScStringCell*)pCell2)->GetString(aText2);
516cdf0e10cSrcweir 				else
517cdf0e10cSrcweir 					((const ScEditCell*)pCell2)->GetString(aText2);
518cdf0e10cSrcweir 				return ( aText1 == aText2 );
519cdf0e10cSrcweir 			}
520cdf0e10cSrcweir 		case CELLTYPE_FORMULA:
521cdf0e10cSrcweir 			{
522cdf0e10cSrcweir 				//!	eingefuegte Zeilen / Spalten beruecksichtigen !!!!!
523cdf0e10cSrcweir 				//!	Vergleichsfunktion an der Formelzelle ???
524cdf0e10cSrcweir 				//!	Abfrage mit ScColumn::SwapRow zusammenfassen!
525cdf0e10cSrcweir 
526cdf0e10cSrcweir 				ScTokenArray* pCode1 = ((ScFormulaCell*)pCell1)->GetCode();
527cdf0e10cSrcweir 				ScTokenArray* pCode2 = ((ScFormulaCell*)pCell2)->GetCode();
528cdf0e10cSrcweir 
529cdf0e10cSrcweir 				if (pCode1->GetLen() == pCode2->GetLen())		// nicht-UPN
530cdf0e10cSrcweir 				{
531cdf0e10cSrcweir 					sal_Bool bEqual = sal_True;
532cdf0e10cSrcweir 					sal_uInt16 nLen = pCode1->GetLen();
533cdf0e10cSrcweir 					FormulaToken** ppToken1 = pCode1->GetArray();
534cdf0e10cSrcweir 					FormulaToken** ppToken2 = pCode2->GetArray();
535cdf0e10cSrcweir 					for (sal_uInt16 i=0; i<nLen; i++)
536cdf0e10cSrcweir 						if ( !ppToken1[i]->TextEqual(*(ppToken2[i])) )
537cdf0e10cSrcweir 						{
538cdf0e10cSrcweir 							bEqual = sal_False;
539cdf0e10cSrcweir 							break;
540cdf0e10cSrcweir 						}
541cdf0e10cSrcweir 
542cdf0e10cSrcweir 					if (bEqual)
543cdf0e10cSrcweir 						return sal_True;
544cdf0e10cSrcweir 				}
545cdf0e10cSrcweir 
546cdf0e10cSrcweir 				return sal_False;		// unterschiedlich lang oder unterschiedliche Tokens
547cdf0e10cSrcweir 			}
548cdf0e10cSrcweir 		default:
549cdf0e10cSrcweir 			DBG_ERROR("huch, was fuer Zellen???");
550cdf0e10cSrcweir 	}
551cdf0e10cSrcweir 	return sal_False;
552cdf0e10cSrcweir }
553cdf0e10cSrcweir 
554cdf0e10cSrcweir // ============================================================================
555cdf0e10cSrcweir 
ScNoteCell(SvtBroadcaster * pBC)556cdf0e10cSrcweir ScNoteCell::ScNoteCell( SvtBroadcaster* pBC ) :
557cdf0e10cSrcweir 	ScBaseCell( CELLTYPE_NOTE )
558cdf0e10cSrcweir {
559cdf0e10cSrcweir     TakeBroadcaster( pBC );
560cdf0e10cSrcweir }
561cdf0e10cSrcweir 
ScNoteCell(ScPostIt * pNote,SvtBroadcaster * pBC)562cdf0e10cSrcweir ScNoteCell::ScNoteCell( ScPostIt* pNote, SvtBroadcaster* pBC ) :
563cdf0e10cSrcweir 	ScBaseCell( CELLTYPE_NOTE )
564cdf0e10cSrcweir {
565cdf0e10cSrcweir     TakeNote( pNote );
566cdf0e10cSrcweir     TakeBroadcaster( pBC );
567cdf0e10cSrcweir }
568cdf0e10cSrcweir 
569cdf0e10cSrcweir #ifdef DBG_UTIL
~ScNoteCell()570cdf0e10cSrcweir ScNoteCell::~ScNoteCell()
571cdf0e10cSrcweir {
572cdf0e10cSrcweir 	eCellType = CELLTYPE_DESTROYED;
573cdf0e10cSrcweir }
574cdf0e10cSrcweir #endif
575cdf0e10cSrcweir 
576cdf0e10cSrcweir // ============================================================================
577cdf0e10cSrcweir 
ScValueCell()578cdf0e10cSrcweir ScValueCell::ScValueCell() :
579cdf0e10cSrcweir 	ScBaseCell( CELLTYPE_VALUE ),
580cdf0e10cSrcweir 	mfValue( 0.0 )
581cdf0e10cSrcweir {
582cdf0e10cSrcweir }
583cdf0e10cSrcweir 
ScValueCell(double fValue)584cdf0e10cSrcweir ScValueCell::ScValueCell( double fValue ) :
585cdf0e10cSrcweir 	ScBaseCell( CELLTYPE_VALUE ),
586cdf0e10cSrcweir 	mfValue( fValue )
587cdf0e10cSrcweir {
588cdf0e10cSrcweir }
589cdf0e10cSrcweir 
590cdf0e10cSrcweir #ifdef DBG_UTIL
~ScValueCell()591cdf0e10cSrcweir ScValueCell::~ScValueCell()
592cdf0e10cSrcweir {
593cdf0e10cSrcweir 	eCellType = CELLTYPE_DESTROYED;
594cdf0e10cSrcweir }
595cdf0e10cSrcweir #endif
596cdf0e10cSrcweir 
597cdf0e10cSrcweir // ============================================================================
598cdf0e10cSrcweir 
ScStringCell()599cdf0e10cSrcweir ScStringCell::ScStringCell() :
600cdf0e10cSrcweir 	ScBaseCell( CELLTYPE_STRING )
601cdf0e10cSrcweir {
602cdf0e10cSrcweir }
603cdf0e10cSrcweir 
ScStringCell(const String & rString)604cdf0e10cSrcweir ScStringCell::ScStringCell( const String& rString ) :
605cdf0e10cSrcweir 	ScBaseCell( CELLTYPE_STRING ),
606cdf0e10cSrcweir     maString( rString.intern() )
607cdf0e10cSrcweir {
608cdf0e10cSrcweir }
609cdf0e10cSrcweir 
610cdf0e10cSrcweir #ifdef DBG_UTIL
~ScStringCell()611cdf0e10cSrcweir ScStringCell::~ScStringCell()
612cdf0e10cSrcweir {
613cdf0e10cSrcweir 	eCellType = CELLTYPE_DESTROYED;
614cdf0e10cSrcweir }
615cdf0e10cSrcweir #endif
616cdf0e10cSrcweir 
617cdf0e10cSrcweir // ============================================================================
618cdf0e10cSrcweir 
619cdf0e10cSrcweir //
620cdf0e10cSrcweir //		ScFormulaCell
621cdf0e10cSrcweir //
622cdf0e10cSrcweir 
ScFormulaCell()623cdf0e10cSrcweir ScFormulaCell::ScFormulaCell() :
624cdf0e10cSrcweir 	ScBaseCell( CELLTYPE_FORMULA ),
625cdf0e10cSrcweir     eTempGrammar( FormulaGrammar::GRAM_DEFAULT),
626cdf0e10cSrcweir 	pCode( NULL ),
627cdf0e10cSrcweir 	pDocument( NULL ),
628cdf0e10cSrcweir 	pPrevious(0),
629cdf0e10cSrcweir 	pNext(0),
630cdf0e10cSrcweir 	pPreviousTrack(0),
631cdf0e10cSrcweir 	pNextTrack(0),
632cdf0e10cSrcweir 	nFormatIndex(0),
633cdf0e10cSrcweir 	nFormatType( NUMBERFORMAT_NUMBER ),
634cdf0e10cSrcweir     nSeenInIteration(0),
635cdf0e10cSrcweir 	cMatrixFlag ( MM_NONE ),
636cdf0e10cSrcweir 	bDirty( sal_False ),
637cdf0e10cSrcweir 	bChanged( sal_False ),
638cdf0e10cSrcweir 	bRunning( sal_False ),
639cdf0e10cSrcweir 	bCompile( sal_False ),
640cdf0e10cSrcweir 	bSubTotal( sal_False ),
641cdf0e10cSrcweir 	bIsIterCell( sal_False ),
642cdf0e10cSrcweir 	bInChangeTrack( sal_False ),
643cdf0e10cSrcweir 	bTableOpDirty( sal_False ),
644cdf0e10cSrcweir 	bNeedListening( sal_False ),
645dfb14cdcSPavel Janík 	pValidRefToken( NULL ),
646dfb14cdcSPavel Janík 	aPos(0,0,0)
647cdf0e10cSrcweir {
648cdf0e10cSrcweir }
649cdf0e10cSrcweir 
ScFormulaCell(ScDocument * pDoc,const ScAddress & rPos,const String & rFormula,const FormulaGrammar::Grammar eGrammar,sal_uInt8 cMatInd)650cdf0e10cSrcweir ScFormulaCell::ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos,
651cdf0e10cSrcweir 							  const String& rFormula,
652cdf0e10cSrcweir                               const FormulaGrammar::Grammar eGrammar,
653cdf0e10cSrcweir 							  sal_uInt8 cMatInd ) :
654cdf0e10cSrcweir 	ScBaseCell( CELLTYPE_FORMULA ),
655cdf0e10cSrcweir     eTempGrammar( eGrammar),
656cdf0e10cSrcweir 	pCode( NULL ),
657cdf0e10cSrcweir 	pDocument( pDoc ),
658cdf0e10cSrcweir 	pPrevious(0),
659cdf0e10cSrcweir 	pNext(0),
660cdf0e10cSrcweir 	pPreviousTrack(0),
661cdf0e10cSrcweir 	pNextTrack(0),
662cdf0e10cSrcweir 	nFormatIndex(0),
663cdf0e10cSrcweir 	nFormatType( NUMBERFORMAT_NUMBER ),
664cdf0e10cSrcweir     nSeenInIteration(0),
665cdf0e10cSrcweir 	cMatrixFlag ( cMatInd ),
666cdf0e10cSrcweir 	bDirty( sal_True ), // -> wg. Benutzung im Fkt.AutoPiloten, war: cMatInd != 0
667cdf0e10cSrcweir 	bChanged( sal_False ),
668cdf0e10cSrcweir 	bRunning( sal_False ),
669cdf0e10cSrcweir 	bCompile( sal_False ),
670cdf0e10cSrcweir 	bSubTotal( sal_False ),
671cdf0e10cSrcweir 	bIsIterCell( sal_False ),
672cdf0e10cSrcweir 	bInChangeTrack( sal_False ),
673cdf0e10cSrcweir 	bTableOpDirty( sal_False ),
674cdf0e10cSrcweir 	bNeedListening( sal_False ),
675dfb14cdcSPavel Janík 	pValidRefToken( NULL ),
676dfb14cdcSPavel Janík 	aPos( rPos )
677cdf0e10cSrcweir {
678cdf0e10cSrcweir     Compile( rFormula, sal_True, eGrammar );    // bNoListening, Insert does that
679cdf0e10cSrcweir }
680cdf0e10cSrcweir 
681cdf0e10cSrcweir // Wird von den Importfiltern verwendet
682cdf0e10cSrcweir 
ScFormulaCell(ScDocument * pDoc,const ScAddress & rPos,const ScTokenArray * pArr,const FormulaGrammar::Grammar eGrammar,sal_uInt8 cInd)683cdf0e10cSrcweir ScFormulaCell::ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos,
684cdf0e10cSrcweir 							  const ScTokenArray* pArr,
685cdf0e10cSrcweir                               const FormulaGrammar::Grammar eGrammar, sal_uInt8 cInd ) :
686cdf0e10cSrcweir 	ScBaseCell( CELLTYPE_FORMULA ),
687cdf0e10cSrcweir     eTempGrammar( eGrammar),
688cdf0e10cSrcweir 	pCode( pArr ? new ScTokenArray( *pArr ) : new ScTokenArray ),
689cdf0e10cSrcweir 	pDocument( pDoc ),
690cdf0e10cSrcweir 	pPrevious(0),
691cdf0e10cSrcweir 	pNext(0),
692cdf0e10cSrcweir 	pPreviousTrack(0),
693cdf0e10cSrcweir 	pNextTrack(0),
694cdf0e10cSrcweir 	nFormatIndex(0),
695cdf0e10cSrcweir 	nFormatType( NUMBERFORMAT_NUMBER ),
696cdf0e10cSrcweir     nSeenInIteration(0),
697cdf0e10cSrcweir 	cMatrixFlag ( cInd ),
698cdf0e10cSrcweir 	bDirty( NULL != pArr ), // -> wg. Benutzung im Fkt.AutoPiloten, war: cInd != 0
699cdf0e10cSrcweir 	bChanged( sal_False ),
700cdf0e10cSrcweir 	bRunning( sal_False ),
701cdf0e10cSrcweir 	bCompile( sal_False ),
702cdf0e10cSrcweir 	bSubTotal( sal_False ),
703cdf0e10cSrcweir 	bIsIterCell( sal_False ),
704cdf0e10cSrcweir 	bInChangeTrack( sal_False ),
705cdf0e10cSrcweir 	bTableOpDirty( sal_False ),
706cdf0e10cSrcweir 	bNeedListening( sal_False ),
707dfb14cdcSPavel Janík 	pValidRefToken( NULL ),
708dfb14cdcSPavel Janík 	aPos( rPos )
709cdf0e10cSrcweir {
710cdf0e10cSrcweir 	// UPN-Array erzeugen
711cdf0e10cSrcweir 	if( pCode->GetLen() && !pCode->GetCodeError() && !pCode->GetCodeLen() )
712cdf0e10cSrcweir 	{
713cdf0e10cSrcweir 		ScCompiler aComp( pDocument, aPos, *pCode);
714cdf0e10cSrcweir         aComp.SetGrammar(eTempGrammar);
715cdf0e10cSrcweir 		bSubTotal = aComp.CompileTokenArray();
716cdf0e10cSrcweir 		nFormatType = aComp.GetNumFormatType();
717cdf0e10cSrcweir 	}
718cdf0e10cSrcweir 	else
719cdf0e10cSrcweir 	{
720cdf0e10cSrcweir 		pCode->Reset();
721cdf0e10cSrcweir 		if ( pCode->GetNextOpCodeRPN( ocSubTotal ) )
722cdf0e10cSrcweir 			bSubTotal = sal_True;
723cdf0e10cSrcweir 	}
724cdf0e10cSrcweir }
725cdf0e10cSrcweir 
ScFormulaCell(const ScFormulaCell & rCell,ScDocument & rDoc,const ScAddress & rPos,int nCloneFlags)726cdf0e10cSrcweir ScFormulaCell::ScFormulaCell( const ScFormulaCell& rCell, ScDocument& rDoc, const ScAddress& rPos, int nCloneFlags ) :
727cdf0e10cSrcweir     ScBaseCell( rCell ),
728cdf0e10cSrcweir 	SvtListener(),
729cdf0e10cSrcweir 	aResult( rCell.aResult ),
730cdf0e10cSrcweir     eTempGrammar( rCell.eTempGrammar),
731cdf0e10cSrcweir 	pDocument( &rDoc ),
732cdf0e10cSrcweir 	pPrevious(0),
733cdf0e10cSrcweir 	pNext(0),
734cdf0e10cSrcweir 	pPreviousTrack(0),
735cdf0e10cSrcweir 	pNextTrack(0),
736cdf0e10cSrcweir 	nFormatIndex( &rDoc == rCell.pDocument ? rCell.nFormatIndex : 0 ),
737cdf0e10cSrcweir 	nFormatType( rCell.nFormatType ),
738cdf0e10cSrcweir     nSeenInIteration(0),
739cdf0e10cSrcweir 	cMatrixFlag ( rCell.cMatrixFlag ),
740cdf0e10cSrcweir 	bDirty( rCell.bDirty ),
741cdf0e10cSrcweir 	bChanged( rCell.bChanged ),
742cdf0e10cSrcweir 	bRunning( sal_False ),
743cdf0e10cSrcweir 	bCompile( rCell.bCompile ),
744cdf0e10cSrcweir 	bSubTotal( rCell.bSubTotal ),
745cdf0e10cSrcweir 	bIsIterCell( sal_False ),
746cdf0e10cSrcweir 	bInChangeTrack( sal_False ),
747cdf0e10cSrcweir 	bTableOpDirty( sal_False ),
748cdf0e10cSrcweir 	bNeedListening( sal_False ),
749dfb14cdcSPavel Janík 	aPos( rPos )
750cdf0e10cSrcweir {
75109a04e03SWang Lei     if ( rCell.pValidRefToken )
75209a04e03SWang Lei         pValidRefToken = static_cast<ScToken*>(rCell.pValidRefToken->Clone());
75309a04e03SWang Lei     else
75409a04e03SWang Lei         pValidRefToken = NULL;
75509a04e03SWang Lei 
75629adda49SJian Fang Zhang 	pCode = (rCell.pCode) ? rCell.pCode->Clone() : NULL;
757cdf0e10cSrcweir 
758cdf0e10cSrcweir     if ( nCloneFlags & SC_CLONECELL_ADJUST3DREL )
759cdf0e10cSrcweir         pCode->ReadjustRelative3DReferences( rCell.aPos, aPos );
760cdf0e10cSrcweir 
761cdf0e10cSrcweir 	// evtl. Fehler zuruecksetzen und neu kompilieren
762cdf0e10cSrcweir 	//	nicht im Clipboard - da muss das Fehlerflag erhalten bleiben
763cdf0e10cSrcweir 	//	Spezialfall Laenge=0: als Fehlerzelle erzeugt, dann auch Fehler behalten
764cdf0e10cSrcweir 	if ( pCode->GetCodeError() && !pDocument->IsClipboard() && pCode->GetLen() )
765cdf0e10cSrcweir 	{
766cdf0e10cSrcweir 		pCode->SetCodeError( 0 );
767cdf0e10cSrcweir 		bCompile = sal_True;
768cdf0e10cSrcweir 	}
769cdf0e10cSrcweir     //! Compile ColRowNames on URM_MOVE/URM_COPY _after_ UpdateReference
770cdf0e10cSrcweir     sal_Bool bCompileLater = sal_False;
771cdf0e10cSrcweir     sal_Bool bClipMode = rCell.pDocument->IsClipboard();
772cdf0e10cSrcweir 	if( !bCompile )
773cdf0e10cSrcweir     {   // Name references with references and ColRowNames
774cdf0e10cSrcweir         pCode->Reset();
775cdf0e10cSrcweir         ScToken* t;
776cdf0e10cSrcweir         while ( ( t = static_cast<ScToken*>(pCode->GetNextReferenceOrName()) ) != NULL && !bCompile )
777cdf0e10cSrcweir 		{
778cdf0e10cSrcweir             if ( t->GetOpCode() == ocExternalRef )
779cdf0e10cSrcweir             {
780cdf0e10cSrcweir                 // External name, cell, and area references.
781cdf0e10cSrcweir                 bCompile = true;
782cdf0e10cSrcweir             }
783cdf0e10cSrcweir 			else if ( t->GetType() == svIndex )
784cdf0e10cSrcweir 			{
785cdf0e10cSrcweir 				ScRangeData* pRangeData = rDoc.GetRangeName()->FindIndex( t->GetIndex() );
786cdf0e10cSrcweir 				if( pRangeData )
787cdf0e10cSrcweir 				{
788cdf0e10cSrcweir 					if( pRangeData->HasReferences() )
789cdf0e10cSrcweir 						bCompile = sal_True;
790cdf0e10cSrcweir 				}
791cdf0e10cSrcweir 				else
792cdf0e10cSrcweir                     bCompile = sal_True;    // invalid reference!
793cdf0e10cSrcweir 			}
794cdf0e10cSrcweir 			else if ( t->GetOpCode() == ocColRowName )
795cdf0e10cSrcweir 			{
796cdf0e10cSrcweir                 bCompile = sal_True;        // new lookup needed
797cdf0e10cSrcweir                 bCompileLater = bClipMode;
798cdf0e10cSrcweir 			}
799cdf0e10cSrcweir 		}
800cdf0e10cSrcweir 	}
801cdf0e10cSrcweir 	if( bCompile )
802cdf0e10cSrcweir 	{
803cdf0e10cSrcweir         if ( !bCompileLater && bClipMode )
804cdf0e10cSrcweir 		{
805cdf0e10cSrcweir             // Merging ranges needs the actual positions after UpdateReference.
806cdf0e10cSrcweir             // ColRowNames need new lookup after positions are adjusted.
807cdf0e10cSrcweir             bCompileLater = pCode->HasOpCode( ocRange) || pCode->HasOpCode( ocColRowName);
808cdf0e10cSrcweir 		}
809cdf0e10cSrcweir         if ( !bCompileLater )
810cdf0e10cSrcweir         {
811cdf0e10cSrcweir             // bNoListening, not at all if in Clipboard/Undo,
812cdf0e10cSrcweir             // and not from Clipboard either, instead after Insert(Clone) and UpdateReference.
813cdf0e10cSrcweir             CompileTokenArray( sal_True );
814cdf0e10cSrcweir         }
815cdf0e10cSrcweir 	}
816cdf0e10cSrcweir 
817cdf0e10cSrcweir     if( nCloneFlags & SC_CLONECELL_STARTLISTENING )
818cdf0e10cSrcweir         StartListeningTo( &rDoc );
819cdf0e10cSrcweir }
820cdf0e10cSrcweir 
~ScFormulaCell()821cdf0e10cSrcweir ScFormulaCell::~ScFormulaCell()
822cdf0e10cSrcweir {
823cdf0e10cSrcweir 	pDocument->RemoveFromFormulaTree( this );
824cdf0e10cSrcweir 
825cdf0e10cSrcweir     if (pDocument->HasExternalRefManager())
826cdf0e10cSrcweir         pDocument->GetExternalRefManager()->removeRefCell(this);
827cdf0e10cSrcweir 
828cdf0e10cSrcweir 	delete pCode;
829cdf0e10cSrcweir #ifdef DBG_UTIL
830cdf0e10cSrcweir 	eCellType = CELLTYPE_DESTROYED;
831cdf0e10cSrcweir #endif
83261e64f4aSWang Lei     DELETEZ(pValidRefToken);
833cdf0e10cSrcweir }
834cdf0e10cSrcweir 
GetFormula(rtl::OUStringBuffer & rBuffer,const FormulaGrammar::Grammar eGrammar) const835cdf0e10cSrcweir void ScFormulaCell::GetFormula( rtl::OUStringBuffer& rBuffer,
836cdf0e10cSrcweir                                 const FormulaGrammar::Grammar eGrammar ) const
837cdf0e10cSrcweir {
838cdf0e10cSrcweir     if( pCode->GetCodeError() && !pCode->GetLen() )
839cdf0e10cSrcweir     {
840cdf0e10cSrcweir         rBuffer = rtl::OUStringBuffer( ScGlobal::GetErrorString( pCode->GetCodeError()));
841cdf0e10cSrcweir         return;
842cdf0e10cSrcweir     }
843cdf0e10cSrcweir     else if( cMatrixFlag == MM_REFERENCE )
844cdf0e10cSrcweir     {
845cdf0e10cSrcweir         // Reference to another cell that contains a matrix formula.
846cdf0e10cSrcweir         pCode->Reset();
847cdf0e10cSrcweir         ScToken* p = static_cast<ScToken*>(pCode->GetNextReferenceRPN());
848cdf0e10cSrcweir         if( p )
849cdf0e10cSrcweir         {
850cdf0e10cSrcweir             /* FIXME: original GetFormula() code obtained
851cdf0e10cSrcweir              * pCell only if (!this->IsInChangeTrack()),
852cdf0e10cSrcweir              * GetEnglishFormula() omitted that test.
853cdf0e10cSrcweir              * Can we live without in all cases? */
854cdf0e10cSrcweir             ScBaseCell* pCell;
855cdf0e10cSrcweir             ScSingleRefData& rRef = p->GetSingleRef();
856cdf0e10cSrcweir             rRef.CalcAbsIfRel( aPos );
857cdf0e10cSrcweir             if ( rRef.Valid() )
858cdf0e10cSrcweir                 pCell = pDocument->GetCell( ScAddress( rRef.nCol,
859cdf0e10cSrcweir                             rRef.nRow, rRef.nTab ) );
860cdf0e10cSrcweir             else
861cdf0e10cSrcweir                 pCell = NULL;
862cdf0e10cSrcweir             if (pCell && pCell->GetCellType() == CELLTYPE_FORMULA)
863cdf0e10cSrcweir             {
864cdf0e10cSrcweir                 ((ScFormulaCell*)pCell)->GetFormula( rBuffer, eGrammar);
865cdf0e10cSrcweir                 return;
866cdf0e10cSrcweir             }
867cdf0e10cSrcweir             else
868cdf0e10cSrcweir             {
869cdf0e10cSrcweir                 ScCompiler aComp( pDocument, aPos, *pCode);
870cdf0e10cSrcweir                 aComp.SetGrammar(eGrammar);
871cdf0e10cSrcweir                 aComp.CreateStringFromTokenArray( rBuffer );
872cdf0e10cSrcweir             }
873cdf0e10cSrcweir         }
874cdf0e10cSrcweir         else
875cdf0e10cSrcweir         {
876cdf0e10cSrcweir             DBG_ERROR("ScFormulaCell::GetFormula: not a matrix");
877cdf0e10cSrcweir         }
878cdf0e10cSrcweir     }
879cdf0e10cSrcweir     else
880cdf0e10cSrcweir     {
881cdf0e10cSrcweir         ScCompiler aComp( pDocument, aPos, *pCode);
882cdf0e10cSrcweir         aComp.SetGrammar(eGrammar);
883cdf0e10cSrcweir         aComp.CreateStringFromTokenArray( rBuffer );
884cdf0e10cSrcweir     }
885cdf0e10cSrcweir 
886cdf0e10cSrcweir     sal_Unicode ch('=');
887cdf0e10cSrcweir     rBuffer.insert( 0, &ch, 1 );
888cdf0e10cSrcweir     if( cMatrixFlag )
889cdf0e10cSrcweir     {
890cdf0e10cSrcweir         sal_Unicode ch2('{');
891cdf0e10cSrcweir         rBuffer.insert( 0, &ch2, 1);
892cdf0e10cSrcweir         rBuffer.append( sal_Unicode('}'));
893cdf0e10cSrcweir     }
894cdf0e10cSrcweir }
895cdf0e10cSrcweir 
GetFormula(String & rFormula,const FormulaGrammar::Grammar eGrammar) const896cdf0e10cSrcweir void ScFormulaCell::GetFormula( String& rFormula, const FormulaGrammar::Grammar eGrammar ) const
897cdf0e10cSrcweir {
898cdf0e10cSrcweir     rtl::OUStringBuffer rBuffer( rFormula );
899cdf0e10cSrcweir     GetFormula( rBuffer, eGrammar );
900cdf0e10cSrcweir     rFormula = rBuffer;
901cdf0e10cSrcweir }
902cdf0e10cSrcweir 
GetResultDimensions(SCSIZE & rCols,SCSIZE & rRows)903cdf0e10cSrcweir void ScFormulaCell::GetResultDimensions( SCSIZE& rCols, SCSIZE& rRows )
904cdf0e10cSrcweir {
905cdf0e10cSrcweir 	if (IsDirtyOrInTableOpDirty() && pDocument->GetAutoCalc())
906cdf0e10cSrcweir 		Interpret();
907cdf0e10cSrcweir 
908cdf0e10cSrcweir     const ScMatrix* pMat = NULL;
909cdf0e10cSrcweir     if (!pCode->GetCodeError() && aResult.GetType() == svMatrixCell &&
910cdf0e10cSrcweir             ((pMat = static_cast<const ScToken*>(aResult.GetToken().get())->GetMatrix()) != 0))
911cdf0e10cSrcweir 		pMat->GetDimensions( rCols, rRows );
912cdf0e10cSrcweir 	else
913cdf0e10cSrcweir 	{
914cdf0e10cSrcweir 		rCols = 0;
915cdf0e10cSrcweir 		rRows = 0;
916cdf0e10cSrcweir 	}
917cdf0e10cSrcweir }
918cdf0e10cSrcweir 
Compile(const String & rFormula,sal_Bool bNoListening,const FormulaGrammar::Grammar eGrammar)919cdf0e10cSrcweir void ScFormulaCell::Compile( const String& rFormula, sal_Bool bNoListening,
920cdf0e10cSrcweir                             const FormulaGrammar::Grammar eGrammar )
921cdf0e10cSrcweir {
92229adda49SJian Fang Zhang 	//#118851#, the initialization code for pCode after it can not be gnored if it is still NULL
92329adda49SJian Fang Zhang 	if ( pCode && pDocument->IsClipOrUndo() ) return;
924cdf0e10cSrcweir 	sal_Bool bWasInFormulaTree = pDocument->IsInFormulaTree( this );
925cdf0e10cSrcweir 	if ( bWasInFormulaTree )
926cdf0e10cSrcweir 		pDocument->RemoveFromFormulaTree( this );
927cdf0e10cSrcweir 	// pCode darf fuer Abfragen noch nicht geloescht, muss aber leer sein
928cdf0e10cSrcweir 	if ( pCode )
929cdf0e10cSrcweir 		pCode->Clear();
930cdf0e10cSrcweir 	ScTokenArray* pCodeOld = pCode;
931cdf0e10cSrcweir 	ScCompiler aComp( pDocument, aPos);
932cdf0e10cSrcweir     aComp.SetGrammar(eGrammar);
933cdf0e10cSrcweir 	pCode = aComp.CompileString( rFormula );
934cdf0e10cSrcweir 	if ( pCodeOld )
935cdf0e10cSrcweir 		delete pCodeOld;
936cdf0e10cSrcweir 	if( !pCode->GetCodeError() )
937cdf0e10cSrcweir 	{
938cdf0e10cSrcweir 		if ( !pCode->GetLen() && aResult.GetHybridFormula().Len() && rFormula == aResult.GetHybridFormula() )
939cdf0e10cSrcweir 		{	// #65994# nicht rekursiv CompileTokenArray/Compile/CompileTokenArray
940cdf0e10cSrcweir 			if ( rFormula.GetChar(0) == '=' )
941cdf0e10cSrcweir 				pCode->AddBad( rFormula.GetBuffer() + 1 );
942cdf0e10cSrcweir 			else
943cdf0e10cSrcweir 				pCode->AddBad( rFormula.GetBuffer() );
944cdf0e10cSrcweir 		}
945cdf0e10cSrcweir 		bCompile = sal_True;
946cdf0e10cSrcweir 		CompileTokenArray( bNoListening );
947cdf0e10cSrcweir 	}
948cdf0e10cSrcweir 	else
949cdf0e10cSrcweir 	{
950cdf0e10cSrcweir 		bChanged = sal_True;
951cdf0e10cSrcweir 		SetTextWidth( TEXTWIDTH_DIRTY );
952cdf0e10cSrcweir 		SetScriptType( SC_SCRIPTTYPE_UNKNOWN );
953cdf0e10cSrcweir 	}
954cdf0e10cSrcweir 	if ( bWasInFormulaTree )
955cdf0e10cSrcweir 		pDocument->PutInFormulaTree( this );
956cdf0e10cSrcweir }
957cdf0e10cSrcweir 
958cdf0e10cSrcweir 
CompileTokenArray(sal_Bool bNoListening)959cdf0e10cSrcweir void ScFormulaCell::CompileTokenArray( sal_Bool bNoListening )
960cdf0e10cSrcweir {
961cdf0e10cSrcweir     // Not already compiled?
962cdf0e10cSrcweir     if( !pCode->GetLen() && aResult.GetHybridFormula().Len() )
963cdf0e10cSrcweir         Compile( aResult.GetHybridFormula(), bNoListening, eTempGrammar);
964cdf0e10cSrcweir 	else if( bCompile && !pDocument->IsClipOrUndo() && !pCode->GetCodeError() )
965cdf0e10cSrcweir 	{
966cdf0e10cSrcweir 		// RPN length may get changed
967cdf0e10cSrcweir 		sal_Bool bWasInFormulaTree = pDocument->IsInFormulaTree( this );
968cdf0e10cSrcweir 		if ( bWasInFormulaTree )
969cdf0e10cSrcweir 			pDocument->RemoveFromFormulaTree( this );
970cdf0e10cSrcweir 
971cdf0e10cSrcweir 		// Loading from within filter? No listening yet!
972cdf0e10cSrcweir 		if( pDocument->IsInsertingFromOtherDoc() )
973cdf0e10cSrcweir 			bNoListening = sal_True;
974cdf0e10cSrcweir 
975cdf0e10cSrcweir 		if( !bNoListening && pCode->GetCodeLen() )
976cdf0e10cSrcweir 			EndListeningTo( pDocument );
977cdf0e10cSrcweir 		ScCompiler aComp(pDocument, aPos, *pCode);
978cdf0e10cSrcweir         aComp.SetGrammar(pDocument->GetGrammar());
979cdf0e10cSrcweir 		bSubTotal = aComp.CompileTokenArray();
980cdf0e10cSrcweir 		if( !pCode->GetCodeError() )
981cdf0e10cSrcweir 		{
982cdf0e10cSrcweir 			nFormatType = aComp.GetNumFormatType();
983cdf0e10cSrcweir 			nFormatIndex = 0;
984cdf0e10cSrcweir 			bChanged = sal_True;
985cdf0e10cSrcweir             aResult.SetToken( NULL);
986cdf0e10cSrcweir 			bCompile = sal_False;
987cdf0e10cSrcweir 			if ( !bNoListening )
988cdf0e10cSrcweir 				StartListeningTo( pDocument );
989cdf0e10cSrcweir 		}
990cdf0e10cSrcweir 		if ( bWasInFormulaTree )
991cdf0e10cSrcweir 			pDocument->PutInFormulaTree( this );
992cdf0e10cSrcweir 	}
993cdf0e10cSrcweir }
994cdf0e10cSrcweir 
995cdf0e10cSrcweir 
CompileXML(ScProgress & rProgress)996cdf0e10cSrcweir void ScFormulaCell::CompileXML( ScProgress& rProgress )
997cdf0e10cSrcweir {
998cdf0e10cSrcweir 	if ( cMatrixFlag == MM_REFERENCE )
999cdf0e10cSrcweir 	{	// is already token code via ScDocFunc::EnterMatrix, ScDocument::InsertMatrixFormula
1000cdf0e10cSrcweir 		// just establish listeners
1001cdf0e10cSrcweir 		StartListeningTo( pDocument );
1002cdf0e10cSrcweir 		return ;
1003cdf0e10cSrcweir 	}
1004cdf0e10cSrcweir 
1005cdf0e10cSrcweir 	ScCompiler aComp( pDocument, aPos, *pCode);
1006cdf0e10cSrcweir     aComp.SetGrammar(eTempGrammar);
1007cdf0e10cSrcweir     String aFormula, aFormulaNmsp;
1008cdf0e10cSrcweir     aComp.CreateStringFromXMLTokenArray( aFormula, aFormulaNmsp );
1009cdf0e10cSrcweir     pDocument->DecXMLImportedFormulaCount( aFormula.Len() );
1010cdf0e10cSrcweir     rProgress.SetStateCountDownOnPercent( pDocument->GetXMLImportedFormulaCount() );
1011cdf0e10cSrcweir 	// pCode darf fuer Abfragen noch nicht geloescht, muss aber leer sein
1012cdf0e10cSrcweir 	if ( pCode )
1013cdf0e10cSrcweir 		pCode->Clear();
1014cdf0e10cSrcweir 	ScTokenArray* pCodeOld = pCode;
1015cdf0e10cSrcweir     pCode = aComp.CompileString( aFormula, aFormulaNmsp );
1016cdf0e10cSrcweir 	delete pCodeOld;
1017cdf0e10cSrcweir 	if( !pCode->GetCodeError() )
1018cdf0e10cSrcweir 	{
1019cdf0e10cSrcweir 		if ( !pCode->GetLen() )
1020cdf0e10cSrcweir 		{
1021cdf0e10cSrcweir 			if ( aFormula.GetChar(0) == '=' )
1022cdf0e10cSrcweir 				pCode->AddBad( aFormula.GetBuffer() + 1 );
1023cdf0e10cSrcweir 			else
1024cdf0e10cSrcweir 				pCode->AddBad( aFormula.GetBuffer() );
1025cdf0e10cSrcweir 		}
1026cdf0e10cSrcweir 		bSubTotal = aComp.CompileTokenArray();
1027cdf0e10cSrcweir 		if( !pCode->GetCodeError() )
1028cdf0e10cSrcweir 		{
1029cdf0e10cSrcweir 			nFormatType = aComp.GetNumFormatType();
1030cdf0e10cSrcweir 			nFormatIndex = 0;
1031cdf0e10cSrcweir 			bChanged = sal_True;
1032cdf0e10cSrcweir 			bCompile = sal_False;
1033cdf0e10cSrcweir 			StartListeningTo( pDocument );
1034cdf0e10cSrcweir 		}
1035cdf0e10cSrcweir 	}
1036cdf0e10cSrcweir 	else
1037cdf0e10cSrcweir 	{
1038cdf0e10cSrcweir 		bChanged = sal_True;
1039cdf0e10cSrcweir 		SetTextWidth( TEXTWIDTH_DIRTY );
1040cdf0e10cSrcweir 		SetScriptType( SC_SCRIPTTYPE_UNKNOWN );
1041cdf0e10cSrcweir 	}
1042cdf0e10cSrcweir 
1043cdf0e10cSrcweir 	//	Same as in Load: after loading, it must be known if ocMacro is in any formula
1044cdf0e10cSrcweir 	//	(for macro warning, CompileXML is called at the end of loading XML file)
1045cdf0e10cSrcweir 	if ( !pDocument->GetHasMacroFunc() && pCode->HasOpCodeRPN( ocMacro ) )
1046cdf0e10cSrcweir 		pDocument->SetHasMacroFunc( sal_True );
1047cdf0e10cSrcweir }
1048cdf0e10cSrcweir 
1049cdf0e10cSrcweir 
CalcAfterLoad()1050cdf0e10cSrcweir void ScFormulaCell::CalcAfterLoad()
1051cdf0e10cSrcweir {
1052cdf0e10cSrcweir 	sal_Bool bNewCompiled = sal_False;
1053cdf0e10cSrcweir 	// Falls ein Calc 1.0-Doc eingelesen wird, haben wir ein Ergebnis,
1054cdf0e10cSrcweir 	// aber kein TokenArray
1055cdf0e10cSrcweir 	if( !pCode->GetLen() && aResult.GetHybridFormula().Len() )
1056cdf0e10cSrcweir 	{
1057cdf0e10cSrcweir         Compile( aResult.GetHybridFormula(), sal_True, eTempGrammar);
1058cdf0e10cSrcweir 		aResult.SetToken( NULL);
1059cdf0e10cSrcweir 		bDirty = sal_True;
1060cdf0e10cSrcweir 		bNewCompiled = sal_True;
1061cdf0e10cSrcweir 	}
1062cdf0e10cSrcweir 	// Das UPN-Array wird nicht erzeugt, wenn ein Calc 3.0-Doc eingelesen
1063cdf0e10cSrcweir 	// wurde, da die RangeNames erst jetzt existieren.
1064cdf0e10cSrcweir 	if( pCode->GetLen() && !pCode->GetCodeLen() && !pCode->GetCodeError() )
1065cdf0e10cSrcweir 	{
1066cdf0e10cSrcweir 		ScCompiler aComp(pDocument, aPos, *pCode);
1067cdf0e10cSrcweir         aComp.SetGrammar(pDocument->GetGrammar());
1068cdf0e10cSrcweir 		bSubTotal = aComp.CompileTokenArray();
1069cdf0e10cSrcweir 		nFormatType = aComp.GetNumFormatType();
1070cdf0e10cSrcweir 		nFormatIndex = 0;
1071cdf0e10cSrcweir 		bDirty = sal_True;
1072cdf0e10cSrcweir 		bCompile = sal_False;
1073cdf0e10cSrcweir 		bNewCompiled = sal_True;
1074cdf0e10cSrcweir 	}
1075cdf0e10cSrcweir 	// irgendwie koennen unter os/2 mit rotter FPU-Exception /0 ohne Err503
1076cdf0e10cSrcweir 	// gespeichert werden, woraufhin spaeter im NumberFormatter die BLC Lib
1077cdf0e10cSrcweir 	// bei einem fabs(-NAN) abstuerzt (#32739#)
1078cdf0e10cSrcweir 	// hier fuer alle Systeme ausbuegeln, damit da auch Err503 steht
1079cdf0e10cSrcweir 	if ( aResult.IsValue() && !::rtl::math::isFinite( aResult.GetDouble() ) )
1080cdf0e10cSrcweir 	{
1081cdf0e10cSrcweir 		DBG_ERRORFILE("Formelzelle INFINITY !!! Woher kommt das Dokument?");
1082cdf0e10cSrcweir 		aResult.SetResultError( errIllegalFPOperation );
1083cdf0e10cSrcweir 		bDirty = sal_True;
1084cdf0e10cSrcweir 	}
1085cdf0e10cSrcweir 	// DoubleRefs bei binaeren Operatoren waren vor v5.0 immer Matrix,
1086cdf0e10cSrcweir 	// jetzt nur noch wenn in Matrixformel, sonst implizite Schnittmenge
1087cdf0e10cSrcweir 	if ( pDocument->GetSrcVersion() < SC_MATRIX_DOUBLEREF &&
1088cdf0e10cSrcweir 			GetMatrixFlag() == MM_NONE && pCode->HasMatrixDoubleRefOps() )
1089cdf0e10cSrcweir 	{
1090cdf0e10cSrcweir 		cMatrixFlag = MM_FORMULA;
1091cdf0e10cSrcweir         SetMatColsRows( 1, 1);
1092cdf0e10cSrcweir 	}
1093cdf0e10cSrcweir 	// Muss die Zelle berechnet werden?
1094cdf0e10cSrcweir 	// Nach Load koennen Zellen einen Fehlercode enthalten, auch dann
1095cdf0e10cSrcweir 	// Listener starten und ggbf. neu berechnen wenn nicht RECALCMODE_NORMAL
1096cdf0e10cSrcweir 	if( !bNewCompiled || !pCode->GetCodeError() )
1097cdf0e10cSrcweir 	{
1098cdf0e10cSrcweir 		StartListeningTo( pDocument );
1099cdf0e10cSrcweir 		if( !pCode->IsRecalcModeNormal() )
1100cdf0e10cSrcweir 			bDirty = sal_True;
1101cdf0e10cSrcweir 	}
1102cdf0e10cSrcweir 	if ( pCode->IsRecalcModeAlways() )
1103cdf0e10cSrcweir 	{	// zufall(), heute(), jetzt() bleiben immer im FormulaTree, damit sie
1104cdf0e10cSrcweir 		// auch bei jedem F9 berechnet werden.
1105cdf0e10cSrcweir 		bDirty = sal_True;
1106cdf0e10cSrcweir 	}
1107cdf0e10cSrcweir 	// Noch kein SetDirty weil noch nicht alle Listener bekannt, erst in
1108cdf0e10cSrcweir 	// SetDirtyAfterLoad.
1109cdf0e10cSrcweir }
1110cdf0e10cSrcweir 
1111cdf0e10cSrcweir 
MarkUsedExternalReferences()1112cdf0e10cSrcweir bool ScFormulaCell::MarkUsedExternalReferences()
1113cdf0e10cSrcweir {
1114cdf0e10cSrcweir     return pCode && pDocument->MarkUsedExternalReferences( *pCode);
1115cdf0e10cSrcweir }
1116cdf0e10cSrcweir 
1117cdf0e10cSrcweir 
1118cdf0e10cSrcweir // FIXME: set to 0
1119cdf0e10cSrcweir #define erDEBUGDOT 0
1120cdf0e10cSrcweir // If set to 1, write output that's suitable for graphviz tools like dot.
1121cdf0e10cSrcweir // Only node1 -> node2 entries are written, you'll have to manually surround
1122cdf0e10cSrcweir // the file content with [strict] digraph name { ... }
1123cdf0e10cSrcweir // The ``strict'' keyword might be necessary in case of multiple identical
1124cdf0e10cSrcweir // paths like they occur in iterations, otherwise dot may consume too much
1125cdf0e10cSrcweir // memory when generating the layout, or you'll get unreadable output. On the
1126cdf0e10cSrcweir // other hand, information about recurring calculation is lost then.
1127cdf0e10cSrcweir // Generates output only if variable nDebug is set in debugger, see below.
1128cdf0e10cSrcweir // FIXME: currently doesn't cope with iterations and recursions. Code fragments
1129cdf0e10cSrcweir // are a leftover from a previous debug session, meant as a pointer.
1130cdf0e10cSrcweir #if erDEBUGDOT
1131cdf0e10cSrcweir #include <cstdio>
1132cdf0e10cSrcweir using ::std::fopen;
1133cdf0e10cSrcweir using ::std::fprintf;
1134cdf0e10cSrcweir #include <vector>
1135cdf0e10cSrcweir static const char aDebugDotFile[] = "ttt_debug.dot";
1136cdf0e10cSrcweir #endif
1137cdf0e10cSrcweir 
Interpret()1138cdf0e10cSrcweir void ScFormulaCell::Interpret()
1139cdf0e10cSrcweir {
1140cdf0e10cSrcweir 
1141cdf0e10cSrcweir #if erDEBUGDOT
1142cdf0e10cSrcweir     static int nDebug = 0;
1143cdf0e10cSrcweir     static const int erDEBUGDOTRUN = 3;
1144cdf0e10cSrcweir     static FILE* pDebugFile = 0;
1145cdf0e10cSrcweir     static sal_Int32 nDebugRootCount = 0;
1146cdf0e10cSrcweir     static unsigned int nDebugPathCount = 0;
1147cdf0e10cSrcweir     static ScAddress aDebugLastPos( ScAddress::INITIALIZE_INVALID);
1148cdf0e10cSrcweir     static ScAddress aDebugThisPos( ScAddress::INITIALIZE_INVALID);
1149cdf0e10cSrcweir     typedef ::std::vector< ByteString > DebugVector;
1150cdf0e10cSrcweir     static DebugVector aDebugVec;
1151cdf0e10cSrcweir     class DebugElement
1152cdf0e10cSrcweir     {
1153cdf0e10cSrcweir         public:
1154cdf0e10cSrcweir             static void push( ScFormulaCell* pCell )
1155cdf0e10cSrcweir             {
1156cdf0e10cSrcweir                 aDebugThisPos = pCell->aPos;
1157cdf0e10cSrcweir                 if (aDebugVec.empty())
1158cdf0e10cSrcweir                 {
1159cdf0e10cSrcweir                     ByteString aR( "root_");
1160cdf0e10cSrcweir                     aR += ByteString::CreateFromInt32( ++nDebugRootCount);
1161cdf0e10cSrcweir                     aDebugVec.push_back( aR);
1162cdf0e10cSrcweir                 }
1163cdf0e10cSrcweir                 String aStr;
1164cdf0e10cSrcweir                 pCell->aPos.Format( aStr, SCA_VALID | SCA_TAB_3D, pCell->GetDocument(),
1165cdf0e10cSrcweir                                     pCell->GetDocument()->GetAddressConvention() );
1166cdf0e10cSrcweir                 ByteString aB( aStr, RTL_TEXTENCODING_UTF8);
1167cdf0e10cSrcweir                 aDebugVec.push_back( aB);
1168cdf0e10cSrcweir             }
1169cdf0e10cSrcweir             static void pop()
1170cdf0e10cSrcweir             {
1171cdf0e10cSrcweir                 aDebugLastPos = aDebugThisPos;
1172cdf0e10cSrcweir                 if (!aDebugVec.empty())
1173cdf0e10cSrcweir                 {
1174cdf0e10cSrcweir                     aDebugVec.pop_back();
1175cdf0e10cSrcweir                     if (aDebugVec.size() == 1)
1176cdf0e10cSrcweir                     {
1177cdf0e10cSrcweir                         aDebugVec.pop_back();
1178cdf0e10cSrcweir                         aDebugLastPos = ScAddress( ScAddress::INITIALIZE_INVALID);
1179cdf0e10cSrcweir                     }
1180cdf0e10cSrcweir                 }
1181cdf0e10cSrcweir             }
1182cdf0e10cSrcweir             DebugElement( ScFormulaCell* p ) { push(p); }
1183cdf0e10cSrcweir             ~DebugElement() { pop(); }
1184cdf0e10cSrcweir     };
1185cdf0e10cSrcweir     class DebugDot
1186cdf0e10cSrcweir     {
1187cdf0e10cSrcweir         public:
1188cdf0e10cSrcweir             static void out( const char* pColor )
1189cdf0e10cSrcweir             {
1190cdf0e10cSrcweir                 if (nDebug != erDEBUGDOTRUN)
1191cdf0e10cSrcweir                     return;
1192cdf0e10cSrcweir                 char pColorString[256];
1193cdf0e10cSrcweir                 sprintf( pColorString, (*pColor ?
1194cdf0e10cSrcweir                             ",color=\"%s\",fontcolor=\"%s\"" : "%s%s"), pColor,
1195cdf0e10cSrcweir                         pColor);
1196cdf0e10cSrcweir                 size_t n = aDebugVec.size();
1197cdf0e10cSrcweir                 fprintf( pDebugFile,
1198cdf0e10cSrcweir                         "\"%s\" -> \"%s\" [label=\"%u\"%s];  // v:%d\n",
1199cdf0e10cSrcweir                         aDebugVec[n-2].GetBuffer(), aDebugVec[n-1].GetBuffer(),
1200cdf0e10cSrcweir                         ++nDebugPathCount, pColorString, n-1);
1201cdf0e10cSrcweir                 fflush( pDebugFile);
1202cdf0e10cSrcweir             }
1203cdf0e10cSrcweir     };
1204cdf0e10cSrcweir     #define erDEBUGDOT_OUT( p )             (DebugDot::out(p))
1205cdf0e10cSrcweir     #define erDEBUGDOT_ELEMENT_PUSH( p )    (DebugElement::push(p))
1206cdf0e10cSrcweir     #define erDEBUGDOT_ELEMENT_POP()        (DebugElement::pop())
1207cdf0e10cSrcweir #else
1208cdf0e10cSrcweir     #define erDEBUGDOT_OUT( p )
1209cdf0e10cSrcweir     #define erDEBUGDOT_ELEMENT_PUSH( p )
1210cdf0e10cSrcweir     #define erDEBUGDOT_ELEMENT_POP()
1211cdf0e10cSrcweir #endif
1212cdf0e10cSrcweir 
1213cdf0e10cSrcweir 	if (!IsDirtyOrInTableOpDirty() || pDocument->GetRecursionHelper().IsInReturn())
1214cdf0e10cSrcweir         return;     // no double/triple processing
1215cdf0e10cSrcweir 
1216cdf0e10cSrcweir 	//!	HACK:
1217cdf0e10cSrcweir 	//	Wenn der Aufruf aus einem Reschedule im DdeLink-Update kommt, dirty stehenlassen
1218cdf0e10cSrcweir 	//	Besser: Dde-Link Update ohne Reschedule oder ganz asynchron !!!
1219cdf0e10cSrcweir 
1220cdf0e10cSrcweir     if ( pDocument->IsInDdeLinkUpdate() )
1221cdf0e10cSrcweir 		return;
1222cdf0e10cSrcweir 
1223cdf0e10cSrcweir #if erDEBUGDOT
1224cdf0e10cSrcweir     // set nDebug=1 in debugger to init things
1225cdf0e10cSrcweir     if (nDebug == 1)
1226cdf0e10cSrcweir     {
1227cdf0e10cSrcweir         ++nDebug;
1228cdf0e10cSrcweir         pDebugFile = fopen( aDebugDotFile, "a");
1229cdf0e10cSrcweir         if (!pDebugFile)
1230cdf0e10cSrcweir             nDebug = 0;
1231cdf0e10cSrcweir         else
1232cdf0e10cSrcweir             nDebug = erDEBUGDOTRUN;
1233cdf0e10cSrcweir     }
1234cdf0e10cSrcweir     // set nDebug=3 (erDEBUGDOTRUN) in debugger to get any output
1235cdf0e10cSrcweir     DebugElement aDebugElem( this);
1236cdf0e10cSrcweir     // set nDebug=5 in debugger to close output
1237cdf0e10cSrcweir     if (nDebug == 5)
1238cdf0e10cSrcweir     {
1239cdf0e10cSrcweir         nDebug = 0;
1240cdf0e10cSrcweir         fclose( pDebugFile);
1241cdf0e10cSrcweir         pDebugFile = 0;
1242cdf0e10cSrcweir     }
1243cdf0e10cSrcweir #endif
1244cdf0e10cSrcweir 
1245cdf0e10cSrcweir 	if (bRunning)
1246cdf0e10cSrcweir 	{
1247cdf0e10cSrcweir 
1248cdf0e10cSrcweir #if erDEBUGDOT
1249cdf0e10cSrcweir         if (!pDocument->GetRecursionHelper().IsDoingIteration() ||
1250cdf0e10cSrcweir                 aDebugThisPos != aDebugLastPos)
1251cdf0e10cSrcweir             erDEBUGDOT_OUT(aDebugThisPos == aDebugLastPos ? "orange" :
1252cdf0e10cSrcweir                     (pDocument->GetRecursionHelper().GetIteration() ? "blue" :
1253cdf0e10cSrcweir                      "red"));
1254cdf0e10cSrcweir #endif
1255cdf0e10cSrcweir 
1256cdf0e10cSrcweir         if (!pDocument->GetDocOptions().IsIter())
1257cdf0e10cSrcweir         {
1258cdf0e10cSrcweir 			aResult.SetResultError( errCircularReference );
1259cdf0e10cSrcweir             return;
1260cdf0e10cSrcweir         }
1261cdf0e10cSrcweir 
1262cdf0e10cSrcweir         if (aResult.GetResultError() == errCircularReference)
1263cdf0e10cSrcweir             aResult.SetResultError( 0 );
1264cdf0e10cSrcweir 
1265cdf0e10cSrcweir         // Start or add to iteration list.
1266cdf0e10cSrcweir         if (!pDocument->GetRecursionHelper().IsDoingIteration() ||
1267cdf0e10cSrcweir                 !pDocument->GetRecursionHelper().GetRecursionInIterationStack().top()->bIsIterCell)
1268cdf0e10cSrcweir             pDocument->GetRecursionHelper().SetInIterationReturn( true);
1269cdf0e10cSrcweir 
1270cdf0e10cSrcweir         return;
1271cdf0e10cSrcweir 	}
1272cdf0e10cSrcweir     // #63038# no multiple interprets for GetErrCode, IsValue, GetValue and
1273cdf0e10cSrcweir     // different entry point recursions. Would also lead to premature
1274cdf0e10cSrcweir     // convergence in iterations.
1275cdf0e10cSrcweir     if (pDocument->GetRecursionHelper().GetIteration() && nSeenInIteration ==
1276cdf0e10cSrcweir             pDocument->GetRecursionHelper().GetIteration())
1277cdf0e10cSrcweir 		return ;
1278cdf0e10cSrcweir 
1279cdf0e10cSrcweir     erDEBUGDOT_OUT( pDocument->GetRecursionHelper().GetIteration() ? "magenta" : "");
1280cdf0e10cSrcweir 
1281cdf0e10cSrcweir     ScRecursionHelper& rRecursionHelper = pDocument->GetRecursionHelper();
1282cdf0e10cSrcweir     sal_Bool bOldRunning = bRunning;
1283cdf0e10cSrcweir     if (rRecursionHelper.GetRecursionCount() > MAXRECURSION)
1284cdf0e10cSrcweir     {
1285cdf0e10cSrcweir         bRunning = sal_True;
1286cdf0e10cSrcweir         rRecursionHelper.SetInRecursionReturn( true);
1287cdf0e10cSrcweir     }
1288cdf0e10cSrcweir     else
1289cdf0e10cSrcweir     {
1290cdf0e10cSrcweir         InterpretTail( SCITP_NORMAL);
1291cdf0e10cSrcweir     }
1292cdf0e10cSrcweir 
1293cdf0e10cSrcweir     // While leaving a recursion or iteration stack, insert its cells to the
1294cdf0e10cSrcweir     // recursion list in reverse order.
1295cdf0e10cSrcweir     if (rRecursionHelper.IsInReturn())
1296cdf0e10cSrcweir     {
1297cdf0e10cSrcweir         if (rRecursionHelper.GetRecursionCount() > 0 ||
1298cdf0e10cSrcweir                 !rRecursionHelper.IsDoingRecursion())
1299cdf0e10cSrcweir             rRecursionHelper.Insert( this, bOldRunning, aResult);
1300cdf0e10cSrcweir         bool bIterationFromRecursion = false;
1301cdf0e10cSrcweir         bool bResumeIteration = false;
1302cdf0e10cSrcweir         do
1303cdf0e10cSrcweir         {
1304cdf0e10cSrcweir             if ((rRecursionHelper.IsInIterationReturn() &&
1305cdf0e10cSrcweir                         rRecursionHelper.GetRecursionCount() == 0 &&
1306cdf0e10cSrcweir                         !rRecursionHelper.IsDoingIteration()) ||
1307cdf0e10cSrcweir                     bIterationFromRecursion || bResumeIteration)
1308cdf0e10cSrcweir             {
1309cdf0e10cSrcweir                 ScFormulaCell* pIterCell = this; // scope for debug convenience
1310cdf0e10cSrcweir                 bool & rDone = rRecursionHelper.GetConvergingReference();
1311cdf0e10cSrcweir                 rDone = false;
1312cdf0e10cSrcweir                 if (!bIterationFromRecursion && bResumeIteration)
1313cdf0e10cSrcweir                 {
1314cdf0e10cSrcweir                     bResumeIteration = false;
1315cdf0e10cSrcweir                     // Resuming iteration expands the range.
1316cdf0e10cSrcweir                     ScFormulaRecursionList::const_iterator aOldStart(
1317cdf0e10cSrcweir                             rRecursionHelper.GetLastIterationStart());
1318cdf0e10cSrcweir                     rRecursionHelper.ResumeIteration();
1319cdf0e10cSrcweir                     // Mark new cells being in iteration.
1320cdf0e10cSrcweir                     for (ScFormulaRecursionList::const_iterator aIter(
1321cdf0e10cSrcweir                                 rRecursionHelper.GetIterationStart()); aIter !=
1322cdf0e10cSrcweir                             aOldStart; ++aIter)
1323cdf0e10cSrcweir                     {
1324cdf0e10cSrcweir                         pIterCell = (*aIter).pCell;
1325cdf0e10cSrcweir                         pIterCell->bIsIterCell = sal_True;
1326cdf0e10cSrcweir                     }
1327cdf0e10cSrcweir                     // Mark older cells dirty again, in case they converted
1328cdf0e10cSrcweir                     // without accounting for all remaining cells in the circle
1329cdf0e10cSrcweir                     // that weren't touched so far, e.g. conditional. Restore
1330cdf0e10cSrcweir                     // backuped result.
1331cdf0e10cSrcweir                     sal_uInt16 nIteration = rRecursionHelper.GetIteration();
1332cdf0e10cSrcweir                     for (ScFormulaRecursionList::const_iterator aIter(
1333cdf0e10cSrcweir                                 aOldStart); aIter !=
1334cdf0e10cSrcweir                             rRecursionHelper.GetIterationEnd(); ++aIter)
1335cdf0e10cSrcweir                     {
1336cdf0e10cSrcweir                         pIterCell = (*aIter).pCell;
1337cdf0e10cSrcweir                         if (pIterCell->nSeenInIteration == nIteration)
1338cdf0e10cSrcweir                         {
1339cdf0e10cSrcweir                             if (!pIterCell->bDirty || aIter == aOldStart)
1340cdf0e10cSrcweir                             {
1341cdf0e10cSrcweir                                 pIterCell->aResult = (*aIter).aPreviousResult;
1342cdf0e10cSrcweir                             }
1343cdf0e10cSrcweir                             --pIterCell->nSeenInIteration;
1344cdf0e10cSrcweir                         }
1345cdf0e10cSrcweir                         pIterCell->bDirty = sal_True;
1346cdf0e10cSrcweir                     }
1347cdf0e10cSrcweir                 }
1348cdf0e10cSrcweir                 else
1349cdf0e10cSrcweir                 {
1350cdf0e10cSrcweir                     bResumeIteration = false;
1351cdf0e10cSrcweir                     // Close circle once.
1352cdf0e10cSrcweir                     rRecursionHelper.GetList().back().pCell->InterpretTail(
1353cdf0e10cSrcweir                             SCITP_CLOSE_ITERATION_CIRCLE);
1354cdf0e10cSrcweir                     // Start at 1, init things.
1355cdf0e10cSrcweir                     rRecursionHelper.StartIteration();
1356cdf0e10cSrcweir                     // Mark all cells being in iteration.
1357cdf0e10cSrcweir                     for (ScFormulaRecursionList::const_iterator aIter(
1358cdf0e10cSrcweir                                 rRecursionHelper.GetIterationStart()); aIter !=
1359cdf0e10cSrcweir                             rRecursionHelper.GetIterationEnd(); ++aIter)
1360cdf0e10cSrcweir                     {
1361cdf0e10cSrcweir                         pIterCell = (*aIter).pCell;
1362cdf0e10cSrcweir                         pIterCell->bIsIterCell = sal_True;
1363cdf0e10cSrcweir                     }
1364cdf0e10cSrcweir                 }
1365cdf0e10cSrcweir                 bIterationFromRecursion = false;
1366cdf0e10cSrcweir                 sal_uInt16 nIterMax = pDocument->GetDocOptions().GetIterCount();
1367cdf0e10cSrcweir                 for ( ; rRecursionHelper.GetIteration() <= nIterMax && !rDone;
1368cdf0e10cSrcweir                         rRecursionHelper.IncIteration())
1369cdf0e10cSrcweir                 {
1370cdf0e10cSrcweir                     rDone = true;
1371cdf0e10cSrcweir                     for ( ScFormulaRecursionList::iterator aIter(
1372cdf0e10cSrcweir                                 rRecursionHelper.GetIterationStart()); aIter !=
1373cdf0e10cSrcweir                             rRecursionHelper.GetIterationEnd() &&
1374cdf0e10cSrcweir                             !rRecursionHelper.IsInReturn(); ++aIter)
1375cdf0e10cSrcweir                     {
1376cdf0e10cSrcweir                         pIterCell = (*aIter).pCell;
1377cdf0e10cSrcweir                         if (pIterCell->IsDirtyOrInTableOpDirty() &&
1378cdf0e10cSrcweir                                 rRecursionHelper.GetIteration() !=
1379cdf0e10cSrcweir                                 pIterCell->GetSeenInIteration())
1380cdf0e10cSrcweir                         {
1381cdf0e10cSrcweir                             (*aIter).aPreviousResult = pIterCell->aResult;
1382cdf0e10cSrcweir                             pIterCell->InterpretTail( SCITP_FROM_ITERATION);
1383cdf0e10cSrcweir                         }
1384cdf0e10cSrcweir                         rDone = rDone && !pIterCell->IsDirtyOrInTableOpDirty();
1385cdf0e10cSrcweir                     }
1386cdf0e10cSrcweir                     if (rRecursionHelper.IsInReturn())
1387cdf0e10cSrcweir                     {
1388cdf0e10cSrcweir                         bResumeIteration = true;
1389cdf0e10cSrcweir                         break;  // for
1390cdf0e10cSrcweir                         // Don't increment iteration.
1391cdf0e10cSrcweir                     }
1392cdf0e10cSrcweir                 }
1393cdf0e10cSrcweir                 if (!bResumeIteration)
1394cdf0e10cSrcweir                 {
1395cdf0e10cSrcweir                     if (rDone)
1396cdf0e10cSrcweir                     {
1397cdf0e10cSrcweir                         for (ScFormulaRecursionList::const_iterator aIter(
1398cdf0e10cSrcweir                                     rRecursionHelper.GetIterationStart());
1399cdf0e10cSrcweir                                 aIter != rRecursionHelper.GetIterationEnd();
1400cdf0e10cSrcweir                                 ++aIter)
1401cdf0e10cSrcweir                         {
1402cdf0e10cSrcweir                             pIterCell = (*aIter).pCell;
1403cdf0e10cSrcweir                             pIterCell->bIsIterCell = sal_False;
1404cdf0e10cSrcweir                             pIterCell->nSeenInIteration = 0;
1405cdf0e10cSrcweir                             pIterCell->bRunning = (*aIter).bOldRunning;
1406cdf0e10cSrcweir                         }
1407cdf0e10cSrcweir                     }
1408cdf0e10cSrcweir                     else
1409cdf0e10cSrcweir                     {
1410cdf0e10cSrcweir                         for (ScFormulaRecursionList::const_iterator aIter(
1411cdf0e10cSrcweir                                     rRecursionHelper.GetIterationStart());
1412cdf0e10cSrcweir                                 aIter != rRecursionHelper.GetIterationEnd();
1413cdf0e10cSrcweir                                 ++aIter)
1414cdf0e10cSrcweir                         {
1415cdf0e10cSrcweir                             pIterCell = (*aIter).pCell;
1416cdf0e10cSrcweir                             pIterCell->bIsIterCell = sal_False;
1417cdf0e10cSrcweir                             pIterCell->nSeenInIteration = 0;
1418cdf0e10cSrcweir                             pIterCell->bRunning = (*aIter).bOldRunning;
1419cdf0e10cSrcweir                             // If one cell didn't converge, all cells of this
1420cdf0e10cSrcweir                             // circular dependency don't, no matter whether
1421cdf0e10cSrcweir                             // single cells did.
1422cdf0e10cSrcweir                             pIterCell->bDirty = sal_False;
1423cdf0e10cSrcweir                             pIterCell->bTableOpDirty = sal_False;
1424cdf0e10cSrcweir                             pIterCell->aResult.SetResultError( errNoConvergence);
1425cdf0e10cSrcweir                             pIterCell->bChanged = sal_True;
1426cdf0e10cSrcweir                             pIterCell->SetTextWidth( TEXTWIDTH_DIRTY);
1427cdf0e10cSrcweir                             pIterCell->SetScriptType( SC_SCRIPTTYPE_UNKNOWN);
1428cdf0e10cSrcweir                         }
1429cdf0e10cSrcweir                     }
1430cdf0e10cSrcweir                     // End this iteration and remove entries.
1431cdf0e10cSrcweir                     rRecursionHelper.EndIteration();
1432cdf0e10cSrcweir                     bResumeIteration = rRecursionHelper.IsDoingIteration();
1433cdf0e10cSrcweir                 }
1434cdf0e10cSrcweir             }
1435cdf0e10cSrcweir             if (rRecursionHelper.IsInRecursionReturn() &&
1436cdf0e10cSrcweir                     rRecursionHelper.GetRecursionCount() == 0 &&
1437cdf0e10cSrcweir                     !rRecursionHelper.IsDoingRecursion())
1438cdf0e10cSrcweir             {
1439cdf0e10cSrcweir                 bIterationFromRecursion = false;
1440cdf0e10cSrcweir                 // Iterate over cells known so far, start with the last cell
1441cdf0e10cSrcweir                 // encountered, inserting new cells if another recursion limit
1442cdf0e10cSrcweir                 // is reached. Repeat until solved.
1443cdf0e10cSrcweir                 rRecursionHelper.SetDoingRecursion( true);
1444cdf0e10cSrcweir                 do
1445cdf0e10cSrcweir                 {
1446cdf0e10cSrcweir                     rRecursionHelper.SetInRecursionReturn( false);
1447cdf0e10cSrcweir                     for (ScFormulaRecursionList::const_iterator aIter(
1448cdf0e10cSrcweir                                 rRecursionHelper.GetStart());
1449cdf0e10cSrcweir                             !rRecursionHelper.IsInReturn() && aIter !=
1450cdf0e10cSrcweir                             rRecursionHelper.GetEnd(); ++aIter)
1451cdf0e10cSrcweir                     {
1452cdf0e10cSrcweir                         ScFormulaCell* pCell = (*aIter).pCell;
1453cdf0e10cSrcweir                         if (pCell->IsDirtyOrInTableOpDirty())
1454cdf0e10cSrcweir                         {
1455cdf0e10cSrcweir                             pCell->InterpretTail( SCITP_NORMAL);
1456cdf0e10cSrcweir                             if (!pCell->IsDirtyOrInTableOpDirty() && !pCell->IsIterCell())
1457cdf0e10cSrcweir                                 pCell->bRunning = (*aIter).bOldRunning;
1458cdf0e10cSrcweir                         }
1459cdf0e10cSrcweir                     }
1460cdf0e10cSrcweir                 } while (rRecursionHelper.IsInRecursionReturn());
1461cdf0e10cSrcweir                 rRecursionHelper.SetDoingRecursion( false);
1462cdf0e10cSrcweir                 if (rRecursionHelper.IsInIterationReturn())
1463cdf0e10cSrcweir                 {
1464cdf0e10cSrcweir                     if (!bResumeIteration)
1465cdf0e10cSrcweir                         bIterationFromRecursion = true;
1466cdf0e10cSrcweir                 }
1467cdf0e10cSrcweir                 else if (bResumeIteration ||
1468cdf0e10cSrcweir                         rRecursionHelper.IsDoingIteration())
1469cdf0e10cSrcweir                     rRecursionHelper.GetList().erase(
1470cdf0e10cSrcweir                             rRecursionHelper.GetStart(),
1471cdf0e10cSrcweir                             rRecursionHelper.GetLastIterationStart());
1472cdf0e10cSrcweir                 else
1473cdf0e10cSrcweir                     rRecursionHelper.Clear();
1474cdf0e10cSrcweir             }
1475cdf0e10cSrcweir         } while (bIterationFromRecursion || bResumeIteration);
1476cdf0e10cSrcweir     }
1477cdf0e10cSrcweir }
1478cdf0e10cSrcweir 
InterpretTail(ScInterpretTailParameter eTailParam)1479cdf0e10cSrcweir void ScFormulaCell::InterpretTail( ScInterpretTailParameter eTailParam )
1480cdf0e10cSrcweir {
1481cdf0e10cSrcweir     class RecursionCounter
1482cdf0e10cSrcweir     {
1483cdf0e10cSrcweir         ScRecursionHelper&  rRec;
1484cdf0e10cSrcweir         bool                bStackedInIteration;
1485cdf0e10cSrcweir         public:
1486cdf0e10cSrcweir         RecursionCounter( ScRecursionHelper& r, ScFormulaCell* p ) : rRec(r)
1487cdf0e10cSrcweir         {
1488cdf0e10cSrcweir             bStackedInIteration = rRec.IsDoingIteration();
1489cdf0e10cSrcweir             if (bStackedInIteration)
1490cdf0e10cSrcweir                 rRec.GetRecursionInIterationStack().push( p);
1491cdf0e10cSrcweir             rRec.IncRecursionCount();
1492cdf0e10cSrcweir         }
1493cdf0e10cSrcweir         ~RecursionCounter()
1494cdf0e10cSrcweir         {
1495cdf0e10cSrcweir             rRec.DecRecursionCount();
1496cdf0e10cSrcweir             if (bStackedInIteration)
1497cdf0e10cSrcweir                 rRec.GetRecursionInIterationStack().pop();
1498cdf0e10cSrcweir         }
1499cdf0e10cSrcweir     } aRecursionCounter( pDocument->GetRecursionHelper(), this);
1500cdf0e10cSrcweir     nSeenInIteration = pDocument->GetRecursionHelper().GetIteration();
1501cdf0e10cSrcweir     if( !pCode->GetCodeLen() && !pCode->GetCodeError() )
1502cdf0e10cSrcweir     {
1503cdf0e10cSrcweir         // #i11719# no UPN and no error and no token code but result string present
1504cdf0e10cSrcweir         // => interpretation of this cell during name-compilation and unknown names
1505cdf0e10cSrcweir         // => can't exchange underlying code array in CompileTokenArray() /
1506cdf0e10cSrcweir         // Compile() because interpreter's token iterator would crash.
1507cdf0e10cSrcweir         // This should only be a temporary condition and, since we set an
1508cdf0e10cSrcweir         // error, if ran into it again we'd bump into the dirty-clearing
1509cdf0e10cSrcweir         // condition further down.
1510cdf0e10cSrcweir         if ( !pCode->GetLen() && aResult.GetHybridFormula().Len() )
1511cdf0e10cSrcweir         {
1512cdf0e10cSrcweir             pCode->SetCodeError( errNoCode );
1513cdf0e10cSrcweir             // This is worth an assertion; if encountered in daily work
1514cdf0e10cSrcweir             // documents we might need another solution. Or just confirm correctness.
1515cdf0e10cSrcweir             DBG_ERRORFILE( "ScFormulaCell::Interpret: no UPN, no error, no token, but string" );
1516cdf0e10cSrcweir             return;
1517cdf0e10cSrcweir         }
1518cdf0e10cSrcweir         CompileTokenArray();
1519cdf0e10cSrcweir     }
1520cdf0e10cSrcweir 
1521cdf0e10cSrcweir     if( pCode->GetCodeLen() && pDocument )
1522cdf0e10cSrcweir     {
1523cdf0e10cSrcweir         class StackCleaner
1524cdf0e10cSrcweir         {
1525cdf0e10cSrcweir             ScDocument*     pDoc;
1526cdf0e10cSrcweir             ScInterpreter*  pInt;
1527cdf0e10cSrcweir             public:
1528cdf0e10cSrcweir             StackCleaner( ScDocument* pD, ScInterpreter* pI )
1529cdf0e10cSrcweir                 : pDoc(pD), pInt(pI)
1530cdf0e10cSrcweir                 {}
1531cdf0e10cSrcweir             ~StackCleaner()
1532cdf0e10cSrcweir             {
1533cdf0e10cSrcweir                 delete pInt;
1534cdf0e10cSrcweir                 pDoc->DecInterpretLevel();
1535cdf0e10cSrcweir             }
1536cdf0e10cSrcweir         };
1537cdf0e10cSrcweir         pDocument->IncInterpretLevel();
1538cdf0e10cSrcweir         ScInterpreter* p = new ScInterpreter( this, pDocument, aPos, *pCode );
1539cdf0e10cSrcweir         StackCleaner aStackCleaner( pDocument, p);
1540cdf0e10cSrcweir         sal_uInt16 nOldErrCode = aResult.GetResultError();
1541cdf0e10cSrcweir         if ( nSeenInIteration == 0 )
1542cdf0e10cSrcweir         {   // Only the first time
1543cdf0e10cSrcweir             // With bChanged=sal_False, if a newly compiled cell has a result of
1544cdf0e10cSrcweir             // 0.0, no change is detected and the cell will not be repainted.
1545cdf0e10cSrcweir             // bChanged = sal_False;
1546cdf0e10cSrcweir             aResult.SetResultError( 0 );
1547cdf0e10cSrcweir         }
1548cdf0e10cSrcweir 
1549cdf0e10cSrcweir         switch ( aResult.GetResultError() )
1550cdf0e10cSrcweir         {
1551cdf0e10cSrcweir             case errCircularReference :     // will be determined again if so
1552cdf0e10cSrcweir                 aResult.SetResultError( 0 );
1553cdf0e10cSrcweir             break;
1554cdf0e10cSrcweir         }
1555cdf0e10cSrcweir 
1556cdf0e10cSrcweir         sal_Bool bOldRunning = bRunning;
1557cdf0e10cSrcweir         bRunning = sal_True;
1558cdf0e10cSrcweir         p->Interpret();
1559cdf0e10cSrcweir         if (pDocument->GetRecursionHelper().IsInReturn() && eTailParam != SCITP_CLOSE_ITERATION_CIRCLE)
1560cdf0e10cSrcweir         {
1561cdf0e10cSrcweir             if (nSeenInIteration > 0)
1562cdf0e10cSrcweir                 --nSeenInIteration;     // retry when iteration is resumed
1563cdf0e10cSrcweir             return;
1564cdf0e10cSrcweir         }
1565cdf0e10cSrcweir         bRunning = bOldRunning;
156661e64f4aSWang Lei //-> i120962: If the cell was applied reference formula, get the valid token
156761e64f4aSWang Lei         if (pValidRefToken)
156861e64f4aSWang Lei             DELETEZ(pValidRefToken);
156961e64f4aSWang Lei         if (p->IsReferenceFunc() && p->GetLastStackRefToken())
157061e64f4aSWang Lei             pValidRefToken = static_cast<ScToken*>(p->GetLastStackRefToken()->Clone());
157161e64f4aSWang Lei //<- i120962
1572cdf0e10cSrcweir 
1573cdf0e10cSrcweir         // #i102616# For single-sheet saving consider only content changes, not format type,
1574cdf0e10cSrcweir         // because format type isn't set on loading (might be changed later)
1575cdf0e10cSrcweir         sal_Bool bContentChanged = sal_False;
1576cdf0e10cSrcweir 
1577cdf0e10cSrcweir         // Do not create a HyperLink() cell if the formula results in an error.
1578cdf0e10cSrcweir         if( p->GetError() && pCode->IsHyperLink())
1579cdf0e10cSrcweir             pCode->SetHyperLink(sal_False);
1580cdf0e10cSrcweir 
1581cdf0e10cSrcweir         if( p->GetError() && p->GetError() != errCircularReference)
1582cdf0e10cSrcweir         {
1583cdf0e10cSrcweir             bDirty = sal_False;
1584cdf0e10cSrcweir             bTableOpDirty = sal_False;
1585cdf0e10cSrcweir             bChanged = sal_True;
1586cdf0e10cSrcweir         }
1587cdf0e10cSrcweir         if (eTailParam == SCITP_FROM_ITERATION && IsDirtyOrInTableOpDirty())
1588cdf0e10cSrcweir         {
1589cdf0e10cSrcweir             bool bIsValue = aResult.IsValue();  // the previous type
1590cdf0e10cSrcweir             // Did it converge?
1591cdf0e10cSrcweir             if ((bIsValue && p->GetResultType() == svDouble && fabs(
1592cdf0e10cSrcweir                             p->GetNumResult() - aResult.GetDouble()) <=
1593cdf0e10cSrcweir                         pDocument->GetDocOptions().GetIterEps()) ||
1594cdf0e10cSrcweir                     (!bIsValue && p->GetResultType() == svString &&
1595cdf0e10cSrcweir                      p->GetStringResult() == aResult.GetString()))
1596cdf0e10cSrcweir             {
1597cdf0e10cSrcweir                 // A convergence in the first iteration doesn't necessarily
1598cdf0e10cSrcweir                 // mean that it's done, it may be because not all related cells
1599cdf0e10cSrcweir                 // of a circle changed their values yet. If the set really
1600cdf0e10cSrcweir                 // converges it will do so also during the next iteration. This
1601cdf0e10cSrcweir                 // fixes situations like of #i44115#. If this wasn't wanted an
1602cdf0e10cSrcweir                 // initial "uncalculated" value would be needed for all cells
1603cdf0e10cSrcweir                 // of a circular dependency => graph needed before calculation.
1604cdf0e10cSrcweir                 if (nSeenInIteration > 1 ||
1605cdf0e10cSrcweir                         pDocument->GetDocOptions().GetIterCount() == 1)
1606cdf0e10cSrcweir                 {
1607cdf0e10cSrcweir                     bDirty = sal_False;
1608cdf0e10cSrcweir                     bTableOpDirty = sal_False;
1609cdf0e10cSrcweir                 }
1610cdf0e10cSrcweir             }
1611cdf0e10cSrcweir         }
1612cdf0e10cSrcweir 
1613cdf0e10cSrcweir         // New error code?
1614cdf0e10cSrcweir         if( p->GetError() != nOldErrCode )
1615cdf0e10cSrcweir         {
1616cdf0e10cSrcweir             bChanged = sal_True;
1617cdf0e10cSrcweir             // bContentChanged only has to be set if the file content would be changed
1618cdf0e10cSrcweir             if ( aResult.GetCellResultType() != svUnknown )
1619cdf0e10cSrcweir                 bContentChanged = sal_True;
1620cdf0e10cSrcweir         }
1621cdf0e10cSrcweir         // Different number format?
1622cdf0e10cSrcweir         if( nFormatType != p->GetRetFormatType() )
1623cdf0e10cSrcweir         {
1624cdf0e10cSrcweir             nFormatType = p->GetRetFormatType();
1625cdf0e10cSrcweir             bChanged = sal_True;
1626cdf0e10cSrcweir         }
1627cdf0e10cSrcweir         if( nFormatIndex != p->GetRetFormatIndex() )
1628cdf0e10cSrcweir         {
1629cdf0e10cSrcweir             nFormatIndex = p->GetRetFormatIndex();
1630cdf0e10cSrcweir             bChanged = sal_True;
1631cdf0e10cSrcweir         }
1632cdf0e10cSrcweir 
1633cdf0e10cSrcweir         // In case of changes just obtain the result, no temporary and
1634cdf0e10cSrcweir         // comparison needed anymore.
1635cdf0e10cSrcweir         if (bChanged)
1636cdf0e10cSrcweir         {
1637cdf0e10cSrcweir             // #i102616# Compare anyway if the sheet is still marked unchanged for single-sheet saving
1638cdf0e10cSrcweir             // Also handle special cases of initial results after loading.
1639cdf0e10cSrcweir 
1640cdf0e10cSrcweir             if ( !bContentChanged && pDocument->IsStreamValid(aPos.Tab()) )
1641cdf0e10cSrcweir             {
1642cdf0e10cSrcweir                 ScFormulaResult aNewResult( p->GetResultToken());
1643cdf0e10cSrcweir                 StackVar eOld = aResult.GetCellResultType();
1644cdf0e10cSrcweir                 StackVar eNew = aNewResult.GetCellResultType();
1645cdf0e10cSrcweir                 if ( eOld == svUnknown && ( eNew == svError || ( eNew == svDouble && aNewResult.GetDouble() == 0.0 ) ) )
1646cdf0e10cSrcweir                 {
1647cdf0e10cSrcweir                     // ScXMLTableRowCellContext::EndElement doesn't call SetFormulaResultDouble for 0
1648cdf0e10cSrcweir                     // -> no change
1649cdf0e10cSrcweir                 }
1650cdf0e10cSrcweir                 else
1651cdf0e10cSrcweir                 {
1652cdf0e10cSrcweir                     if ( eOld == svHybridCell )     // string result from SetFormulaResultString?
1653cdf0e10cSrcweir                         eOld = svString;            // ScHybridCellToken has a valid GetString method
1654cdf0e10cSrcweir 
1655cdf0e10cSrcweir                     // #i106045# use approxEqual to compare with stored value
1656cdf0e10cSrcweir                     bContentChanged = (eOld != eNew ||
1657cdf0e10cSrcweir                             (eNew == svDouble && !rtl::math::approxEqual( aResult.GetDouble(), aNewResult.GetDouble() )) ||
1658cdf0e10cSrcweir                             (eNew == svString && aResult.GetString() != aNewResult.GetString()));
1659cdf0e10cSrcweir                 }
1660cdf0e10cSrcweir             }
1661cdf0e10cSrcweir 
1662cdf0e10cSrcweir             aResult.SetToken( p->GetResultToken() );
1663cdf0e10cSrcweir         }
1664cdf0e10cSrcweir         else
1665cdf0e10cSrcweir         {
1666cdf0e10cSrcweir             ScFormulaResult aNewResult( p->GetResultToken());
1667cdf0e10cSrcweir             StackVar eOld = aResult.GetCellResultType();
1668cdf0e10cSrcweir             StackVar eNew = aNewResult.GetCellResultType();
1669cdf0e10cSrcweir             bChanged = (eOld != eNew ||
1670cdf0e10cSrcweir                     (eNew == svDouble && aResult.GetDouble() != aNewResult.GetDouble()) ||
1671cdf0e10cSrcweir                     (eNew == svString && aResult.GetString() != aNewResult.GetString()));
1672cdf0e10cSrcweir 
1673cdf0e10cSrcweir             // #i102616# handle special cases of initial results after loading (only if the sheet is still marked unchanged)
1674cdf0e10cSrcweir             if ( bChanged && !bContentChanged && pDocument->IsStreamValid(aPos.Tab()) )
1675cdf0e10cSrcweir             {
1676cdf0e10cSrcweir                 if ( ( eOld == svUnknown && ( eNew == svError || ( eNew == svDouble && aNewResult.GetDouble() == 0.0 ) ) ) ||
1677cdf0e10cSrcweir                      ( eOld == svHybridCell && eNew == svString && aResult.GetString() == aNewResult.GetString() ) ||
1678cdf0e10cSrcweir                      ( eOld == svDouble && eNew == svDouble && rtl::math::approxEqual( aResult.GetDouble(), aNewResult.GetDouble() ) ) )
1679cdf0e10cSrcweir                 {
1680cdf0e10cSrcweir                     // no change, see above
1681cdf0e10cSrcweir                 }
1682cdf0e10cSrcweir                 else
1683cdf0e10cSrcweir                     bContentChanged = sal_True;
1684cdf0e10cSrcweir             }
1685cdf0e10cSrcweir 
1686cdf0e10cSrcweir             aResult.Assign( aNewResult);
1687cdf0e10cSrcweir         }
1688cdf0e10cSrcweir 
1689cdf0e10cSrcweir         // Precision as shown?
1690cdf0e10cSrcweir         if ( aResult.IsValue() && !p->GetError()
1691cdf0e10cSrcweir           && pDocument->GetDocOptions().IsCalcAsShown()
1692cdf0e10cSrcweir           && nFormatType != NUMBERFORMAT_DATE
1693cdf0e10cSrcweir           && nFormatType != NUMBERFORMAT_TIME
1694cdf0e10cSrcweir           && nFormatType != NUMBERFORMAT_DATETIME )
1695cdf0e10cSrcweir         {
1696cdf0e10cSrcweir             sal_uLong nFormat = pDocument->GetNumberFormat( aPos );
1697cdf0e10cSrcweir             if ( nFormatIndex && (nFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0 )
1698cdf0e10cSrcweir                 nFormat = nFormatIndex;
1699cdf0e10cSrcweir             if ( (nFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0 )
1700cdf0e10cSrcweir                 nFormat = ScGlobal::GetStandardFormat(
1701cdf0e10cSrcweir                     *pDocument->GetFormatTable(), nFormat, nFormatType );
1702cdf0e10cSrcweir             aResult.SetDouble( pDocument->RoundValueAsShown(
1703cdf0e10cSrcweir                         aResult.GetDouble(), nFormat));
1704cdf0e10cSrcweir         }
1705cdf0e10cSrcweir         if (eTailParam == SCITP_NORMAL)
1706cdf0e10cSrcweir         {
1707cdf0e10cSrcweir             bDirty = sal_False;
1708cdf0e10cSrcweir             bTableOpDirty = sal_False;
1709cdf0e10cSrcweir         }
1710cdf0e10cSrcweir         if( aResult.GetMatrix().Is() )
1711cdf0e10cSrcweir         {
1712cdf0e10cSrcweir             // If the formula wasn't entered as a matrix formula, live on with
1713cdf0e10cSrcweir             // the upper left corner and let reference counting delete the matrix.
1714cdf0e10cSrcweir             if( cMatrixFlag != MM_FORMULA && !pCode->IsHyperLink() )
1715cdf0e10cSrcweir                 aResult.SetToken( aResult.GetCellResultToken());
1716cdf0e10cSrcweir         }
1717cdf0e10cSrcweir         if ( aResult.IsValue() && !::rtl::math::isFinite( aResult.GetDouble() ) )
1718cdf0e10cSrcweir         {
1719cdf0e10cSrcweir             // Coded double error may occur via filter import.
1720cdf0e10cSrcweir             sal_uInt16 nErr = GetDoubleErrorValue( aResult.GetDouble());
1721cdf0e10cSrcweir             aResult.SetResultError( nErr);
1722cdf0e10cSrcweir             bChanged = bContentChanged = true;
1723cdf0e10cSrcweir         }
1724cdf0e10cSrcweir         if( bChanged )
1725cdf0e10cSrcweir         {
1726cdf0e10cSrcweir             SetTextWidth( TEXTWIDTH_DIRTY );
1727cdf0e10cSrcweir             SetScriptType( SC_SCRIPTTYPE_UNKNOWN );
1728cdf0e10cSrcweir         }
1729cdf0e10cSrcweir         if (bContentChanged && pDocument->IsStreamValid(aPos.Tab()))
1730cdf0e10cSrcweir         {
1731cdf0e10cSrcweir             // pass bIgnoreLock=sal_True, because even if called from pending row height update,
1732cdf0e10cSrcweir             // a changed result must still reset the stream flag
1733cdf0e10cSrcweir             pDocument->SetStreamValid(aPos.Tab(), sal_False, sal_True);
1734cdf0e10cSrcweir         }
1735cdf0e10cSrcweir         if ( !pCode->IsRecalcModeAlways() )
1736cdf0e10cSrcweir             pDocument->RemoveFromFormulaTree( this );
1737cdf0e10cSrcweir 
1738cdf0e10cSrcweir         //  FORCED Zellen auch sofort auf Gueltigkeit testen (evtl. Makro starten)
1739cdf0e10cSrcweir 
1740cdf0e10cSrcweir         if ( pCode->IsRecalcModeForced() )
1741cdf0e10cSrcweir         {
1742cdf0e10cSrcweir             sal_uLong nValidation = ((const SfxUInt32Item*) pDocument->GetAttr(
1743cdf0e10cSrcweir                     aPos.Col(), aPos.Row(), aPos.Tab(), ATTR_VALIDDATA ))->GetValue();
1744cdf0e10cSrcweir             if ( nValidation )
1745cdf0e10cSrcweir             {
1746cdf0e10cSrcweir                 const ScValidationData* pData = pDocument->GetValidationEntry( nValidation );
1747cdf0e10cSrcweir                 if ( pData && !pData->IsDataValid( this, aPos ) )
1748cdf0e10cSrcweir                     pData->DoCalcError( this );
1749cdf0e10cSrcweir             }
1750cdf0e10cSrcweir         }
1751cdf0e10cSrcweir 
1752cdf0e10cSrcweir         // Reschedule verlangsamt das ganze erheblich, nur bei Prozentaenderung ausfuehren
1753cdf0e10cSrcweir         ScProgress::GetInterpretProgress()->SetStateCountDownOnPercent(
1754cdf0e10cSrcweir             pDocument->GetFormulaCodeInTree()/MIN_NO_CODES_PER_PROGRESS_UPDATE );
1755cdf0e10cSrcweir     }
1756cdf0e10cSrcweir     else
1757cdf0e10cSrcweir     {
1758cdf0e10cSrcweir         //  Zelle bei Compiler-Fehlern nicht ewig auf dirty stehenlassen
1759cdf0e10cSrcweir         DBG_ASSERT( pCode->GetCodeError(), "kein UPN-Code und kein Fehler ?!?!" );
1760cdf0e10cSrcweir         bDirty = sal_False;
1761cdf0e10cSrcweir         bTableOpDirty = sal_False;
1762cdf0e10cSrcweir     }
1763cdf0e10cSrcweir }
1764cdf0e10cSrcweir 
1765cdf0e10cSrcweir 
SetMatColsRows(SCCOL nCols,SCROW nRows)1766cdf0e10cSrcweir void ScFormulaCell::SetMatColsRows( SCCOL nCols, SCROW nRows )
1767cdf0e10cSrcweir {
1768cdf0e10cSrcweir     ScMatrixFormulaCellToken* pMat = aResult.GetMatrixFormulaCellTokenNonConst();
1769cdf0e10cSrcweir     if (pMat)
1770cdf0e10cSrcweir         pMat->SetMatColsRows( nCols, nRows);
1771cdf0e10cSrcweir     else if (nCols || nRows)
1772cdf0e10cSrcweir         aResult.SetToken( new ScMatrixFormulaCellToken( nCols, nRows));
1773cdf0e10cSrcweir }
1774cdf0e10cSrcweir 
1775cdf0e10cSrcweir 
GetMatColsRows(SCCOL & nCols,SCROW & nRows) const1776cdf0e10cSrcweir void ScFormulaCell::GetMatColsRows( SCCOL & nCols, SCROW & nRows ) const
1777cdf0e10cSrcweir {
1778cdf0e10cSrcweir     const ScMatrixFormulaCellToken* pMat = aResult.GetMatrixFormulaCellToken();
1779cdf0e10cSrcweir     if (pMat)
1780cdf0e10cSrcweir         pMat->GetMatColsRows( nCols, nRows);
1781cdf0e10cSrcweir     else
1782cdf0e10cSrcweir     {
1783cdf0e10cSrcweir         nCols = 0;
1784cdf0e10cSrcweir         nRows = 0;
1785cdf0e10cSrcweir     }
1786cdf0e10cSrcweir }
1787cdf0e10cSrcweir 
1788cdf0e10cSrcweir 
GetStandardFormat(SvNumberFormatter & rFormatter,sal_uLong nFormat) const1789cdf0e10cSrcweir sal_uLong ScFormulaCell::GetStandardFormat( SvNumberFormatter& rFormatter, sal_uLong nFormat ) const
1790cdf0e10cSrcweir {
1791cdf0e10cSrcweir 	if ( nFormatIndex && (nFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0 )
1792cdf0e10cSrcweir 		return nFormatIndex;
1793cdf0e10cSrcweir     //! not ScFormulaCell::IsValue(), that could reinterpret the formula again.
1794cdf0e10cSrcweir 	if ( aResult.IsValue() )
1795cdf0e10cSrcweir 		return ScGlobal::GetStandardFormat(	aResult.GetDouble(), rFormatter, nFormat, nFormatType );
1796cdf0e10cSrcweir 	else
1797cdf0e10cSrcweir 		return ScGlobal::GetStandardFormat(	rFormatter, nFormat, nFormatType );
1798cdf0e10cSrcweir }
1799cdf0e10cSrcweir 
1800cdf0e10cSrcweir 
Notify(SvtBroadcaster &,const SfxHint & rHint)1801cdf0e10cSrcweir void __EXPORT ScFormulaCell::Notify( SvtBroadcaster&, const SfxHint& rHint)
1802cdf0e10cSrcweir {
1803cdf0e10cSrcweir 	if ( !pDocument->IsInDtorClear() && !pDocument->GetHardRecalcState() )
1804cdf0e10cSrcweir 	{
1805cdf0e10cSrcweir 		const ScHint* p = PTR_CAST( ScHint, &rHint );
1806cdf0e10cSrcweir         sal_uLong nHint = (p ? p->GetId() : 0);
1807cdf0e10cSrcweir         if (nHint & (SC_HINT_DATACHANGED | SC_HINT_DYING | SC_HINT_TABLEOPDIRTY))
1808cdf0e10cSrcweir 		{
1809cdf0e10cSrcweir             sal_Bool bForceTrack = sal_False;
1810cdf0e10cSrcweir 			if ( nHint & SC_HINT_TABLEOPDIRTY )
1811cdf0e10cSrcweir             {
1812cdf0e10cSrcweir                 bForceTrack = !bTableOpDirty;
1813cdf0e10cSrcweir                 if ( !bTableOpDirty )
1814cdf0e10cSrcweir                 {
1815cdf0e10cSrcweir                     pDocument->AddTableOpFormulaCell( this );
1816cdf0e10cSrcweir                     bTableOpDirty = sal_True;
1817cdf0e10cSrcweir                 }
1818cdf0e10cSrcweir             }
1819cdf0e10cSrcweir 			else
1820cdf0e10cSrcweir             {
1821cdf0e10cSrcweir                 bForceTrack = !bDirty;
1822cdf0e10cSrcweir 				bDirty = sal_True;
1823cdf0e10cSrcweir             }
1824cdf0e10cSrcweir             // #35962# Don't remove from FormulaTree to put in FormulaTrack to
1825cdf0e10cSrcweir             // put in FormulaTree again and again, only if necessary.
1826cdf0e10cSrcweir             // Any other means except RECALCMODE_ALWAYS by which a cell could
1827cdf0e10cSrcweir             // be in FormulaTree if it would notify other cells through
1828cdf0e10cSrcweir             // FormulaTrack which weren't in FormulaTrack/FormulaTree before?!?
1829cdf0e10cSrcweir             // #87866# Yes. The new TableOpDirty made it necessary to have a
1830cdf0e10cSrcweir             // forced mode where formulas may still be in FormulaTree from
1831cdf0e10cSrcweir             // TableOpDirty but have to notify dependents for normal dirty.
1832cdf0e10cSrcweir             if ( (bForceTrack || !pDocument->IsInFormulaTree( this )
1833cdf0e10cSrcweir 					|| pCode->IsRecalcModeAlways())
1834cdf0e10cSrcweir 					&& !pDocument->IsInFormulaTrack( this ) )
1835cdf0e10cSrcweir 				pDocument->AppendToFormulaTrack( this );
1836cdf0e10cSrcweir 		}
1837cdf0e10cSrcweir 	}
1838cdf0e10cSrcweir }
1839cdf0e10cSrcweir 
SetDirty()1840cdf0e10cSrcweir void ScFormulaCell::SetDirty()
1841cdf0e10cSrcweir {
1842cdf0e10cSrcweir 	if ( !IsInChangeTrack() )
1843cdf0e10cSrcweir 	{
1844cdf0e10cSrcweir 		if ( pDocument->GetHardRecalcState() )
1845cdf0e10cSrcweir 			bDirty = sal_True;
1846cdf0e10cSrcweir 		else
1847cdf0e10cSrcweir 		{
1848cdf0e10cSrcweir 			// Mehrfach-FormulaTracking in Load und in CompileAll
1849cdf0e10cSrcweir 			// nach CopyScenario und CopyBlockFromClip vermeiden.
1850cdf0e10cSrcweir 			// Wenn unbedingtes FormulaTracking noetig, vor SetDirty bDirty=sal_False
1851cdf0e10cSrcweir 			// setzen, z.B. in CompileTokenArray
1852cdf0e10cSrcweir 			if ( !bDirty || !pDocument->IsInFormulaTree( this ) )
1853cdf0e10cSrcweir 			{
1854cdf0e10cSrcweir 				bDirty = sal_True;
1855cdf0e10cSrcweir 				pDocument->AppendToFormulaTrack( this );
1856cdf0e10cSrcweir 				pDocument->TrackFormulas();
1857cdf0e10cSrcweir 			}
1858cdf0e10cSrcweir 		}
1859cdf0e10cSrcweir 
1860cdf0e10cSrcweir         if (pDocument->IsStreamValid(aPos.Tab()))
1861cdf0e10cSrcweir             pDocument->SetStreamValid(aPos.Tab(), sal_False);
1862cdf0e10cSrcweir 	}
1863cdf0e10cSrcweir }
1864cdf0e10cSrcweir 
SetDirtyAfterLoad()1865cdf0e10cSrcweir void ScFormulaCell::SetDirtyAfterLoad()
1866cdf0e10cSrcweir {
1867cdf0e10cSrcweir     bDirty = sal_True;
1868cdf0e10cSrcweir     if ( !pDocument->GetHardRecalcState() )
1869cdf0e10cSrcweir         pDocument->PutInFormulaTree( this );
1870cdf0e10cSrcweir }
1871cdf0e10cSrcweir 
SetTableOpDirty()1872cdf0e10cSrcweir void ScFormulaCell::SetTableOpDirty()
1873cdf0e10cSrcweir {
1874cdf0e10cSrcweir 	if ( !IsInChangeTrack() )
1875cdf0e10cSrcweir 	{
1876cdf0e10cSrcweir 		if ( pDocument->GetHardRecalcState() )
1877cdf0e10cSrcweir 			bTableOpDirty = sal_True;
1878cdf0e10cSrcweir 		else
1879cdf0e10cSrcweir 		{
1880cdf0e10cSrcweir 			if ( !bTableOpDirty || !pDocument->IsInFormulaTree( this ) )
1881cdf0e10cSrcweir 			{
1882cdf0e10cSrcweir                 if ( !bTableOpDirty )
1883cdf0e10cSrcweir                 {
1884cdf0e10cSrcweir                     pDocument->AddTableOpFormulaCell( this );
1885cdf0e10cSrcweir                     bTableOpDirty = sal_True;
1886cdf0e10cSrcweir                 }
1887cdf0e10cSrcweir 				pDocument->AppendToFormulaTrack( this );
1888cdf0e10cSrcweir 				pDocument->TrackFormulas( SC_HINT_TABLEOPDIRTY );
1889cdf0e10cSrcweir 			}
1890cdf0e10cSrcweir 		}
1891cdf0e10cSrcweir 	}
1892cdf0e10cSrcweir }
1893cdf0e10cSrcweir 
1894cdf0e10cSrcweir 
IsDirtyOrInTableOpDirty() const1895cdf0e10cSrcweir sal_Bool ScFormulaCell::IsDirtyOrInTableOpDirty() const
1896cdf0e10cSrcweir {
1897cdf0e10cSrcweir 	return bDirty || (bTableOpDirty && pDocument->IsInInterpreterTableOp());
1898cdf0e10cSrcweir }
1899cdf0e10cSrcweir 
1900cdf0e10cSrcweir 
SetErrCode(sal_uInt16 n)1901cdf0e10cSrcweir void ScFormulaCell::SetErrCode( sal_uInt16 n )
1902cdf0e10cSrcweir {
1903cdf0e10cSrcweir     /* FIXME: check the numerous places where ScTokenArray::GetCodeError() is
1904cdf0e10cSrcweir      * used whether it is solely for transport of a simple result error and get
1905cdf0e10cSrcweir      * rid of that abuse. */
1906cdf0e10cSrcweir 	pCode->SetCodeError( n );
1907cdf0e10cSrcweir     // Hard set errors are transported as result type value per convention,
1908cdf0e10cSrcweir     // e.g. via clipboard. ScFormulaResult::IsValue() and
1909cdf0e10cSrcweir     // ScFormulaResult::GetDouble() handle that.
1910cdf0e10cSrcweir     aResult.SetResultError( n );
1911cdf0e10cSrcweir }
1912cdf0e10cSrcweir 
AddRecalcMode(ScRecalcMode nBits)1913cdf0e10cSrcweir void ScFormulaCell::AddRecalcMode( ScRecalcMode nBits )
1914cdf0e10cSrcweir {
1915cdf0e10cSrcweir 	if ( (nBits & RECALCMODE_EMASK) != RECALCMODE_NORMAL )
1916cdf0e10cSrcweir 		bDirty = sal_True;
1917cdf0e10cSrcweir 	if ( nBits & RECALCMODE_ONLOAD_ONCE )
1918cdf0e10cSrcweir 	{	// OnLoadOnce nur zum Dirty setzen nach Filter-Import
1919cdf0e10cSrcweir 		nBits = (nBits & ~RECALCMODE_EMASK) | RECALCMODE_NORMAL;
1920cdf0e10cSrcweir 	}
1921cdf0e10cSrcweir 	pCode->AddRecalcMode( nBits );
1922cdf0e10cSrcweir }
1923cdf0e10cSrcweir 
1924cdf0e10cSrcweir // Dynamically create the URLField on a mouse-over action on a hyperlink() cell.
GetURLResult(String & rURL,String & rCellText)1925cdf0e10cSrcweir void ScFormulaCell::GetURLResult( String& rURL, String& rCellText )
1926cdf0e10cSrcweir {
1927cdf0e10cSrcweir     String aCellString;
1928cdf0e10cSrcweir 
1929cdf0e10cSrcweir     Color* pColor;
1930cdf0e10cSrcweir 
1931cdf0e10cSrcweir     // Cell Text uses the Cell format while the URL uses
1932cdf0e10cSrcweir     // the default format for the type.
1933cdf0e10cSrcweir     sal_uLong nCellFormat = pDocument->GetNumberFormat( aPos );
1934cdf0e10cSrcweir     SvNumberFormatter* pFormatter = pDocument->GetFormatTable();
1935cdf0e10cSrcweir 
1936cdf0e10cSrcweir     if ( (nCellFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0 )
1937cdf0e10cSrcweir         nCellFormat = GetStandardFormat( *pFormatter,nCellFormat );
1938cdf0e10cSrcweir 
1939cdf0e10cSrcweir    sal_uLong nURLFormat = ScGlobal::GetStandardFormat( *pFormatter,nCellFormat, NUMBERFORMAT_NUMBER);
1940cdf0e10cSrcweir 
1941cdf0e10cSrcweir     if ( IsValue() )
1942cdf0e10cSrcweir     {
1943cdf0e10cSrcweir         double fValue = GetValue();
1944cdf0e10cSrcweir         pFormatter->GetOutputString( fValue, nCellFormat, rCellText, &pColor );
1945cdf0e10cSrcweir     }
1946cdf0e10cSrcweir     else
1947cdf0e10cSrcweir     {
1948cdf0e10cSrcweir         GetString( aCellString );
1949cdf0e10cSrcweir         pFormatter->GetOutputString( aCellString, nCellFormat, rCellText, &pColor );
1950cdf0e10cSrcweir     }
1951cdf0e10cSrcweir     ScConstMatrixRef xMat( aResult.GetMatrix());
1952cdf0e10cSrcweir     if (xMat)
1953cdf0e10cSrcweir     {
1954cdf0e10cSrcweir         ScMatValType nMatValType;
1955cdf0e10cSrcweir         // determine if the matrix result is a string or value.
1956cdf0e10cSrcweir         const ScMatrixValue* pMatVal = xMat->Get(0, 1, nMatValType);
1957cdf0e10cSrcweir         if (pMatVal)
1958cdf0e10cSrcweir         {
1959cdf0e10cSrcweir             if (!ScMatrix::IsValueType( nMatValType))
1960cdf0e10cSrcweir                 rURL = pMatVal->GetString();
1961cdf0e10cSrcweir             else
1962cdf0e10cSrcweir                 pFormatter->GetOutputString( pMatVal->fVal, nURLFormat, rURL, &pColor );
1963cdf0e10cSrcweir         }
1964cdf0e10cSrcweir     }
1965cdf0e10cSrcweir 
1966cdf0e10cSrcweir     if(!rURL.Len())
1967cdf0e10cSrcweir     {
1968cdf0e10cSrcweir         if(IsValue())
1969cdf0e10cSrcweir             pFormatter->GetOutputString( GetValue(), nURLFormat, rURL, &pColor );
1970cdf0e10cSrcweir         else
1971cdf0e10cSrcweir             pFormatter->GetOutputString( aCellString, nURLFormat, rURL, &pColor );
1972cdf0e10cSrcweir     }
1973cdf0e10cSrcweir }
1974cdf0e10cSrcweir 
IsMultilineResult()1975cdf0e10cSrcweir bool ScFormulaCell::IsMultilineResult()
1976cdf0e10cSrcweir {
1977cdf0e10cSrcweir     if (!IsValue())
1978cdf0e10cSrcweir         return aResult.IsMultiline();
1979cdf0e10cSrcweir     return false;
1980cdf0e10cSrcweir }
1981cdf0e10cSrcweir 
CreateURLObject()1982cdf0e10cSrcweir EditTextObject* ScFormulaCell::CreateURLObject()
1983cdf0e10cSrcweir {
1984cdf0e10cSrcweir     String aCellText;
1985cdf0e10cSrcweir     String aURL;
1986cdf0e10cSrcweir     GetURLResult( aURL, aCellText );
1987cdf0e10cSrcweir 
1988cdf0e10cSrcweir     SvxURLField aUrlField( aURL, aCellText, SVXURLFORMAT_APPDEFAULT);
1989cdf0e10cSrcweir     EditEngine& rEE = pDocument->GetEditEngine();
1990cdf0e10cSrcweir     rEE.SetText( EMPTY_STRING );
1991*7a980842SDamjanJovanovic     rEE.QuickInsertField( SvxFieldItem( aUrlField, EE_FEATURE_FIELD ), ESelection( EE_PARA_MAX, EE_INDEX_MAX ) );
1992cdf0e10cSrcweir 
1993cdf0e10cSrcweir     return rEE.CreateTextObject();
1994cdf0e10cSrcweir }
1995cdf0e10cSrcweir 
1996cdf0e10cSrcweir // ============================================================================
1997cdf0e10cSrcweir 
ScDetectiveRefIter(ScFormulaCell * pCell)1998cdf0e10cSrcweir ScDetectiveRefIter::ScDetectiveRefIter( ScFormulaCell* pCell )
1999cdf0e10cSrcweir {
2000cdf0e10cSrcweir 	pCode = pCell->GetCode();
2001cdf0e10cSrcweir 	pCode->Reset();
2002cdf0e10cSrcweir 	aPos = pCell->aPos;
2003cdf0e10cSrcweir }
2004cdf0e10cSrcweir 
lcl_ScDetectiveRefIter_SkipRef(ScToken * p)2005cdf0e10cSrcweir sal_Bool lcl_ScDetectiveRefIter_SkipRef( ScToken* p )
2006cdf0e10cSrcweir {
2007cdf0e10cSrcweir 	ScSingleRefData& rRef1 = p->GetSingleRef();
2008cdf0e10cSrcweir 	if ( rRef1.IsColDeleted() || rRef1.IsRowDeleted() || rRef1.IsTabDeleted()
2009cdf0e10cSrcweir 			|| !rRef1.Valid() )
2010cdf0e10cSrcweir 		return sal_True;
2011cdf0e10cSrcweir 	if ( p->GetType() == svDoubleRef )
2012cdf0e10cSrcweir 	{
2013cdf0e10cSrcweir 		ScSingleRefData& rRef2 = p->GetDoubleRef().Ref2;
2014cdf0e10cSrcweir 		if ( rRef2.IsColDeleted() || rRef2.IsRowDeleted() || rRef2.IsTabDeleted()
2015cdf0e10cSrcweir 				|| !rRef2.Valid() )
2016cdf0e10cSrcweir 			return sal_True;
2017cdf0e10cSrcweir 	}
2018cdf0e10cSrcweir 	return sal_False;
2019cdf0e10cSrcweir }
2020cdf0e10cSrcweir 
GetNextRef(ScRange & rRange)2021cdf0e10cSrcweir sal_Bool ScDetectiveRefIter::GetNextRef( ScRange& rRange )
2022cdf0e10cSrcweir {
2023cdf0e10cSrcweir 	sal_Bool bRet = sal_False;
2024cdf0e10cSrcweir 
2025cdf0e10cSrcweir 	ScToken* p = static_cast<ScToken*>(pCode->GetNextReferenceRPN());
2026cdf0e10cSrcweir 	if (p)
2027cdf0e10cSrcweir 		p->CalcAbsIfRel( aPos );
2028cdf0e10cSrcweir 
2029cdf0e10cSrcweir 	while ( p && lcl_ScDetectiveRefIter_SkipRef( p ) )
2030cdf0e10cSrcweir 	{
2031cdf0e10cSrcweir 		p = static_cast<ScToken*>(pCode->GetNextReferenceRPN());
2032cdf0e10cSrcweir 		if (p)
2033cdf0e10cSrcweir 			p->CalcAbsIfRel( aPos );
2034cdf0e10cSrcweir 	}
2035cdf0e10cSrcweir 
2036cdf0e10cSrcweir 	if( p )
2037cdf0e10cSrcweir 	{
2038cdf0e10cSrcweir 		SingleDoubleRefProvider aProv( *p );
2039cdf0e10cSrcweir 		rRange.aStart.Set( aProv.Ref1.nCol, aProv.Ref1.nRow, aProv.Ref1.nTab );
2040cdf0e10cSrcweir 		rRange.aEnd.Set( aProv.Ref2.nCol, aProv.Ref2.nRow, aProv.Ref2.nTab );
2041cdf0e10cSrcweir 		bRet = sal_True;
2042cdf0e10cSrcweir 	}
2043cdf0e10cSrcweir 
2044cdf0e10cSrcweir 	return bRet;
2045cdf0e10cSrcweir }
2046cdf0e10cSrcweir 
2047cdf0e10cSrcweir // ============================================================================
2048