xref: /aoo41x/main/sc/source/core/data/cell2.cxx (revision 03eb9a00)
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 
22b3f79822SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_sc.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir 
28cdf0e10cSrcweir 
29cdf0e10cSrcweir // INCLUDE ---------------------------------------------------------------
30cdf0e10cSrcweir #include <algorithm>
31cdf0e10cSrcweir #include <deque>
32cdf0e10cSrcweir 
33cdf0e10cSrcweir #include <boost/bind.hpp>
34cdf0e10cSrcweir 
35cdf0e10cSrcweir #include <vcl/mapmod.hxx>
36cdf0e10cSrcweir #include <editeng/editobj.hxx>
37cdf0e10cSrcweir #include <editeng/editstat.hxx>
38cdf0e10cSrcweir 
39cdf0e10cSrcweir #include "cell.hxx"
40cdf0e10cSrcweir #include "compiler.hxx"
41cdf0e10cSrcweir #include "formula/errorcodes.hxx"
42cdf0e10cSrcweir #include "document.hxx"
43cdf0e10cSrcweir #include "rangenam.hxx"
44cdf0e10cSrcweir #include "rechead.hxx"
45cdf0e10cSrcweir #include "refupdat.hxx"
46cdf0e10cSrcweir #include "scmatrix.hxx"
47cdf0e10cSrcweir #include "editutil.hxx"
48cdf0e10cSrcweir #include "chgtrack.hxx"
49cdf0e10cSrcweir #include "externalrefmgr.hxx"
50cdf0e10cSrcweir 
51cdf0e10cSrcweir using namespace formula;
52cdf0e10cSrcweir 
53cdf0e10cSrcweir // STATIC DATA -----------------------------------------------------------
54cdf0e10cSrcweir 
55cdf0e10cSrcweir #ifdef USE_MEMPOOL
56cdf0e10cSrcweir const sal_uInt16 nMemPoolEditCell = (0x1000 - 64) / sizeof(ScNoteCell);
IMPL_FIXEDMEMPOOL_NEWDEL(ScEditCell,nMemPoolEditCell,nMemPoolEditCell)57cdf0e10cSrcweir IMPL_FIXEDMEMPOOL_NEWDEL( ScEditCell, nMemPoolEditCell, nMemPoolEditCell )
58cdf0e10cSrcweir #endif
59cdf0e10cSrcweir 
60cdf0e10cSrcweir // ============================================================================
61cdf0e10cSrcweir 
62cdf0e10cSrcweir ScEditCell::ScEditCell( const EditTextObject* pObject, ScDocument* pDocP,
63cdf0e10cSrcweir             const SfxItemPool* pFromPool )  :
64cdf0e10cSrcweir         ScBaseCell( CELLTYPE_EDIT ),
65cdf0e10cSrcweir         pString( NULL ),
66cdf0e10cSrcweir         pDoc( pDocP )
67cdf0e10cSrcweir {
68cdf0e10cSrcweir     SetTextObject( pObject, pFromPool );
69cdf0e10cSrcweir }
70cdf0e10cSrcweir 
ScEditCell(const ScEditCell & rCell,ScDocument & rDoc)71cdf0e10cSrcweir ScEditCell::ScEditCell( const ScEditCell& rCell, ScDocument& rDoc )  :
72cdf0e10cSrcweir         ScBaseCell( rCell ),
73cdf0e10cSrcweir         pString( NULL ),
74cdf0e10cSrcweir         pDoc( &rDoc )
75cdf0e10cSrcweir {
76cdf0e10cSrcweir     SetTextObject( rCell.pData, rCell.pDoc->GetEditPool() );
77cdf0e10cSrcweir }
78cdf0e10cSrcweir 
ScEditCell(const String & rString,ScDocument * pDocP)79cdf0e10cSrcweir ScEditCell::ScEditCell( const String& rString, ScDocument* pDocP )  :
80cdf0e10cSrcweir         ScBaseCell( CELLTYPE_EDIT ),
81cdf0e10cSrcweir         pString( NULL ),
82cdf0e10cSrcweir         pDoc( pDocP )
83cdf0e10cSrcweir {
84cdf0e10cSrcweir     DBG_ASSERT( rString.Search('\n') != STRING_NOTFOUND ||
85cdf0e10cSrcweir                 rString.Search(CHAR_CR) != STRING_NOTFOUND,
86cdf0e10cSrcweir                 "EditCell mit einfachem Text !?!?" );
87cdf0e10cSrcweir 
88cdf0e10cSrcweir     EditEngine& rEngine = pDoc->GetEditEngine();
89cdf0e10cSrcweir     rEngine.SetText( rString );
90cdf0e10cSrcweir     pData = rEngine.CreateTextObject();
91cdf0e10cSrcweir }
92cdf0e10cSrcweir 
~ScEditCell()93cdf0e10cSrcweir ScEditCell::~ScEditCell()
94cdf0e10cSrcweir {
95cdf0e10cSrcweir     delete pData;
96cdf0e10cSrcweir     delete pString;
97cdf0e10cSrcweir 
98cdf0e10cSrcweir #ifdef DBG_UTIL
99cdf0e10cSrcweir     eCellType = CELLTYPE_DESTROYED;
100cdf0e10cSrcweir #endif
101cdf0e10cSrcweir }
102cdf0e10cSrcweir 
SetData(const EditTextObject * pObject,const SfxItemPool * pFromPool)103cdf0e10cSrcweir void ScEditCell::SetData( const EditTextObject* pObject,
104cdf0e10cSrcweir             const SfxItemPool* pFromPool )
105cdf0e10cSrcweir {
106cdf0e10cSrcweir     if ( pString )
107cdf0e10cSrcweir     {
108cdf0e10cSrcweir         delete pString;
109cdf0e10cSrcweir         pString = NULL;
110cdf0e10cSrcweir     }
111cdf0e10cSrcweir     delete pData;
112cdf0e10cSrcweir     SetTextObject( pObject, pFromPool );
113cdf0e10cSrcweir }
114cdf0e10cSrcweir 
GetData(const EditTextObject * & rpObject) const115cdf0e10cSrcweir void ScEditCell::GetData( const EditTextObject*& rpObject ) const
116cdf0e10cSrcweir {
117cdf0e10cSrcweir     rpObject = pData;
118cdf0e10cSrcweir }
119cdf0e10cSrcweir 
GetString(String & rString) const120cdf0e10cSrcweir void ScEditCell::GetString( String& rString ) const
121cdf0e10cSrcweir {
122cdf0e10cSrcweir     if ( pString )
123cdf0e10cSrcweir         rString = *pString;
124cdf0e10cSrcweir     else if ( pData )
125cdf0e10cSrcweir     {
126cdf0e10cSrcweir         // auch Text von URL-Feldern, Doc-Engine ist eine ScFieldEditEngine
127cdf0e10cSrcweir         EditEngine& rEngine = pDoc->GetEditEngine();
128cdf0e10cSrcweir         rEngine.SetText( *pData );
129cdf0e10cSrcweir         rString = ScEditUtil::GetMultilineString(rEngine); // string with line separators between paragraphs
130cdf0e10cSrcweir         // cache short strings for formulas
131cdf0e10cSrcweir         if ( rString.Len() < 256 )
132cdf0e10cSrcweir             ((ScEditCell*)this)->pString = new String( rString );   //! non-const
133cdf0e10cSrcweir     }
134cdf0e10cSrcweir     else
135cdf0e10cSrcweir         rString.Erase();
136cdf0e10cSrcweir }
137cdf0e10cSrcweir 
SetTextObject(const EditTextObject * pObject,const SfxItemPool * pFromPool)138cdf0e10cSrcweir void ScEditCell::SetTextObject( const EditTextObject* pObject,
139cdf0e10cSrcweir             const SfxItemPool* pFromPool )
140cdf0e10cSrcweir {
141cdf0e10cSrcweir     if ( pObject )
142cdf0e10cSrcweir     {
143cdf0e10cSrcweir         if ( pFromPool && pDoc->GetEditPool() == pFromPool )
144cdf0e10cSrcweir             pData = pObject->Clone();
145cdf0e10cSrcweir         else
146cdf0e10cSrcweir         {   //! anderer Pool
147cdf0e10cSrcweir             // Leider gibt es keinen anderen Weg, um den Pool umzuhaengen,
148cdf0e10cSrcweir             // als das Object durch eine entsprechende Engine zu schleusen..
149cdf0e10cSrcweir             EditEngine& rEngine = pDoc->GetEditEngine();
150cdf0e10cSrcweir             if ( pObject->HasOnlineSpellErrors() )
151cdf0e10cSrcweir             {
152cdf0e10cSrcweir                 sal_uLong nControl = rEngine.GetControlWord();
153cdf0e10cSrcweir                 const sal_uLong nSpellControl = EE_CNTRL_ONLINESPELLING | EE_CNTRL_ALLOWBIGOBJS;
154cdf0e10cSrcweir                 sal_Bool bNewControl = ( (nControl & nSpellControl) != nSpellControl );
155cdf0e10cSrcweir                 if ( bNewControl )
156cdf0e10cSrcweir                     rEngine.SetControlWord( nControl | nSpellControl );
157cdf0e10cSrcweir                 rEngine.SetText( *pObject );
158cdf0e10cSrcweir                 pData = rEngine.CreateTextObject();
159cdf0e10cSrcweir                 if ( bNewControl )
160cdf0e10cSrcweir                     rEngine.SetControlWord( nControl );
161cdf0e10cSrcweir             }
162cdf0e10cSrcweir             else
163cdf0e10cSrcweir             {
164cdf0e10cSrcweir                 rEngine.SetText( *pObject );
165cdf0e10cSrcweir                 pData = rEngine.CreateTextObject();
166cdf0e10cSrcweir             }
167cdf0e10cSrcweir         }
168cdf0e10cSrcweir     }
169cdf0e10cSrcweir     else
170cdf0e10cSrcweir         pData = NULL;
171cdf0e10cSrcweir }
172cdf0e10cSrcweir 
173cdf0e10cSrcweir // ============================================================================
174cdf0e10cSrcweir 
175cdf0e10cSrcweir namespace
176cdf0e10cSrcweir {
177cdf0e10cSrcweir 
178cdf0e10cSrcweir using std::deque;
179cdf0e10cSrcweir 
180cdf0e10cSrcweir typedef SCCOLROW(*DimensionSelector)(const ScSingleRefData&);
181cdf0e10cSrcweir 
182cdf0e10cSrcweir 
lcl_GetCol(const ScSingleRefData & rData)183cdf0e10cSrcweir static SCCOLROW lcl_GetCol(const ScSingleRefData& rData)
184cdf0e10cSrcweir {
185cdf0e10cSrcweir     return rData.nCol;
186cdf0e10cSrcweir }
187cdf0e10cSrcweir 
188cdf0e10cSrcweir 
lcl_GetRow(const ScSingleRefData & rData)189cdf0e10cSrcweir static SCCOLROW lcl_GetRow(const ScSingleRefData& rData)
190cdf0e10cSrcweir {
191cdf0e10cSrcweir     return rData.nRow;
192cdf0e10cSrcweir }
193cdf0e10cSrcweir 
194cdf0e10cSrcweir 
lcl_GetTab(const ScSingleRefData & rData)195cdf0e10cSrcweir static SCCOLROW lcl_GetTab(const ScSingleRefData& rData)
196cdf0e10cSrcweir {
197cdf0e10cSrcweir     return rData.nTab;
198cdf0e10cSrcweir }
199cdf0e10cSrcweir 
200cdf0e10cSrcweir 
201cdf0e10cSrcweir /** Check if both references span the same range in selected dimension.
202cdf0e10cSrcweir  */
203cdf0e10cSrcweir static bool
lcl_checkRangeDimension(const SingleDoubleRefProvider & rRef1,const SingleDoubleRefProvider & rRef2,const DimensionSelector aWhich)204cdf0e10cSrcweir lcl_checkRangeDimension(
205cdf0e10cSrcweir         const SingleDoubleRefProvider& rRef1,
206cdf0e10cSrcweir         const SingleDoubleRefProvider& rRef2,
207cdf0e10cSrcweir         const DimensionSelector aWhich)
208cdf0e10cSrcweir {
209cdf0e10cSrcweir     return
210cdf0e10cSrcweir         aWhich(rRef1.Ref1) == aWhich(rRef2.Ref1)
211cdf0e10cSrcweir         && aWhich(rRef1.Ref2) == aWhich(rRef2.Ref2);
212cdf0e10cSrcweir }
213cdf0e10cSrcweir 
214cdf0e10cSrcweir 
215cdf0e10cSrcweir static bool
lcl_checkRangeDimensions(const SingleDoubleRefProvider & rRef1,const SingleDoubleRefProvider & rRef2,bool & bCol,bool & bRow,bool & bTab)216cdf0e10cSrcweir lcl_checkRangeDimensions(
217cdf0e10cSrcweir         const SingleDoubleRefProvider& rRef1,
218cdf0e10cSrcweir         const SingleDoubleRefProvider& rRef2,
219cdf0e10cSrcweir         bool& bCol, bool& bRow, bool& bTab)
220cdf0e10cSrcweir {
221cdf0e10cSrcweir     const bool bSameCols(lcl_checkRangeDimension(rRef1, rRef2, lcl_GetCol));
222cdf0e10cSrcweir     const bool bSameRows(lcl_checkRangeDimension(rRef1, rRef2, lcl_GetRow));
223cdf0e10cSrcweir     const bool bSameTabs(lcl_checkRangeDimension(rRef1, rRef2, lcl_GetTab));
224cdf0e10cSrcweir 
225cdf0e10cSrcweir     // Test if exactly two dimensions are equal
226cdf0e10cSrcweir     if (!(bSameCols ^ bSameRows ^ bSameTabs)
227cdf0e10cSrcweir             && (bSameCols || bSameRows || bSameTabs))
228cdf0e10cSrcweir     {
229cdf0e10cSrcweir         bCol = !bSameCols;
230cdf0e10cSrcweir         bRow = !bSameRows;
231cdf0e10cSrcweir         bTab = !bSameTabs;
232cdf0e10cSrcweir         return true;
233cdf0e10cSrcweir     }
234cdf0e10cSrcweir     return false;
235cdf0e10cSrcweir }
236cdf0e10cSrcweir 
237cdf0e10cSrcweir 
238cdf0e10cSrcweir /** Check if references in given reference list can possibly
239cdf0e10cSrcweir     form a range. To do that, two of their dimensions must be the same.
240cdf0e10cSrcweir  */
241cdf0e10cSrcweir static bool
lcl_checkRangeDimensions(const deque<ScToken * >::const_iterator aBegin,const deque<ScToken * >::const_iterator aEnd,bool & bCol,bool & bRow,bool & bTab)242cdf0e10cSrcweir lcl_checkRangeDimensions(
243cdf0e10cSrcweir         const deque<ScToken*>::const_iterator aBegin,
244cdf0e10cSrcweir         const deque<ScToken*>::const_iterator aEnd,
245cdf0e10cSrcweir         bool& bCol, bool& bRow, bool& bTab)
246cdf0e10cSrcweir {
247cdf0e10cSrcweir     deque<ScToken*>::const_iterator aCur(aBegin);
248cdf0e10cSrcweir     ++aCur;
249cdf0e10cSrcweir     const SingleDoubleRefProvider aRef(**aBegin);
250cdf0e10cSrcweir     bool bOk(false);
251cdf0e10cSrcweir     {
252cdf0e10cSrcweir         const SingleDoubleRefProvider aRefCur(**aCur);
253cdf0e10cSrcweir         bOk = lcl_checkRangeDimensions(aRef, aRefCur, bCol, bRow, bTab);
254cdf0e10cSrcweir     }
255cdf0e10cSrcweir     while (bOk && aCur != aEnd)
256cdf0e10cSrcweir     {
257cdf0e10cSrcweir         const SingleDoubleRefProvider aRefCur(**aCur);
258cdf0e10cSrcweir         bool bColTmp(false);
259cdf0e10cSrcweir         bool bRowTmp(false);
260cdf0e10cSrcweir         bool bTabTmp(false);
261cdf0e10cSrcweir         bOk = lcl_checkRangeDimensions(aRef, aRefCur, bColTmp, bRowTmp, bTabTmp);
262cdf0e10cSrcweir         bOk = bOk && (bCol == bColTmp && bRow == bRowTmp && bTab == bTabTmp);
263cdf0e10cSrcweir         ++aCur;
264cdf0e10cSrcweir     }
265cdf0e10cSrcweir 
266cdf0e10cSrcweir     if (bOk && aCur == aEnd)
267cdf0e10cSrcweir     {
268cdf0e10cSrcweir         bCol = bCol;
269cdf0e10cSrcweir         bRow = bRow;
270cdf0e10cSrcweir         bTab = bTab;
271cdf0e10cSrcweir         return true;
272cdf0e10cSrcweir     }
273cdf0e10cSrcweir     return false;
274cdf0e10cSrcweir }
275cdf0e10cSrcweir 
276cdf0e10cSrcweir 
277cdf0e10cSrcweir bool
lcl_lessReferenceBy(const ScToken * const pRef1,const ScToken * const pRef2,const DimensionSelector aWhich)278cdf0e10cSrcweir lcl_lessReferenceBy(
279cdf0e10cSrcweir         const ScToken* const pRef1, const ScToken* const pRef2,
280cdf0e10cSrcweir         const DimensionSelector aWhich)
281cdf0e10cSrcweir {
282cdf0e10cSrcweir     const SingleDoubleRefProvider rRef1(*pRef1);
283cdf0e10cSrcweir     const SingleDoubleRefProvider rRef2(*pRef2);
284cdf0e10cSrcweir     return aWhich(rRef1.Ref1) < aWhich(rRef2.Ref1);
285cdf0e10cSrcweir }
286cdf0e10cSrcweir 
287cdf0e10cSrcweir 
288cdf0e10cSrcweir /** Returns true if range denoted by token pRef2 starts immediately after
289cdf0e10cSrcweir     range denoted by token pRef1. Dimension, in which the comparison takes
290cdf0e10cSrcweir     place, is given by aWhich.
291cdf0e10cSrcweir  */
292cdf0e10cSrcweir bool
lcl_isImmediatelyFollowing(const ScToken * const pRef1,const ScToken * const pRef2,const DimensionSelector aWhich)293cdf0e10cSrcweir lcl_isImmediatelyFollowing(
294cdf0e10cSrcweir         const ScToken* const pRef1, const ScToken* const pRef2,
295cdf0e10cSrcweir         const DimensionSelector aWhich)
296cdf0e10cSrcweir {
297cdf0e10cSrcweir     const SingleDoubleRefProvider rRef1(*pRef1);
298cdf0e10cSrcweir     const SingleDoubleRefProvider rRef2(*pRef2);
299cdf0e10cSrcweir     return aWhich(rRef2.Ref1) - aWhich(rRef1.Ref2) == 1;
300cdf0e10cSrcweir }
301cdf0e10cSrcweir 
302cdf0e10cSrcweir 
303cdf0e10cSrcweir static bool
lcl_checkIfAdjacent(const deque<ScToken * > & rReferences,const DimensionSelector aWhich)304cdf0e10cSrcweir lcl_checkIfAdjacent(
305cdf0e10cSrcweir         const deque<ScToken*>& rReferences,
306cdf0e10cSrcweir         const DimensionSelector aWhich)
307cdf0e10cSrcweir {
308cdf0e10cSrcweir     typedef deque<ScToken*>::const_iterator Iter;
309cdf0e10cSrcweir     Iter aBegin(rReferences.begin());
310cdf0e10cSrcweir     Iter aEnd(rReferences.end());
311cdf0e10cSrcweir     Iter aBegin1(aBegin);
312cdf0e10cSrcweir     ++aBegin1, --aEnd;
313cdf0e10cSrcweir     return std::equal(
314cdf0e10cSrcweir             aBegin, aEnd, aBegin1,
315cdf0e10cSrcweir             boost::bind(lcl_isImmediatelyFollowing, _1, _2, aWhich));
316cdf0e10cSrcweir }
317cdf0e10cSrcweir 
318cdf0e10cSrcweir 
319cdf0e10cSrcweir static void
lcl_fillRangeFromRefList(const deque<ScToken * > & rReferences,ScRange & rRange)320cdf0e10cSrcweir lcl_fillRangeFromRefList(
321cdf0e10cSrcweir         const deque<ScToken*>& rReferences, ScRange& rRange)
322cdf0e10cSrcweir {
323cdf0e10cSrcweir     const ScSingleRefData aStart(
324cdf0e10cSrcweir             SingleDoubleRefProvider(*rReferences.front()).Ref1);
325cdf0e10cSrcweir     rRange.aStart.Set(aStart.nCol, aStart.nRow, aStart.nTab);
326cdf0e10cSrcweir     const ScSingleRefData aEnd(
327cdf0e10cSrcweir             SingleDoubleRefProvider(*rReferences.back()).Ref2);
328cdf0e10cSrcweir     rRange.aEnd.Set(aEnd.nCol, aEnd.nRow, aEnd.nTab);
329cdf0e10cSrcweir }
330cdf0e10cSrcweir 
331cdf0e10cSrcweir 
332cdf0e10cSrcweir static bool
lcl_refListFormsOneRange(const ScAddress & aPos,deque<ScToken * > & rReferences,ScRange & rRange)333cdf0e10cSrcweir lcl_refListFormsOneRange(
334cdf0e10cSrcweir         const ScAddress& aPos, deque<ScToken*>& rReferences,
335cdf0e10cSrcweir         ScRange& rRange)
336cdf0e10cSrcweir {
337cdf0e10cSrcweir     std::for_each(
338cdf0e10cSrcweir             rReferences.begin(), rReferences.end(),
339cdf0e10cSrcweir             bind(&ScToken::CalcAbsIfRel, _1, aPos))
340cdf0e10cSrcweir         ;
341cdf0e10cSrcweir     if (rReferences.size() == 1) {
342cdf0e10cSrcweir         lcl_fillRangeFromRefList(rReferences, rRange);
343cdf0e10cSrcweir         return true;
344cdf0e10cSrcweir     }
345cdf0e10cSrcweir 
346cdf0e10cSrcweir     bool bCell(false);
347cdf0e10cSrcweir     bool bRow(false);
348cdf0e10cSrcweir     bool bTab(false);
349cdf0e10cSrcweir     if (lcl_checkRangeDimensions(rReferences.begin(), rReferences.end(),
350cdf0e10cSrcweir             bCell, bRow, bTab))
351cdf0e10cSrcweir     {
352cdf0e10cSrcweir         DimensionSelector aWhich;
353cdf0e10cSrcweir         if (bCell)
354cdf0e10cSrcweir         {
355cdf0e10cSrcweir             aWhich = lcl_GetCol;
356cdf0e10cSrcweir         }
357cdf0e10cSrcweir         else if (bRow)
358cdf0e10cSrcweir         {
359cdf0e10cSrcweir             aWhich = lcl_GetRow;
360cdf0e10cSrcweir         }
361cdf0e10cSrcweir         else if (bTab)
362cdf0e10cSrcweir         {
363cdf0e10cSrcweir             aWhich = lcl_GetTab;
364cdf0e10cSrcweir         }
365cdf0e10cSrcweir         else
366cdf0e10cSrcweir         {
367cdf0e10cSrcweir             OSL_ENSURE(false, "lcl_checkRangeDimensions shouldn't allow that!");
368cdf0e10cSrcweir             aWhich = lcl_GetRow;    // initialize to avoid warning
369cdf0e10cSrcweir         }
370cdf0e10cSrcweir         // Sort the references by start of range
371cdf0e10cSrcweir         std::sort(rReferences.begin(), rReferences.end(),
372cdf0e10cSrcweir                 boost::bind(lcl_lessReferenceBy, _1, _2, aWhich));
373cdf0e10cSrcweir         if (lcl_checkIfAdjacent(rReferences, aWhich))
374cdf0e10cSrcweir         {
375cdf0e10cSrcweir             lcl_fillRangeFromRefList(rReferences, rRange);
376cdf0e10cSrcweir             return true;
377cdf0e10cSrcweir         }
378cdf0e10cSrcweir     }
379cdf0e10cSrcweir     return false;
380cdf0e10cSrcweir }
381cdf0e10cSrcweir 
382cdf0e10cSrcweir 
lcl_isReference(const FormulaToken & rToken)383cdf0e10cSrcweir bool lcl_isReference(const FormulaToken& rToken)
384cdf0e10cSrcweir {
385cdf0e10cSrcweir     return
386cdf0e10cSrcweir         rToken.GetType() == svSingleRef ||
387cdf0e10cSrcweir         rToken.GetType() == svDoubleRef;
388cdf0e10cSrcweir }
389cdf0e10cSrcweir 
390cdf0e10cSrcweir }
391cdf0e10cSrcweir 
IsEmpty()392cdf0e10cSrcweir sal_Bool ScFormulaCell::IsEmpty()
393cdf0e10cSrcweir {
394cdf0e10cSrcweir     if (IsDirtyOrInTableOpDirty() && pDocument->GetAutoCalc())
395cdf0e10cSrcweir         Interpret();
396cdf0e10cSrcweir     return aResult.GetCellResultType() == formula::svEmptyCell;
397cdf0e10cSrcweir }
398cdf0e10cSrcweir 
IsEmptyDisplayedAsString()399cdf0e10cSrcweir sal_Bool ScFormulaCell::IsEmptyDisplayedAsString()
400cdf0e10cSrcweir {
401cdf0e10cSrcweir     if (IsDirtyOrInTableOpDirty() && pDocument->GetAutoCalc())
402cdf0e10cSrcweir         Interpret();
403cdf0e10cSrcweir     return aResult.IsEmptyDisplayedAsString();
404cdf0e10cSrcweir }
405cdf0e10cSrcweir 
IsValue()406cdf0e10cSrcweir sal_Bool ScFormulaCell::IsValue()
407cdf0e10cSrcweir {
408cdf0e10cSrcweir     if (IsDirtyOrInTableOpDirty() && pDocument->GetAutoCalc())
409cdf0e10cSrcweir         Interpret();
410cdf0e10cSrcweir     return aResult.IsValue();
411cdf0e10cSrcweir }
412cdf0e10cSrcweir 
GetValue()413cdf0e10cSrcweir double ScFormulaCell::GetValue()
414cdf0e10cSrcweir {
415cdf0e10cSrcweir     if (IsDirtyOrInTableOpDirty() && pDocument->GetAutoCalc())
416cdf0e10cSrcweir         Interpret();
417cdf0e10cSrcweir     if ((!pCode->GetCodeError() || pCode->GetCodeError() == errDoubleRef) &&
418cdf0e10cSrcweir             !aResult.GetResultError())
419cdf0e10cSrcweir         return aResult.GetDouble();
420cdf0e10cSrcweir     return 0.0;
421cdf0e10cSrcweir }
422cdf0e10cSrcweir 
GetValueAlways()423cdf0e10cSrcweir double ScFormulaCell::GetValueAlways()
424cdf0e10cSrcweir {
425cdf0e10cSrcweir     // for goal seek: return result value even if error code is set
426cdf0e10cSrcweir 
427cdf0e10cSrcweir     if (IsDirtyOrInTableOpDirty() && pDocument->GetAutoCalc())
428cdf0e10cSrcweir         Interpret();
429cdf0e10cSrcweir     return aResult.GetDouble();
430cdf0e10cSrcweir }
431cdf0e10cSrcweir 
GetString(String & rString)432cdf0e10cSrcweir void ScFormulaCell::GetString( String& rString )
433cdf0e10cSrcweir {
434cdf0e10cSrcweir     if (IsDirtyOrInTableOpDirty() && pDocument->GetAutoCalc())
435cdf0e10cSrcweir         Interpret();
436cdf0e10cSrcweir     if ((!pCode->GetCodeError() || pCode->GetCodeError() == errDoubleRef) &&
437cdf0e10cSrcweir             !aResult.GetResultError())
438cdf0e10cSrcweir         rString = aResult.GetString();
439cdf0e10cSrcweir     else
440cdf0e10cSrcweir         rString.Erase();
441cdf0e10cSrcweir }
442cdf0e10cSrcweir 
GetMatrix()443cdf0e10cSrcweir const ScMatrix* ScFormulaCell::GetMatrix()
444cdf0e10cSrcweir {
445cdf0e10cSrcweir     if ( pDocument->GetAutoCalc() )
446cdf0e10cSrcweir     {
447*03eb9a00SHerbert Dürr         if( IsDirtyOrInTableOpDirty()
448cdf0e10cSrcweir         // Was stored !bDirty but an accompanying matrix cell was bDirty?
449*03eb9a00SHerbert Dürr         || (!bDirty && cMatrixFlag == MM_FORMULA && !aResult.GetMatrix().Is()))
450cdf0e10cSrcweir             Interpret();
451cdf0e10cSrcweir     }
452cdf0e10cSrcweir     return aResult.GetMatrix();
453cdf0e10cSrcweir }
454cdf0e10cSrcweir 
GetMatrixOrigin(ScAddress & rPos) const455cdf0e10cSrcweir sal_Bool ScFormulaCell::GetMatrixOrigin( ScAddress& rPos ) const
456cdf0e10cSrcweir {
457cdf0e10cSrcweir     switch ( cMatrixFlag )
458cdf0e10cSrcweir     {
459cdf0e10cSrcweir         case MM_FORMULA :
460cdf0e10cSrcweir             rPos = aPos;
461cdf0e10cSrcweir             return sal_True;
462cdf0e10cSrcweir //        break;
463cdf0e10cSrcweir         case MM_REFERENCE :
464cdf0e10cSrcweir         {
465cdf0e10cSrcweir             pCode->Reset();
466cdf0e10cSrcweir             ScToken* t = static_cast<ScToken*>(pCode->GetNextReferenceRPN());
467cdf0e10cSrcweir             if( t )
468cdf0e10cSrcweir             {
469cdf0e10cSrcweir                 ScSingleRefData& rRef = t->GetSingleRef();
470cdf0e10cSrcweir                 rRef.CalcAbsIfRel( aPos );
471cdf0e10cSrcweir                 if ( rRef.Valid() )
472cdf0e10cSrcweir                 {
473cdf0e10cSrcweir                     rPos.Set( rRef.nCol, rRef.nRow, rRef.nTab );
474cdf0e10cSrcweir                     return sal_True;
475cdf0e10cSrcweir                 }
476cdf0e10cSrcweir             }
477cdf0e10cSrcweir         }
478cdf0e10cSrcweir         break;
479cdf0e10cSrcweir     }
480cdf0e10cSrcweir     return sal_False;
481cdf0e10cSrcweir }
482cdf0e10cSrcweir 
483cdf0e10cSrcweir 
484cdf0e10cSrcweir /*
485cdf0e10cSrcweir  Edge-Values:
486cdf0e10cSrcweir 
487cdf0e10cSrcweir    8
488cdf0e10cSrcweir  4   16
489cdf0e10cSrcweir    2
490cdf0e10cSrcweir 
491cdf0e10cSrcweir  innerhalb: 1
492cdf0e10cSrcweir  ausserhalb: 0
493cdf0e10cSrcweir  (reserviert: offen: 32)
494cdf0e10cSrcweir  */
495cdf0e10cSrcweir 
GetMatrixEdge(ScAddress & rOrgPos)496cdf0e10cSrcweir sal_uInt16 ScFormulaCell::GetMatrixEdge( ScAddress& rOrgPos )
497cdf0e10cSrcweir {
498cdf0e10cSrcweir     switch ( cMatrixFlag )
499cdf0e10cSrcweir     {
500cdf0e10cSrcweir         case MM_FORMULA :
501cdf0e10cSrcweir         case MM_REFERENCE :
502cdf0e10cSrcweir         {
503cdf0e10cSrcweir             static SCCOL nC;
504cdf0e10cSrcweir             static SCROW nR;
505cdf0e10cSrcweir             ScAddress aOrg;
506cdf0e10cSrcweir             if ( !GetMatrixOrigin( aOrg ) )
507cdf0e10cSrcweir                 return 0;               // dumm gelaufen..
508cdf0e10cSrcweir             if ( aOrg != rOrgPos )
509cdf0e10cSrcweir             {   // erstes Mal oder andere Matrix als letztes Mal
510cdf0e10cSrcweir                 rOrgPos = aOrg;
511cdf0e10cSrcweir                 ScFormulaCell* pFCell;
512cdf0e10cSrcweir                 if ( cMatrixFlag == MM_REFERENCE )
513cdf0e10cSrcweir                     pFCell = (ScFormulaCell*) pDocument->GetCell( aOrg );
514cdf0e10cSrcweir                 else
515cdf0e10cSrcweir                     pFCell = this;      // this MM_FORMULA
516cdf0e10cSrcweir                 // this gibt's nur einmal, kein Vergleich auf pFCell==this
517cdf0e10cSrcweir                 if ( pFCell && pFCell->GetCellType() == CELLTYPE_FORMULA
518cdf0e10cSrcweir                   && pFCell->cMatrixFlag == MM_FORMULA )
519cdf0e10cSrcweir                 {
520cdf0e10cSrcweir                     pFCell->GetMatColsRows( nC, nR );
521cdf0e10cSrcweir                     if ( nC == 0 || nR == 0 )
522cdf0e10cSrcweir                     {   // aus altem Dokument geladen, neu erzeugen
523cdf0e10cSrcweir                         nC = 1;
524cdf0e10cSrcweir                         nR = 1;
525cdf0e10cSrcweir                         ScAddress aTmpOrg;
526cdf0e10cSrcweir                         ScBaseCell* pCell;
527cdf0e10cSrcweir                         ScAddress aAdr( aOrg );
528cdf0e10cSrcweir                         aAdr.IncCol();
529cdf0e10cSrcweir                         sal_Bool bCont = sal_True;
530cdf0e10cSrcweir                         do
531cdf0e10cSrcweir                         {
532cdf0e10cSrcweir                             pCell = pDocument->GetCell( aAdr );
533cdf0e10cSrcweir                             if ( pCell && pCell->GetCellType() == CELLTYPE_FORMULA
534cdf0e10cSrcweir                               && ((ScFormulaCell*)pCell)->cMatrixFlag == MM_REFERENCE
535cdf0e10cSrcweir                               && GetMatrixOrigin( aTmpOrg ) && aTmpOrg == aOrg )
536cdf0e10cSrcweir                             {
537cdf0e10cSrcweir                                 nC++;
538cdf0e10cSrcweir                                 aAdr.IncCol();
539cdf0e10cSrcweir                             }
540cdf0e10cSrcweir                             else
541cdf0e10cSrcweir                                 bCont = sal_False;
542cdf0e10cSrcweir                         } while ( bCont );
543cdf0e10cSrcweir                         aAdr = aOrg;
544cdf0e10cSrcweir                         aAdr.IncRow();
545cdf0e10cSrcweir                         bCont = sal_True;
546cdf0e10cSrcweir                         do
547cdf0e10cSrcweir                         {
548cdf0e10cSrcweir                             pCell = pDocument->GetCell( aAdr );
549cdf0e10cSrcweir                             if ( pCell && pCell->GetCellType() == CELLTYPE_FORMULA
550cdf0e10cSrcweir                               && ((ScFormulaCell*)pCell)->cMatrixFlag == MM_REFERENCE
551cdf0e10cSrcweir                               && GetMatrixOrigin( aTmpOrg ) && aTmpOrg == aOrg )
552cdf0e10cSrcweir                             {
553cdf0e10cSrcweir                                 nR++;
554cdf0e10cSrcweir                                 aAdr.IncRow();
555cdf0e10cSrcweir                             }
556cdf0e10cSrcweir                             else
557cdf0e10cSrcweir                                 bCont = sal_False;
558cdf0e10cSrcweir                         } while ( bCont );
559cdf0e10cSrcweir                         pFCell->SetMatColsRows( nC, nR );
560cdf0e10cSrcweir                     }
561cdf0e10cSrcweir                 }
562cdf0e10cSrcweir                 else
563cdf0e10cSrcweir                 {
564cdf0e10cSrcweir #ifdef DBG_UTIL
565cdf0e10cSrcweir                     String aTmp;
566cdf0e10cSrcweir                     ByteString aMsg( "broken Matrix, no MatFormula at origin, Pos: " );
567cdf0e10cSrcweir                     aPos.Format( aTmp, SCA_VALID_COL | SCA_VALID_ROW, pDocument );
568cdf0e10cSrcweir                     aMsg += ByteString( aTmp, RTL_TEXTENCODING_ASCII_US );
569cdf0e10cSrcweir                     aMsg += ", MatOrg: ";
570cdf0e10cSrcweir                     aOrg.Format( aTmp, SCA_VALID_COL | SCA_VALID_ROW, pDocument );
571cdf0e10cSrcweir                     aMsg += ByteString( aTmp, RTL_TEXTENCODING_ASCII_US );
572cdf0e10cSrcweir                     DBG_ERRORFILE( aMsg.GetBuffer() );
573cdf0e10cSrcweir #endif
574cdf0e10cSrcweir                     return 0;           // bad luck ...
575cdf0e10cSrcweir                 }
576cdf0e10cSrcweir             }
577cdf0e10cSrcweir             // here we are, healthy and clean, somewhere in between
578cdf0e10cSrcweir             SCsCOL dC = aPos.Col() - aOrg.Col();
579cdf0e10cSrcweir             SCsROW dR = aPos.Row() - aOrg.Row();
580cdf0e10cSrcweir             sal_uInt16 nEdges = 0;
581cdf0e10cSrcweir             if ( dC >= 0 && dR >= 0 && dC < nC && dR < nR )
582cdf0e10cSrcweir             {
583cdf0e10cSrcweir                 if ( dC == 0 )
584cdf0e10cSrcweir                     nEdges |= 4;            // linke Kante
585cdf0e10cSrcweir                 if ( dC+1 == nC )
586cdf0e10cSrcweir                     nEdges |= 16;           // rechte Kante
587cdf0e10cSrcweir                 if ( dR == 0 )
588cdf0e10cSrcweir                     nEdges |= 8;            // obere Kante
589cdf0e10cSrcweir                 if ( dR+1 == nR )
590cdf0e10cSrcweir                     nEdges |= 2;            // untere Kante
591cdf0e10cSrcweir                 if ( !nEdges )
592cdf0e10cSrcweir                     nEdges = 1;             // mittendrin
593cdf0e10cSrcweir             }
594cdf0e10cSrcweir #ifdef DBG_UTIL
595cdf0e10cSrcweir             else
596cdf0e10cSrcweir             {
597cdf0e10cSrcweir                 String aTmp;
598cdf0e10cSrcweir                 ByteString aMsg( "broken Matrix, Pos: " );
599cdf0e10cSrcweir                 aPos.Format( aTmp, SCA_VALID_COL | SCA_VALID_ROW, pDocument );
600cdf0e10cSrcweir                 aMsg += ByteString( aTmp, RTL_TEXTENCODING_ASCII_US );
601cdf0e10cSrcweir                 aMsg += ", MatOrg: ";
602cdf0e10cSrcweir                 aOrg.Format( aTmp, SCA_VALID_COL | SCA_VALID_ROW, pDocument );
603cdf0e10cSrcweir                 aMsg += ByteString( aTmp, RTL_TEXTENCODING_ASCII_US );
604cdf0e10cSrcweir                 aMsg += ", MatCols: ";
605cdf0e10cSrcweir                 aMsg += ByteString::CreateFromInt32( nC );
606cdf0e10cSrcweir                 aMsg += ", MatRows: ";
607cdf0e10cSrcweir                 aMsg += ByteString::CreateFromInt32( nR );
608cdf0e10cSrcweir                 aMsg += ", DiffCols: ";
609cdf0e10cSrcweir                 aMsg += ByteString::CreateFromInt32( dC );
610cdf0e10cSrcweir                 aMsg += ", DiffRows: ";
611cdf0e10cSrcweir                 aMsg += ByteString::CreateFromInt32( dR );
612cdf0e10cSrcweir                 DBG_ERRORFILE( aMsg.GetBuffer() );
613cdf0e10cSrcweir             }
614cdf0e10cSrcweir #endif
615cdf0e10cSrcweir             return nEdges;
616cdf0e10cSrcweir //            break;
617cdf0e10cSrcweir         }
618cdf0e10cSrcweir         default:
619cdf0e10cSrcweir             return 0;
620cdf0e10cSrcweir     }
621cdf0e10cSrcweir }
622cdf0e10cSrcweir 
GetErrCode()623cdf0e10cSrcweir sal_uInt16 ScFormulaCell::GetErrCode()
624cdf0e10cSrcweir {
625cdf0e10cSrcweir     if (IsDirtyOrInTableOpDirty() && pDocument->GetAutoCalc())
626cdf0e10cSrcweir         Interpret();
627cdf0e10cSrcweir     /* FIXME: If ScTokenArray::SetCodeError() was really only for code errors
628cdf0e10cSrcweir      * and not also abused for signaling other error conditions we could bail
629cdf0e10cSrcweir      * out even before attempting to interpret broken code. */
630cdf0e10cSrcweir     sal_uInt16 nErr =  pCode->GetCodeError();
631cdf0e10cSrcweir     if (nErr)
632cdf0e10cSrcweir         return nErr;
633cdf0e10cSrcweir     return aResult.GetResultError();
634cdf0e10cSrcweir }
635cdf0e10cSrcweir 
GetRawError()636cdf0e10cSrcweir sal_uInt16 ScFormulaCell::GetRawError()
637cdf0e10cSrcweir {
638cdf0e10cSrcweir     sal_uInt16 nErr =  pCode->GetCodeError();
639cdf0e10cSrcweir     if (nErr)
640cdf0e10cSrcweir         return nErr;
641cdf0e10cSrcweir     return aResult.GetResultError();
642cdf0e10cSrcweir }
643cdf0e10cSrcweir 
HasOneReference(ScRange & r) const644cdf0e10cSrcweir sal_Bool ScFormulaCell::HasOneReference( ScRange& r ) const
645cdf0e10cSrcweir {
646cdf0e10cSrcweir     pCode->Reset();
647cdf0e10cSrcweir     ScToken* p = static_cast<ScToken*>(pCode->GetNextReferenceRPN());
648cdf0e10cSrcweir     if( p && !pCode->GetNextReferenceRPN() )        // nur eine!
649cdf0e10cSrcweir     {
650cdf0e10cSrcweir         p->CalcAbsIfRel( aPos );
651cdf0e10cSrcweir         SingleDoubleRefProvider aProv( *p );
652cdf0e10cSrcweir         r.aStart.Set( aProv.Ref1.nCol,
653cdf0e10cSrcweir                       aProv.Ref1.nRow,
654cdf0e10cSrcweir                       aProv.Ref1.nTab );
655cdf0e10cSrcweir         r.aEnd.Set( aProv.Ref2.nCol,
656cdf0e10cSrcweir                     aProv.Ref2.nRow,
657cdf0e10cSrcweir                     aProv.Ref2.nTab );
658cdf0e10cSrcweir         return sal_True;
659cdf0e10cSrcweir     }
660cdf0e10cSrcweir     else
661cdf0e10cSrcweir         return sal_False;
662cdf0e10cSrcweir }
663cdf0e10cSrcweir 
664cdf0e10cSrcweir bool
HasRefListExpressibleAsOneReference(ScRange & rRange) const665cdf0e10cSrcweir ScFormulaCell::HasRefListExpressibleAsOneReference(ScRange& rRange) const
666cdf0e10cSrcweir {
667cdf0e10cSrcweir     /* If there appears just one reference in the formula, it's the same
668cdf0e10cSrcweir        as HasOneReference(). If there are more of them, they can denote
669cdf0e10cSrcweir        one range if they are (sole) arguments of one function.
670cdf0e10cSrcweir        Union of these references must form one range and their
671cdf0e10cSrcweir        intersection must be empty set.
672cdf0e10cSrcweir     */
673cdf0e10cSrcweir 
674cdf0e10cSrcweir     // Detect the simple case of exactly one reference in advance without all
675cdf0e10cSrcweir     // overhead.
676cdf0e10cSrcweir     // #i107741# Doing so actually makes outlines using SUBTOTAL(x;reference)
677cdf0e10cSrcweir     // work again, where the function does not have only references.
678cdf0e10cSrcweir     if (HasOneReference( rRange))
679cdf0e10cSrcweir         return true;
680cdf0e10cSrcweir 
681cdf0e10cSrcweir     pCode->Reset();
682cdf0e10cSrcweir     // Get first reference, if any
683cdf0e10cSrcweir     ScToken* const pFirstReference(
684cdf0e10cSrcweir             dynamic_cast<ScToken*>(pCode->GetNextReferenceRPN()));
685cdf0e10cSrcweir     if (pFirstReference)
686cdf0e10cSrcweir     {
687cdf0e10cSrcweir         // Collect all consecutive references, starting by the one
688cdf0e10cSrcweir         // already found
689cdf0e10cSrcweir         std::deque<ScToken*> aReferences;
690cdf0e10cSrcweir         aReferences.push_back(pFirstReference);
691cdf0e10cSrcweir         FormulaToken* pToken(pCode->NextRPN());
692cdf0e10cSrcweir         FormulaToken* pFunction(0);
693cdf0e10cSrcweir         while (pToken)
694cdf0e10cSrcweir         {
695cdf0e10cSrcweir             if (lcl_isReference(*pToken))
696cdf0e10cSrcweir             {
697cdf0e10cSrcweir                 aReferences.push_back(dynamic_cast<ScToken*>(pToken));
698cdf0e10cSrcweir                 pToken = pCode->NextRPN();
699cdf0e10cSrcweir             }
700cdf0e10cSrcweir             else
701cdf0e10cSrcweir             {
702cdf0e10cSrcweir                 if (pToken->IsFunction())
703cdf0e10cSrcweir                 {
704cdf0e10cSrcweir                     pFunction = pToken;
705cdf0e10cSrcweir                 }
706cdf0e10cSrcweir                 break;
707cdf0e10cSrcweir             }
708cdf0e10cSrcweir         }
709cdf0e10cSrcweir         if (pFunction && !pCode->GetNextReferenceRPN()
710cdf0e10cSrcweir                 && (pFunction->GetParamCount() == aReferences.size()))
711cdf0e10cSrcweir         {
712cdf0e10cSrcweir             return lcl_refListFormsOneRange(aPos, aReferences, rRange);
713cdf0e10cSrcweir         }
714cdf0e10cSrcweir     }
715cdf0e10cSrcweir     return false;
716cdf0e10cSrcweir }
717cdf0e10cSrcweir 
HasRelNameReference() const718cdf0e10cSrcweir sal_Bool ScFormulaCell::HasRelNameReference() const
719cdf0e10cSrcweir {
720cdf0e10cSrcweir     pCode->Reset();
721cdf0e10cSrcweir     ScToken* t;
722cdf0e10cSrcweir     while ( ( t = static_cast<ScToken*>(pCode->GetNextReferenceRPN()) ) != NULL )
723cdf0e10cSrcweir     {
724cdf0e10cSrcweir         if ( t->GetSingleRef().IsRelName() ||
725cdf0e10cSrcweir                 (t->GetType() == formula::svDoubleRef &&
726cdf0e10cSrcweir                 t->GetDoubleRef().Ref2.IsRelName()) )
727cdf0e10cSrcweir             return sal_True;
728cdf0e10cSrcweir     }
729cdf0e10cSrcweir     return sal_False;
730cdf0e10cSrcweir }
731cdf0e10cSrcweir 
HasColRowName() const732cdf0e10cSrcweir sal_Bool ScFormulaCell::HasColRowName() const
733cdf0e10cSrcweir {
734cdf0e10cSrcweir     pCode->Reset();
735cdf0e10cSrcweir     return (pCode->GetNextColRowName() != NULL);
736cdf0e10cSrcweir }
737cdf0e10cSrcweir 
UpdateReference(UpdateRefMode eUpdateRefMode,const ScRange & r,SCsCOL nDx,SCsROW nDy,SCsTAB nDz,ScDocument * pUndoDoc,const ScAddress * pUndoCellPos)738cdf0e10cSrcweir void ScFormulaCell::UpdateReference(UpdateRefMode eUpdateRefMode,
739cdf0e10cSrcweir                                     const ScRange& r,
740cdf0e10cSrcweir                                     SCsCOL nDx, SCsROW nDy, SCsTAB nDz,
741cdf0e10cSrcweir                                     ScDocument* pUndoDoc, const ScAddress* pUndoCellPos )
742cdf0e10cSrcweir {
743cdf0e10cSrcweir     SCCOL nCol1 = r.aStart.Col();
744cdf0e10cSrcweir     SCROW nRow1 = r.aStart.Row();
745cdf0e10cSrcweir     SCTAB nTab1 = r.aStart.Tab();
746cdf0e10cSrcweir     SCCOL nCol2 = r.aEnd.Col();
747cdf0e10cSrcweir     SCROW nRow2 = r.aEnd.Row();
748cdf0e10cSrcweir     SCTAB nTab2 = r.aEnd.Tab();
749cdf0e10cSrcweir     SCCOL nCol = aPos.Col();
750cdf0e10cSrcweir     SCROW nRow = aPos.Row();
751cdf0e10cSrcweir     SCTAB nTab = aPos.Tab();
752cdf0e10cSrcweir     ScAddress aUndoPos( aPos );         // position for undo cell in pUndoDoc
753cdf0e10cSrcweir     if ( pUndoCellPos )
754cdf0e10cSrcweir         aUndoPos = *pUndoCellPos;
755cdf0e10cSrcweir     ScAddress aOldPos( aPos );
756cdf0e10cSrcweir //  sal_Bool bPosChanged = sal_False;           // ob diese Zelle bewegt wurde
757cdf0e10cSrcweir     sal_Bool bIsInsert = sal_False;
758cdf0e10cSrcweir     if (eUpdateRefMode == URM_INSDEL)
759cdf0e10cSrcweir     {
760cdf0e10cSrcweir         bIsInsert = (nDx >= 0 && nDy >= 0 && nDz >= 0);
761cdf0e10cSrcweir         if ( nDx && nRow >= nRow1 && nRow <= nRow2 &&
762cdf0e10cSrcweir             nTab >= nTab1 && nTab <= nTab2 )
763cdf0e10cSrcweir         {
764cdf0e10cSrcweir             if (nCol >= nCol1)
765cdf0e10cSrcweir             {
766cdf0e10cSrcweir                 nCol = sal::static_int_cast<SCCOL>( nCol + nDx );
767cdf0e10cSrcweir                 if ((SCsCOL) nCol < 0)
768cdf0e10cSrcweir                     nCol = 0;
769cdf0e10cSrcweir                 else if ( nCol > MAXCOL )
770cdf0e10cSrcweir                     nCol = MAXCOL;
771cdf0e10cSrcweir                 aPos.SetCol( nCol );
772cdf0e10cSrcweir //              bPosChanged = sal_True;
773cdf0e10cSrcweir             }
774cdf0e10cSrcweir         }
775cdf0e10cSrcweir         if ( nDy && nCol >= nCol1 && nCol <= nCol2 &&
776cdf0e10cSrcweir             nTab >= nTab1 && nTab <= nTab2 )
777cdf0e10cSrcweir         {
778cdf0e10cSrcweir             if (nRow >= nRow1)
779cdf0e10cSrcweir             {
780cdf0e10cSrcweir                 nRow = sal::static_int_cast<SCROW>( nRow + nDy );
781cdf0e10cSrcweir                 if ((SCsROW) nRow < 0)
782cdf0e10cSrcweir                     nRow = 0;
783cdf0e10cSrcweir                 else if ( nRow > MAXROW )
784cdf0e10cSrcweir                     nRow = MAXROW;
785cdf0e10cSrcweir                 aPos.SetRow( nRow );
786cdf0e10cSrcweir //              bPosChanged = sal_True;
787cdf0e10cSrcweir             }
788cdf0e10cSrcweir         }
789cdf0e10cSrcweir         if ( nDz && nCol >= nCol1 && nCol <= nCol2 &&
790cdf0e10cSrcweir             nRow >= nRow1 && nRow <= nRow2 )
791cdf0e10cSrcweir         {
792cdf0e10cSrcweir             if (nTab >= nTab1)
793cdf0e10cSrcweir             {
794cdf0e10cSrcweir                 SCTAB nMaxTab = pDocument->GetTableCount() - 1;
795cdf0e10cSrcweir                 nTab = sal::static_int_cast<SCTAB>( nTab + nDz );
796cdf0e10cSrcweir                 if ((SCsTAB) nTab < 0)
797cdf0e10cSrcweir                     nTab = 0;
798cdf0e10cSrcweir                 else if ( nTab > nMaxTab )
799cdf0e10cSrcweir                     nTab = nMaxTab;
800cdf0e10cSrcweir                 aPos.SetTab( nTab );
801cdf0e10cSrcweir //              bPosChanged = sal_True;
802cdf0e10cSrcweir             }
803cdf0e10cSrcweir         }
804cdf0e10cSrcweir     }
805cdf0e10cSrcweir     else if ( r.In( aPos ) )
806cdf0e10cSrcweir     {
807cdf0e10cSrcweir         aOldPos.Set( nCol - nDx, nRow - nDy, nTab - nDz );
808cdf0e10cSrcweir //      bPosChanged = sal_True;
809cdf0e10cSrcweir     }
810cdf0e10cSrcweir 
811cdf0e10cSrcweir     sal_Bool bHasRefs = sal_False;
812cdf0e10cSrcweir     sal_Bool bHasColRowNames = sal_False;
813cdf0e10cSrcweir     sal_Bool bOnRefMove = sal_False;
814cdf0e10cSrcweir     if ( !pDocument->IsClipOrUndo() )
815cdf0e10cSrcweir     {
816cdf0e10cSrcweir         pCode->Reset();
817cdf0e10cSrcweir         bHasRefs = (pCode->GetNextReferenceRPN() != NULL);
818cdf0e10cSrcweir         if ( !bHasRefs || eUpdateRefMode == URM_COPY )
819cdf0e10cSrcweir         {
820cdf0e10cSrcweir             pCode->Reset();
821cdf0e10cSrcweir             bHasColRowNames = (pCode->GetNextColRowName() != NULL);
822cdf0e10cSrcweir             bHasRefs = bHasRefs || bHasColRowNames;
823cdf0e10cSrcweir         }
824cdf0e10cSrcweir         bOnRefMove = pCode->IsRecalcModeOnRefMove();
825cdf0e10cSrcweir     }
826cdf0e10cSrcweir     if( bHasRefs || bOnRefMove )
827cdf0e10cSrcweir     {
828cdf0e10cSrcweir         ScTokenArray* pOld = pUndoDoc ? pCode->Clone() : NULL;
829cdf0e10cSrcweir         sal_Bool bValChanged;
830cdf0e10cSrcweir         ScRangeData* pRangeData;
831cdf0e10cSrcweir         sal_Bool bRangeModified;            // any range, not only shared formula
832cdf0e10cSrcweir         sal_Bool bRefSizeChanged;
833cdf0e10cSrcweir         if ( bHasRefs )
834cdf0e10cSrcweir         {
835cdf0e10cSrcweir             ScCompiler aComp(pDocument, aPos, *pCode);
836cdf0e10cSrcweir             aComp.SetGrammar(pDocument->GetGrammar());
837cdf0e10cSrcweir             pRangeData = aComp.UpdateReference(eUpdateRefMode, aOldPos, r,
838cdf0e10cSrcweir                                              nDx, nDy, nDz,
839cdf0e10cSrcweir                                              bValChanged, bRefSizeChanged);
840cdf0e10cSrcweir             bRangeModified = aComp.HasModifiedRange();
841cdf0e10cSrcweir         }
842cdf0e10cSrcweir         else
843cdf0e10cSrcweir         {
844cdf0e10cSrcweir             bValChanged = sal_False;
845cdf0e10cSrcweir             pRangeData = NULL;
846cdf0e10cSrcweir             bRangeModified = sal_False;
847cdf0e10cSrcweir             bRefSizeChanged = sal_False;
848cdf0e10cSrcweir         }
849cdf0e10cSrcweir         if ( bOnRefMove )
850cdf0e10cSrcweir             bOnRefMove = (bValChanged || (aPos != aOldPos));
851cdf0e10cSrcweir             // Cell may reference itself, e.g. ocColumn, ocRow without parameter
852cdf0e10cSrcweir 
853cdf0e10cSrcweir         sal_Bool bColRowNameCompile, bHasRelName, bNewListening, bInDeleteUndo;
854cdf0e10cSrcweir         if ( bHasRefs )
855cdf0e10cSrcweir         {
856cdf0e10cSrcweir             // Upon Insert ColRowNames have to be recompiled in case the
857cdf0e10cSrcweir             // insertion occurs right in front of the range.
858cdf0e10cSrcweir             bColRowNameCompile =
859cdf0e10cSrcweir                 (eUpdateRefMode == URM_INSDEL && (nDx > 0 || nDy > 0));
860cdf0e10cSrcweir             if ( bColRowNameCompile )
861cdf0e10cSrcweir             {
862cdf0e10cSrcweir                 bColRowNameCompile = sal_False;
863cdf0e10cSrcweir                 ScToken* t;
864cdf0e10cSrcweir                 ScRangePairList* pColList = pDocument->GetColNameRanges();
865cdf0e10cSrcweir                 ScRangePairList* pRowList = pDocument->GetRowNameRanges();
866cdf0e10cSrcweir                 pCode->Reset();
867cdf0e10cSrcweir                 while ( !bColRowNameCompile && (t = static_cast<ScToken*>(pCode->GetNextColRowName())) != NULL )
868cdf0e10cSrcweir                 {
869cdf0e10cSrcweir                     ScSingleRefData& rRef = t->GetSingleRef();
870cdf0e10cSrcweir                     if ( nDy > 0 && rRef.IsColRel() )
871cdf0e10cSrcweir                     {   // ColName
872cdf0e10cSrcweir                         rRef.CalcAbsIfRel( aPos );
873cdf0e10cSrcweir                         ScAddress aAdr( rRef.nCol, rRef.nRow, rRef.nTab );
874cdf0e10cSrcweir                         ScRangePair* pR = pColList->Find( aAdr );
875cdf0e10cSrcweir                         if ( pR )
876cdf0e10cSrcweir                         {   // definiert
877cdf0e10cSrcweir                             if ( pR->GetRange(1).aStart.Row() == nRow1 )
878cdf0e10cSrcweir                                 bColRowNameCompile = sal_True;
879cdf0e10cSrcweir                         }
880cdf0e10cSrcweir                         else
881cdf0e10cSrcweir                         {   // on the fly
882cdf0e10cSrcweir                             if ( rRef.nRow + 1 == nRow1 )
883cdf0e10cSrcweir                                 bColRowNameCompile = sal_True;
884cdf0e10cSrcweir                         }
885cdf0e10cSrcweir                     }
886cdf0e10cSrcweir                     if ( nDx > 0 && rRef.IsRowRel() )
887cdf0e10cSrcweir                     {   // RowName
888cdf0e10cSrcweir                         rRef.CalcAbsIfRel( aPos );
889cdf0e10cSrcweir                         ScAddress aAdr( rRef.nCol, rRef.nRow, rRef.nTab );
890cdf0e10cSrcweir                         ScRangePair* pR = pRowList->Find( aAdr );
891cdf0e10cSrcweir                         if ( pR )
892cdf0e10cSrcweir                         {   // definiert
893cdf0e10cSrcweir                             if ( pR->GetRange(1).aStart.Col() == nCol1 )
894cdf0e10cSrcweir                                 bColRowNameCompile = sal_True;
895cdf0e10cSrcweir                         }
896cdf0e10cSrcweir                         else
897cdf0e10cSrcweir                         {   // on the fly
898cdf0e10cSrcweir                             if ( rRef.nCol + 1 == nCol1 )
899cdf0e10cSrcweir                                 bColRowNameCompile = sal_True;
900cdf0e10cSrcweir                         }
901cdf0e10cSrcweir                     }
902cdf0e10cSrcweir                 }
903cdf0e10cSrcweir             }
904cdf0e10cSrcweir             else if ( eUpdateRefMode == URM_MOVE )
905cdf0e10cSrcweir             {   // bei Move/D&D neu kompilieren wenn ColRowName verschoben wurde
906cdf0e10cSrcweir                 // oder diese Zelle auf einen zeigt und verschoben wurde
907cdf0e10cSrcweir                 bColRowNameCompile = bCompile;      // evtl. aus Copy-ctor
908cdf0e10cSrcweir                 if ( !bColRowNameCompile )
909cdf0e10cSrcweir                 {
910cdf0e10cSrcweir                     sal_Bool bMoved = (aPos != aOldPos);
911cdf0e10cSrcweir                     pCode->Reset();
912cdf0e10cSrcweir                     ScToken* t = static_cast<ScToken*>(pCode->GetNextColRowName());
913cdf0e10cSrcweir                     if ( t && bMoved )
914cdf0e10cSrcweir                         bColRowNameCompile = sal_True;
915cdf0e10cSrcweir                     while ( t && !bColRowNameCompile )
916cdf0e10cSrcweir                     {
917cdf0e10cSrcweir                         ScSingleRefData& rRef = t->GetSingleRef();
918cdf0e10cSrcweir                         rRef.CalcAbsIfRel( aPos );
919cdf0e10cSrcweir                         if ( rRef.Valid() )
920cdf0e10cSrcweir                         {
921cdf0e10cSrcweir                             ScAddress aAdr( rRef.nCol, rRef.nRow, rRef.nTab );
922cdf0e10cSrcweir                             if ( r.In( aAdr ) )
923cdf0e10cSrcweir                                 bColRowNameCompile = sal_True;
924cdf0e10cSrcweir                         }
925cdf0e10cSrcweir                         t = static_cast<ScToken*>(pCode->GetNextColRowName());
926cdf0e10cSrcweir                     }
927cdf0e10cSrcweir                 }
928cdf0e10cSrcweir             }
929cdf0e10cSrcweir             else if ( eUpdateRefMode == URM_COPY && bHasColRowNames && bValChanged )
930cdf0e10cSrcweir             {
931cdf0e10cSrcweir                 bColRowNameCompile = sal_True;
932cdf0e10cSrcweir             }
933cdf0e10cSrcweir             ScChangeTrack* pChangeTrack = pDocument->GetChangeTrack();
934cdf0e10cSrcweir             if ( pChangeTrack && pChangeTrack->IsInDeleteUndo() )
935cdf0e10cSrcweir                 bInDeleteUndo = sal_True;
936cdf0e10cSrcweir             else
937cdf0e10cSrcweir                 bInDeleteUndo = sal_False;
938cdf0e10cSrcweir             // RelNameRefs are always moved
939cdf0e10cSrcweir             bHasRelName = HasRelNameReference();
940cdf0e10cSrcweir             // Reference changed and new listening needed?
941cdf0e10cSrcweir             // Except in Insert/Delete without specialties.
942cdf0e10cSrcweir             bNewListening = (bRangeModified || pRangeData || bColRowNameCompile
943cdf0e10cSrcweir                     || (bValChanged && (eUpdateRefMode != URM_INSDEL ||
944cdf0e10cSrcweir                             bInDeleteUndo || bRefSizeChanged)) ||
945cdf0e10cSrcweir                     (bHasRelName && eUpdateRefMode != URM_COPY))
946cdf0e10cSrcweir                 // #i36299# Don't duplicate action during cut&paste / drag&drop
947cdf0e10cSrcweir                 // on a cell in the range moved, start/end listeners is done
948cdf0e10cSrcweir                 // via ScDocument::DeleteArea() and ScDocument::CopyFromClip().
949cdf0e10cSrcweir                 && !(eUpdateRefMode == URM_MOVE &&
950cdf0e10cSrcweir                         pDocument->IsInsertingFromOtherDoc() && r.In(aPos));
951cdf0e10cSrcweir             if ( bNewListening )
952cdf0e10cSrcweir                 EndListeningTo( pDocument, pOld, aOldPos );
953cdf0e10cSrcweir         }
954cdf0e10cSrcweir         else
955cdf0e10cSrcweir         {
956cdf0e10cSrcweir             bColRowNameCompile = bHasRelName = bNewListening = bInDeleteUndo =
957cdf0e10cSrcweir                 sal_False;
958cdf0e10cSrcweir         }
959cdf0e10cSrcweir 
960cdf0e10cSrcweir         sal_Bool bNeedDirty;
961cdf0e10cSrcweir         // NeedDirty bei Aenderungen ausser Copy und Move/Insert ohne RelNames
962cdf0e10cSrcweir         if ( bRangeModified || pRangeData || bColRowNameCompile ||
963cdf0e10cSrcweir                 (bValChanged && eUpdateRefMode != URM_COPY &&
964cdf0e10cSrcweir                  (eUpdateRefMode != URM_MOVE || bHasRelName) &&
965cdf0e10cSrcweir                  (!bIsInsert || bHasRelName || bInDeleteUndo ||
966cdf0e10cSrcweir                   bRefSizeChanged)) || bOnRefMove)
967cdf0e10cSrcweir             bNeedDirty = sal_True;
968cdf0e10cSrcweir         else
969cdf0e10cSrcweir             bNeedDirty = sal_False;
970cdf0e10cSrcweir         if (pUndoDoc && (bValChanged || pRangeData || bOnRefMove))
971cdf0e10cSrcweir         {
972cdf0e10cSrcweir             //  Copy the cell to aUndoPos, which is its current position in the document,
973cdf0e10cSrcweir             //  so this works when UpdateReference is called before moving the cells
974cdf0e10cSrcweir             //  (InsertCells/DeleteCells - aPos is changed above) as well as when UpdateReference
975cdf0e10cSrcweir             //  is called after moving the cells (MoveBlock/PasteFromClip - aOldPos is changed).
976cdf0e10cSrcweir 
977cdf0e10cSrcweir             // If there is already a formula cell in the undo document, don't overwrite it,
978cdf0e10cSrcweir             // the first (oldest) is the important cell.
979cdf0e10cSrcweir             if ( pUndoDoc->GetCellType( aUndoPos ) != CELLTYPE_FORMULA )
980cdf0e10cSrcweir             {
981cdf0e10cSrcweir                 ScFormulaCell* pFCell = new ScFormulaCell( pUndoDoc, aUndoPos,
982cdf0e10cSrcweir                         pOld, eTempGrammar, cMatrixFlag );
983cdf0e10cSrcweir                 pFCell->aResult.SetToken( NULL);  // to recognize it as changed later (Cut/Paste!)
984cdf0e10cSrcweir                 pUndoDoc->PutCell( aUndoPos, pFCell );
985cdf0e10cSrcweir             }
986cdf0e10cSrcweir         }
987cdf0e10cSrcweir         // #i116833# If the formula is changed, always invalidate the stream (even if the result is the same).
988cdf0e10cSrcweir         // If the formula is moved, the change is recognized separately.
989cdf0e10cSrcweir         if (bValChanged && pDocument->IsStreamValid(aPos.Tab()))
990cdf0e10cSrcweir             pDocument->SetStreamValid(aPos.Tab(), sal_False);
991cdf0e10cSrcweir         bValChanged = sal_False;
992cdf0e10cSrcweir         if ( pRangeData )
993cdf0e10cSrcweir         {   // Replace shared formula with own formula
994cdf0e10cSrcweir             pDocument->RemoveFromFormulaTree( this );   // update formula count
995cdf0e10cSrcweir             delete pCode;
996cdf0e10cSrcweir             pCode = pRangeData->GetCode()->Clone();
997cdf0e10cSrcweir             // #i18937# #i110008# call MoveRelWrap, but with the old position
998cdf0e10cSrcweir             ScCompiler::MoveRelWrap(*pCode, pDocument, aOldPos, pRangeData->GetMaxCol(), pRangeData->GetMaxRow());
999cdf0e10cSrcweir             ScCompiler aComp2(pDocument, aPos, *pCode);
1000cdf0e10cSrcweir             aComp2.SetGrammar(pDocument->GetGrammar());
1001cdf0e10cSrcweir             aComp2.UpdateSharedFormulaReference( eUpdateRefMode, aOldPos, r,
1002cdf0e10cSrcweir                 nDx, nDy, nDz );
1003cdf0e10cSrcweir             bValChanged = sal_True;
1004cdf0e10cSrcweir             bNeedDirty = sal_True;
1005cdf0e10cSrcweir         }
1006cdf0e10cSrcweir         if ( ( bCompile = (bCompile || bValChanged || bRangeModified || bColRowNameCompile) ) != 0 )
1007cdf0e10cSrcweir         {
1008cdf0e10cSrcweir             CompileTokenArray( bNewListening ); // kein Listening
1009cdf0e10cSrcweir             bNeedDirty = sal_True;
1010cdf0e10cSrcweir         }
1011cdf0e10cSrcweir         if ( !bInDeleteUndo )
1012cdf0e10cSrcweir         {   // In ChangeTrack Delete-Reject listeners are established in
1013cdf0e10cSrcweir             // InsertCol/InsertRow
1014cdf0e10cSrcweir             if ( bNewListening )
1015cdf0e10cSrcweir             {
1016cdf0e10cSrcweir                 if ( eUpdateRefMode == URM_INSDEL )
1017cdf0e10cSrcweir                 {
1018cdf0e10cSrcweir                     // Inserts/Deletes re-establish listeners after all
1019cdf0e10cSrcweir                     // UpdateReference calls.
1020cdf0e10cSrcweir                     // All replaced shared formula listeners have to be
1021cdf0e10cSrcweir                     // established after an Insert or Delete. Do nothing here.
1022cdf0e10cSrcweir                     SetNeedsListening( sal_True);
1023cdf0e10cSrcweir                 }
1024cdf0e10cSrcweir                 else
1025cdf0e10cSrcweir                     StartListeningTo( pDocument );
1026cdf0e10cSrcweir             }
1027cdf0e10cSrcweir         }
1028cdf0e10cSrcweir         if ( bNeedDirty && (!(eUpdateRefMode == URM_INSDEL && bHasRelName) || pRangeData) )
1029cdf0e10cSrcweir         {   // Referenzen abgeschnitten, ungueltig o.ae.?
1030cdf0e10cSrcweir             sal_Bool bOldAutoCalc = pDocument->GetAutoCalc();
1031cdf0e10cSrcweir             // kein Interpret in SubMinimalRecalc wegen evtl. falscher Referenzen
1032cdf0e10cSrcweir             pDocument->SetAutoCalc( sal_False );
1033cdf0e10cSrcweir             SetDirty();
1034cdf0e10cSrcweir             pDocument->SetAutoCalc( bOldAutoCalc );
1035cdf0e10cSrcweir         }
1036cdf0e10cSrcweir 
1037cdf0e10cSrcweir         delete pOld;
1038cdf0e10cSrcweir     }
1039cdf0e10cSrcweir }
1040cdf0e10cSrcweir 
UpdateInsertTab(SCTAB nTable)1041cdf0e10cSrcweir void ScFormulaCell::UpdateInsertTab(SCTAB nTable)
1042cdf0e10cSrcweir {
1043cdf0e10cSrcweir     sal_Bool bPosChanged = ( aPos.Tab() >= nTable ? sal_True : sal_False );
1044cdf0e10cSrcweir     pCode->Reset();
1045cdf0e10cSrcweir     if( pCode->GetNextReferenceRPN() && !pDocument->IsClipOrUndo() )
1046cdf0e10cSrcweir     {
1047cdf0e10cSrcweir         EndListeningTo( pDocument );
1048cdf0e10cSrcweir         // IncTab _nach_ EndListeningTo und _vor_ Compiler UpdateInsertTab !
1049cdf0e10cSrcweir         if ( bPosChanged )
1050cdf0e10cSrcweir             aPos.IncTab();
1051cdf0e10cSrcweir         ScRangeData* pRangeData;
1052cdf0e10cSrcweir         ScCompiler aComp(pDocument, aPos, *pCode);
1053cdf0e10cSrcweir         aComp.SetGrammar(pDocument->GetGrammar());
1054cdf0e10cSrcweir         pRangeData = aComp.UpdateInsertTab( nTable, sal_False );
1055cdf0e10cSrcweir         if (pRangeData)                     // Shared Formula gegen echte Formel
1056cdf0e10cSrcweir         {                                   // austauschen
1057cdf0e10cSrcweir             sal_Bool bRefChanged;
1058cdf0e10cSrcweir             pDocument->RemoveFromFormulaTree( this );   // update formula count
1059cdf0e10cSrcweir             delete pCode;
1060cdf0e10cSrcweir             pCode = new ScTokenArray( *pRangeData->GetCode() );
1061cdf0e10cSrcweir             ScCompiler aComp2(pDocument, aPos, *pCode);
1062cdf0e10cSrcweir             aComp2.SetGrammar(pDocument->GetGrammar());
1063cdf0e10cSrcweir             aComp2.MoveRelWrap(pRangeData->GetMaxCol(), pRangeData->GetMaxRow());
1064cdf0e10cSrcweir             aComp2.UpdateInsertTab( nTable, sal_False );
1065cdf0e10cSrcweir             // If the shared formula contained a named range/formula containing
1066cdf0e10cSrcweir             // an absolute reference to a sheet, those have to be readjusted.
1067cdf0e10cSrcweir             aComp2.UpdateDeleteTab( nTable, sal_False, sal_True, bRefChanged );
1068cdf0e10cSrcweir             bCompile = sal_True;
1069cdf0e10cSrcweir         }
1070cdf0e10cSrcweir         // kein StartListeningTo weil pTab[nTab] noch nicht existiert!
1071cdf0e10cSrcweir     }
1072cdf0e10cSrcweir     else if ( bPosChanged )
1073cdf0e10cSrcweir         aPos.IncTab();
1074cdf0e10cSrcweir }
1075cdf0e10cSrcweir 
UpdateDeleteTab(SCTAB nTable,sal_Bool bIsMove)1076cdf0e10cSrcweir sal_Bool ScFormulaCell::UpdateDeleteTab(SCTAB nTable, sal_Bool bIsMove)
1077cdf0e10cSrcweir {
1078cdf0e10cSrcweir     sal_Bool bRefChanged = sal_False;
1079cdf0e10cSrcweir     sal_Bool bPosChanged = ( aPos.Tab() > nTable ? sal_True : sal_False );
1080cdf0e10cSrcweir     pCode->Reset();
1081cdf0e10cSrcweir     if( pCode->GetNextReferenceRPN() && !pDocument->IsClipOrUndo() )
1082cdf0e10cSrcweir     {
1083cdf0e10cSrcweir         EndListeningTo( pDocument );
1084cdf0e10cSrcweir         // IncTab _nach_ EndListeningTo und _vor_ Compiler UpdateDeleteTab !
1085cdf0e10cSrcweir         if ( bPosChanged )
1086cdf0e10cSrcweir             aPos.IncTab(-1);
1087cdf0e10cSrcweir         ScRangeData* pRangeData;
1088cdf0e10cSrcweir         ScCompiler aComp(pDocument, aPos, *pCode);
1089cdf0e10cSrcweir         aComp.SetGrammar(pDocument->GetGrammar());
1090cdf0e10cSrcweir         pRangeData = aComp.UpdateDeleteTab(nTable, bIsMove, sal_False, bRefChanged);
1091cdf0e10cSrcweir         if (pRangeData)                     // Shared Formula gegen echte Formel
1092cdf0e10cSrcweir         {                                   // austauschen
1093cdf0e10cSrcweir             pDocument->RemoveFromFormulaTree( this );   // update formula count
1094cdf0e10cSrcweir             delete pCode;
1095cdf0e10cSrcweir             pCode = pRangeData->GetCode()->Clone();
1096cdf0e10cSrcweir             ScCompiler aComp2(pDocument, aPos, *pCode);
1097cdf0e10cSrcweir             aComp2.SetGrammar(pDocument->GetGrammar());
1098cdf0e10cSrcweir             aComp2.CompileTokenArray();
1099cdf0e10cSrcweir             aComp2.MoveRelWrap(pRangeData->GetMaxCol(), pRangeData->GetMaxRow());
1100cdf0e10cSrcweir             aComp2.UpdateDeleteTab( nTable, sal_False, sal_False, bRefChanged );
1101cdf0e10cSrcweir             // If the shared formula contained a named range/formula containing
1102cdf0e10cSrcweir             // an absolute reference to a sheet, those have to be readjusted.
1103cdf0e10cSrcweir             aComp2.UpdateInsertTab( nTable,sal_True );
1104cdf0e10cSrcweir             // bRefChanged kann beim letzten UpdateDeleteTab zurueckgesetzt worden sein
1105cdf0e10cSrcweir             bRefChanged = sal_True;
1106cdf0e10cSrcweir             bCompile = sal_True;
1107cdf0e10cSrcweir         }
1108cdf0e10cSrcweir         // kein StartListeningTo weil pTab[nTab] noch nicht korrekt!
1109cdf0e10cSrcweir     }
1110cdf0e10cSrcweir     else if ( bPosChanged )
1111cdf0e10cSrcweir         aPos.IncTab(-1);
1112cdf0e10cSrcweir 
1113cdf0e10cSrcweir     return bRefChanged;
1114cdf0e10cSrcweir }
1115cdf0e10cSrcweir 
UpdateMoveTab(SCTAB nOldPos,SCTAB nNewPos,SCTAB nTabNo)1116cdf0e10cSrcweir void ScFormulaCell::UpdateMoveTab( SCTAB nOldPos, SCTAB nNewPos, SCTAB nTabNo )
1117cdf0e10cSrcweir {
1118cdf0e10cSrcweir     pCode->Reset();
1119cdf0e10cSrcweir     if( pCode->GetNextReferenceRPN() && !pDocument->IsClipOrUndo() )
1120cdf0e10cSrcweir     {
1121cdf0e10cSrcweir         EndListeningTo( pDocument );
1122cdf0e10cSrcweir         // SetTab _nach_ EndListeningTo und _vor_ Compiler UpdateMoveTab !
1123cdf0e10cSrcweir         aPos.SetTab( nTabNo );
1124cdf0e10cSrcweir         ScRangeData* pRangeData;
1125cdf0e10cSrcweir         ScCompiler aComp(pDocument, aPos, *pCode);
1126cdf0e10cSrcweir         aComp.SetGrammar(pDocument->GetGrammar());
1127cdf0e10cSrcweir         pRangeData = aComp.UpdateMoveTab( nOldPos, nNewPos, sal_False );
1128cdf0e10cSrcweir         if (pRangeData)                     // Shared Formula gegen echte Formel
1129cdf0e10cSrcweir         {                                   // austauschen
1130cdf0e10cSrcweir             pDocument->RemoveFromFormulaTree( this );   // update formula count
1131cdf0e10cSrcweir             delete pCode;
1132cdf0e10cSrcweir             pCode = pRangeData->GetCode()->Clone();
1133cdf0e10cSrcweir             ScCompiler aComp2(pDocument, aPos, *pCode);
1134cdf0e10cSrcweir             aComp2.SetGrammar(pDocument->GetGrammar());
1135cdf0e10cSrcweir             aComp2.CompileTokenArray();
1136cdf0e10cSrcweir             aComp2.MoveRelWrap(pRangeData->GetMaxCol(), pRangeData->GetMaxRow());
1137cdf0e10cSrcweir             aComp2.UpdateMoveTab( nOldPos, nNewPos, sal_True );
1138cdf0e10cSrcweir             bCompile = sal_True;
1139cdf0e10cSrcweir         }
1140cdf0e10cSrcweir         // kein StartListeningTo weil pTab[nTab] noch nicht korrekt!
1141cdf0e10cSrcweir     }
1142cdf0e10cSrcweir     else
1143cdf0e10cSrcweir         aPos.SetTab( nTabNo );
1144cdf0e10cSrcweir }
1145cdf0e10cSrcweir 
UpdateInsertTabAbs(SCTAB nTable)1146cdf0e10cSrcweir void ScFormulaCell::UpdateInsertTabAbs(SCTAB nTable)
1147cdf0e10cSrcweir {
1148cdf0e10cSrcweir     if( !pDocument->IsClipOrUndo() )
1149cdf0e10cSrcweir     {
1150cdf0e10cSrcweir         pCode->Reset();
1151cdf0e10cSrcweir         ScToken* p = static_cast<ScToken*>(pCode->GetNextReferenceRPN());
1152cdf0e10cSrcweir         while( p )
1153cdf0e10cSrcweir         {
1154cdf0e10cSrcweir             ScSingleRefData& rRef1 = p->GetSingleRef();
1155cdf0e10cSrcweir             if( !rRef1.IsTabRel() && (SCsTAB) nTable <= rRef1.nTab )
1156cdf0e10cSrcweir                 rRef1.nTab++;
1157cdf0e10cSrcweir             if( p->GetType() == formula::svDoubleRef )
1158cdf0e10cSrcweir             {
1159cdf0e10cSrcweir                 ScSingleRefData& rRef2 = p->GetDoubleRef().Ref2;
1160cdf0e10cSrcweir                 if( !rRef2.IsTabRel() && (SCsTAB) nTable <= rRef2.nTab )
1161cdf0e10cSrcweir                     rRef2.nTab++;
1162cdf0e10cSrcweir             }
1163cdf0e10cSrcweir             p = static_cast<ScToken*>(pCode->GetNextReferenceRPN());
1164cdf0e10cSrcweir         }
1165cdf0e10cSrcweir     }
1166cdf0e10cSrcweir }
1167cdf0e10cSrcweir 
TestTabRefAbs(SCTAB nTable)1168cdf0e10cSrcweir sal_Bool ScFormulaCell::TestTabRefAbs(SCTAB nTable)
1169cdf0e10cSrcweir {
1170cdf0e10cSrcweir     sal_Bool bRet = sal_False;
1171cdf0e10cSrcweir     if( !pDocument->IsClipOrUndo() )
1172cdf0e10cSrcweir     {
1173cdf0e10cSrcweir         pCode->Reset();
1174cdf0e10cSrcweir         ScToken* p = static_cast<ScToken*>(pCode->GetNextReferenceRPN());
1175cdf0e10cSrcweir         while( p )
1176cdf0e10cSrcweir         {
1177cdf0e10cSrcweir             ScSingleRefData& rRef1 = p->GetSingleRef();
1178cdf0e10cSrcweir             if( !rRef1.IsTabRel() )
1179cdf0e10cSrcweir             {
1180cdf0e10cSrcweir                 if( (SCsTAB) nTable != rRef1.nTab )
1181cdf0e10cSrcweir                     bRet = sal_True;
1182cdf0e10cSrcweir                 else if (nTable != aPos.Tab())
1183cdf0e10cSrcweir                     rRef1.nTab = aPos.Tab();
1184cdf0e10cSrcweir             }
1185cdf0e10cSrcweir             if( p->GetType() == formula::svDoubleRef )
1186cdf0e10cSrcweir             {
1187cdf0e10cSrcweir                 ScSingleRefData& rRef2 = p->GetDoubleRef().Ref2;
1188cdf0e10cSrcweir                 if( !rRef2.IsTabRel() )
1189cdf0e10cSrcweir                 {
1190cdf0e10cSrcweir                     if( (SCsTAB) nTable != rRef2.nTab )
1191cdf0e10cSrcweir                         bRet = sal_True;
1192cdf0e10cSrcweir                     else if (nTable != aPos.Tab())
1193cdf0e10cSrcweir                         rRef2.nTab = aPos.Tab();
1194cdf0e10cSrcweir                 }
1195cdf0e10cSrcweir             }
1196cdf0e10cSrcweir             p = static_cast<ScToken*>(pCode->GetNextReferenceRPN());
1197cdf0e10cSrcweir         }
1198cdf0e10cSrcweir     }
1199cdf0e10cSrcweir     return bRet;
1200cdf0e10cSrcweir }
1201cdf0e10cSrcweir 
UpdateCompile(sal_Bool bForceIfNameInUse)1202cdf0e10cSrcweir void ScFormulaCell::UpdateCompile( sal_Bool bForceIfNameInUse )
1203cdf0e10cSrcweir {
1204cdf0e10cSrcweir     if ( bForceIfNameInUse && !bCompile )
1205cdf0e10cSrcweir         bCompile = pCode->HasNameOrColRowName();
1206cdf0e10cSrcweir     if ( bCompile )
1207cdf0e10cSrcweir         pCode->SetCodeError( 0 );   // make sure it will really be compiled
1208cdf0e10cSrcweir     CompileTokenArray();
1209cdf0e10cSrcweir }
1210cdf0e10cSrcweir 
1211cdf0e10cSrcweir //  Referenzen transponieren - wird nur in Clipboard-Dokumenten aufgerufen
1212cdf0e10cSrcweir 
TransposeReference()1213cdf0e10cSrcweir void ScFormulaCell::TransposeReference()
1214cdf0e10cSrcweir {
1215cdf0e10cSrcweir     sal_Bool bFound = sal_False;
1216cdf0e10cSrcweir     pCode->Reset();
1217cdf0e10cSrcweir     ScToken* t;
1218cdf0e10cSrcweir     while ( ( t = static_cast<ScToken*>(pCode->GetNextReference()) ) != NULL )
1219cdf0e10cSrcweir     {
1220cdf0e10cSrcweir         ScSingleRefData& rRef1 = t->GetSingleRef();
1221cdf0e10cSrcweir         if ( rRef1.IsColRel() && rRef1.IsRowRel() )
1222cdf0e10cSrcweir         {
1223cdf0e10cSrcweir             sal_Bool bDouble = (t->GetType() == formula::svDoubleRef);
1224cdf0e10cSrcweir             ScSingleRefData& rRef2 = (bDouble ? t->GetDoubleRef().Ref2 : rRef1);
1225cdf0e10cSrcweir             if ( !bDouble || (rRef2.IsColRel() && rRef2.IsRowRel()) )
1226cdf0e10cSrcweir             {
1227cdf0e10cSrcweir                 sal_Int16 nTemp;
1228cdf0e10cSrcweir 
1229cdf0e10cSrcweir                 nTemp = rRef1.nRelCol;
1230cdf0e10cSrcweir                 rRef1.nRelCol = static_cast<SCCOL>(rRef1.nRelRow);
1231cdf0e10cSrcweir                 rRef1.nRelRow = static_cast<SCROW>(nTemp);
1232cdf0e10cSrcweir 
1233cdf0e10cSrcweir                 if ( bDouble )
1234cdf0e10cSrcweir                 {
1235cdf0e10cSrcweir                     nTemp = rRef2.nRelCol;
1236cdf0e10cSrcweir                     rRef2.nRelCol = static_cast<SCCOL>(rRef2.nRelRow);
1237cdf0e10cSrcweir                     rRef2.nRelRow = static_cast<SCROW>(nTemp);
1238cdf0e10cSrcweir                 }
1239cdf0e10cSrcweir 
1240cdf0e10cSrcweir                 bFound = sal_True;
1241cdf0e10cSrcweir             }
1242cdf0e10cSrcweir         }
1243cdf0e10cSrcweir     }
1244cdf0e10cSrcweir 
1245cdf0e10cSrcweir     if (bFound)
1246cdf0e10cSrcweir         bCompile = sal_True;
1247cdf0e10cSrcweir }
1248cdf0e10cSrcweir 
UpdateTranspose(const ScRange & rSource,const ScAddress & rDest,ScDocument * pUndoDoc)1249cdf0e10cSrcweir void ScFormulaCell::UpdateTranspose( const ScRange& rSource, const ScAddress& rDest,
1250cdf0e10cSrcweir                                         ScDocument* pUndoDoc )
1251cdf0e10cSrcweir {
1252cdf0e10cSrcweir     EndListeningTo( pDocument );
1253cdf0e10cSrcweir 
1254cdf0e10cSrcweir     ScAddress aOldPos = aPos;
1255cdf0e10cSrcweir     sal_Bool bPosChanged = sal_False;           // ob diese Zelle bewegt wurde
1256cdf0e10cSrcweir 
1257cdf0e10cSrcweir     ScRange aDestRange( rDest, ScAddress(
1258cdf0e10cSrcweir                 static_cast<SCCOL>(rDest.Col() + rSource.aEnd.Row() - rSource.aStart.Row()),
1259cdf0e10cSrcweir                 static_cast<SCROW>(rDest.Row() + rSource.aEnd.Col() - rSource.aStart.Col()),
1260cdf0e10cSrcweir                 rDest.Tab() + rSource.aEnd.Tab() - rSource.aStart.Tab() ) );
1261cdf0e10cSrcweir     if ( aDestRange.In( aOldPos ) )
1262cdf0e10cSrcweir     {
1263cdf0e10cSrcweir         //  Position zurueckrechnen
1264cdf0e10cSrcweir         SCsCOL nRelPosX = aOldPos.Col();
1265cdf0e10cSrcweir         SCsROW nRelPosY = aOldPos.Row();
1266cdf0e10cSrcweir         SCsTAB nRelPosZ = aOldPos.Tab();
1267cdf0e10cSrcweir         ScRefUpdate::DoTranspose( nRelPosX, nRelPosY, nRelPosZ, pDocument, aDestRange, rSource.aStart );
1268cdf0e10cSrcweir         aOldPos.Set( nRelPosX, nRelPosY, nRelPosZ );
1269cdf0e10cSrcweir         bPosChanged = sal_True;
1270cdf0e10cSrcweir     }
1271cdf0e10cSrcweir 
1272cdf0e10cSrcweir     ScTokenArray* pOld = pUndoDoc ? pCode->Clone() : NULL;
1273cdf0e10cSrcweir     sal_Bool bRefChanged = sal_False;
1274cdf0e10cSrcweir     ScToken* t;
1275cdf0e10cSrcweir 
1276cdf0e10cSrcweir     ScRangeData* pShared = NULL;
1277cdf0e10cSrcweir     pCode->Reset();
1278cdf0e10cSrcweir     while( (t = static_cast<ScToken*>(pCode->GetNextReferenceOrName())) != NULL )
1279cdf0e10cSrcweir     {
1280cdf0e10cSrcweir         if( t->GetOpCode() == ocName )
1281cdf0e10cSrcweir         {
1282cdf0e10cSrcweir             ScRangeData* pName = pDocument->GetRangeName()->FindIndex( t->GetIndex() );
1283cdf0e10cSrcweir             if (pName)
1284cdf0e10cSrcweir             {
1285cdf0e10cSrcweir                 if (pName->IsModified())
1286cdf0e10cSrcweir                     bRefChanged = sal_True;
1287cdf0e10cSrcweir                 if (pName->HasType(RT_SHAREDMOD))
1288cdf0e10cSrcweir                     pShared = pName;
1289cdf0e10cSrcweir             }
1290cdf0e10cSrcweir         }
1291cdf0e10cSrcweir         else if( t->GetType() != svIndex )
1292cdf0e10cSrcweir         {
1293cdf0e10cSrcweir             t->CalcAbsIfRel( aOldPos );
1294cdf0e10cSrcweir             sal_Bool bMod;
1295cdf0e10cSrcweir             {   // own scope for SingleDoubleRefModifier dtor if SingleRef
1296cdf0e10cSrcweir                 SingleDoubleRefModifier aMod( *t );
1297cdf0e10cSrcweir                 ScComplexRefData& rRef = aMod.Ref();
1298cdf0e10cSrcweir                 bMod = (ScRefUpdate::UpdateTranspose( pDocument, rSource,
1299cdf0e10cSrcweir                     rDest, rRef ) != UR_NOTHING || bPosChanged);
1300cdf0e10cSrcweir             }
1301cdf0e10cSrcweir             if ( bMod )
1302cdf0e10cSrcweir             {
1303cdf0e10cSrcweir                 t->CalcRelFromAbs( aPos );
1304cdf0e10cSrcweir                 bRefChanged = sal_True;
1305cdf0e10cSrcweir             }
1306cdf0e10cSrcweir         }
1307cdf0e10cSrcweir     }
1308cdf0e10cSrcweir 
1309cdf0e10cSrcweir     if (pShared)            // Shared Formula gegen echte Formel austauschen
1310cdf0e10cSrcweir     {
1311cdf0e10cSrcweir         pDocument->RemoveFromFormulaTree( this );   // update formula count
1312cdf0e10cSrcweir         delete pCode;
1313cdf0e10cSrcweir         pCode = new ScTokenArray( *pShared->GetCode() );
1314cdf0e10cSrcweir         bRefChanged = sal_True;
1315cdf0e10cSrcweir         pCode->Reset();
1316cdf0e10cSrcweir         while( (t = static_cast<ScToken*>(pCode->GetNextReference())) != NULL )
1317cdf0e10cSrcweir         {
1318cdf0e10cSrcweir             if( t->GetType() != svIndex )
1319cdf0e10cSrcweir             {
1320cdf0e10cSrcweir                 t->CalcAbsIfRel( aOldPos );
1321cdf0e10cSrcweir                 sal_Bool bMod;
1322cdf0e10cSrcweir                 {   // own scope for SingleDoubleRefModifier dtor if SingleRef
1323cdf0e10cSrcweir                     SingleDoubleRefModifier aMod( *t );
1324cdf0e10cSrcweir                     ScComplexRefData& rRef = aMod.Ref();
1325cdf0e10cSrcweir                     bMod = (ScRefUpdate::UpdateTranspose( pDocument, rSource,
1326cdf0e10cSrcweir                         rDest, rRef ) != UR_NOTHING || bPosChanged);
1327cdf0e10cSrcweir                 }
1328cdf0e10cSrcweir                 if ( bMod )
1329cdf0e10cSrcweir                     t->CalcRelFromAbs( aPos );
1330cdf0e10cSrcweir             }
1331cdf0e10cSrcweir         }
1332cdf0e10cSrcweir     }
1333cdf0e10cSrcweir 
1334cdf0e10cSrcweir     if (bRefChanged)
1335cdf0e10cSrcweir     {
1336cdf0e10cSrcweir         if (pUndoDoc)
1337cdf0e10cSrcweir         {
1338cdf0e10cSrcweir             ScFormulaCell* pFCell = new ScFormulaCell( pUndoDoc, aPos, pOld,
1339cdf0e10cSrcweir                     eTempGrammar, cMatrixFlag);
1340cdf0e10cSrcweir             pFCell->aResult.SetToken( NULL);  // to recognize it as changed later (Cut/Paste!)
1341cdf0e10cSrcweir             pUndoDoc->PutCell( aPos.Col(), aPos.Row(), aPos.Tab(), pFCell );
1342cdf0e10cSrcweir         }
1343cdf0e10cSrcweir 
1344cdf0e10cSrcweir         bCompile = sal_True;
1345cdf0e10cSrcweir         CompileTokenArray();                // ruft auch StartListeningTo
1346cdf0e10cSrcweir         SetDirty();
1347cdf0e10cSrcweir     }
1348cdf0e10cSrcweir     else
1349cdf0e10cSrcweir         StartListeningTo( pDocument );      // Listener wie vorher
1350cdf0e10cSrcweir 
1351cdf0e10cSrcweir     delete pOld;
1352cdf0e10cSrcweir }
1353cdf0e10cSrcweir 
UpdateGrow(const ScRange & rArea,SCCOL nGrowX,SCROW nGrowY)1354cdf0e10cSrcweir void ScFormulaCell::UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY )
1355cdf0e10cSrcweir {
1356cdf0e10cSrcweir     EndListeningTo( pDocument );
1357cdf0e10cSrcweir 
1358cdf0e10cSrcweir     sal_Bool bRefChanged = sal_False;
1359cdf0e10cSrcweir     ScToken* t;
1360cdf0e10cSrcweir     ScRangeData* pShared = NULL;
1361cdf0e10cSrcweir 
1362cdf0e10cSrcweir     pCode->Reset();
1363cdf0e10cSrcweir     while( (t = static_cast<ScToken*>(pCode->GetNextReferenceOrName())) != NULL )
1364cdf0e10cSrcweir     {
1365cdf0e10cSrcweir         if( t->GetOpCode() == ocName )
1366cdf0e10cSrcweir         {
1367cdf0e10cSrcweir             ScRangeData* pName = pDocument->GetRangeName()->FindIndex( t->GetIndex() );
1368cdf0e10cSrcweir             if (pName)
1369cdf0e10cSrcweir             {
1370cdf0e10cSrcweir                 if (pName->IsModified())
1371cdf0e10cSrcweir                     bRefChanged = sal_True;
1372cdf0e10cSrcweir                 if (pName->HasType(RT_SHAREDMOD))
1373cdf0e10cSrcweir                     pShared = pName;
1374cdf0e10cSrcweir             }
1375cdf0e10cSrcweir         }
1376cdf0e10cSrcweir         else if( t->GetType() != svIndex )
1377cdf0e10cSrcweir         {
1378cdf0e10cSrcweir             t->CalcAbsIfRel( aPos );
1379cdf0e10cSrcweir             sal_Bool bMod;
1380cdf0e10cSrcweir             {   // own scope for SingleDoubleRefModifier dtor if SingleRef
1381cdf0e10cSrcweir                 SingleDoubleRefModifier aMod( *t );
1382cdf0e10cSrcweir                 ScComplexRefData& rRef = aMod.Ref();
1383cdf0e10cSrcweir                 bMod = (ScRefUpdate::UpdateGrow( rArea,nGrowX,nGrowY,
1384cdf0e10cSrcweir                     rRef ) != UR_NOTHING);
1385cdf0e10cSrcweir             }
1386cdf0e10cSrcweir             if ( bMod )
1387cdf0e10cSrcweir             {
1388cdf0e10cSrcweir                 t->CalcRelFromAbs( aPos );
1389cdf0e10cSrcweir                 bRefChanged = sal_True;
1390cdf0e10cSrcweir             }
1391cdf0e10cSrcweir         }
1392cdf0e10cSrcweir     }
1393cdf0e10cSrcweir 
1394cdf0e10cSrcweir     if (pShared)            // Shared Formula gegen echte Formel austauschen
1395cdf0e10cSrcweir     {
1396cdf0e10cSrcweir         pDocument->RemoveFromFormulaTree( this );   // update formula count
1397cdf0e10cSrcweir         delete pCode;
1398cdf0e10cSrcweir         pCode = new ScTokenArray( *pShared->GetCode() );
1399cdf0e10cSrcweir         bRefChanged = sal_True;
1400cdf0e10cSrcweir         pCode->Reset();
1401cdf0e10cSrcweir         while( (t = static_cast<ScToken*>(pCode->GetNextReference())) != NULL )
1402cdf0e10cSrcweir         {
1403cdf0e10cSrcweir             if( t->GetType() != svIndex )
1404cdf0e10cSrcweir             {
1405cdf0e10cSrcweir                 t->CalcAbsIfRel( aPos );
1406cdf0e10cSrcweir                 sal_Bool bMod;
1407cdf0e10cSrcweir                 {   // own scope for SingleDoubleRefModifier dtor if SingleRef
1408cdf0e10cSrcweir                     SingleDoubleRefModifier aMod( *t );
1409cdf0e10cSrcweir                     ScComplexRefData& rRef = aMod.Ref();
1410cdf0e10cSrcweir                     bMod = (ScRefUpdate::UpdateGrow( rArea,nGrowX,nGrowY,
1411cdf0e10cSrcweir                         rRef ) != UR_NOTHING);
1412cdf0e10cSrcweir                 }
1413cdf0e10cSrcweir                 if ( bMod )
1414cdf0e10cSrcweir                     t->CalcRelFromAbs( aPos );
1415cdf0e10cSrcweir             }
1416cdf0e10cSrcweir         }
1417cdf0e10cSrcweir     }
1418cdf0e10cSrcweir 
1419cdf0e10cSrcweir     if (bRefChanged)
1420cdf0e10cSrcweir     {
1421cdf0e10cSrcweir         bCompile = sal_True;
1422cdf0e10cSrcweir         CompileTokenArray();                // ruft auch StartListeningTo
1423cdf0e10cSrcweir         SetDirty();
1424cdf0e10cSrcweir     }
1425cdf0e10cSrcweir     else
1426cdf0e10cSrcweir         StartListeningTo( pDocument );      // Listener wie vorher
1427cdf0e10cSrcweir }
1428cdf0e10cSrcweir 
lcl_IsRangeNameInUse(sal_uInt16 nIndex,ScTokenArray * pCode,ScRangeName * pNames)1429cdf0e10cSrcweir sal_Bool lcl_IsRangeNameInUse(sal_uInt16 nIndex, ScTokenArray* pCode, ScRangeName* pNames)
1430cdf0e10cSrcweir {
1431cdf0e10cSrcweir     for (FormulaToken* p = pCode->First(); p; p = pCode->Next())
1432cdf0e10cSrcweir     {
1433cdf0e10cSrcweir         if (p->GetOpCode() == ocName)
1434cdf0e10cSrcweir         {
1435cdf0e10cSrcweir             if (p->GetIndex() == nIndex)
1436cdf0e10cSrcweir                 return sal_True;
1437cdf0e10cSrcweir             else
1438cdf0e10cSrcweir             {
1439cdf0e10cSrcweir                 //  RangeData kann Null sein in bestimmten Excel-Dateien (#31168#)
1440cdf0e10cSrcweir                 ScRangeData* pSubName = pNames->FindIndex(p->GetIndex());
1441cdf0e10cSrcweir                 if (pSubName && lcl_IsRangeNameInUse(nIndex,
1442cdf0e10cSrcweir                                     pSubName->GetCode(), pNames))
1443cdf0e10cSrcweir                     return sal_True;
1444cdf0e10cSrcweir             }
1445cdf0e10cSrcweir         }
1446cdf0e10cSrcweir     }
1447cdf0e10cSrcweir     return sal_False;
1448cdf0e10cSrcweir }
1449cdf0e10cSrcweir 
IsRangeNameInUse(sal_uInt16 nIndex) const1450cdf0e10cSrcweir sal_Bool ScFormulaCell::IsRangeNameInUse(sal_uInt16 nIndex) const
1451cdf0e10cSrcweir {
1452cdf0e10cSrcweir     return lcl_IsRangeNameInUse( nIndex, pCode, pDocument->GetRangeName() );
1453cdf0e10cSrcweir }
1454cdf0e10cSrcweir 
lcl_FindRangeNamesInUse(std::set<sal_uInt16> & rIndexes,ScTokenArray * pCode,ScRangeName * pNames)1455cdf0e10cSrcweir void lcl_FindRangeNamesInUse(std::set<sal_uInt16>& rIndexes, ScTokenArray* pCode, ScRangeName* pNames)
1456cdf0e10cSrcweir {
1457cdf0e10cSrcweir     for (FormulaToken* p = pCode->First(); p; p = pCode->Next())
1458cdf0e10cSrcweir     {
1459cdf0e10cSrcweir         if (p->GetOpCode() == ocName)
1460cdf0e10cSrcweir         {
1461cdf0e10cSrcweir             sal_uInt16 nTokenIndex = p->GetIndex();
1462cdf0e10cSrcweir             rIndexes.insert( nTokenIndex );
1463cdf0e10cSrcweir 
1464cdf0e10cSrcweir             ScRangeData* pSubName = pNames->FindIndex(p->GetIndex());
1465cdf0e10cSrcweir             if (pSubName)
1466cdf0e10cSrcweir                 lcl_FindRangeNamesInUse(rIndexes, pSubName->GetCode(), pNames);
1467cdf0e10cSrcweir         }
1468cdf0e10cSrcweir     }
1469cdf0e10cSrcweir }
1470cdf0e10cSrcweir 
FindRangeNamesInUse(std::set<sal_uInt16> & rIndexes) const1471cdf0e10cSrcweir void ScFormulaCell::FindRangeNamesInUse(std::set<sal_uInt16>& rIndexes) const
1472cdf0e10cSrcweir {
1473cdf0e10cSrcweir     lcl_FindRangeNamesInUse( rIndexes, pCode, pDocument->GetRangeName() );
1474cdf0e10cSrcweir }
1475cdf0e10cSrcweir 
ReplaceRangeNamesInUse(const ScRangeData::IndexMap & rMap)1476cdf0e10cSrcweir void ScFormulaCell::ReplaceRangeNamesInUse( const ScRangeData::IndexMap& rMap )
1477cdf0e10cSrcweir {
1478cdf0e10cSrcweir     for( FormulaToken* p = pCode->First(); p; p = pCode->Next() )
1479cdf0e10cSrcweir     {
1480cdf0e10cSrcweir         if( p->GetOpCode() == ocName )
1481cdf0e10cSrcweir         {
1482cdf0e10cSrcweir             sal_uInt16 nIndex = p->GetIndex();
1483cdf0e10cSrcweir             ScRangeData::IndexMap::const_iterator itr = rMap.find(nIndex);
1484cdf0e10cSrcweir             sal_uInt16 nNewIndex = itr == rMap.end() ? nIndex : itr->second;
1485cdf0e10cSrcweir             if ( nIndex != nNewIndex )
1486cdf0e10cSrcweir             {
1487cdf0e10cSrcweir                 p->SetIndex( nNewIndex );
1488cdf0e10cSrcweir                 bCompile = sal_True;
1489cdf0e10cSrcweir             }
1490cdf0e10cSrcweir         }
1491cdf0e10cSrcweir     }
1492cdf0e10cSrcweir     if( bCompile )
1493cdf0e10cSrcweir         CompileTokenArray();
1494cdf0e10cSrcweir }
1495cdf0e10cSrcweir 
CompileDBFormula()1496cdf0e10cSrcweir void ScFormulaCell::CompileDBFormula()
1497cdf0e10cSrcweir {
1498cdf0e10cSrcweir     for( FormulaToken* p = pCode->First(); p; p = pCode->Next() )
1499cdf0e10cSrcweir     {
1500cdf0e10cSrcweir         if ( p->GetOpCode() == ocDBArea
1501cdf0e10cSrcweir             || (p->GetOpCode() == ocName && p->GetIndex() >= SC_START_INDEX_DB_COLL) )
1502cdf0e10cSrcweir         {
1503cdf0e10cSrcweir             bCompile = sal_True;
1504cdf0e10cSrcweir             CompileTokenArray();
1505cdf0e10cSrcweir             SetDirty();
1506cdf0e10cSrcweir             break;
1507cdf0e10cSrcweir         }
1508cdf0e10cSrcweir     }
1509cdf0e10cSrcweir }
1510cdf0e10cSrcweir 
CompileDBFormula(sal_Bool bCreateFormulaString)1511cdf0e10cSrcweir void ScFormulaCell::CompileDBFormula( sal_Bool bCreateFormulaString )
1512cdf0e10cSrcweir {
1513cdf0e10cSrcweir     // zwei Phasen, muessen (!) nacheinander aufgerufen werden:
1514cdf0e10cSrcweir     // 1. FormelString mit alten Namen erzeugen
1515cdf0e10cSrcweir     // 2. FormelString mit neuen Namen kompilieren
1516cdf0e10cSrcweir     if ( bCreateFormulaString )
1517cdf0e10cSrcweir     {
1518cdf0e10cSrcweir         sal_Bool bRecompile = sal_False;
1519cdf0e10cSrcweir         pCode->Reset();
1520cdf0e10cSrcweir         for ( FormulaToken* p = pCode->First(); p && !bRecompile; p = pCode->Next() )
1521cdf0e10cSrcweir         {
1522cdf0e10cSrcweir             switch ( p->GetOpCode() )
1523cdf0e10cSrcweir             {
1524cdf0e10cSrcweir                 case ocBad:             // DB-Bereich evtl. zugefuegt
1525cdf0e10cSrcweir                 case ocColRowName:      // #36762# falls Namensgleichheit
1526cdf0e10cSrcweir                 case ocDBArea:          // DB-Bereich
1527cdf0e10cSrcweir                     bRecompile = sal_True;
1528cdf0e10cSrcweir                 break;
1529cdf0e10cSrcweir                 case ocName:
1530cdf0e10cSrcweir                     if ( p->GetIndex() >= SC_START_INDEX_DB_COLL )
1531cdf0e10cSrcweir                         bRecompile = sal_True;  // DB-Bereich
1532cdf0e10cSrcweir                 break;
1533cdf0e10cSrcweir                 default:
1534cdf0e10cSrcweir                     ; // nothing
1535cdf0e10cSrcweir             }
1536cdf0e10cSrcweir         }
1537cdf0e10cSrcweir         if ( bRecompile )
1538cdf0e10cSrcweir         {
1539cdf0e10cSrcweir             String aFormula;
1540cdf0e10cSrcweir             GetFormula( aFormula, formula::FormulaGrammar::GRAM_NATIVE);
1541cdf0e10cSrcweir             if ( GetMatrixFlag() != MM_NONE && aFormula.Len() )
1542cdf0e10cSrcweir             {
1543cdf0e10cSrcweir                 if ( aFormula.GetChar( aFormula.Len()-1 ) == '}' )
1544cdf0e10cSrcweir                     aFormula.Erase( aFormula.Len()-1 , 1 );
1545cdf0e10cSrcweir                 if ( aFormula.GetChar(0) == '{' )
1546cdf0e10cSrcweir                     aFormula.Erase( 0, 1 );
1547cdf0e10cSrcweir             }
1548cdf0e10cSrcweir             EndListeningTo( pDocument );
1549cdf0e10cSrcweir             pDocument->RemoveFromFormulaTree( this );
1550cdf0e10cSrcweir             pCode->Clear();
1551cdf0e10cSrcweir             SetHybridFormula( aFormula, formula::FormulaGrammar::GRAM_NATIVE);
1552cdf0e10cSrcweir         }
1553cdf0e10cSrcweir     }
1554cdf0e10cSrcweir     else if ( !pCode->GetLen() && aResult.GetHybridFormula().Len() )
1555cdf0e10cSrcweir     {
1556cdf0e10cSrcweir         Compile( aResult.GetHybridFormula(), sal_False, eTempGrammar );
1557cdf0e10cSrcweir         aResult.SetToken( NULL);
1558cdf0e10cSrcweir         SetDirty();
1559cdf0e10cSrcweir     }
1560cdf0e10cSrcweir }
1561cdf0e10cSrcweir 
CompileNameFormula(sal_Bool bCreateFormulaString)1562cdf0e10cSrcweir void ScFormulaCell::CompileNameFormula( sal_Bool bCreateFormulaString )
1563cdf0e10cSrcweir {
1564cdf0e10cSrcweir     // zwei Phasen, muessen (!) nacheinander aufgerufen werden:
1565cdf0e10cSrcweir     // 1. FormelString mit alten RangeNames erzeugen
1566cdf0e10cSrcweir     // 2. FormelString mit neuen RangeNames kompilieren
1567cdf0e10cSrcweir     if ( bCreateFormulaString )
1568cdf0e10cSrcweir     {
1569cdf0e10cSrcweir         sal_Bool bRecompile = sal_False;
1570cdf0e10cSrcweir         pCode->Reset();
1571cdf0e10cSrcweir         for ( FormulaToken* p = pCode->First(); p && !bRecompile; p = pCode->Next() )
1572cdf0e10cSrcweir         {
1573cdf0e10cSrcweir             switch ( p->GetOpCode() )
1574cdf0e10cSrcweir             {
1575cdf0e10cSrcweir                 case ocBad:             // RangeName evtl. zugefuegt
1576cdf0e10cSrcweir                 case ocColRowName:      // #36762# falls Namensgleichheit
1577cdf0e10cSrcweir                     bRecompile = sal_True;
1578cdf0e10cSrcweir                 break;
1579cdf0e10cSrcweir                 default:
1580cdf0e10cSrcweir                     if ( p->GetType() == svIndex )
1581cdf0e10cSrcweir                         bRecompile = sal_True;  // RangeName
1582cdf0e10cSrcweir             }
1583cdf0e10cSrcweir         }
1584cdf0e10cSrcweir         if ( bRecompile )
1585cdf0e10cSrcweir         {
1586cdf0e10cSrcweir             String aFormula;
1587cdf0e10cSrcweir             GetFormula( aFormula, formula::FormulaGrammar::GRAM_NATIVE);
1588cdf0e10cSrcweir             if ( GetMatrixFlag() != MM_NONE && aFormula.Len() )
1589cdf0e10cSrcweir             {
1590cdf0e10cSrcweir                 if ( aFormula.GetChar( aFormula.Len()-1 ) == '}' )
1591cdf0e10cSrcweir                     aFormula.Erase( aFormula.Len()-1 , 1 );
1592cdf0e10cSrcweir                 if ( aFormula.GetChar(0) == '{' )
1593cdf0e10cSrcweir                     aFormula.Erase( 0, 1 );
1594cdf0e10cSrcweir             }
1595cdf0e10cSrcweir             EndListeningTo( pDocument );
1596cdf0e10cSrcweir             pDocument->RemoveFromFormulaTree( this );
1597cdf0e10cSrcweir             pCode->Clear();
1598cdf0e10cSrcweir             SetHybridFormula( aFormula, formula::FormulaGrammar::GRAM_NATIVE);
1599cdf0e10cSrcweir         }
1600cdf0e10cSrcweir     }
1601cdf0e10cSrcweir     else if ( !pCode->GetLen() && aResult.GetHybridFormula().Len() )
1602cdf0e10cSrcweir     {
1603cdf0e10cSrcweir         Compile( aResult.GetHybridFormula(), sal_False, eTempGrammar );
1604cdf0e10cSrcweir         aResult.SetToken( NULL);
1605cdf0e10cSrcweir         SetDirty();
1606cdf0e10cSrcweir     }
1607cdf0e10cSrcweir }
1608cdf0e10cSrcweir 
CompileColRowNameFormula()1609cdf0e10cSrcweir void ScFormulaCell::CompileColRowNameFormula()
1610cdf0e10cSrcweir {
1611cdf0e10cSrcweir     pCode->Reset();
1612cdf0e10cSrcweir     for ( FormulaToken* p = pCode->First(); p; p = pCode->Next() )
1613cdf0e10cSrcweir     {
1614cdf0e10cSrcweir         if ( p->GetOpCode() == ocColRowName )
1615cdf0e10cSrcweir         {
1616cdf0e10cSrcweir             bCompile = sal_True;
1617cdf0e10cSrcweir             CompileTokenArray();
1618cdf0e10cSrcweir             SetDirty();
1619cdf0e10cSrcweir             break;
1620cdf0e10cSrcweir         }
1621cdf0e10cSrcweir     }
1622cdf0e10cSrcweir }
1623cdf0e10cSrcweir 
1624cdf0e10cSrcweir // ============================================================================
1625cdf0e10cSrcweir 
1626