xref: /AOO41X/main/sc/source/core/data/column.cxx (revision 3a02adb192a454612d9255c0c219a65a4fe24f93)
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
10cdf0e10cSrcweir  *
11b3f79822SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
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.
19cdf0e10cSrcweir  *
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 
31cdf0e10cSrcweir #include <map>
32cdf0e10cSrcweir 
33cdf0e10cSrcweir #include <svl/poolcach.hxx>
34cdf0e10cSrcweir #include <svl/zforlist.hxx>
35cdf0e10cSrcweir #include <editeng/scripttypeitem.hxx>
36cdf0e10cSrcweir #include <string.h>
37cdf0e10cSrcweir 
38cdf0e10cSrcweir #include "scitems.hxx"
39cdf0e10cSrcweir #include "column.hxx"
40cdf0e10cSrcweir #include "cell.hxx"
41cdf0e10cSrcweir #include "document.hxx"
42cdf0e10cSrcweir #include "docpool.hxx"
43cdf0e10cSrcweir #include "attarray.hxx"
44cdf0e10cSrcweir #include "patattr.hxx"
45cdf0e10cSrcweir #include "compiler.hxx"
46cdf0e10cSrcweir #include "brdcst.hxx"
47cdf0e10cSrcweir #include "markdata.hxx"
48cdf0e10cSrcweir #include "detfunc.hxx"			// for Notes in Sort/Swap
49cdf0e10cSrcweir #include "postit.hxx"
50cdf0e10cSrcweir 
51cdf0e10cSrcweir //#pragma optimize ( "", off )
52cdf0e10cSrcweir //	nur Search ohne Optimierung!
53cdf0e10cSrcweir 
54cdf0e10cSrcweir // STATIC DATA -----------------------------------------------------------
55cdf0e10cSrcweir using namespace formula;
56cdf0e10cSrcweir 
IsAmbiguousScriptNonZero(sal_uInt8 nScript)57cdf0e10cSrcweir inline sal_Bool IsAmbiguousScriptNonZero( sal_uInt8 nScript )
58cdf0e10cSrcweir {
59cdf0e10cSrcweir 	//!	move to a header file
60cdf0e10cSrcweir 	return ( nScript != SCRIPTTYPE_LATIN &&
61cdf0e10cSrcweir 			 nScript != SCRIPTTYPE_ASIAN &&
62cdf0e10cSrcweir 			 nScript != SCRIPTTYPE_COMPLEX &&
63cdf0e10cSrcweir 			 nScript != 0 );
64cdf0e10cSrcweir }
65cdf0e10cSrcweir 
66cdf0e10cSrcweir // -----------------------------------------------------------------------------------------
67cdf0e10cSrcweir 
68cdf0e10cSrcweir 
ScColumn()69cdf0e10cSrcweir ScColumn::ScColumn() :
70cdf0e10cSrcweir 	nCol( 0 ),
71cdf0e10cSrcweir 	nCount( 0 ),
72cdf0e10cSrcweir 	nLimit( 0 ),
73cdf0e10cSrcweir 	pItems( NULL ),
74cdf0e10cSrcweir     pAttrArray( NULL ),
75cdf0e10cSrcweir     pDocument( NULL )
76cdf0e10cSrcweir {
77cdf0e10cSrcweir }
78cdf0e10cSrcweir 
79cdf0e10cSrcweir 
~ScColumn()80cdf0e10cSrcweir ScColumn::~ScColumn()
81cdf0e10cSrcweir {
82cdf0e10cSrcweir 	FreeAll();
83cdf0e10cSrcweir 	if (pAttrArray) delete pAttrArray;
84cdf0e10cSrcweir }
85cdf0e10cSrcweir 
86cdf0e10cSrcweir 
Init(SCCOL nNewCol,SCTAB nNewTab,ScDocument * pDoc)87cdf0e10cSrcweir void ScColumn::Init(SCCOL nNewCol, SCTAB nNewTab, ScDocument* pDoc)
88cdf0e10cSrcweir {
89cdf0e10cSrcweir 	nCol = nNewCol;
90cdf0e10cSrcweir 	nTab = nNewTab;
91cdf0e10cSrcweir 	pDocument = pDoc;
92cdf0e10cSrcweir 	pAttrArray = new ScAttrArray( nCol, nTab, pDocument );
93cdf0e10cSrcweir }
94cdf0e10cSrcweir 
95cdf0e10cSrcweir 
GetNextUnprotected(SCROW nRow,sal_Bool bUp) const96cdf0e10cSrcweir SCsROW ScColumn::GetNextUnprotected( SCROW nRow, sal_Bool bUp ) const
97cdf0e10cSrcweir {
98cdf0e10cSrcweir 	return pAttrArray->GetNextUnprotected(nRow, bUp);
99cdf0e10cSrcweir }
100cdf0e10cSrcweir 
101cdf0e10cSrcweir 
GetBlockMatrixEdges(SCROW nRow1,SCROW nRow2,sal_uInt16 nMask) const102cdf0e10cSrcweir sal_uInt16 ScColumn::GetBlockMatrixEdges( SCROW nRow1, SCROW nRow2, sal_uInt16 nMask ) const
103cdf0e10cSrcweir {
104cdf0e10cSrcweir 	// nix:0, mitte:1, unten:2, links:4, oben:8, rechts:16, offen:32
105cdf0e10cSrcweir 	if ( !pItems )
106cdf0e10cSrcweir 		return 0;
107cdf0e10cSrcweir 	if ( nRow1 == nRow2 )
108cdf0e10cSrcweir 	{
109cdf0e10cSrcweir 		SCSIZE nIndex;
110cdf0e10cSrcweir 		if ( Search( nRow1, nIndex ) )
111cdf0e10cSrcweir 		{
112cdf0e10cSrcweir 			ScBaseCell* pCell = pItems[nIndex].pCell;
113cdf0e10cSrcweir 			if ( pCell->GetCellType() == CELLTYPE_FORMULA
114cdf0e10cSrcweir 				&& ((ScFormulaCell*)pCell)->GetMatrixFlag() )
115cdf0e10cSrcweir 			{
116cdf0e10cSrcweir 				ScAddress aOrg( ScAddress::INITIALIZE_INVALID );
117cdf0e10cSrcweir 				return ((ScFormulaCell*)pCell)->GetMatrixEdge( aOrg );
118cdf0e10cSrcweir 			}
119cdf0e10cSrcweir 		}
120cdf0e10cSrcweir 		return 0;
121cdf0e10cSrcweir 	}
122cdf0e10cSrcweir 	else
123cdf0e10cSrcweir 	{
124cdf0e10cSrcweir 		ScAddress aOrg( ScAddress::INITIALIZE_INVALID );
125cdf0e10cSrcweir 		sal_Bool bOpen = sal_False;
126cdf0e10cSrcweir 		sal_uInt16 nEdges = 0;
127cdf0e10cSrcweir 		SCSIZE nIndex;
128cdf0e10cSrcweir 		Search( nRow1, nIndex );
129cdf0e10cSrcweir 		while ( nIndex < nCount && pItems[nIndex].nRow <= nRow2 )
130cdf0e10cSrcweir 		{
131cdf0e10cSrcweir 			ScBaseCell* pCell = pItems[nIndex].pCell;
132cdf0e10cSrcweir 			if ( pCell->GetCellType() == CELLTYPE_FORMULA
133cdf0e10cSrcweir 				&& ((ScFormulaCell*)pCell)->GetMatrixFlag() )
134cdf0e10cSrcweir 			{
135cdf0e10cSrcweir 				nEdges = ((ScFormulaCell*)pCell)->GetMatrixEdge( aOrg );
136cdf0e10cSrcweir 				if ( nEdges )
137cdf0e10cSrcweir 				{
138cdf0e10cSrcweir 					if ( nEdges & 8 )
139cdf0e10cSrcweir 						bOpen = sal_True;	// obere Kante oeffnet, weitersehen
140cdf0e10cSrcweir 					else if ( !bOpen )
141cdf0e10cSrcweir 						return nEdges | 32;	// es gibt was, was nicht geoeffnet wurde
142cdf0e10cSrcweir 					else if ( nEdges & 1 )
143cdf0e10cSrcweir 						return nEdges;	// mittendrin
144cdf0e10cSrcweir 					// (nMask & 16 und  (4 und nicht 16)) oder
145cdf0e10cSrcweir 					// (nMask & 4  und (16 und nicht 4))
146cdf0e10cSrcweir 					if ( ((nMask & 16) && (nEdges & 4)  && !(nEdges & 16))
147cdf0e10cSrcweir 						|| ((nMask & 4)  && (nEdges & 16) && !(nEdges & 4)) )
148cdf0e10cSrcweir 						return nEdges;	// nur linke/rechte Kante
149cdf0e10cSrcweir 					if ( nEdges & 2 )
150cdf0e10cSrcweir 						bOpen = sal_False;	// untere Kante schliesst
151cdf0e10cSrcweir 				}
152cdf0e10cSrcweir 			}
153cdf0e10cSrcweir 			nIndex++;
154cdf0e10cSrcweir 		}
155cdf0e10cSrcweir 		if ( bOpen )
156cdf0e10cSrcweir 			nEdges |= 32;			// es geht noch weiter
157cdf0e10cSrcweir 		return nEdges;
158cdf0e10cSrcweir 	}
159cdf0e10cSrcweir }
160cdf0e10cSrcweir 
161cdf0e10cSrcweir 
HasSelectionMatrixFragment(const ScMarkData & rMark) const162cdf0e10cSrcweir sal_Bool ScColumn::HasSelectionMatrixFragment(const ScMarkData& rMark) const
163cdf0e10cSrcweir {
164cdf0e10cSrcweir 	if ( rMark.IsMultiMarked() )
165cdf0e10cSrcweir 	{
166cdf0e10cSrcweir 		sal_Bool bFound = sal_False;
167cdf0e10cSrcweir 
168cdf0e10cSrcweir 		ScAddress aOrg( ScAddress::INITIALIZE_INVALID );
169cdf0e10cSrcweir 		ScAddress aCurOrg( ScAddress::INITIALIZE_INVALID );
170cdf0e10cSrcweir 		SCROW nTop, nBottom;
171cdf0e10cSrcweir 		ScMarkArrayIter aMarkIter( rMark.GetArray()+nCol );
172cdf0e10cSrcweir 		while ( !bFound && aMarkIter.Next( nTop, nBottom ) )
173cdf0e10cSrcweir 		{
174cdf0e10cSrcweir 			sal_Bool bOpen = sal_False;
175cdf0e10cSrcweir 			sal_uInt16 nEdges;
176cdf0e10cSrcweir 			SCSIZE nIndex;
177cdf0e10cSrcweir 			Search( nTop, nIndex );
178cdf0e10cSrcweir 			while ( !bFound && nIndex < nCount && pItems[nIndex].nRow <= nBottom )
179cdf0e10cSrcweir 			{
180cdf0e10cSrcweir 				ScBaseCell* pCell = pItems[nIndex].pCell;
181cdf0e10cSrcweir 				if ( pCell->GetCellType() == CELLTYPE_FORMULA
182cdf0e10cSrcweir 					&& ((ScFormulaCell*)pCell)->GetMatrixFlag() )
183cdf0e10cSrcweir 				{
184cdf0e10cSrcweir 					nEdges = ((ScFormulaCell*)pCell)->GetMatrixEdge( aOrg );
185cdf0e10cSrcweir 					if ( nEdges )
186cdf0e10cSrcweir 					{
187cdf0e10cSrcweir 						if ( nEdges & 8 )
188cdf0e10cSrcweir 							bOpen = sal_True;	// obere Kante oeffnet, weitersehen
189cdf0e10cSrcweir 						else if ( !bOpen )
190cdf0e10cSrcweir 							return sal_True;	// es gibt was, was nicht geoeffnet wurde
191cdf0e10cSrcweir 						else if ( nEdges & 1 )
192cdf0e10cSrcweir 							bFound = sal_True;	// mittendrin, alles selektiert?
193cdf0e10cSrcweir 						// (4 und nicht 16) oder (16 und nicht 4)
194cdf0e10cSrcweir 						if ( (((nEdges & 4) | 16) ^ ((nEdges & 16) | 4)) )
195cdf0e10cSrcweir 							bFound = sal_True;	// nur linke/rechte Kante, alles selektiert?
196cdf0e10cSrcweir 						if ( nEdges & 2 )
197cdf0e10cSrcweir 							bOpen = sal_False;	// untere Kante schliesst
198cdf0e10cSrcweir 
199cdf0e10cSrcweir 						if ( bFound )
200cdf0e10cSrcweir 						{	// alles selektiert?
201cdf0e10cSrcweir 							if ( aCurOrg != aOrg )
202cdf0e10cSrcweir 							{	// neue Matrix zu pruefen?
203cdf0e10cSrcweir 								aCurOrg = aOrg;
204cdf0e10cSrcweir 								ScFormulaCell* pFCell;
205cdf0e10cSrcweir 								if ( ((ScFormulaCell*)pCell)->GetMatrixFlag()
206cdf0e10cSrcweir 										== MM_REFERENCE )
207cdf0e10cSrcweir 									pFCell = (ScFormulaCell*) pDocument->GetCell( aOrg );
208cdf0e10cSrcweir 								else
209cdf0e10cSrcweir 									pFCell = (ScFormulaCell*)pCell;
210cdf0e10cSrcweir                                 SCCOL nC;
211cdf0e10cSrcweir                                 SCROW nR;
212cdf0e10cSrcweir                                 pFCell->GetMatColsRows( nC, nR );
213cdf0e10cSrcweir 								ScRange aRange( aOrg, ScAddress(
214cdf0e10cSrcweir 									aOrg.Col() + nC - 1, aOrg.Row() + nR - 1,
215cdf0e10cSrcweir 									aOrg.Tab() ) );
216cdf0e10cSrcweir 								if ( rMark.IsAllMarked( aRange ) )
217cdf0e10cSrcweir 									bFound = sal_False;
218cdf0e10cSrcweir 							}
219cdf0e10cSrcweir 							else
220cdf0e10cSrcweir 								bFound = sal_False;		// war schon
221cdf0e10cSrcweir 						}
222cdf0e10cSrcweir 					}
223cdf0e10cSrcweir 				}
224cdf0e10cSrcweir 				nIndex++;
225cdf0e10cSrcweir 			}
226cdf0e10cSrcweir 			if ( bOpen )
227cdf0e10cSrcweir 				return sal_True;
228cdf0e10cSrcweir 		}
229cdf0e10cSrcweir 		return bFound;
230cdf0e10cSrcweir 	}
231cdf0e10cSrcweir 	else
232cdf0e10cSrcweir 		return sal_False;
233cdf0e10cSrcweir }
234cdf0e10cSrcweir 
235cdf0e10cSrcweir 
236cdf0e10cSrcweir //UNUSED2009-05 sal_Bool ScColumn::HasLines( SCROW nRow1, SCROW nRow2, Rectangle& rSizes,
237cdf0e10cSrcweir //UNUSED2009-05                             sal_Bool bLeft, sal_Bool bRight ) const
238cdf0e10cSrcweir //UNUSED2009-05 {
239cdf0e10cSrcweir //UNUSED2009-05     return pAttrArray->HasLines( nRow1, nRow2, rSizes, bLeft, bRight );
240cdf0e10cSrcweir //UNUSED2009-05 }
241cdf0e10cSrcweir 
242cdf0e10cSrcweir 
HasAttrib(SCROW nRow1,SCROW nRow2,sal_uInt16 nMask) const243cdf0e10cSrcweir bool ScColumn::HasAttrib( SCROW nRow1, SCROW nRow2, sal_uInt16 nMask ) const
244cdf0e10cSrcweir {
245cdf0e10cSrcweir 	return pAttrArray->HasAttrib( nRow1, nRow2, nMask );
246cdf0e10cSrcweir }
247cdf0e10cSrcweir 
248cdf0e10cSrcweir 
HasAttribSelection(const ScMarkData & rMark,sal_uInt16 nMask) const249cdf0e10cSrcweir sal_Bool ScColumn::HasAttribSelection( const ScMarkData& rMark, sal_uInt16 nMask ) const
250cdf0e10cSrcweir {
251cdf0e10cSrcweir 	sal_Bool bFound = sal_False;
252cdf0e10cSrcweir 
253cdf0e10cSrcweir 	SCROW nTop;
254cdf0e10cSrcweir 	SCROW nBottom;
255cdf0e10cSrcweir 
256cdf0e10cSrcweir 	if (rMark.IsMultiMarked())
257cdf0e10cSrcweir 	{
258cdf0e10cSrcweir 		ScMarkArrayIter aMarkIter( rMark.GetArray()+nCol );
259cdf0e10cSrcweir 		while (aMarkIter.Next( nTop, nBottom ) && !bFound)
260cdf0e10cSrcweir 		{
261cdf0e10cSrcweir 			if (pAttrArray->HasAttrib( nTop, nBottom, nMask ))
262cdf0e10cSrcweir 				bFound = sal_True;
263cdf0e10cSrcweir 		}
264cdf0e10cSrcweir 	}
265cdf0e10cSrcweir 
266cdf0e10cSrcweir 	return bFound;
267cdf0e10cSrcweir }
268cdf0e10cSrcweir 
269cdf0e10cSrcweir 
ExtendMerge(SCCOL nThisCol,SCROW nStartRow,SCROW nEndRow,SCCOL & rPaintCol,SCROW & rPaintRow,sal_Bool bRefresh,sal_Bool bAttrs)270cdf0e10cSrcweir sal_Bool ScColumn::ExtendMerge( SCCOL nThisCol, SCROW nStartRow, SCROW nEndRow,
271cdf0e10cSrcweir 							SCCOL& rPaintCol, SCROW& rPaintRow,
272cdf0e10cSrcweir 							sal_Bool bRefresh, sal_Bool bAttrs )
273cdf0e10cSrcweir {
274cdf0e10cSrcweir 	return pAttrArray->ExtendMerge( nThisCol, nStartRow, nEndRow, rPaintCol, rPaintRow, bRefresh, bAttrs );
275cdf0e10cSrcweir }
276cdf0e10cSrcweir 
277cdf0e10cSrcweir 
MergeSelectionPattern(ScMergePatternState & rState,const ScMarkData & rMark,sal_Bool bDeep) const278cdf0e10cSrcweir void ScColumn::MergeSelectionPattern( ScMergePatternState& rState, const ScMarkData& rMark, sal_Bool bDeep ) const
279cdf0e10cSrcweir {
280cdf0e10cSrcweir 	SCROW nTop;
281cdf0e10cSrcweir 	SCROW nBottom;
282cdf0e10cSrcweir 
283cdf0e10cSrcweir 	if ( rMark.IsMultiMarked() )
284cdf0e10cSrcweir 	{
285cdf0e10cSrcweir         const ScMarkArray* pArray = rMark.GetArray() + nCol;
286cdf0e10cSrcweir         if ( pArray->HasMarks() )
287cdf0e10cSrcweir         {
288cdf0e10cSrcweir             ScMarkArrayIter aMarkIter( pArray );
289cdf0e10cSrcweir             while (aMarkIter.Next( nTop, nBottom ))
290cdf0e10cSrcweir                 pAttrArray->MergePatternArea( nTop, nBottom, rState, bDeep );
291cdf0e10cSrcweir         }
292cdf0e10cSrcweir 	}
293cdf0e10cSrcweir }
294cdf0e10cSrcweir 
295cdf0e10cSrcweir 
MergePatternArea(ScMergePatternState & rState,SCROW nRow1,SCROW nRow2,sal_Bool bDeep) const296cdf0e10cSrcweir void ScColumn::MergePatternArea( ScMergePatternState& rState, SCROW nRow1, SCROW nRow2, sal_Bool bDeep ) const
297cdf0e10cSrcweir {
298cdf0e10cSrcweir 	pAttrArray->MergePatternArea( nRow1, nRow2, rState, bDeep );
299cdf0e10cSrcweir }
300cdf0e10cSrcweir 
301cdf0e10cSrcweir 
MergeBlockFrame(SvxBoxItem * pLineOuter,SvxBoxInfoItem * pLineInner,ScLineFlags & rFlags,SCROW nStartRow,SCROW nEndRow,sal_Bool bLeft,SCCOL nDistRight) const302cdf0e10cSrcweir void ScColumn::MergeBlockFrame( SvxBoxItem* pLineOuter, SvxBoxInfoItem* pLineInner,
303cdf0e10cSrcweir 							ScLineFlags& rFlags,
304cdf0e10cSrcweir 							SCROW nStartRow, SCROW nEndRow, sal_Bool bLeft, SCCOL nDistRight ) const
305cdf0e10cSrcweir {
306cdf0e10cSrcweir 	pAttrArray->MergeBlockFrame( pLineOuter, pLineInner, rFlags, nStartRow, nEndRow, bLeft, nDistRight );
307cdf0e10cSrcweir }
308cdf0e10cSrcweir 
309cdf0e10cSrcweir 
ApplyBlockFrame(const SvxBoxItem * pLineOuter,const SvxBoxInfoItem * pLineInner,SCROW nStartRow,SCROW nEndRow,sal_Bool bLeft,SCCOL nDistRight)310cdf0e10cSrcweir void ScColumn::ApplyBlockFrame( const SvxBoxItem* pLineOuter, const SvxBoxInfoItem* pLineInner,
311cdf0e10cSrcweir 							SCROW nStartRow, SCROW nEndRow, sal_Bool bLeft, SCCOL nDistRight )
312cdf0e10cSrcweir {
313cdf0e10cSrcweir 	pAttrArray->ApplyBlockFrame( pLineOuter, pLineInner, nStartRow, nEndRow, bLeft, nDistRight );
314cdf0e10cSrcweir }
315cdf0e10cSrcweir 
316cdf0e10cSrcweir 
GetPattern(SCROW nRow) const317cdf0e10cSrcweir const ScPatternAttr* ScColumn::GetPattern( SCROW nRow ) const
318cdf0e10cSrcweir {
319cdf0e10cSrcweir 	return pAttrArray->GetPattern( nRow );
320cdf0e10cSrcweir }
321cdf0e10cSrcweir 
GetPatternRange(SCROW & rStartRow,SCROW & rEndRow,SCROW nRow) const322*3a02adb1SWang Lei const ScPatternAttr* ScColumn::GetPatternRange( SCROW& rStartRow, SCROW& rEndRow, SCROW nRow ) const
323*3a02adb1SWang Lei {
324*3a02adb1SWang Lei 	return pAttrArray->GetPatternRange( rStartRow, rEndRow, nRow );
325*3a02adb1SWang Lei }
326cdf0e10cSrcweir 
GetAttr(SCROW nRow,sal_uInt16 nWhich) const327cdf0e10cSrcweir const SfxPoolItem* ScColumn::GetAttr( SCROW nRow, sal_uInt16 nWhich ) const
328cdf0e10cSrcweir {
329cdf0e10cSrcweir 	return &pAttrArray->GetPattern( nRow )->GetItemSet().Get(nWhich);
330cdf0e10cSrcweir }
331cdf0e10cSrcweir 
332cdf0e10cSrcweir 
GetMostUsedPattern(SCROW nStartRow,SCROW nEndRow) const333cdf0e10cSrcweir const ScPatternAttr* ScColumn::GetMostUsedPattern( SCROW nStartRow, SCROW nEndRow ) const
334cdf0e10cSrcweir {
335cdf0e10cSrcweir     ::std::map< const ScPatternAttr*, size_t > aAttrMap;
336cdf0e10cSrcweir     const ScPatternAttr* pMaxPattern = 0;
337cdf0e10cSrcweir     size_t nMaxCount = 0;
338cdf0e10cSrcweir 
339cdf0e10cSrcweir     ScAttrIterator aAttrIter( pAttrArray, nStartRow, nEndRow );
340cdf0e10cSrcweir     const ScPatternAttr* pPattern;
341cdf0e10cSrcweir     SCROW nAttrRow1 = 0, nAttrRow2 = 0;
342cdf0e10cSrcweir 
343cdf0e10cSrcweir     while( (pPattern = aAttrIter.Next( nAttrRow1, nAttrRow2 )) != 0 )
344cdf0e10cSrcweir     {
345cdf0e10cSrcweir         size_t& rnCount = aAttrMap[ pPattern ];
346cdf0e10cSrcweir         rnCount += (nAttrRow2 - nAttrRow1 + 1);
347cdf0e10cSrcweir         if( rnCount > nMaxCount )
348cdf0e10cSrcweir         {
349cdf0e10cSrcweir             pMaxPattern = pPattern;
350cdf0e10cSrcweir             nMaxCount = rnCount;
351cdf0e10cSrcweir         }
352cdf0e10cSrcweir     }
353cdf0e10cSrcweir 
354cdf0e10cSrcweir     return pMaxPattern;
355cdf0e10cSrcweir }
356cdf0e10cSrcweir 
357cdf0e10cSrcweir 
GetNumberFormat(SCROW nRow) const358cdf0e10cSrcweir sal_uLong ScColumn::GetNumberFormat( SCROW nRow ) const
359cdf0e10cSrcweir {
360cdf0e10cSrcweir 	return pAttrArray->GetPattern( nRow )->GetNumberFormat( pDocument->GetFormatTable() );
361cdf0e10cSrcweir }
362cdf0e10cSrcweir 
363cdf0e10cSrcweir 
ApplySelectionCache(SfxItemPoolCache * pCache,const ScMarkData & rMark)364cdf0e10cSrcweir SCsROW ScColumn::ApplySelectionCache( SfxItemPoolCache* pCache, const ScMarkData& rMark )
365cdf0e10cSrcweir {
366cdf0e10cSrcweir     SCROW nTop = 0;
367cdf0e10cSrcweir     SCROW nBottom = 0;
368cdf0e10cSrcweir 	sal_Bool bFound = sal_False;
369cdf0e10cSrcweir 
370cdf0e10cSrcweir 	if ( rMark.IsMultiMarked() )
371cdf0e10cSrcweir 	{
372cdf0e10cSrcweir 		ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol );
373cdf0e10cSrcweir 		while (aMarkIter.Next( nTop, nBottom ))
374cdf0e10cSrcweir 		{
375cdf0e10cSrcweir 			pAttrArray->ApplyCacheArea( nTop, nBottom, pCache );
376cdf0e10cSrcweir 			bFound = sal_True;
377cdf0e10cSrcweir 		}
378cdf0e10cSrcweir 	}
379cdf0e10cSrcweir 
380cdf0e10cSrcweir 	if (!bFound)
381cdf0e10cSrcweir 		return -1;
382cdf0e10cSrcweir 	else if (nTop==0 && nBottom==MAXROW)
383cdf0e10cSrcweir 		return 0;
384cdf0e10cSrcweir 	else
385cdf0e10cSrcweir 		return nBottom;
386cdf0e10cSrcweir }
387cdf0e10cSrcweir 
388cdf0e10cSrcweir 
ChangeSelectionIndent(sal_Bool bIncrement,const ScMarkData & rMark)389cdf0e10cSrcweir void ScColumn::ChangeSelectionIndent( sal_Bool bIncrement, const ScMarkData& rMark )
390cdf0e10cSrcweir {
391cdf0e10cSrcweir 	SCROW nTop;
392cdf0e10cSrcweir 	SCROW nBottom;
393cdf0e10cSrcweir 
394cdf0e10cSrcweir 	if ( pAttrArray && rMark.IsMultiMarked() )
395cdf0e10cSrcweir 	{
396cdf0e10cSrcweir 		ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol );
397cdf0e10cSrcweir 		while (aMarkIter.Next( nTop, nBottom ))
398cdf0e10cSrcweir 			pAttrArray->ChangeIndent(nTop, nBottom, bIncrement);
399cdf0e10cSrcweir 	}
400cdf0e10cSrcweir }
401cdf0e10cSrcweir 
402cdf0e10cSrcweir 
ClearSelectionItems(const sal_uInt16 * pWhich,const ScMarkData & rMark)403cdf0e10cSrcweir void ScColumn::ClearSelectionItems( const sal_uInt16* pWhich,const ScMarkData& rMark )
404cdf0e10cSrcweir {
405cdf0e10cSrcweir 	SCROW nTop;
406cdf0e10cSrcweir 	SCROW nBottom;
407cdf0e10cSrcweir 
408cdf0e10cSrcweir 	if ( pAttrArray && rMark.IsMultiMarked() )
409cdf0e10cSrcweir 	{
410cdf0e10cSrcweir 		ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol );
411cdf0e10cSrcweir 		while (aMarkIter.Next( nTop, nBottom ))
412cdf0e10cSrcweir 			pAttrArray->ClearItems(nTop, nBottom, pWhich);
413cdf0e10cSrcweir 	}
414cdf0e10cSrcweir }
415cdf0e10cSrcweir 
416cdf0e10cSrcweir 
DeleteSelection(sal_uInt16 nDelFlag,const ScMarkData & rMark)417cdf0e10cSrcweir void ScColumn::DeleteSelection( sal_uInt16 nDelFlag, const ScMarkData& rMark )
418cdf0e10cSrcweir {
419cdf0e10cSrcweir 	SCROW nTop;
420cdf0e10cSrcweir 	SCROW nBottom;
421cdf0e10cSrcweir 
422cdf0e10cSrcweir 	if ( rMark.IsMultiMarked() )
423cdf0e10cSrcweir 	{
424cdf0e10cSrcweir 		ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol );
425cdf0e10cSrcweir 		while (aMarkIter.Next( nTop, nBottom ))
426cdf0e10cSrcweir             DeleteArea(nTop, nBottom, nDelFlag);
427cdf0e10cSrcweir 	}
428cdf0e10cSrcweir }
429cdf0e10cSrcweir 
430cdf0e10cSrcweir 
ApplyPattern(SCROW nRow,const ScPatternAttr & rPatAttr)431cdf0e10cSrcweir void ScColumn::ApplyPattern( SCROW nRow, const ScPatternAttr& rPatAttr )
432cdf0e10cSrcweir {
433cdf0e10cSrcweir 	const SfxItemSet* pSet = &rPatAttr.GetItemSet();
434cdf0e10cSrcweir 	SfxItemPoolCache aCache( pDocument->GetPool(), pSet );
435cdf0e10cSrcweir 
436cdf0e10cSrcweir 	const ScPatternAttr* pPattern = pAttrArray->GetPattern( nRow );
437cdf0e10cSrcweir 
438cdf0e10cSrcweir 	//	sal_True = alten Eintrag behalten
439cdf0e10cSrcweir 
440cdf0e10cSrcweir 	ScPatternAttr* pNewPattern = (ScPatternAttr*) &aCache.ApplyTo( *pPattern, sal_True );
441cdf0e10cSrcweir 	ScDocumentPool::CheckRef( *pPattern );
442cdf0e10cSrcweir 	ScDocumentPool::CheckRef( *pNewPattern );
443cdf0e10cSrcweir 
444cdf0e10cSrcweir 	if (pNewPattern != pPattern)
445cdf0e10cSrcweir 	  pAttrArray->SetPattern( nRow, pNewPattern );
446cdf0e10cSrcweir }
447cdf0e10cSrcweir 
448cdf0e10cSrcweir 
ApplyPatternArea(SCROW nStartRow,SCROW nEndRow,const ScPatternAttr & rPatAttr)449cdf0e10cSrcweir void ScColumn::ApplyPatternArea( SCROW nStartRow, SCROW nEndRow, const ScPatternAttr& rPatAttr )
450cdf0e10cSrcweir {
451cdf0e10cSrcweir 	const SfxItemSet* pSet = &rPatAttr.GetItemSet();
452cdf0e10cSrcweir 	SfxItemPoolCache aCache( pDocument->GetPool(), pSet );
453cdf0e10cSrcweir 	pAttrArray->ApplyCacheArea( nStartRow, nEndRow, &aCache );
454cdf0e10cSrcweir }
455cdf0e10cSrcweir 
456cdf0e10cSrcweir 
ApplyPatternIfNumberformatIncompatible(const ScRange & rRange,const ScPatternAttr & rPattern,short nNewType)457cdf0e10cSrcweir void ScColumn::ApplyPatternIfNumberformatIncompatible( const ScRange& rRange,
458cdf0e10cSrcweir 		const ScPatternAttr& rPattern, short nNewType )
459cdf0e10cSrcweir {
460cdf0e10cSrcweir 	const SfxItemSet* pSet = &rPattern.GetItemSet();
461cdf0e10cSrcweir 	SfxItemPoolCache aCache( pDocument->GetPool(), pSet );
462cdf0e10cSrcweir 	SvNumberFormatter* pFormatter = pDocument->GetFormatTable();
463cdf0e10cSrcweir 	SCROW nEndRow = rRange.aEnd.Row();
464cdf0e10cSrcweir 	for ( SCROW nRow = rRange.aStart.Row(); nRow <= nEndRow; nRow++ )
465cdf0e10cSrcweir 	{
466cdf0e10cSrcweir 		SCROW nRow1, nRow2;
467cdf0e10cSrcweir 		const ScPatternAttr* pPattern = pAttrArray->GetPatternRange(
468cdf0e10cSrcweir 			nRow1, nRow2, nRow );
469cdf0e10cSrcweir 		sal_uLong nFormat = pPattern->GetNumberFormat( pFormatter );
470cdf0e10cSrcweir 		short nOldType = pFormatter->GetType( nFormat );
471cdf0e10cSrcweir 		if ( nOldType == nNewType || pFormatter->IsCompatible( nOldType, nNewType ) )
472cdf0e10cSrcweir 			nRow = nRow2;
473cdf0e10cSrcweir 		else
474cdf0e10cSrcweir 		{
475cdf0e10cSrcweir 			SCROW nNewRow1 = Max( nRow1, nRow );
476cdf0e10cSrcweir 			SCROW nNewRow2 = Min( nRow2, nEndRow );
477cdf0e10cSrcweir 			pAttrArray->ApplyCacheArea( nNewRow1, nNewRow2, &aCache );
478cdf0e10cSrcweir 			nRow = nNewRow2;
479cdf0e10cSrcweir 		}
480cdf0e10cSrcweir 	}
481cdf0e10cSrcweir }
482cdf0e10cSrcweir 
483cdf0e10cSrcweir 
ApplyStyle(SCROW nRow,const ScStyleSheet & rStyle)484cdf0e10cSrcweir void ScColumn::ApplyStyle( SCROW nRow, const ScStyleSheet& rStyle )
485cdf0e10cSrcweir {
486cdf0e10cSrcweir 	const ScPatternAttr* pPattern = pAttrArray->GetPattern(nRow);
487cdf0e10cSrcweir 	ScPatternAttr* pNewPattern = new ScPatternAttr(*pPattern);
488cdf0e10cSrcweir 	if (pNewPattern)
489cdf0e10cSrcweir 	{
490cdf0e10cSrcweir 		pNewPattern->SetStyleSheet((ScStyleSheet*)&rStyle);
491cdf0e10cSrcweir 		pAttrArray->SetPattern(nRow, pNewPattern, sal_True);
492cdf0e10cSrcweir 		delete pNewPattern;
493cdf0e10cSrcweir 	}
494cdf0e10cSrcweir }
495cdf0e10cSrcweir 
496cdf0e10cSrcweir 
ApplyStyleArea(SCROW nStartRow,SCROW nEndRow,const ScStyleSheet & rStyle)497cdf0e10cSrcweir void ScColumn::ApplyStyleArea( SCROW nStartRow, SCROW nEndRow, const ScStyleSheet& rStyle )
498cdf0e10cSrcweir {
499cdf0e10cSrcweir 	pAttrArray->ApplyStyleArea(nStartRow, nEndRow, (ScStyleSheet*)&rStyle);
500cdf0e10cSrcweir }
501cdf0e10cSrcweir 
502cdf0e10cSrcweir 
ApplySelectionStyle(const ScStyleSheet & rStyle,const ScMarkData & rMark)503cdf0e10cSrcweir void ScColumn::ApplySelectionStyle(const ScStyleSheet& rStyle, const ScMarkData& rMark)
504cdf0e10cSrcweir {
505cdf0e10cSrcweir 	SCROW nTop;
506cdf0e10cSrcweir 	SCROW nBottom;
507cdf0e10cSrcweir 
508cdf0e10cSrcweir 	if ( rMark.IsMultiMarked() )
509cdf0e10cSrcweir 	{
510cdf0e10cSrcweir 		ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol );
511cdf0e10cSrcweir 		while (aMarkIter.Next( nTop, nBottom ))
512cdf0e10cSrcweir 			pAttrArray->ApplyStyleArea(nTop, nBottom, (ScStyleSheet*)&rStyle);
513cdf0e10cSrcweir 	}
514cdf0e10cSrcweir }
515cdf0e10cSrcweir 
516cdf0e10cSrcweir 
ApplySelectionLineStyle(const ScMarkData & rMark,const SvxBorderLine * pLine,sal_Bool bColorOnly)517cdf0e10cSrcweir void ScColumn::ApplySelectionLineStyle( const ScMarkData& rMark,
518cdf0e10cSrcweir 									const SvxBorderLine* pLine, sal_Bool bColorOnly )
519cdf0e10cSrcweir {
520cdf0e10cSrcweir 	if ( bColorOnly && !pLine )
521cdf0e10cSrcweir 		return;
522cdf0e10cSrcweir 
523cdf0e10cSrcweir 	SCROW nTop;
524cdf0e10cSrcweir 	SCROW nBottom;
525cdf0e10cSrcweir 
526cdf0e10cSrcweir 	if (rMark.IsMultiMarked())
527cdf0e10cSrcweir 	{
528cdf0e10cSrcweir 		ScMarkArrayIter aMarkIter( rMark.GetArray()+nCol );
529cdf0e10cSrcweir 		while (aMarkIter.Next( nTop, nBottom ))
530cdf0e10cSrcweir 			pAttrArray->ApplyLineStyleArea(nTop, nBottom, pLine, bColorOnly );
531cdf0e10cSrcweir 	}
532cdf0e10cSrcweir }
533cdf0e10cSrcweir 
534cdf0e10cSrcweir 
GetStyle(SCROW nRow) const535cdf0e10cSrcweir const ScStyleSheet* ScColumn::GetStyle( SCROW nRow ) const
536cdf0e10cSrcweir {
537cdf0e10cSrcweir 	return pAttrArray->GetPattern( nRow )->GetStyleSheet();
538cdf0e10cSrcweir }
539cdf0e10cSrcweir 
540cdf0e10cSrcweir 
GetSelectionStyle(const ScMarkData & rMark,sal_Bool & rFound) const541cdf0e10cSrcweir const ScStyleSheet* ScColumn::GetSelectionStyle( const ScMarkData& rMark, sal_Bool& rFound ) const
542cdf0e10cSrcweir {
543cdf0e10cSrcweir 	rFound = sal_False;
544cdf0e10cSrcweir 	if (!rMark.IsMultiMarked())
545cdf0e10cSrcweir 	{
546cdf0e10cSrcweir 		DBG_ERROR("ScColumn::GetSelectionStyle ohne Selektion");
547cdf0e10cSrcweir 		return NULL;
548cdf0e10cSrcweir 	}
549cdf0e10cSrcweir 
550cdf0e10cSrcweir 	sal_Bool bEqual = sal_True;
551cdf0e10cSrcweir 
552cdf0e10cSrcweir 	const ScStyleSheet* pStyle = NULL;
553cdf0e10cSrcweir 	const ScStyleSheet* pNewStyle;
554cdf0e10cSrcweir 
555cdf0e10cSrcweir 	ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol );
556cdf0e10cSrcweir 	SCROW nTop;
557cdf0e10cSrcweir 	SCROW nBottom;
558cdf0e10cSrcweir 	while (bEqual && aMarkIter.Next( nTop, nBottom ))
559cdf0e10cSrcweir 	{
560cdf0e10cSrcweir 		ScAttrIterator aAttrIter( pAttrArray, nTop, nBottom );
561cdf0e10cSrcweir 		SCROW nRow;
562cdf0e10cSrcweir 		SCROW nDummy;
563cdf0e10cSrcweir 		const ScPatternAttr* pPattern;
564cdf0e10cSrcweir         while (bEqual && ( pPattern = aAttrIter.Next( nRow, nDummy ) ) != NULL)
565cdf0e10cSrcweir 		{
566cdf0e10cSrcweir 			pNewStyle = pPattern->GetStyleSheet();
567cdf0e10cSrcweir 			rFound = sal_True;
568cdf0e10cSrcweir 			if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) )
569cdf0e10cSrcweir 				bEqual = sal_False;												// unterschiedliche
570cdf0e10cSrcweir 			pStyle = pNewStyle;
571cdf0e10cSrcweir 		}
572cdf0e10cSrcweir 	}
573cdf0e10cSrcweir 
574cdf0e10cSrcweir 	return bEqual ? pStyle : NULL;
575cdf0e10cSrcweir }
576cdf0e10cSrcweir 
577cdf0e10cSrcweir 
GetAreaStyle(sal_Bool & rFound,SCROW nRow1,SCROW nRow2) const578cdf0e10cSrcweir const ScStyleSheet*	ScColumn::GetAreaStyle( sal_Bool& rFound, SCROW nRow1, SCROW nRow2 ) const
579cdf0e10cSrcweir {
580cdf0e10cSrcweir 	rFound = sal_False;
581cdf0e10cSrcweir 
582cdf0e10cSrcweir 	sal_Bool bEqual = sal_True;
583cdf0e10cSrcweir 
584cdf0e10cSrcweir 	const ScStyleSheet* pStyle = NULL;
585cdf0e10cSrcweir 	const ScStyleSheet* pNewStyle;
586cdf0e10cSrcweir 
587cdf0e10cSrcweir 	ScAttrIterator aAttrIter( pAttrArray, nRow1, nRow2 );
588cdf0e10cSrcweir 	SCROW nRow;
589cdf0e10cSrcweir 	SCROW nDummy;
590cdf0e10cSrcweir 	const ScPatternAttr* pPattern;
591cdf0e10cSrcweir     while (bEqual && ( pPattern = aAttrIter.Next( nRow, nDummy ) ) != NULL)
592cdf0e10cSrcweir 	{
593cdf0e10cSrcweir 		pNewStyle = pPattern->GetStyleSheet();
594cdf0e10cSrcweir 		rFound = sal_True;
595cdf0e10cSrcweir 		if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) )
596cdf0e10cSrcweir 			bEqual = sal_False;												// unterschiedliche
597cdf0e10cSrcweir 		pStyle = pNewStyle;
598cdf0e10cSrcweir 	}
599cdf0e10cSrcweir 
600cdf0e10cSrcweir 	return bEqual ? pStyle : NULL;
601cdf0e10cSrcweir }
602cdf0e10cSrcweir 
FindStyleSheet(const SfxStyleSheetBase * pStyleSheet,ScFlatBoolRowSegments & rUsedRows,bool bReset)603cdf0e10cSrcweir void ScColumn::FindStyleSheet( const SfxStyleSheetBase* pStyleSheet, ScFlatBoolRowSegments& rUsedRows, bool bReset )
604cdf0e10cSrcweir {
605cdf0e10cSrcweir     pAttrArray->FindStyleSheet( pStyleSheet, rUsedRows, bReset );
606cdf0e10cSrcweir }
607cdf0e10cSrcweir 
IsStyleSheetUsed(const ScStyleSheet & rStyle,sal_Bool bGatherAllStyles) const608cdf0e10cSrcweir sal_Bool ScColumn::IsStyleSheetUsed( const ScStyleSheet& rStyle, sal_Bool bGatherAllStyles ) const
609cdf0e10cSrcweir {
610cdf0e10cSrcweir 	return pAttrArray->IsStyleSheetUsed( rStyle, bGatherAllStyles );
611cdf0e10cSrcweir }
612cdf0e10cSrcweir 
613cdf0e10cSrcweir 
ApplyFlags(SCROW nStartRow,SCROW nEndRow,sal_Int16 nFlags)614cdf0e10cSrcweir sal_Bool ScColumn::ApplyFlags( SCROW nStartRow, SCROW nEndRow, sal_Int16 nFlags )
615cdf0e10cSrcweir {
616cdf0e10cSrcweir 	return pAttrArray->ApplyFlags( nStartRow, nEndRow, nFlags );
617cdf0e10cSrcweir }
618cdf0e10cSrcweir 
619cdf0e10cSrcweir 
RemoveFlags(SCROW nStartRow,SCROW nEndRow,sal_Int16 nFlags)620cdf0e10cSrcweir sal_Bool ScColumn::RemoveFlags( SCROW nStartRow, SCROW nEndRow, sal_Int16 nFlags )
621cdf0e10cSrcweir {
622cdf0e10cSrcweir 	return pAttrArray->RemoveFlags( nStartRow, nEndRow, nFlags );
623cdf0e10cSrcweir }
624cdf0e10cSrcweir 
625cdf0e10cSrcweir 
ClearItems(SCROW nStartRow,SCROW nEndRow,const sal_uInt16 * pWhich)626cdf0e10cSrcweir void ScColumn::ClearItems( SCROW nStartRow, SCROW nEndRow, const sal_uInt16* pWhich )
627cdf0e10cSrcweir {
628cdf0e10cSrcweir 	pAttrArray->ClearItems( nStartRow, nEndRow, pWhich );
629cdf0e10cSrcweir }
630cdf0e10cSrcweir 
631cdf0e10cSrcweir 
SetPattern(SCROW nRow,const ScPatternAttr & rPatAttr,sal_Bool bPutToPool)632cdf0e10cSrcweir void ScColumn::SetPattern( SCROW nRow, const ScPatternAttr& rPatAttr, sal_Bool bPutToPool )
633cdf0e10cSrcweir {
634cdf0e10cSrcweir 	pAttrArray->SetPattern( nRow, &rPatAttr, bPutToPool );
635cdf0e10cSrcweir }
636cdf0e10cSrcweir 
637cdf0e10cSrcweir 
SetPatternArea(SCROW nStartRow,SCROW nEndRow,const ScPatternAttr & rPatAttr,sal_Bool bPutToPool)638cdf0e10cSrcweir void ScColumn::SetPatternArea( SCROW nStartRow, SCROW nEndRow,
639cdf0e10cSrcweir 								const ScPatternAttr& rPatAttr, sal_Bool bPutToPool )
640cdf0e10cSrcweir {
641cdf0e10cSrcweir 	pAttrArray->SetPatternArea( nStartRow, nEndRow, &rPatAttr, bPutToPool );
642cdf0e10cSrcweir }
643cdf0e10cSrcweir 
644cdf0e10cSrcweir 
ApplyAttr(SCROW nRow,const SfxPoolItem & rAttr)645cdf0e10cSrcweir void ScColumn::ApplyAttr( SCROW nRow, const SfxPoolItem& rAttr )
646cdf0e10cSrcweir {
647cdf0e10cSrcweir 	//	um nur ein neues SetItem zu erzeugen, brauchen wir keinen SfxItemPoolCache.
648cdf0e10cSrcweir 	//!	Achtung: der SfxItemPoolCache scheint zuviele Refs fuer das neue SetItem zu erzeugen ??
649cdf0e10cSrcweir 
650cdf0e10cSrcweir 	ScDocumentPool* pDocPool = pDocument->GetPool();
651cdf0e10cSrcweir 
652cdf0e10cSrcweir 	const ScPatternAttr* pOldPattern = pAttrArray->GetPattern( nRow );
653cdf0e10cSrcweir 	ScPatternAttr* pTemp = new ScPatternAttr(*pOldPattern);
654cdf0e10cSrcweir 	pTemp->GetItemSet().Put(rAttr);
655cdf0e10cSrcweir 	const ScPatternAttr* pNewPattern = (const ScPatternAttr*) &pDocPool->Put( *pTemp );
656cdf0e10cSrcweir 
657cdf0e10cSrcweir 	if ( pNewPattern != pOldPattern )
658cdf0e10cSrcweir 		pAttrArray->SetPattern( nRow, pNewPattern );
659cdf0e10cSrcweir 	else
660cdf0e10cSrcweir 		pDocPool->Remove( *pNewPattern );		// ausser Spesen nichts gewesen
661cdf0e10cSrcweir 
662cdf0e10cSrcweir 	delete pTemp;
663cdf0e10cSrcweir 
664cdf0e10cSrcweir 		// alte Version mit SfxItemPoolCache:
665cdf0e10cSrcweir #if 0
666cdf0e10cSrcweir 	SfxItemPoolCache aCache( pDocument->GetPool(), &rAttr );
667cdf0e10cSrcweir 
668cdf0e10cSrcweir 	const ScPatternAttr* pPattern = pAttrArray->GetPattern( nRow );
669cdf0e10cSrcweir 
670cdf0e10cSrcweir 	//	sal_True = alten Eintrag behalten
671cdf0e10cSrcweir 
672cdf0e10cSrcweir 	ScPatternAttr* pNewPattern = (ScPatternAttr*) &aCache.ApplyTo( *pPattern, sal_True );
673cdf0e10cSrcweir 	ScDocumentPool::CheckRef( *pPattern );
674cdf0e10cSrcweir 	ScDocumentPool::CheckRef( *pNewPattern );
675cdf0e10cSrcweir 
676cdf0e10cSrcweir 	if (pNewPattern != pPattern)
677cdf0e10cSrcweir 	  pAttrArray->SetPattern( nRow, pNewPattern );
678cdf0e10cSrcweir #endif
679cdf0e10cSrcweir }
680cdf0e10cSrcweir 
681cdf0e10cSrcweir #ifdef _MSC_VER
682cdf0e10cSrcweir #pragma optimize ( "", off )
683cdf0e10cSrcweir #endif
684cdf0e10cSrcweir 
685cdf0e10cSrcweir 
Search(SCROW nRow,SCSIZE & nIndex) const686cdf0e10cSrcweir sal_Bool ScColumn::Search( SCROW nRow, SCSIZE& nIndex ) const
687cdf0e10cSrcweir {
688cdf0e10cSrcweir 	if ( !pItems || !nCount )
689cdf0e10cSrcweir 	{
690cdf0e10cSrcweir 		nIndex = 0;
691cdf0e10cSrcweir 		return sal_False;
692cdf0e10cSrcweir 	}
693cdf0e10cSrcweir 	SCROW nMinRow = pItems[0].nRow;
694cdf0e10cSrcweir 	if ( nRow <= nMinRow )
695cdf0e10cSrcweir 	{
696cdf0e10cSrcweir 		nIndex = 0;
697cdf0e10cSrcweir 		return nRow == nMinRow;
698cdf0e10cSrcweir 	}
699cdf0e10cSrcweir 	SCROW nMaxRow = pItems[nCount-1].nRow;
700cdf0e10cSrcweir 	if ( nRow >= nMaxRow )
701cdf0e10cSrcweir 	{
702cdf0e10cSrcweir 		if ( nRow == nMaxRow )
703cdf0e10cSrcweir 		{
704cdf0e10cSrcweir 			nIndex = nCount - 1;
705cdf0e10cSrcweir 			return sal_True;
706cdf0e10cSrcweir 		}
707cdf0e10cSrcweir 		else
708cdf0e10cSrcweir 		{
709cdf0e10cSrcweir 			nIndex = nCount;
710cdf0e10cSrcweir 			return sal_False;
711cdf0e10cSrcweir 		}
712cdf0e10cSrcweir 	}
713cdf0e10cSrcweir 
714cdf0e10cSrcweir 	long nOldLo, nOldHi;
715cdf0e10cSrcweir 	long	nLo 	= nOldLo = 0;
716cdf0e10cSrcweir     long	nHi 	= nOldHi = Min(static_cast<long>(nCount)-1, static_cast<long>(nRow) );
717cdf0e10cSrcweir 	long	i		= 0;
718cdf0e10cSrcweir 	sal_Bool	bFound	= sal_False;
719cdf0e10cSrcweir 	// quite continuous distribution? => interpolating search
720cdf0e10cSrcweir 	sal_Bool	bInterpol = (static_cast<SCSIZE>(nMaxRow - nMinRow) < nCount * 2);
721cdf0e10cSrcweir 	SCROW	nR;
722cdf0e10cSrcweir 
723cdf0e10cSrcweir 	while ( !bFound && nLo <= nHi )
724cdf0e10cSrcweir 	{
725cdf0e10cSrcweir 		if ( !bInterpol || nHi - nLo < 3 )
726cdf0e10cSrcweir 			i = (nLo+nHi) / 2;			// no effort, no division by zero
727cdf0e10cSrcweir 		else
728cdf0e10cSrcweir 		{	// interpolating search
729cdf0e10cSrcweir 			long nLoRow = pItems[nLo].nRow;		// no unsigned underflow upon substraction
730cdf0e10cSrcweir 			i = nLo + (long)((long)(nRow - nLoRow) * (nHi - nLo)
731cdf0e10cSrcweir 				/ (pItems[nHi].nRow - nLoRow));
732cdf0e10cSrcweir 			if ( i < 0 || static_cast<SCSIZE>(i) >= nCount )
733cdf0e10cSrcweir 			{	// oops ...
734cdf0e10cSrcweir 				i = (nLo+nHi) / 2;
735cdf0e10cSrcweir 				bInterpol = sal_False;
736cdf0e10cSrcweir 			}
737cdf0e10cSrcweir 		}
738cdf0e10cSrcweir 		nR = pItems[i].nRow;
739cdf0e10cSrcweir 		if ( nR < nRow )
740cdf0e10cSrcweir 		{
741cdf0e10cSrcweir 			nLo = i+1;
742cdf0e10cSrcweir 			if ( bInterpol )
743cdf0e10cSrcweir 			{
744cdf0e10cSrcweir 				if ( nLo <= nOldLo )
745cdf0e10cSrcweir 					bInterpol = sal_False;
746cdf0e10cSrcweir 				else
747cdf0e10cSrcweir 					nOldLo = nLo;
748cdf0e10cSrcweir 			}
749cdf0e10cSrcweir 		}
750cdf0e10cSrcweir 		else
751cdf0e10cSrcweir 		{
752cdf0e10cSrcweir 			if ( nR > nRow )
753cdf0e10cSrcweir 			{
754cdf0e10cSrcweir 				nHi = i-1;
755cdf0e10cSrcweir 				if ( bInterpol )
756cdf0e10cSrcweir 				{
757cdf0e10cSrcweir 					if ( nHi >= nOldHi )
758cdf0e10cSrcweir 						bInterpol = sal_False;
759cdf0e10cSrcweir 					else
760cdf0e10cSrcweir 						nOldHi = nHi;
761cdf0e10cSrcweir 				}
762cdf0e10cSrcweir 			}
763cdf0e10cSrcweir 			else
764cdf0e10cSrcweir 				bFound = sal_True;
765cdf0e10cSrcweir 		}
766cdf0e10cSrcweir 	}
767cdf0e10cSrcweir 	if (bFound)
768cdf0e10cSrcweir 		nIndex = static_cast<SCSIZE>(i);
769cdf0e10cSrcweir 	else
770cdf0e10cSrcweir 		nIndex = static_cast<SCSIZE>(nLo); // rear index
771cdf0e10cSrcweir 	return bFound;
772cdf0e10cSrcweir }
773cdf0e10cSrcweir 
774cdf0e10cSrcweir #ifdef _MSC_VER
775cdf0e10cSrcweir #pragma optimize ( "", on )
776cdf0e10cSrcweir #endif
777cdf0e10cSrcweir 
778cdf0e10cSrcweir 
GetCell(SCROW nRow) const779cdf0e10cSrcweir ScBaseCell* ScColumn::GetCell( SCROW nRow ) const
780cdf0e10cSrcweir {
781cdf0e10cSrcweir 	SCSIZE nIndex;
782cdf0e10cSrcweir 	if (Search(nRow, nIndex))
783cdf0e10cSrcweir 		return pItems[nIndex].pCell;
784cdf0e10cSrcweir 	return NULL;
785cdf0e10cSrcweir }
786cdf0e10cSrcweir 
787cdf0e10cSrcweir 
Resize(SCSIZE nSize)788cdf0e10cSrcweir void ScColumn::Resize( SCSIZE nSize )
789cdf0e10cSrcweir {
790cdf0e10cSrcweir     if (nSize > sal::static_int_cast<SCSIZE>(MAXROWCOUNT))
791cdf0e10cSrcweir 		nSize = MAXROWCOUNT;
792cdf0e10cSrcweir 	if (nSize < nCount)
793cdf0e10cSrcweir 		nSize = nCount;
794cdf0e10cSrcweir 
795cdf0e10cSrcweir 	ColEntry* pNewItems;
796cdf0e10cSrcweir 	if (nSize)
797cdf0e10cSrcweir 	{
798cdf0e10cSrcweir 		SCSIZE nNewSize = nSize + COLUMN_DELTA - 1;
799cdf0e10cSrcweir 		nNewSize -= nNewSize % COLUMN_DELTA;
800cdf0e10cSrcweir 		nLimit = nNewSize;
801cdf0e10cSrcweir 		pNewItems = new ColEntry[nLimit];
802cdf0e10cSrcweir 	}
803cdf0e10cSrcweir 	else
804cdf0e10cSrcweir 	{
805cdf0e10cSrcweir 		nLimit = 0;
806cdf0e10cSrcweir 		pNewItems = NULL;
807cdf0e10cSrcweir 	}
808cdf0e10cSrcweir 	if (pItems)
809cdf0e10cSrcweir 	{
810cdf0e10cSrcweir 		if (pNewItems)
811cdf0e10cSrcweir 			memmove( pNewItems, pItems, nCount * sizeof(ColEntry) );
812cdf0e10cSrcweir 		delete[] pItems;
813cdf0e10cSrcweir 	}
814cdf0e10cSrcweir 	pItems = pNewItems;
815cdf0e10cSrcweir }
816cdf0e10cSrcweir 
817cdf0e10cSrcweir //	SwapRow zum Sortieren
818cdf0e10cSrcweir 
819cdf0e10cSrcweir namespace {
820cdf0e10cSrcweir 
821cdf0e10cSrcweir /** Moves broadcaster from old cell to new cell if exists, otherwise creates a new note cell. */
lclTakeBroadcaster(ScBaseCell * & rpCell,SvtBroadcaster * pBC)822cdf0e10cSrcweir void lclTakeBroadcaster( ScBaseCell*& rpCell, SvtBroadcaster* pBC )
823cdf0e10cSrcweir {
824cdf0e10cSrcweir     if( pBC )
825cdf0e10cSrcweir     {
826cdf0e10cSrcweir         if( rpCell )
827cdf0e10cSrcweir             rpCell->TakeBroadcaster( pBC );
828cdf0e10cSrcweir         else
829cdf0e10cSrcweir             rpCell = new ScNoteCell( pBC );
830cdf0e10cSrcweir     }
831cdf0e10cSrcweir }
832cdf0e10cSrcweir 
833cdf0e10cSrcweir } // namespace
834cdf0e10cSrcweir 
SwapRow(SCROW nRow1,SCROW nRow2)835cdf0e10cSrcweir void ScColumn::SwapRow(SCROW nRow1, SCROW nRow2)
836cdf0e10cSrcweir {
837cdf0e10cSrcweir     /*  Simple swap of cell pointers does not work if broadcasters exist (crash
838cdf0e10cSrcweir         if cell broadcasts directly or indirectly to itself). While swapping
839cdf0e10cSrcweir         the cells, broadcasters have to remain at old positions! */
840cdf0e10cSrcweir 
841cdf0e10cSrcweir     /*  While cloning cells, do not clone notes, but move note pointers to new
842cdf0e10cSrcweir         cells. This prevents creation of new caption drawing objects for every
843cdf0e10cSrcweir         swap operation while sorting. */
844cdf0e10cSrcweir 
845cdf0e10cSrcweir 	ScBaseCell* pCell1 = 0;
846cdf0e10cSrcweir 	SCSIZE nIndex1;
847cdf0e10cSrcweir 	if ( Search( nRow1, nIndex1 ) )
848cdf0e10cSrcweir 		pCell1 = pItems[nIndex1].pCell;
849cdf0e10cSrcweir 
850cdf0e10cSrcweir     ScBaseCell* pCell2 = 0;
851cdf0e10cSrcweir 	SCSIZE nIndex2;
852cdf0e10cSrcweir 	if ( Search( nRow2, nIndex2 ) )
853cdf0e10cSrcweir 		pCell2 = pItems[nIndex2].pCell;
854cdf0e10cSrcweir 
855cdf0e10cSrcweir     // no cells found, nothing to do
856cdf0e10cSrcweir 	if ( !pCell1 && !pCell2 )
857cdf0e10cSrcweir 		return ;
858cdf0e10cSrcweir 
859cdf0e10cSrcweir     // swap variables if first cell is empty, to save some code below
860cdf0e10cSrcweir     if ( !pCell1 )
861cdf0e10cSrcweir     {
862cdf0e10cSrcweir         ::std::swap( nRow1, nRow2 );
863cdf0e10cSrcweir         ::std::swap( nIndex1, nIndex2 );
864cdf0e10cSrcweir         ::std::swap( pCell1, pCell2 );
865cdf0e10cSrcweir     }
866cdf0e10cSrcweir 
867cdf0e10cSrcweir     // from here: first cell (pCell1, nIndex1) exists always
868cdf0e10cSrcweir 
869cdf0e10cSrcweir     ScAddress aPos1( nCol, nRow1, nTab );
870cdf0e10cSrcweir     ScAddress aPos2( nCol, nRow2, nTab );
871cdf0e10cSrcweir 
872cdf0e10cSrcweir 	CellType eType1 = pCell1->GetCellType();
873cdf0e10cSrcweir 	CellType eType2 = pCell2 ? pCell2->GetCellType() : CELLTYPE_NONE;
874cdf0e10cSrcweir 
875cdf0e10cSrcweir     ScFormulaCell* pFmlaCell1 = (eType1 == CELLTYPE_FORMULA) ? static_cast< ScFormulaCell* >( pCell1 ) : 0;
876cdf0e10cSrcweir     ScFormulaCell* pFmlaCell2 = (eType2 == CELLTYPE_FORMULA) ? static_cast< ScFormulaCell* >( pCell2 ) : 0;
877cdf0e10cSrcweir 
878cdf0e10cSrcweir     // simple swap if no formula cells present
879cdf0e10cSrcweir 	if ( !pFmlaCell1 && !pFmlaCell2 )
880cdf0e10cSrcweir 	{
881cdf0e10cSrcweir         // remember cell broadcasters, must remain at old position
882cdf0e10cSrcweir         SvtBroadcaster* pBC1 = pCell1->ReleaseBroadcaster();
883cdf0e10cSrcweir 
884cdf0e10cSrcweir 		if ( pCell2 )
885cdf0e10cSrcweir 		{
886cdf0e10cSrcweir             /*  Both cells exist, no formula cells involved, a simple swap can
887cdf0e10cSrcweir                 be performed (but keep broadcasters and notes at old position). */
888cdf0e10cSrcweir 			pItems[nIndex1].pCell = pCell2;
889cdf0e10cSrcweir 			pItems[nIndex2].pCell = pCell1;
890cdf0e10cSrcweir 
891cdf0e10cSrcweir             SvtBroadcaster* pBC2 = pCell2->ReleaseBroadcaster();
892cdf0e10cSrcweir             pCell1->TakeBroadcaster( pBC2 );
893cdf0e10cSrcweir             pCell2->TakeBroadcaster( pBC1 );
894cdf0e10cSrcweir 		}
895cdf0e10cSrcweir 		else
896cdf0e10cSrcweir 		{
897cdf0e10cSrcweir 			ScNoteCell* pDummyCell = pBC1 ? new ScNoteCell( pBC1 ) : 0;
898cdf0e10cSrcweir 			if ( pDummyCell )
899cdf0e10cSrcweir 			{
900cdf0e10cSrcweir                 // insert dummy note cell (without note) containing old broadcaster
901cdf0e10cSrcweir 				pItems[nIndex1].pCell = pDummyCell;
902cdf0e10cSrcweir 			}
903cdf0e10cSrcweir 			else
904cdf0e10cSrcweir 			{
905cdf0e10cSrcweir                 // remove ColEntry at old position
906cdf0e10cSrcweir 				--nCount;
907cdf0e10cSrcweir 				memmove( &pItems[nIndex1], &pItems[nIndex1 + 1], (nCount - nIndex1) * sizeof(ColEntry) );
908cdf0e10cSrcweir 				pItems[nCount].nRow = 0;
909cdf0e10cSrcweir 				pItems[nCount].pCell = 0;
910cdf0e10cSrcweir 			}
911cdf0e10cSrcweir 
912cdf0e10cSrcweir             // insert ColEntry at new position
913cdf0e10cSrcweir 			Insert( nRow2, pCell1 );
914cdf0e10cSrcweir 		}
915cdf0e10cSrcweir 
916cdf0e10cSrcweir 		return;
917cdf0e10cSrcweir 	}
918cdf0e10cSrcweir 
919cdf0e10cSrcweir 	// from here: at least one of the cells is a formula cell
920cdf0e10cSrcweir 
921cdf0e10cSrcweir     /*  Never move any array formulas. Disabling sort if parts of array
922cdf0e10cSrcweir         formulas are contained is done at UI. */
923cdf0e10cSrcweir     if ( (pFmlaCell1 && (pFmlaCell1->GetMatrixFlag() != 0)) || (pFmlaCell2 && (pFmlaCell2->GetMatrixFlag() != 0)) )
924cdf0e10cSrcweir         return;
925cdf0e10cSrcweir 
926cdf0e10cSrcweir     // do not swap, if formulas are equal
927cdf0e10cSrcweir 	if ( pFmlaCell1 && pFmlaCell2 )
928cdf0e10cSrcweir 	{
929cdf0e10cSrcweir 		ScTokenArray* pCode1 = pFmlaCell1->GetCode();
930cdf0e10cSrcweir 		ScTokenArray* pCode2 = pFmlaCell2->GetCode();
931cdf0e10cSrcweir 
932cdf0e10cSrcweir 		if (pCode1->GetLen() == pCode2->GetLen())		// nicht-UPN
933cdf0e10cSrcweir 		{
934cdf0e10cSrcweir 			sal_Bool bEqual = sal_True;
935cdf0e10cSrcweir 			sal_uInt16 nLen = pCode1->GetLen();
936cdf0e10cSrcweir 			FormulaToken** ppToken1 = pCode1->GetArray();
937cdf0e10cSrcweir 			FormulaToken** ppToken2 = pCode2->GetArray();
938cdf0e10cSrcweir 			for (sal_uInt16 i=0; i<nLen; i++)
939cdf0e10cSrcweir             {
940cdf0e10cSrcweir                 if ( !ppToken1[i]->TextEqual(*(ppToken2[i])) ||
941cdf0e10cSrcweir                         ppToken1[i]->Is3DRef() || ppToken2[i]->Is3DRef() )
942cdf0e10cSrcweir 				{
943cdf0e10cSrcweir 					bEqual = sal_False;
944cdf0e10cSrcweir 					break;
945cdf0e10cSrcweir 				}
946cdf0e10cSrcweir             }
947cdf0e10cSrcweir 
948cdf0e10cSrcweir             // do not swap formula cells with equal formulas, but swap notes
949cdf0e10cSrcweir 			if (bEqual)
950cdf0e10cSrcweir             {
951cdf0e10cSrcweir                 ScPostIt* pNote1 = pCell1->ReleaseNote();
952cdf0e10cSrcweir                 pCell1->TakeNote( pCell2->ReleaseNote() );
953cdf0e10cSrcweir                 pCell2->TakeNote( pNote1 );
954cdf0e10cSrcweir 				return;
955cdf0e10cSrcweir             }
956cdf0e10cSrcweir 		}
957cdf0e10cSrcweir 	}
958cdf0e10cSrcweir 
959cdf0e10cSrcweir 	//	hier kein UpdateReference wegen #30529# - mitsortiert werden nur noch relative Referenzen
960cdf0e10cSrcweir //	long dy = (long)nRow2 - (long)nRow1;
961cdf0e10cSrcweir 
962cdf0e10cSrcweir     /*  Create clone of pCell1 at position of pCell2 (pCell1 exists always, see
963cdf0e10cSrcweir         variable swapping above). Do not clone the note, but move pointer of
964cdf0e10cSrcweir         old note to new cell. */
965cdf0e10cSrcweir     ScBaseCell* pNew2 = pCell1->CloneWithoutNote( *pDocument, aPos2, SC_CLONECELL_ADJUST3DREL );
966cdf0e10cSrcweir     pNew2->TakeNote( pCell1->ReleaseNote() );
967cdf0e10cSrcweir 
968cdf0e10cSrcweir     /*  Create clone of pCell2 at position of pCell1. Do not clone the note,
969cdf0e10cSrcweir         but move pointer of old note to new cell. */
970cdf0e10cSrcweir 	ScBaseCell* pNew1 = 0;
971cdf0e10cSrcweir 	if ( pCell2 )
972cdf0e10cSrcweir 	{
973cdf0e10cSrcweir         pNew1 = pCell2->CloneWithoutNote( *pDocument, aPos1, SC_CLONECELL_ADJUST3DREL );
974cdf0e10cSrcweir         pNew1->TakeNote( pCell2->ReleaseNote() );
975cdf0e10cSrcweir 	}
976cdf0e10cSrcweir 
977cdf0e10cSrcweir     // move old broadcasters new cells at the same old position
978cdf0e10cSrcweir     SvtBroadcaster* pBC1 = pCell1->ReleaseBroadcaster();
979cdf0e10cSrcweir     lclTakeBroadcaster( pNew1, pBC1 );
980cdf0e10cSrcweir     SvtBroadcaster* pBC2 = pCell2 ? pCell2->ReleaseBroadcaster() : 0;
981cdf0e10cSrcweir     lclTakeBroadcaster( pNew2, pBC2 );
982cdf0e10cSrcweir 
983cdf0e10cSrcweir 	/*  Insert the new cells. Old cell has to be deleted, if there is no new
984cdf0e10cSrcweir         cell (call to Insert deletes old cell by itself). */
985cdf0e10cSrcweir 	if ( !pNew1 )
986cdf0e10cSrcweir 		Delete( nRow1 );            // deletes pCell1
987cdf0e10cSrcweir 	else
988cdf0e10cSrcweir         Insert( nRow1, pNew1 );     // deletes pCell1, inserts pNew1
989cdf0e10cSrcweir 
990cdf0e10cSrcweir 	if ( pCell2 && !pNew2 )
991cdf0e10cSrcweir 		Delete( nRow2 );            // deletes pCell2
992cdf0e10cSrcweir 	else if ( pNew2 )
993cdf0e10cSrcweir 		Insert( nRow2, pNew2 );     // deletes pCell2 (if existing), inserts pNew2
994cdf0e10cSrcweir }
995cdf0e10cSrcweir 
996cdf0e10cSrcweir 
SwapCell(SCROW nRow,ScColumn & rCol)997cdf0e10cSrcweir void ScColumn::SwapCell( SCROW nRow, ScColumn& rCol)
998cdf0e10cSrcweir {
999cdf0e10cSrcweir 	ScBaseCell* pCell1 = 0;
1000cdf0e10cSrcweir 	SCSIZE nIndex1;
1001cdf0e10cSrcweir 	if ( Search( nRow, nIndex1 ) )
1002cdf0e10cSrcweir 		pCell1 = pItems[nIndex1].pCell;
1003cdf0e10cSrcweir 
1004cdf0e10cSrcweir     ScBaseCell* pCell2 = 0;
1005cdf0e10cSrcweir 	SCSIZE nIndex2;
1006cdf0e10cSrcweir 	if ( rCol.Search( nRow, nIndex2 ) )
1007cdf0e10cSrcweir 		pCell2 = rCol.pItems[nIndex2].pCell;
1008cdf0e10cSrcweir 
1009cdf0e10cSrcweir     // reverse call if own cell is missing (ensures own existing cell in following code)
1010cdf0e10cSrcweir     if( !pCell1 )
1011cdf0e10cSrcweir     {
1012cdf0e10cSrcweir         if( pCell2 )
1013cdf0e10cSrcweir             rCol.SwapCell( nRow, *this );
1014cdf0e10cSrcweir         return;
1015cdf0e10cSrcweir     }
1016cdf0e10cSrcweir 
1017cdf0e10cSrcweir     // from here: own cell (pCell1, nIndex1) exists always
1018cdf0e10cSrcweir 
1019cdf0e10cSrcweir     ScFormulaCell* pFmlaCell1 = (pCell1->GetCellType() == CELLTYPE_FORMULA) ? static_cast< ScFormulaCell* >( pCell1 ) : 0;
1020cdf0e10cSrcweir 	ScFormulaCell* pFmlaCell2 = (pCell2 && (pCell2->GetCellType() == CELLTYPE_FORMULA)) ? static_cast< ScFormulaCell* >( pCell2 ) : 0;
1021cdf0e10cSrcweir 
1022cdf0e10cSrcweir 	if ( pCell2 )
1023cdf0e10cSrcweir 	{
1024cdf0e10cSrcweir 		// Tauschen
1025cdf0e10cSrcweir 		pItems[nIndex1].pCell = pCell2;
1026cdf0e10cSrcweir 		rCol.pItems[nIndex2].pCell = pCell1;
1027cdf0e10cSrcweir 		// Referenzen aktualisieren
1028cdf0e10cSrcweir 		SCsCOL dx = rCol.nCol - nCol;
1029cdf0e10cSrcweir 		if ( pFmlaCell1 )
1030cdf0e10cSrcweir 		{
1031cdf0e10cSrcweir 			ScRange aRange( ScAddress( rCol.nCol, 0, nTab ),
1032cdf0e10cSrcweir 							ScAddress( rCol.nCol, MAXROW, nTab ) );
1033cdf0e10cSrcweir 			pFmlaCell1->aPos.SetCol( rCol.nCol );
1034cdf0e10cSrcweir 			pFmlaCell1->UpdateReference(URM_MOVE, aRange, dx, 0, 0);
1035cdf0e10cSrcweir 		}
1036cdf0e10cSrcweir 		if ( pFmlaCell2 )
1037cdf0e10cSrcweir 		{
1038cdf0e10cSrcweir 			ScRange aRange( ScAddress( nCol, 0, nTab ),
1039cdf0e10cSrcweir 							ScAddress( nCol, MAXROW, nTab ) );
1040cdf0e10cSrcweir 			pFmlaCell2->aPos.SetCol( nCol );
1041cdf0e10cSrcweir 			pFmlaCell2->UpdateReference(URM_MOVE, aRange, -dx, 0, 0);
1042cdf0e10cSrcweir 		}
1043cdf0e10cSrcweir 	}
1044cdf0e10cSrcweir 	else
1045cdf0e10cSrcweir     {
1046cdf0e10cSrcweir         // Loeschen
1047cdf0e10cSrcweir         --nCount;
1048cdf0e10cSrcweir         memmove( &pItems[nIndex1], &pItems[nIndex1 + 1], (nCount - nIndex1) * sizeof(ColEntry) );
1049cdf0e10cSrcweir         pItems[nCount].nRow = 0;
1050cdf0e10cSrcweir         pItems[nCount].pCell = 0;
1051cdf0e10cSrcweir         // Referenzen aktualisieren
1052cdf0e10cSrcweir         SCsCOL dx = rCol.nCol - nCol;
1053cdf0e10cSrcweir         if ( pFmlaCell1 )
1054cdf0e10cSrcweir         {
1055cdf0e10cSrcweir             ScRange aRange( ScAddress( rCol.nCol, 0, nTab ),
1056cdf0e10cSrcweir                             ScAddress( rCol.nCol, MAXROW, nTab ) );
1057cdf0e10cSrcweir             pFmlaCell1->aPos.SetCol( rCol.nCol );
1058cdf0e10cSrcweir             pFmlaCell1->UpdateReference(URM_MOVE, aRange, dx, 0, 0);
1059cdf0e10cSrcweir         }
1060cdf0e10cSrcweir         // Einfuegen
1061cdf0e10cSrcweir         rCol.Insert(nRow, pCell1);
1062cdf0e10cSrcweir     }
1063cdf0e10cSrcweir }
1064cdf0e10cSrcweir 
1065cdf0e10cSrcweir 
TestInsertCol(SCROW nStartRow,SCROW nEndRow) const1066cdf0e10cSrcweir sal_Bool ScColumn::TestInsertCol( SCROW nStartRow, SCROW nEndRow) const
1067cdf0e10cSrcweir {
1068cdf0e10cSrcweir 	if (!IsEmpty())
1069cdf0e10cSrcweir 	{
1070cdf0e10cSrcweir 		sal_Bool bTest = sal_True;
1071cdf0e10cSrcweir 		if (pItems)
1072cdf0e10cSrcweir 			for (SCSIZE i=0; (i<nCount) && bTest; i++)
1073cdf0e10cSrcweir 				bTest = (pItems[i].nRow < nStartRow) || (pItems[i].nRow > nEndRow)
1074cdf0e10cSrcweir                         || pItems[i].pCell->IsBlank();
1075cdf0e10cSrcweir 
1076cdf0e10cSrcweir 		//	AttrArray testet nur zusammengefasste
1077cdf0e10cSrcweir 
1078cdf0e10cSrcweir 		if ((bTest) && (pAttrArray))
1079cdf0e10cSrcweir 			bTest = pAttrArray->TestInsertCol(nStartRow, nEndRow);
1080cdf0e10cSrcweir 
1081cdf0e10cSrcweir 		//!		rausgeschobene Attribute bei Undo beruecksichtigen
1082cdf0e10cSrcweir 
1083cdf0e10cSrcweir 		return bTest;
1084cdf0e10cSrcweir 	}
1085cdf0e10cSrcweir 	else
1086cdf0e10cSrcweir 		return sal_True;
1087cdf0e10cSrcweir }
1088cdf0e10cSrcweir 
1089cdf0e10cSrcweir 
TestInsertRow(SCSIZE nSize) const1090cdf0e10cSrcweir sal_Bool ScColumn::TestInsertRow( SCSIZE nSize ) const
1091cdf0e10cSrcweir {
1092cdf0e10cSrcweir     //  AttrArray only looks for merged cells
1093cdf0e10cSrcweir 
1094cdf0e10cSrcweir 	if ( pItems && nCount )
1095cdf0e10cSrcweir         return ( nSize <= sal::static_int_cast<SCSIZE>(MAXROW) &&
1096cdf0e10cSrcweir                  pItems[nCount-1].nRow <= MAXROW-(SCROW)nSize && pAttrArray->TestInsertRow( nSize ) );
1097cdf0e10cSrcweir 	else
1098cdf0e10cSrcweir 		return pAttrArray->TestInsertRow( nSize );
1099cdf0e10cSrcweir 
1100cdf0e10cSrcweir #if 0
1101cdf0e10cSrcweir 	//!		rausgeschobene Attribute bei Undo beruecksichtigen
1102cdf0e10cSrcweir 
1103cdf0e10cSrcweir 	if ( nSize > static_cast<SCSIZE>(MAXROW) )
1104cdf0e10cSrcweir 		return sal_False;
1105cdf0e10cSrcweir 
1106cdf0e10cSrcweir 	SCSIZE nVis = nCount;
1107cdf0e10cSrcweir     while ( nVis && pItems[nVis-1].pCell->IsBlank() )
1108cdf0e10cSrcweir 		--nVis;
1109cdf0e10cSrcweir 
1110cdf0e10cSrcweir 	if ( nVis )
1111cdf0e10cSrcweir 		return ( pItems[nVis-1].nRow <= MAXROW-nSize );
1112cdf0e10cSrcweir 	else
1113cdf0e10cSrcweir 		return sal_True;
1114cdf0e10cSrcweir #endif
1115cdf0e10cSrcweir }
1116cdf0e10cSrcweir 
1117cdf0e10cSrcweir 
InsertRow(SCROW nStartRow,SCSIZE nSize)1118cdf0e10cSrcweir void ScColumn::InsertRow( SCROW nStartRow, SCSIZE nSize )
1119cdf0e10cSrcweir {
1120cdf0e10cSrcweir 	pAttrArray->InsertRow( nStartRow, nSize );
1121cdf0e10cSrcweir 
1122cdf0e10cSrcweir 	//!	Search
1123cdf0e10cSrcweir 
1124cdf0e10cSrcweir 	if ( !pItems || !nCount )
1125cdf0e10cSrcweir 		return;
1126cdf0e10cSrcweir 
1127cdf0e10cSrcweir 	SCSIZE i;
1128cdf0e10cSrcweir 	Search( nStartRow, i );
1129cdf0e10cSrcweir 	if ( i >= nCount )
1130cdf0e10cSrcweir 		return ;
1131cdf0e10cSrcweir 
1132cdf0e10cSrcweir 	sal_Bool bOldAutoCalc = pDocument->GetAutoCalc();
1133cdf0e10cSrcweir 	pDocument->SetAutoCalc( sal_False );	// Mehrfachberechnungen vermeiden
1134cdf0e10cSrcweir 
1135cdf0e10cSrcweir 	SCSIZE nNewCount = nCount;
1136cdf0e10cSrcweir 	sal_Bool bCountChanged = sal_False;
1137cdf0e10cSrcweir 	ScAddress aAdr( nCol, 0, nTab );
1138cdf0e10cSrcweir     ScHint aHint( SC_HINT_DATACHANGED, aAdr, NULL );    // only areas (ScBaseCell* == NULL)
1139cdf0e10cSrcweir     ScAddress& rAddress = aHint.GetAddress();
1140cdf0e10cSrcweir     // for sparse occupation use single broadcasts, not ranges
1141cdf0e10cSrcweir     sal_Bool bSingleBroadcasts = (((pItems[nCount-1].nRow - pItems[i].nRow) /
1142cdf0e10cSrcweir                 (nCount - i)) > 1);
1143cdf0e10cSrcweir     if ( bSingleBroadcasts )
1144cdf0e10cSrcweir     {
1145cdf0e10cSrcweir         SCROW nLastBroadcast = MAXROW+1;
1146cdf0e10cSrcweir         for ( ; i < nCount; i++)
1147cdf0e10cSrcweir         {
1148cdf0e10cSrcweir             SCROW nOldRow = pItems[i].nRow;
1149cdf0e10cSrcweir             // #43940# Aenderung Quelle broadcasten
1150cdf0e10cSrcweir             if ( nLastBroadcast != nOldRow )
1151cdf0e10cSrcweir             {   // direkt aufeinanderfolgende nicht doppelt broadcasten
1152cdf0e10cSrcweir                 rAddress.SetRow( nOldRow );
1153cdf0e10cSrcweir                 pDocument->AreaBroadcast( aHint );
1154cdf0e10cSrcweir             }
1155cdf0e10cSrcweir             SCROW nNewRow = (pItems[i].nRow += nSize);
1156cdf0e10cSrcweir             // #43940# Aenderung Ziel broadcasten
1157cdf0e10cSrcweir             rAddress.SetRow( nNewRow );
1158cdf0e10cSrcweir             pDocument->AreaBroadcast( aHint );
1159cdf0e10cSrcweir             nLastBroadcast = nNewRow;
1160cdf0e10cSrcweir             ScBaseCell* pCell = pItems[i].pCell;
1161cdf0e10cSrcweir             if ( pCell->GetCellType() == CELLTYPE_FORMULA )
1162cdf0e10cSrcweir                 ((ScFormulaCell*)pCell)->aPos.SetRow( nNewRow );
1163cdf0e10cSrcweir             if ( nNewRow > MAXROW && !bCountChanged )
1164cdf0e10cSrcweir             {
1165cdf0e10cSrcweir                 nNewCount = i;
1166cdf0e10cSrcweir                 bCountChanged = sal_True;
1167cdf0e10cSrcweir             }
1168cdf0e10cSrcweir         }
1169cdf0e10cSrcweir     }
1170cdf0e10cSrcweir     else
1171cdf0e10cSrcweir     {
1172cdf0e10cSrcweir         rAddress.SetRow( pItems[i].nRow );
1173cdf0e10cSrcweir         ScRange aRange( rAddress );
1174cdf0e10cSrcweir         for ( ; i < nCount; i++)
1175cdf0e10cSrcweir         {
1176cdf0e10cSrcweir             SCROW nNewRow = (pItems[i].nRow += nSize);
1177cdf0e10cSrcweir             ScBaseCell* pCell = pItems[i].pCell;
1178cdf0e10cSrcweir             if ( pCell->GetCellType() == CELLTYPE_FORMULA )
1179cdf0e10cSrcweir                 ((ScFormulaCell*)pCell)->aPos.SetRow( nNewRow );
1180cdf0e10cSrcweir             if ( nNewRow > MAXROW && !bCountChanged )
1181cdf0e10cSrcweir             {
1182cdf0e10cSrcweir                 nNewCount = i;
1183cdf0e10cSrcweir                 bCountChanged = sal_True;
1184cdf0e10cSrcweir                 aRange.aEnd.SetRow( MAXROW );
1185cdf0e10cSrcweir             }
1186cdf0e10cSrcweir         }
1187cdf0e10cSrcweir         if ( !bCountChanged )
1188cdf0e10cSrcweir             aRange.aEnd.SetRow( pItems[nCount-1].nRow );
1189cdf0e10cSrcweir         pDocument->AreaBroadcastInRange( aRange, aHint );
1190cdf0e10cSrcweir     }
1191cdf0e10cSrcweir 
1192cdf0e10cSrcweir 	if (bCountChanged)
1193cdf0e10cSrcweir 	{
1194cdf0e10cSrcweir 		SCSIZE nDelCount = nCount - nNewCount;
1195cdf0e10cSrcweir 		ScBaseCell** ppDelCells = new ScBaseCell*[nDelCount];
1196cdf0e10cSrcweir 		SCROW* pDelRows = new SCROW[nDelCount];
1197cdf0e10cSrcweir 		for (i = 0; i < nDelCount; i++)
1198cdf0e10cSrcweir 		{
1199cdf0e10cSrcweir 			ppDelCells[i] = pItems[nNewCount+i].pCell;
1200cdf0e10cSrcweir 			pDelRows[i] = pItems[nNewCount+i].nRow;
1201cdf0e10cSrcweir 		}
1202cdf0e10cSrcweir 		nCount = nNewCount;
1203cdf0e10cSrcweir 
1204cdf0e10cSrcweir 		for (i = 0; i < nDelCount; i++)
1205cdf0e10cSrcweir 		{
1206cdf0e10cSrcweir 			ScBaseCell* pCell = ppDelCells[i];
1207cdf0e10cSrcweir             DBG_ASSERT( pCell->IsBlank(), "sichtbare Zelle weggeschoben" );
1208cdf0e10cSrcweir 			SvtBroadcaster* pBC = pCell->GetBroadcaster();
1209cdf0e10cSrcweir 			if (pBC)
1210cdf0e10cSrcweir 			{
1211cdf0e10cSrcweir 				MoveListeners( *pBC, pDelRows[i] - nSize );
1212cdf0e10cSrcweir                 pCell->DeleteBroadcaster();
1213cdf0e10cSrcweir 				pCell->Delete();
1214cdf0e10cSrcweir 			}
1215cdf0e10cSrcweir 		}
1216cdf0e10cSrcweir 
1217cdf0e10cSrcweir 		delete [] pDelRows;
1218cdf0e10cSrcweir 		delete [] ppDelCells;
1219cdf0e10cSrcweir 	}
1220cdf0e10cSrcweir 
1221cdf0e10cSrcweir 	pDocument->SetAutoCalc( bOldAutoCalc );
1222cdf0e10cSrcweir }
1223cdf0e10cSrcweir 
1224cdf0e10cSrcweir 
CopyToClip(SCROW nRow1,SCROW nRow2,ScColumn & rColumn,sal_Bool bKeepScenarioFlags,sal_Bool bCloneNoteCaptions)1225cdf0e10cSrcweir void ScColumn::CopyToClip(SCROW nRow1, SCROW nRow2, ScColumn& rColumn, sal_Bool bKeepScenarioFlags, sal_Bool bCloneNoteCaptions)
1226cdf0e10cSrcweir {
1227cdf0e10cSrcweir 	pAttrArray->CopyArea( nRow1, nRow2, 0, *rColumn.pAttrArray,
1228cdf0e10cSrcweir 							bKeepScenarioFlags ? (SC_MF_ALL & ~SC_MF_SCENARIO) : SC_MF_ALL );
1229cdf0e10cSrcweir 
1230cdf0e10cSrcweir 	SCSIZE i;
1231cdf0e10cSrcweir 	SCSIZE nBlockCount = 0;
1232cdf0e10cSrcweir     SCSIZE nStartIndex = 0, nEndIndex = 0;
1233cdf0e10cSrcweir 	for (i = 0; i < nCount; i++)
1234cdf0e10cSrcweir 		if ((pItems[i].nRow >= nRow1) && (pItems[i].nRow <= nRow2))
1235cdf0e10cSrcweir 		{
1236cdf0e10cSrcweir 			if (!nBlockCount)
1237cdf0e10cSrcweir 				nStartIndex = i;
1238cdf0e10cSrcweir 			nEndIndex = i;
1239cdf0e10cSrcweir 			++nBlockCount;
1240cdf0e10cSrcweir 
1241cdf0e10cSrcweir 			//	im Clipboard muessen interpretierte Zellen stehen, um andere Formate
1242cdf0e10cSrcweir 			//	(Text, Grafik...) erzueugen zu koennen
1243cdf0e10cSrcweir 
1244cdf0e10cSrcweir 			if ( pItems[i].pCell->GetCellType() == CELLTYPE_FORMULA )
1245cdf0e10cSrcweir 			{
1246cdf0e10cSrcweir 				ScFormulaCell* pFCell = (ScFormulaCell*) pItems[i].pCell;
1247cdf0e10cSrcweir 				if (pFCell->GetDirty() && pDocument->GetAutoCalc())
1248cdf0e10cSrcweir 					pFCell->Interpret();
1249cdf0e10cSrcweir 			}
1250cdf0e10cSrcweir 		}
1251cdf0e10cSrcweir 
1252cdf0e10cSrcweir 	if (nBlockCount)
1253cdf0e10cSrcweir 	{
1254cdf0e10cSrcweir         int nCloneFlags = bCloneNoteCaptions ? SC_CLONECELL_DEFAULT : SC_CLONECELL_NOCAPTION;
1255cdf0e10cSrcweir 		rColumn.Resize( rColumn.GetCellCount() + nBlockCount );
1256cdf0e10cSrcweir         ScAddress aOwnPos( nCol, 0, nTab );
1257cdf0e10cSrcweir         ScAddress aDestPos( rColumn.nCol, 0, rColumn.nTab );
1258cdf0e10cSrcweir 		for (i = nStartIndex; i <= nEndIndex; i++)
1259cdf0e10cSrcweir         {
1260cdf0e10cSrcweir             aOwnPos.SetRow( pItems[i].nRow );
1261cdf0e10cSrcweir             aDestPos.SetRow( pItems[i].nRow );
1262cdf0e10cSrcweir             ScBaseCell* pNewCell = pItems[i].pCell->CloneWithNote( aOwnPos, *rColumn.pDocument, aDestPos, nCloneFlags );
1263cdf0e10cSrcweir             rColumn.Append( aDestPos.Row(), pNewCell );
1264cdf0e10cSrcweir         }
1265cdf0e10cSrcweir 	}
1266cdf0e10cSrcweir }
1267cdf0e10cSrcweir 
1268cdf0e10cSrcweir 
CopyToColumn(SCROW nRow1,SCROW nRow2,sal_uInt16 nFlags,sal_Bool bMarked,ScColumn & rColumn,const ScMarkData * pMarkData,sal_Bool bAsLink)1269cdf0e10cSrcweir void ScColumn::CopyToColumn(SCROW nRow1, SCROW nRow2, sal_uInt16 nFlags, sal_Bool bMarked,
1270cdf0e10cSrcweir 								ScColumn& rColumn, const ScMarkData* pMarkData, sal_Bool bAsLink )
1271cdf0e10cSrcweir {
1272cdf0e10cSrcweir 	if (bMarked)
1273cdf0e10cSrcweir 	{
1274cdf0e10cSrcweir 		SCROW nStart, nEnd;
1275cdf0e10cSrcweir 		if (pMarkData && pMarkData->IsMultiMarked())
1276cdf0e10cSrcweir 		{
1277cdf0e10cSrcweir 			ScMarkArrayIter aIter( pMarkData->GetArray()+nCol );
1278cdf0e10cSrcweir 
1279cdf0e10cSrcweir 			while ( aIter.Next( nStart, nEnd ) && nStart <= nRow2 )
1280cdf0e10cSrcweir 			{
1281cdf0e10cSrcweir 				if ( nEnd >= nRow1 )
1282cdf0e10cSrcweir 					CopyToColumn( Max(nRow1,nStart), Min(nRow2,nEnd),
1283cdf0e10cSrcweir 									nFlags, sal_False, rColumn, pMarkData, bAsLink );
1284cdf0e10cSrcweir 			}
1285cdf0e10cSrcweir 		}
1286cdf0e10cSrcweir 		else
1287cdf0e10cSrcweir 		{
1288cdf0e10cSrcweir 			DBG_ERROR("CopyToColumn: bMarked, aber keine Markierung");
1289cdf0e10cSrcweir 		}
1290cdf0e10cSrcweir 		return;
1291cdf0e10cSrcweir 	}
1292cdf0e10cSrcweir 
1293cdf0e10cSrcweir 	if ( (nFlags & IDF_ATTRIB) != 0 )
1294cdf0e10cSrcweir 	{
1295cdf0e10cSrcweir 		if ( (nFlags & IDF_STYLES) != IDF_STYLES )
1296cdf0e10cSrcweir 		{	// StyleSheets im Zieldokument bleiben erhalten
1297cdf0e10cSrcweir 			// z.B. DIF und RTF Clipboard-Import
1298cdf0e10cSrcweir 			for ( SCROW nRow = nRow1; nRow <= nRow2; nRow++ )
1299cdf0e10cSrcweir 			{
1300cdf0e10cSrcweir 				const ScStyleSheet* pStyle =
1301cdf0e10cSrcweir 					rColumn.pAttrArray->GetPattern( nRow )->GetStyleSheet();
1302cdf0e10cSrcweir 				const ScPatternAttr* pPattern = pAttrArray->GetPattern( nRow );
1303cdf0e10cSrcweir 				ScPatternAttr* pNewPattern = new ScPatternAttr( *pPattern );
1304cdf0e10cSrcweir 				pNewPattern->SetStyleSheet( (ScStyleSheet*)pStyle );
1305cdf0e10cSrcweir 				rColumn.pAttrArray->SetPattern( nRow, pNewPattern, sal_True );
1306cdf0e10cSrcweir 				delete pNewPattern;
1307cdf0e10cSrcweir 			}
1308cdf0e10cSrcweir 		}
1309cdf0e10cSrcweir 		else
1310cdf0e10cSrcweir 			pAttrArray->CopyArea( nRow1, nRow2, 0, *rColumn.pAttrArray);
1311cdf0e10cSrcweir 	}
1312cdf0e10cSrcweir 
1313cdf0e10cSrcweir 
1314cdf0e10cSrcweir 	if ((nFlags & IDF_CONTENTS) != 0)
1315cdf0e10cSrcweir 	{
1316cdf0e10cSrcweir 		SCSIZE i;
1317cdf0e10cSrcweir 		SCSIZE nBlockCount = 0;
1318cdf0e10cSrcweir         SCSIZE nStartIndex = 0, nEndIndex = 0;
1319cdf0e10cSrcweir 		for (i = 0; i < nCount; i++)
1320cdf0e10cSrcweir 			if ((pItems[i].nRow >= nRow1) && (pItems[i].nRow <= nRow2))
1321cdf0e10cSrcweir 			{
1322cdf0e10cSrcweir 				if (!nBlockCount)
1323cdf0e10cSrcweir 					nStartIndex = i;
1324cdf0e10cSrcweir 				nEndIndex = i;
1325cdf0e10cSrcweir 				++nBlockCount;
1326cdf0e10cSrcweir 			}
1327cdf0e10cSrcweir 
1328cdf0e10cSrcweir 		if (nBlockCount)
1329cdf0e10cSrcweir 		{
1330cdf0e10cSrcweir 			rColumn.Resize( rColumn.GetCellCount() + nBlockCount );
1331cdf0e10cSrcweir 			ScAddress aDestPos( rColumn.nCol, 0, rColumn.nTab );
1332cdf0e10cSrcweir 			for (i = nStartIndex; i <= nEndIndex; i++)
1333cdf0e10cSrcweir 			{
1334cdf0e10cSrcweir 				aDestPos.SetRow( pItems[i].nRow );
1335cdf0e10cSrcweir 				ScBaseCell* pNew = bAsLink ?
1336cdf0e10cSrcweir                     CreateRefCell( rColumn.pDocument, aDestPos, i, nFlags ) :
1337cdf0e10cSrcweir                     CloneCell( i, nFlags, *rColumn.pDocument, aDestPos );
1338cdf0e10cSrcweir 
1339cdf0e10cSrcweir 				if (pNew)
1340cdf0e10cSrcweir 					rColumn.Insert(pItems[i].nRow, pNew);
1341cdf0e10cSrcweir 			}
1342cdf0e10cSrcweir 		}
1343cdf0e10cSrcweir 	}
1344cdf0e10cSrcweir }
1345cdf0e10cSrcweir 
1346cdf0e10cSrcweir 
UndoToColumn(SCROW nRow1,SCROW nRow2,sal_uInt16 nFlags,sal_Bool bMarked,ScColumn & rColumn,const ScMarkData * pMarkData)1347cdf0e10cSrcweir void ScColumn::UndoToColumn(SCROW nRow1, SCROW nRow2, sal_uInt16 nFlags, sal_Bool bMarked,
1348cdf0e10cSrcweir 								ScColumn& rColumn, const ScMarkData* pMarkData )
1349cdf0e10cSrcweir {
1350cdf0e10cSrcweir 	if (nRow1 > 0)
1351cdf0e10cSrcweir 		CopyToColumn( 0, nRow1-1, IDF_FORMULA, sal_False, rColumn );
1352cdf0e10cSrcweir 
1353cdf0e10cSrcweir 	CopyToColumn( nRow1, nRow2, nFlags, bMarked, rColumn, pMarkData );		//! bMarked ????
1354cdf0e10cSrcweir 
1355cdf0e10cSrcweir 	if (nRow2 < MAXROW)
1356cdf0e10cSrcweir 		CopyToColumn( nRow2+1, MAXROW, IDF_FORMULA, sal_False, rColumn );
1357cdf0e10cSrcweir }
1358cdf0e10cSrcweir 
1359cdf0e10cSrcweir 
CopyUpdated(const ScColumn & rPosCol,ScColumn & rDestCol) const1360cdf0e10cSrcweir void ScColumn::CopyUpdated( const ScColumn& rPosCol, ScColumn& rDestCol ) const
1361cdf0e10cSrcweir {
1362cdf0e10cSrcweir 	ScDocument& rDestDoc = *rDestCol.pDocument;
1363cdf0e10cSrcweir     ScAddress aOwnPos( nCol, 0, nTab );
1364cdf0e10cSrcweir     ScAddress aDestPos( rDestCol.nCol, 0, rDestCol.nTab );
1365cdf0e10cSrcweir 
1366cdf0e10cSrcweir 	SCSIZE nPosCount = rPosCol.nCount;
1367cdf0e10cSrcweir 	for (SCSIZE nPosIndex = 0; nPosIndex < nPosCount; nPosIndex++)
1368cdf0e10cSrcweir 	{
1369cdf0e10cSrcweir         aOwnPos.SetRow( rPosCol.pItems[nPosIndex].nRow );
1370cdf0e10cSrcweir         aDestPos.SetRow( aOwnPos.Row() );
1371cdf0e10cSrcweir 		SCSIZE nThisIndex;
1372cdf0e10cSrcweir 		if ( Search( aDestPos.Row(), nThisIndex ) )
1373cdf0e10cSrcweir 		{
1374cdf0e10cSrcweir             ScBaseCell* pNew = pItems[nThisIndex].pCell->CloneWithNote( aOwnPos, rDestDoc, aDestPos );
1375cdf0e10cSrcweir 			rDestCol.Insert( aDestPos.Row(), pNew );
1376cdf0e10cSrcweir 		}
1377cdf0e10cSrcweir 	}
1378cdf0e10cSrcweir 
1379cdf0e10cSrcweir 	//	Dummy:
1380cdf0e10cSrcweir 	//	CopyToColumn( 0,MAXROW, IDF_FORMULA, sal_False, rDestCol, NULL, sal_False );
1381cdf0e10cSrcweir }
1382cdf0e10cSrcweir 
1383cdf0e10cSrcweir 
CopyScenarioFrom(const ScColumn & rSrcCol)1384cdf0e10cSrcweir void ScColumn::CopyScenarioFrom( const ScColumn& rSrcCol )
1385cdf0e10cSrcweir {
1386cdf0e10cSrcweir 	//	Dies ist die Szenario-Tabelle, die Daten werden hineinkopiert
1387cdf0e10cSrcweir 
1388cdf0e10cSrcweir 	ScAttrIterator aAttrIter( pAttrArray, 0, MAXROW );
1389cdf0e10cSrcweir 	SCROW nStart = -1, nEnd = -1;
1390cdf0e10cSrcweir 	const ScPatternAttr* pPattern = aAttrIter.Next( nStart, nEnd );
1391cdf0e10cSrcweir 	while (pPattern)
1392cdf0e10cSrcweir 	{
1393cdf0e10cSrcweir 		if ( ((ScMergeFlagAttr&)pPattern->GetItem( ATTR_MERGE_FLAG )).IsScenario() )
1394cdf0e10cSrcweir 		{
1395cdf0e10cSrcweir 			DeleteArea( nStart, nEnd, IDF_CONTENTS );
1396cdf0e10cSrcweir 			((ScColumn&)rSrcCol).
1397cdf0e10cSrcweir 				CopyToColumn( nStart, nEnd, IDF_CONTENTS, sal_False, *this );
1398cdf0e10cSrcweir 
1399cdf0e10cSrcweir 			//	UpdateUsed nicht noetig, schon in TestCopyScenario passiert
1400cdf0e10cSrcweir 
1401cdf0e10cSrcweir 			SCsTAB nDz = nTab - rSrcCol.nTab;
1402cdf0e10cSrcweir 			UpdateReference(URM_COPY, nCol, nStart, nTab,
1403cdf0e10cSrcweir 									  nCol, nEnd,   nTab,
1404cdf0e10cSrcweir 									  0, 0, nDz, NULL);
1405cdf0e10cSrcweir 			UpdateCompile();
1406cdf0e10cSrcweir 		}
1407cdf0e10cSrcweir 
1408cdf0e10cSrcweir 		//!	CopyToColumn "const" machen !!!
1409cdf0e10cSrcweir 
1410cdf0e10cSrcweir 		pPattern = aAttrIter.Next( nStart, nEnd );
1411cdf0e10cSrcweir 	}
1412cdf0e10cSrcweir }
1413cdf0e10cSrcweir 
1414cdf0e10cSrcweir 
CopyScenarioTo(ScColumn & rDestCol) const1415cdf0e10cSrcweir void ScColumn::CopyScenarioTo( ScColumn& rDestCol ) const
1416cdf0e10cSrcweir {
1417cdf0e10cSrcweir 	//	Dies ist die Szenario-Tabelle, die Daten werden in die andere kopiert
1418cdf0e10cSrcweir 
1419cdf0e10cSrcweir 	ScAttrIterator aAttrIter( pAttrArray, 0, MAXROW );
1420cdf0e10cSrcweir 	SCROW nStart = -1, nEnd = -1;
1421cdf0e10cSrcweir 	const ScPatternAttr* pPattern = aAttrIter.Next( nStart, nEnd );
1422cdf0e10cSrcweir 	while (pPattern)
1423cdf0e10cSrcweir 	{
1424cdf0e10cSrcweir 		if ( ((ScMergeFlagAttr&)pPattern->GetItem( ATTR_MERGE_FLAG )).IsScenario() )
1425cdf0e10cSrcweir 		{
1426cdf0e10cSrcweir 			rDestCol.DeleteArea( nStart, nEnd, IDF_CONTENTS );
1427cdf0e10cSrcweir 			((ScColumn*)this)->
1428cdf0e10cSrcweir 				CopyToColumn( nStart, nEnd, IDF_CONTENTS, sal_False, rDestCol );
1429cdf0e10cSrcweir 
1430cdf0e10cSrcweir 			//	UpdateUsed nicht noetig, schon in TestCopyScenario passiert
1431cdf0e10cSrcweir 
1432cdf0e10cSrcweir 			SCsTAB nDz = rDestCol.nTab - nTab;
1433cdf0e10cSrcweir 			rDestCol.UpdateReference(URM_COPY, rDestCol.nCol, nStart, rDestCol.nTab,
1434cdf0e10cSrcweir 											   rDestCol.nCol, nEnd,   rDestCol.nTab,
1435cdf0e10cSrcweir 											   0, 0, nDz, NULL);
1436cdf0e10cSrcweir 			rDestCol.UpdateCompile();
1437cdf0e10cSrcweir 		}
1438cdf0e10cSrcweir 
1439cdf0e10cSrcweir 		//!	CopyToColumn "const" machen !!!
1440cdf0e10cSrcweir 
1441cdf0e10cSrcweir 		pPattern = aAttrIter.Next( nStart, nEnd );
1442cdf0e10cSrcweir 	}
1443cdf0e10cSrcweir }
1444cdf0e10cSrcweir 
1445cdf0e10cSrcweir 
TestCopyScenarioTo(const ScColumn & rDestCol) const1446cdf0e10cSrcweir sal_Bool ScColumn::TestCopyScenarioTo( const ScColumn& rDestCol ) const
1447cdf0e10cSrcweir {
1448cdf0e10cSrcweir 	sal_Bool bOk = sal_True;
1449cdf0e10cSrcweir 	ScAttrIterator aAttrIter( pAttrArray, 0, MAXROW );
1450cdf0e10cSrcweir 	SCROW nStart = 0, nEnd = 0;
1451cdf0e10cSrcweir 	const ScPatternAttr* pPattern = aAttrIter.Next( nStart, nEnd );
1452cdf0e10cSrcweir 	while (pPattern && bOk)
1453cdf0e10cSrcweir 	{
1454cdf0e10cSrcweir 		if ( ((ScMergeFlagAttr&)pPattern->GetItem( ATTR_MERGE_FLAG )).IsScenario() )
1455cdf0e10cSrcweir 			if ( rDestCol.pAttrArray->HasAttrib( nStart, nEnd, HASATTR_PROTECTED ) )
1456cdf0e10cSrcweir 				bOk = sal_False;
1457cdf0e10cSrcweir 
1458cdf0e10cSrcweir 		pPattern = aAttrIter.Next( nStart, nEnd );
1459cdf0e10cSrcweir 	}
1460cdf0e10cSrcweir 	return bOk;
1461cdf0e10cSrcweir }
1462cdf0e10cSrcweir 
1463cdf0e10cSrcweir 
MarkScenarioIn(ScMarkData & rDestMark) const1464cdf0e10cSrcweir void ScColumn::MarkScenarioIn( ScMarkData& rDestMark ) const
1465cdf0e10cSrcweir {
1466cdf0e10cSrcweir 	ScRange aRange( nCol, 0, nTab );
1467cdf0e10cSrcweir 
1468cdf0e10cSrcweir 	ScAttrIterator aAttrIter( pAttrArray, 0, MAXROW );
1469cdf0e10cSrcweir 	SCROW nStart = -1, nEnd = -1;
1470cdf0e10cSrcweir 	const ScPatternAttr* pPattern = aAttrIter.Next( nStart, nEnd );
1471cdf0e10cSrcweir 	while (pPattern)
1472cdf0e10cSrcweir 	{
1473cdf0e10cSrcweir 		if ( ((ScMergeFlagAttr&)pPattern->GetItem( ATTR_MERGE_FLAG )).IsScenario() )
1474cdf0e10cSrcweir 		{
1475cdf0e10cSrcweir 			aRange.aStart.SetRow( nStart );
1476cdf0e10cSrcweir 			aRange.aEnd.SetRow( nEnd );
1477cdf0e10cSrcweir 			rDestMark.SetMultiMarkArea( aRange, sal_True );
1478cdf0e10cSrcweir 		}
1479cdf0e10cSrcweir 
1480cdf0e10cSrcweir 		pPattern = aAttrIter.Next( nStart, nEnd );
1481cdf0e10cSrcweir 	}
1482cdf0e10cSrcweir }
1483cdf0e10cSrcweir 
1484cdf0e10cSrcweir 
SwapCol(ScColumn & rCol)1485cdf0e10cSrcweir void ScColumn::SwapCol(ScColumn& rCol)
1486cdf0e10cSrcweir {
1487cdf0e10cSrcweir 	SCSIZE nTemp;
1488cdf0e10cSrcweir 
1489cdf0e10cSrcweir 	nTemp = rCol.nCount;
1490cdf0e10cSrcweir 	rCol.nCount  = nCount;
1491cdf0e10cSrcweir 	nCount = nTemp;
1492cdf0e10cSrcweir 
1493cdf0e10cSrcweir 	nTemp = rCol.nLimit;
1494cdf0e10cSrcweir 	rCol.nLimit = nLimit;
1495cdf0e10cSrcweir 	nLimit = nTemp;
1496cdf0e10cSrcweir 
1497cdf0e10cSrcweir 	ColEntry* pTempItems = rCol.pItems;
1498cdf0e10cSrcweir 	rCol.pItems = pItems;
1499cdf0e10cSrcweir 	pItems = pTempItems;
1500cdf0e10cSrcweir 
1501cdf0e10cSrcweir 	ScAttrArray* pTempAttr = rCol.pAttrArray;
1502cdf0e10cSrcweir 	rCol.pAttrArray = pAttrArray;
1503cdf0e10cSrcweir 	pAttrArray = pTempAttr;
1504cdf0e10cSrcweir 
1505cdf0e10cSrcweir 	// #38415# AttrArray muss richtige Spaltennummer haben
1506cdf0e10cSrcweir 	pAttrArray->SetCol(nCol);
1507cdf0e10cSrcweir 	rCol.pAttrArray->SetCol(rCol.nCol);
1508cdf0e10cSrcweir 
1509cdf0e10cSrcweir 	SCSIZE i;
1510cdf0e10cSrcweir 	if (pItems)
1511cdf0e10cSrcweir 		for (i = 0; i < nCount; i++)
1512cdf0e10cSrcweir 		{
1513cdf0e10cSrcweir 			ScFormulaCell* pCell = (ScFormulaCell*) pItems[i].pCell;
1514cdf0e10cSrcweir 			if( pCell->GetCellType() == CELLTYPE_FORMULA)
1515cdf0e10cSrcweir 				pCell->aPos.SetCol(nCol);
1516cdf0e10cSrcweir 		}
1517cdf0e10cSrcweir 	if (rCol.pItems)
1518cdf0e10cSrcweir 		for (i = 0; i < rCol.nCount; i++)
1519cdf0e10cSrcweir 		{
1520cdf0e10cSrcweir 			ScFormulaCell* pCell = (ScFormulaCell*) rCol.pItems[i].pCell;
1521cdf0e10cSrcweir 			if( pCell->GetCellType() == CELLTYPE_FORMULA)
1522cdf0e10cSrcweir 				pCell->aPos.SetCol(rCol.nCol);
1523cdf0e10cSrcweir 		}
1524cdf0e10cSrcweir }
1525cdf0e10cSrcweir 
1526cdf0e10cSrcweir 
MoveTo(SCROW nStartRow,SCROW nEndRow,ScColumn & rCol)1527cdf0e10cSrcweir void ScColumn::MoveTo(SCROW nStartRow, SCROW nEndRow, ScColumn& rCol)
1528cdf0e10cSrcweir {
1529cdf0e10cSrcweir 	pAttrArray->MoveTo(nStartRow, nEndRow, *rCol.pAttrArray);
1530cdf0e10cSrcweir 
1531cdf0e10cSrcweir 	if (pItems)
1532cdf0e10cSrcweir 	{
1533cdf0e10cSrcweir         ::std::vector<SCROW> aRows;
1534cdf0e10cSrcweir         bool bConsecutive = true;
1535cdf0e10cSrcweir 		SCSIZE i;
1536cdf0e10cSrcweir         Search( nStartRow, i);  // i points to start row or position thereafter
1537cdf0e10cSrcweir 		SCSIZE nStartPos = i;
1538cdf0e10cSrcweir 		for ( ; i < nCount && pItems[i].nRow <= nEndRow; ++i)
1539cdf0e10cSrcweir 		{
1540cdf0e10cSrcweir             SCROW nRow = pItems[i].nRow;
1541cdf0e10cSrcweir             aRows.push_back( nRow);
1542cdf0e10cSrcweir             rCol.Insert( nRow, pItems[i].pCell);
1543cdf0e10cSrcweir             if (nRow != pItems[i].nRow)
1544cdf0e10cSrcweir             {   // Listener inserted
1545cdf0e10cSrcweir                 bConsecutive = false;
1546cdf0e10cSrcweir                 Search( nRow, i);
1547cdf0e10cSrcweir             }
1548cdf0e10cSrcweir 		}
1549cdf0e10cSrcweir         SCSIZE nStopPos = i;
1550cdf0e10cSrcweir 		if (nStartPos < nStopPos)
1551cdf0e10cSrcweir 		{
1552cdf0e10cSrcweir             // Create list of ranges of cell entry positions
1553cdf0e10cSrcweir             typedef ::std::pair<SCSIZE,SCSIZE> PosPair;
1554cdf0e10cSrcweir             typedef ::std::vector<PosPair> EntryPosPairs;
1555cdf0e10cSrcweir             EntryPosPairs aEntries;
1556cdf0e10cSrcweir             if (bConsecutive)
1557cdf0e10cSrcweir                 aEntries.push_back( PosPair(nStartPos, nStopPos));
1558cdf0e10cSrcweir             else
1559cdf0e10cSrcweir             {
1560cdf0e10cSrcweir                 bool bFirst = true;
1561cdf0e10cSrcweir                 nStopPos = 0;
1562cdf0e10cSrcweir                 for (::std::vector<SCROW>::const_iterator it( aRows.begin());
1563cdf0e10cSrcweir                         it != aRows.end() && nStopPos < nCount; ++it,
1564cdf0e10cSrcweir                         ++nStopPos)
1565cdf0e10cSrcweir                 {
1566cdf0e10cSrcweir                     if (!bFirst && *it != pItems[nStopPos].nRow)
1567cdf0e10cSrcweir                     {
1568cdf0e10cSrcweir                         aEntries.push_back( PosPair(nStartPos, nStopPos));
1569cdf0e10cSrcweir                         bFirst = true;
1570cdf0e10cSrcweir                     }
1571cdf0e10cSrcweir                     if (bFirst && Search( *it, nStartPos))
1572cdf0e10cSrcweir                     {
1573cdf0e10cSrcweir                         bFirst = false;
1574cdf0e10cSrcweir                         nStopPos = nStartPos;
1575cdf0e10cSrcweir                     }
1576cdf0e10cSrcweir                 }
1577cdf0e10cSrcweir                 if (!bFirst && nStartPos < nStopPos)
1578cdf0e10cSrcweir                     aEntries.push_back( PosPair(nStartPos, nStopPos));
1579cdf0e10cSrcweir             }
1580cdf0e10cSrcweir 			// Broadcast changes
1581cdf0e10cSrcweir             ScAddress aAdr( nCol, 0, nTab );
1582cdf0e10cSrcweir             ScHint aHint( SC_HINT_DYING, aAdr, NULL );  // areas only
1583cdf0e10cSrcweir             ScAddress& rAddress = aHint.GetAddress();
1584cdf0e10cSrcweir             ScNoteCell* pNoteCell = new ScNoteCell;		// Dummy like in DeleteRange
1585cdf0e10cSrcweir 
1586cdf0e10cSrcweir             // #121990# must iterate backwards, because indexes of following cells become invalid
1587cdf0e10cSrcweir             for (EntryPosPairs::reverse_iterator it( aEntries.rbegin());
1588cdf0e10cSrcweir                     it != aEntries.rend(); ++it)
1589cdf0e10cSrcweir             {
1590cdf0e10cSrcweir                 nStartPos = (*it).first;
1591cdf0e10cSrcweir                 nStopPos = (*it).second;
1592cdf0e10cSrcweir                 for (i=nStartPos; i<nStopPos; ++i)
1593cdf0e10cSrcweir                     pItems[i].pCell = pNoteCell;
1594cdf0e10cSrcweir                 for (i=nStartPos; i<nStopPos; ++i)
1595cdf0e10cSrcweir                 {
1596cdf0e10cSrcweir                     rAddress.SetRow( pItems[i].nRow );
1597cdf0e10cSrcweir                     pDocument->AreaBroadcast( aHint );
1598cdf0e10cSrcweir                 }
1599cdf0e10cSrcweir                 nCount -= nStopPos - nStartPos;
1600cdf0e10cSrcweir                 memmove( &pItems[nStartPos], &pItems[nStopPos],
1601cdf0e10cSrcweir                         (nCount - nStartPos) * sizeof(ColEntry) );
1602cdf0e10cSrcweir             }
1603cdf0e10cSrcweir             delete pNoteCell;
1604cdf0e10cSrcweir             pItems[nCount].nRow = 0;
1605cdf0e10cSrcweir             pItems[nCount].pCell = NULL;
1606cdf0e10cSrcweir 		}
1607cdf0e10cSrcweir 	}
1608cdf0e10cSrcweir }
1609cdf0e10cSrcweir 
1610cdf0e10cSrcweir 
UpdateReference(UpdateRefMode eUpdateRefMode,SCCOL nCol1,SCROW nRow1,SCTAB nTab1,SCCOL nCol2,SCROW nRow2,SCTAB nTab2,SCsCOL nDx,SCsROW nDy,SCsTAB nDz,ScDocument * pUndoDoc)1611cdf0e10cSrcweir void ScColumn::UpdateReference( UpdateRefMode eUpdateRefMode, SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
1612cdf0e10cSrcweir 			 SCCOL nCol2, SCROW nRow2, SCTAB nTab2, SCsCOL nDx, SCsROW nDy, SCsTAB nDz,
1613cdf0e10cSrcweir 			 ScDocument* pUndoDoc )
1614cdf0e10cSrcweir {
1615cdf0e10cSrcweir 	if (pItems)
1616cdf0e10cSrcweir 	{
1617cdf0e10cSrcweir 		ScRange aRange( ScAddress( nCol1, nRow1, nTab1 ),
1618cdf0e10cSrcweir 						ScAddress( nCol2, nRow2, nTab2 ) );
1619cdf0e10cSrcweir 		if ( eUpdateRefMode == URM_COPY && nRow1 == nRow2 )
1620cdf0e10cSrcweir 		{	// z.B. eine einzelne Zelle aus dem Clipboard eingefuegt
1621cdf0e10cSrcweir 			SCSIZE nIndex;
1622cdf0e10cSrcweir 			if ( Search( nRow1, nIndex ) )
1623cdf0e10cSrcweir 			{
1624cdf0e10cSrcweir 				ScFormulaCell* pCell = (ScFormulaCell*) pItems[nIndex].pCell;
1625cdf0e10cSrcweir 				if( pCell->GetCellType() == CELLTYPE_FORMULA)
1626cdf0e10cSrcweir 					pCell->UpdateReference(	eUpdateRefMode, aRange, nDx, nDy, nDz, pUndoDoc );
1627cdf0e10cSrcweir 			}
1628cdf0e10cSrcweir 		}
1629cdf0e10cSrcweir 		else
1630cdf0e10cSrcweir 		{
1631cdf0e10cSrcweir             // #90279# For performance reasons two loop bodies instead of
1632cdf0e10cSrcweir             // testing for update mode in each iteration.
1633cdf0e10cSrcweir             // Anyways, this is still a bottleneck on large arrays with few
1634cdf0e10cSrcweir             // formulas cells.
1635cdf0e10cSrcweir             if ( eUpdateRefMode == URM_COPY )
1636cdf0e10cSrcweir             {
1637cdf0e10cSrcweir                 SCSIZE i;
1638cdf0e10cSrcweir                 Search( nRow1, i );
1639cdf0e10cSrcweir                 for ( ; i < nCount; i++ )
1640cdf0e10cSrcweir                 {
1641cdf0e10cSrcweir                     SCROW nRow = pItems[i].nRow;
1642cdf0e10cSrcweir                     if ( nRow > nRow2 )
1643cdf0e10cSrcweir                         break;
1644cdf0e10cSrcweir                     ScBaseCell* pCell = pItems[i].pCell;
1645cdf0e10cSrcweir                     if( pCell->GetCellType() == CELLTYPE_FORMULA)
1646cdf0e10cSrcweir                     {
1647cdf0e10cSrcweir                         ((ScFormulaCell*)pCell)->UpdateReference( eUpdateRefMode, aRange, nDx, nDy, nDz, pUndoDoc );
1648cdf0e10cSrcweir                         if ( nRow != pItems[i].nRow )
1649cdf0e10cSrcweir                             Search( nRow, i );  // Listener removed/inserted?
1650cdf0e10cSrcweir                     }
1651cdf0e10cSrcweir                 }
1652cdf0e10cSrcweir             }
1653cdf0e10cSrcweir             else
1654cdf0e10cSrcweir             {
1655cdf0e10cSrcweir                 SCSIZE i = 0;
1656cdf0e10cSrcweir                 for ( ; i < nCount; i++ )
1657cdf0e10cSrcweir                 {
1658cdf0e10cSrcweir                     ScBaseCell* pCell = pItems[i].pCell;
1659cdf0e10cSrcweir                     if( pCell->GetCellType() == CELLTYPE_FORMULA)
1660cdf0e10cSrcweir                     {
1661cdf0e10cSrcweir                         SCROW nRow = pItems[i].nRow;
1662cdf0e10cSrcweir                         // When deleting rows on several sheets, the formula's position may be updated with the first call,
1663cdf0e10cSrcweir                         // so the undo position must be passed from here.
1664cdf0e10cSrcweir                         ScAddress aUndoPos( nCol, nRow, nTab );
1665cdf0e10cSrcweir                         ((ScFormulaCell*)pCell)->UpdateReference( eUpdateRefMode, aRange, nDx, nDy, nDz, pUndoDoc, &aUndoPos );
1666cdf0e10cSrcweir                         if ( nRow != pItems[i].nRow )
1667cdf0e10cSrcweir                             Search( nRow, i );  // Listener removed/inserted?
1668cdf0e10cSrcweir                     }
1669cdf0e10cSrcweir                 }
1670cdf0e10cSrcweir             }
1671cdf0e10cSrcweir 		}
1672cdf0e10cSrcweir 	}
1673cdf0e10cSrcweir }
1674cdf0e10cSrcweir 
1675cdf0e10cSrcweir 
UpdateTranspose(const ScRange & rSource,const ScAddress & rDest,ScDocument * pUndoDoc)1676cdf0e10cSrcweir void ScColumn::UpdateTranspose( const ScRange& rSource, const ScAddress& rDest,
1677cdf0e10cSrcweir 									ScDocument* pUndoDoc )
1678cdf0e10cSrcweir {
1679cdf0e10cSrcweir 	if (pItems)
1680cdf0e10cSrcweir 		for (SCSIZE i=0; i<nCount; i++)
1681cdf0e10cSrcweir 		{
1682cdf0e10cSrcweir 			ScBaseCell* pCell = pItems[i].pCell;
1683cdf0e10cSrcweir 			if (pCell->GetCellType() == CELLTYPE_FORMULA)
1684cdf0e10cSrcweir 			{
1685cdf0e10cSrcweir 				SCROW nRow = pItems[i].nRow;
1686cdf0e10cSrcweir 				((ScFormulaCell*)pCell)->UpdateTranspose( rSource, rDest, pUndoDoc );
1687cdf0e10cSrcweir 				if ( nRow != pItems[i].nRow )
1688cdf0e10cSrcweir 					Search( nRow, i );				// Listener geloescht/eingefuegt?
1689cdf0e10cSrcweir 			}
1690cdf0e10cSrcweir 		}
1691cdf0e10cSrcweir }
1692cdf0e10cSrcweir 
1693cdf0e10cSrcweir 
UpdateGrow(const ScRange & rArea,SCCOL nGrowX,SCROW nGrowY)1694cdf0e10cSrcweir void ScColumn::UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY )
1695cdf0e10cSrcweir {
1696cdf0e10cSrcweir 	if (pItems)
1697cdf0e10cSrcweir 		for (SCSIZE i=0; i<nCount; i++)
1698cdf0e10cSrcweir 		{
1699cdf0e10cSrcweir 			ScBaseCell* pCell = pItems[i].pCell;
1700cdf0e10cSrcweir 			if (pCell->GetCellType() == CELLTYPE_FORMULA)
1701cdf0e10cSrcweir 			{
1702cdf0e10cSrcweir 				SCROW nRow = pItems[i].nRow;
1703cdf0e10cSrcweir 				((ScFormulaCell*)pCell)->UpdateGrow( rArea, nGrowX, nGrowY );
1704cdf0e10cSrcweir 				if ( nRow != pItems[i].nRow )
1705cdf0e10cSrcweir 					Search( nRow, i );				// Listener geloescht/eingefuegt?
1706cdf0e10cSrcweir 			}
1707cdf0e10cSrcweir 		}
1708cdf0e10cSrcweir }
1709cdf0e10cSrcweir 
1710cdf0e10cSrcweir 
UpdateInsertTab(SCTAB nTable)1711cdf0e10cSrcweir void ScColumn::UpdateInsertTab( SCTAB nTable)
1712cdf0e10cSrcweir {
1713cdf0e10cSrcweir     if (nTab >= nTable)
1714cdf0e10cSrcweir         pAttrArray->SetTab(++nTab);
1715cdf0e10cSrcweir 	if( pItems )
1716cdf0e10cSrcweir 		UpdateInsertTabOnlyCells( nTable );
1717cdf0e10cSrcweir }
1718cdf0e10cSrcweir 
1719cdf0e10cSrcweir 
UpdateInsertTabOnlyCells(SCTAB nTable)1720cdf0e10cSrcweir void ScColumn::UpdateInsertTabOnlyCells( SCTAB nTable)
1721cdf0e10cSrcweir {
1722cdf0e10cSrcweir 	if (pItems)
1723cdf0e10cSrcweir 		for (SCSIZE i = 0; i < nCount; i++)
1724cdf0e10cSrcweir 		{
1725cdf0e10cSrcweir 			ScFormulaCell* pCell = (ScFormulaCell*) pItems[i].pCell;
1726cdf0e10cSrcweir 			if( pCell->GetCellType() == CELLTYPE_FORMULA)
1727cdf0e10cSrcweir 			{
1728cdf0e10cSrcweir 				SCROW nRow = pItems[i].nRow;
1729cdf0e10cSrcweir 				pCell->UpdateInsertTab(nTable);
1730cdf0e10cSrcweir 				if ( nRow != pItems[i].nRow )
1731cdf0e10cSrcweir 					Search( nRow, i );		// Listener geloescht/eingefuegt?
1732cdf0e10cSrcweir 			}
1733cdf0e10cSrcweir 		}
1734cdf0e10cSrcweir }
1735cdf0e10cSrcweir 
1736cdf0e10cSrcweir 
UpdateInsertTabAbs(SCTAB nTable)1737cdf0e10cSrcweir void ScColumn::UpdateInsertTabAbs(SCTAB nTable)
1738cdf0e10cSrcweir {
1739cdf0e10cSrcweir 	if (pItems)
1740cdf0e10cSrcweir 		for (SCSIZE i = 0; i < nCount; i++)
1741cdf0e10cSrcweir 		{
1742cdf0e10cSrcweir 			ScFormulaCell* pCell = (ScFormulaCell*) pItems[i].pCell;
1743cdf0e10cSrcweir 			if( pCell->GetCellType() == CELLTYPE_FORMULA)
1744cdf0e10cSrcweir 			{
1745cdf0e10cSrcweir 				SCROW nRow = pItems[i].nRow;
1746cdf0e10cSrcweir 				pCell->UpdateInsertTabAbs(nTable);
1747cdf0e10cSrcweir 				if ( nRow != pItems[i].nRow )
1748cdf0e10cSrcweir 					Search( nRow, i );		// Listener geloescht/eingefuegt?
1749cdf0e10cSrcweir 			}
1750cdf0e10cSrcweir 		}
1751cdf0e10cSrcweir }
1752cdf0e10cSrcweir 
1753cdf0e10cSrcweir 
UpdateDeleteTab(SCTAB nTable,sal_Bool bIsMove,ScColumn * pRefUndo)1754cdf0e10cSrcweir void ScColumn::UpdateDeleteTab( SCTAB nTable, sal_Bool bIsMove, ScColumn* pRefUndo )
1755cdf0e10cSrcweir {
1756cdf0e10cSrcweir 	if (nTab > nTable)
1757cdf0e10cSrcweir 		pAttrArray->SetTab(--nTab);
1758cdf0e10cSrcweir 
1759cdf0e10cSrcweir 	if (pItems)
1760cdf0e10cSrcweir 		for (SCSIZE i = 0; i < nCount; i++)
1761cdf0e10cSrcweir 			if ( pItems[i].pCell->GetCellType() == CELLTYPE_FORMULA )
1762cdf0e10cSrcweir 			{
1763cdf0e10cSrcweir 				SCROW nRow = pItems[i].nRow;
1764cdf0e10cSrcweir 				ScFormulaCell* pOld = (ScFormulaCell*)pItems[i].pCell;
1765cdf0e10cSrcweir 
1766cdf0e10cSrcweir                 /*  Do not copy cell note to the undo document. Undo will copy
1767cdf0e10cSrcweir                     back the formula cell while keeping the original note. */
1768cdf0e10cSrcweir                 ScBaseCell* pSave = pRefUndo ? pOld->CloneWithoutNote( *pDocument ) : 0;
1769cdf0e10cSrcweir 
1770cdf0e10cSrcweir 				sal_Bool bChanged = pOld->UpdateDeleteTab(nTable, bIsMove);
1771cdf0e10cSrcweir 				if ( nRow != pItems[i].nRow )
1772cdf0e10cSrcweir 					Search( nRow, i );		// Listener geloescht/eingefuegt?
1773cdf0e10cSrcweir 
1774cdf0e10cSrcweir 				if (pRefUndo)
1775cdf0e10cSrcweir 				{
1776cdf0e10cSrcweir 					if (bChanged)
1777cdf0e10cSrcweir 						pRefUndo->Insert( nRow, pSave );
1778cdf0e10cSrcweir 					else if(pSave)
1779cdf0e10cSrcweir 						pSave->Delete();
1780cdf0e10cSrcweir 				}
1781cdf0e10cSrcweir 			}
1782cdf0e10cSrcweir }
1783cdf0e10cSrcweir 
1784cdf0e10cSrcweir 
UpdateMoveTab(SCTAB nOldPos,SCTAB nNewPos,SCTAB nTabNo)1785cdf0e10cSrcweir void ScColumn::UpdateMoveTab( SCTAB nOldPos, SCTAB nNewPos, SCTAB nTabNo )
1786cdf0e10cSrcweir {
1787cdf0e10cSrcweir 	nTab = nTabNo;
1788cdf0e10cSrcweir 	pAttrArray->SetTab( nTabNo );
1789cdf0e10cSrcweir 	if (pItems)
1790cdf0e10cSrcweir 		for (SCSIZE i = 0; i < nCount; i++)
1791cdf0e10cSrcweir 		{
1792cdf0e10cSrcweir 			ScFormulaCell* pCell = (ScFormulaCell*) pItems[i].pCell;
1793cdf0e10cSrcweir 			if ( pCell->GetCellType() == CELLTYPE_FORMULA )
1794cdf0e10cSrcweir 			{
1795cdf0e10cSrcweir 				SCROW nRow = pItems[i].nRow;
1796cdf0e10cSrcweir 				pCell->UpdateMoveTab( nOldPos, nNewPos, nTabNo );
1797cdf0e10cSrcweir 				if ( nRow != pItems[i].nRow )
1798cdf0e10cSrcweir 					Search( nRow, i );		// Listener geloescht/eingefuegt?
1799cdf0e10cSrcweir 			}
1800cdf0e10cSrcweir 		}
1801cdf0e10cSrcweir }
1802cdf0e10cSrcweir 
1803cdf0e10cSrcweir 
UpdateCompile(sal_Bool bForceIfNameInUse)1804cdf0e10cSrcweir void ScColumn::UpdateCompile( sal_Bool bForceIfNameInUse )
1805cdf0e10cSrcweir {
1806cdf0e10cSrcweir 	if (pItems)
1807cdf0e10cSrcweir 		for (SCSIZE i = 0; i < nCount; i++)
1808cdf0e10cSrcweir 		{
1809cdf0e10cSrcweir 			ScFormulaCell* p = (ScFormulaCell*) pItems[i].pCell;
1810cdf0e10cSrcweir 			if( p->GetCellType() == CELLTYPE_FORMULA )
1811cdf0e10cSrcweir 			{
1812cdf0e10cSrcweir 				SCROW nRow = pItems[i].nRow;
1813cdf0e10cSrcweir 				p->UpdateCompile( bForceIfNameInUse );
1814cdf0e10cSrcweir 				if ( nRow != pItems[i].nRow )
1815cdf0e10cSrcweir 					Search( nRow, i );		// Listener geloescht/eingefuegt?
1816cdf0e10cSrcweir 			}
1817cdf0e10cSrcweir 		}
1818cdf0e10cSrcweir }
1819cdf0e10cSrcweir 
1820cdf0e10cSrcweir 
SetTabNo(SCTAB nNewTab)1821cdf0e10cSrcweir void ScColumn::SetTabNo(SCTAB nNewTab)
1822cdf0e10cSrcweir {
1823cdf0e10cSrcweir 	nTab = nNewTab;
1824cdf0e10cSrcweir 	pAttrArray->SetTab( nNewTab );
1825cdf0e10cSrcweir 	if (pItems)
1826cdf0e10cSrcweir 		for (SCSIZE i = 0; i < nCount; i++)
1827cdf0e10cSrcweir 		{
1828cdf0e10cSrcweir 			ScFormulaCell* p = (ScFormulaCell*) pItems[i].pCell;
1829cdf0e10cSrcweir 			if( p->GetCellType() == CELLTYPE_FORMULA )
1830cdf0e10cSrcweir 				p->aPos.SetTab( nNewTab );
1831cdf0e10cSrcweir 		}
1832cdf0e10cSrcweir }
1833cdf0e10cSrcweir 
1834cdf0e10cSrcweir 
IsRangeNameInUse(SCROW nRow1,SCROW nRow2,sal_uInt16 nIndex) const1835cdf0e10cSrcweir sal_Bool ScColumn::IsRangeNameInUse(SCROW nRow1, SCROW nRow2, sal_uInt16 nIndex) const
1836cdf0e10cSrcweir {
1837cdf0e10cSrcweir 	sal_Bool bInUse = sal_False;
1838cdf0e10cSrcweir 	if (pItems)
1839cdf0e10cSrcweir 		for (SCSIZE i = 0; !bInUse && (i < nCount); i++)
1840cdf0e10cSrcweir 			if ((pItems[i].nRow >= nRow1) &&
1841cdf0e10cSrcweir 				(pItems[i].nRow <= nRow2) &&
1842cdf0e10cSrcweir 				(pItems[i].pCell->GetCellType() == CELLTYPE_FORMULA))
1843cdf0e10cSrcweir 					bInUse = ((ScFormulaCell*)pItems[i].pCell)->IsRangeNameInUse(nIndex);
1844cdf0e10cSrcweir 	return bInUse;
1845cdf0e10cSrcweir }
1846cdf0e10cSrcweir 
FindRangeNamesInUse(SCROW nRow1,SCROW nRow2,std::set<sal_uInt16> & rIndexes) const1847cdf0e10cSrcweir void ScColumn::FindRangeNamesInUse(SCROW nRow1, SCROW nRow2, std::set<sal_uInt16>& rIndexes) const
1848cdf0e10cSrcweir {
1849cdf0e10cSrcweir     if (pItems)
1850cdf0e10cSrcweir         for (SCSIZE i = 0; i < nCount; i++)
1851cdf0e10cSrcweir             if ((pItems[i].nRow >= nRow1) &&
1852cdf0e10cSrcweir                 (pItems[i].nRow <= nRow2) &&
1853cdf0e10cSrcweir                 (pItems[i].pCell->GetCellType() == CELLTYPE_FORMULA))
1854cdf0e10cSrcweir                     ((ScFormulaCell*)pItems[i].pCell)->FindRangeNamesInUse(rIndexes);
1855cdf0e10cSrcweir }
1856cdf0e10cSrcweir 
ReplaceRangeNamesInUse(SCROW nRow1,SCROW nRow2,const ScRangeData::IndexMap & rMap)1857cdf0e10cSrcweir void ScColumn::ReplaceRangeNamesInUse(SCROW nRow1, SCROW nRow2,
1858cdf0e10cSrcweir                                      const ScRangeData::IndexMap& rMap )
1859cdf0e10cSrcweir {
1860cdf0e10cSrcweir     if (pItems)
1861cdf0e10cSrcweir         for (SCSIZE i = 0; i < nCount; i++)
1862cdf0e10cSrcweir         {
1863cdf0e10cSrcweir             if ((pItems[i].nRow >= nRow1) &&
1864cdf0e10cSrcweir                 (pItems[i].nRow <= nRow2) &&
1865cdf0e10cSrcweir                 (pItems[i].pCell->GetCellType() == CELLTYPE_FORMULA))
1866cdf0e10cSrcweir             {
1867cdf0e10cSrcweir                 SCROW nRow = pItems[i].nRow;
1868cdf0e10cSrcweir                 ((ScFormulaCell*)pItems[i].pCell)->ReplaceRangeNamesInUse( rMap );
1869cdf0e10cSrcweir                 if ( nRow != pItems[i].nRow )
1870cdf0e10cSrcweir                     Search( nRow, i );      // Listener geloescht/eingefuegt?
1871cdf0e10cSrcweir             }
1872cdf0e10cSrcweir         }
1873cdf0e10cSrcweir }
1874cdf0e10cSrcweir 
SetDirtyVar()1875cdf0e10cSrcweir void ScColumn::SetDirtyVar()
1876cdf0e10cSrcweir {
1877cdf0e10cSrcweir 	for (SCSIZE i=0; i<nCount; i++)
1878cdf0e10cSrcweir 	{
1879cdf0e10cSrcweir 		ScFormulaCell* p = (ScFormulaCell*) pItems[i].pCell;
1880cdf0e10cSrcweir 		if( p->GetCellType() == CELLTYPE_FORMULA )
1881cdf0e10cSrcweir 			p->SetDirtyVar();
1882cdf0e10cSrcweir 	}
1883cdf0e10cSrcweir }
1884cdf0e10cSrcweir 
1885cdf0e10cSrcweir 
SetDirty()1886cdf0e10cSrcweir void ScColumn::SetDirty()
1887cdf0e10cSrcweir {
1888cdf0e10cSrcweir 	// wird nur dokumentweit verwendet, kein FormulaTrack
1889cdf0e10cSrcweir 	sal_Bool bOldAutoCalc = pDocument->GetAutoCalc();
1890cdf0e10cSrcweir 	pDocument->SetAutoCalc( sal_False );	// Mehrfachberechnungen vermeiden
1891cdf0e10cSrcweir 	for (SCSIZE i=0; i<nCount; i++)
1892cdf0e10cSrcweir 	{
1893cdf0e10cSrcweir 		ScFormulaCell* p = (ScFormulaCell*) pItems[i].pCell;
1894cdf0e10cSrcweir 		if( p->GetCellType() == CELLTYPE_FORMULA )
1895cdf0e10cSrcweir 		{
1896cdf0e10cSrcweir 			p->SetDirtyVar();
1897cdf0e10cSrcweir 			if ( !pDocument->IsInFormulaTree( p ) )
1898cdf0e10cSrcweir 				pDocument->PutInFormulaTree( p );
1899cdf0e10cSrcweir 		}
1900cdf0e10cSrcweir 	}
1901cdf0e10cSrcweir 	pDocument->SetAutoCalc( bOldAutoCalc );
1902cdf0e10cSrcweir }
1903cdf0e10cSrcweir 
1904cdf0e10cSrcweir 
SetDirty(const ScRange & rRange)1905cdf0e10cSrcweir void ScColumn::SetDirty( const ScRange& rRange )
1906cdf0e10cSrcweir {	// broadcastet alles innerhalb eines Range, mit FormulaTrack
1907cdf0e10cSrcweir 	if ( !pItems || !nCount )
1908cdf0e10cSrcweir 		return ;
1909cdf0e10cSrcweir 	sal_Bool bOldAutoCalc = pDocument->GetAutoCalc();
1910cdf0e10cSrcweir 	pDocument->SetAutoCalc( sal_False );	// Mehrfachberechnungen vermeiden
1911cdf0e10cSrcweir 	SCROW nRow2 = rRange.aEnd.Row();
1912cdf0e10cSrcweir 	ScAddress aPos( nCol, 0, nTab );
1913cdf0e10cSrcweir     ScHint aHint( SC_HINT_DATACHANGED, aPos, NULL );
1914cdf0e10cSrcweir 	SCROW nRow;
1915cdf0e10cSrcweir 	SCSIZE nIndex;
1916cdf0e10cSrcweir 	Search( rRange.aStart.Row(), nIndex );
1917cdf0e10cSrcweir 	while ( nIndex < nCount && (nRow = pItems[nIndex].nRow) <= nRow2 )
1918cdf0e10cSrcweir 	{
1919cdf0e10cSrcweir 		ScBaseCell* pCell = pItems[nIndex].pCell;
1920cdf0e10cSrcweir 		if ( pCell->GetCellType() == CELLTYPE_FORMULA )
1921cdf0e10cSrcweir 			((ScFormulaCell*)pCell)->SetDirty();
1922cdf0e10cSrcweir 		else
1923cdf0e10cSrcweir 		{
1924cdf0e10cSrcweir 			aHint.GetAddress().SetRow( nRow );
1925cdf0e10cSrcweir             aHint.SetCell( pCell );
1926cdf0e10cSrcweir 			pDocument->Broadcast( aHint );
1927cdf0e10cSrcweir 		}
1928cdf0e10cSrcweir 		nIndex++;
1929cdf0e10cSrcweir 	}
1930cdf0e10cSrcweir 	pDocument->SetAutoCalc( bOldAutoCalc );
1931cdf0e10cSrcweir }
1932cdf0e10cSrcweir 
1933cdf0e10cSrcweir 
SetTableOpDirty(const ScRange & rRange)1934cdf0e10cSrcweir void ScColumn::SetTableOpDirty( const ScRange& rRange )
1935cdf0e10cSrcweir {
1936cdf0e10cSrcweir 	if ( !pItems || !nCount )
1937cdf0e10cSrcweir 		return ;
1938cdf0e10cSrcweir 	sal_Bool bOldAutoCalc = pDocument->GetAutoCalc();
1939cdf0e10cSrcweir 	pDocument->SetAutoCalc( sal_False );	// no multiple recalculation
1940cdf0e10cSrcweir 	SCROW nRow2 = rRange.aEnd.Row();
1941cdf0e10cSrcweir 	ScAddress aPos( nCol, 0, nTab );
1942cdf0e10cSrcweir     ScHint aHint( SC_HINT_TABLEOPDIRTY, aPos, NULL );
1943cdf0e10cSrcweir 	SCROW nRow;
1944cdf0e10cSrcweir 	SCSIZE nIndex;
1945cdf0e10cSrcweir 	Search( rRange.aStart.Row(), nIndex );
1946cdf0e10cSrcweir 	while ( nIndex < nCount && (nRow = pItems[nIndex].nRow) <= nRow2 )
1947cdf0e10cSrcweir 	{
1948cdf0e10cSrcweir 		ScBaseCell* pCell = pItems[nIndex].pCell;
1949cdf0e10cSrcweir 		if ( pCell->GetCellType() == CELLTYPE_FORMULA )
1950cdf0e10cSrcweir 			((ScFormulaCell*)pCell)->SetTableOpDirty();
1951cdf0e10cSrcweir 		else
1952cdf0e10cSrcweir 		{
1953cdf0e10cSrcweir 			aHint.GetAddress().SetRow( nRow );
1954cdf0e10cSrcweir             aHint.SetCell( pCell );
1955cdf0e10cSrcweir 			pDocument->Broadcast( aHint );
1956cdf0e10cSrcweir 		}
1957cdf0e10cSrcweir 		nIndex++;
1958cdf0e10cSrcweir 	}
1959cdf0e10cSrcweir 	pDocument->SetAutoCalc( bOldAutoCalc );
1960cdf0e10cSrcweir }
1961cdf0e10cSrcweir 
1962cdf0e10cSrcweir 
SetDirtyAfterLoad()1963cdf0e10cSrcweir void ScColumn::SetDirtyAfterLoad()
1964cdf0e10cSrcweir {
1965cdf0e10cSrcweir 	sal_Bool bOldAutoCalc = pDocument->GetAutoCalc();
1966cdf0e10cSrcweir 	pDocument->SetAutoCalc( sal_False );	// Mehrfachberechnungen vermeiden
1967cdf0e10cSrcweir 	for (SCSIZE i=0; i<nCount; i++)
1968cdf0e10cSrcweir 	{
1969cdf0e10cSrcweir 		ScFormulaCell* p = (ScFormulaCell*) pItems[i].pCell;
1970cdf0e10cSrcweir #if 1
1971cdf0e10cSrcweir         // Simply set dirty and append to FormulaTree, without broadcasting,
1972cdf0e10cSrcweir         // which is a magnitude faster. This is used to calculate the entire
1973cdf0e10cSrcweir         // document, e.g. when loading alien file formats.
1974cdf0e10cSrcweir         if ( p->GetCellType() == CELLTYPE_FORMULA )
1975cdf0e10cSrcweir             p->SetDirtyAfterLoad();
1976cdf0e10cSrcweir #else
1977cdf0e10cSrcweir /* This was used with the binary file format that stored results, where only
1978cdf0e10cSrcweir  * newly compiled and volatile functions and their dependents had to be
1979cdf0e10cSrcweir  * recalculated, which was faster then. Since that was moved to 'binfilter' to
1980cdf0e10cSrcweir  * convert to an XML file this isn't needed anymore, and not used for other
1981cdf0e10cSrcweir  * file formats. Kept for reference in case mechanism needs to be reactivated
1982cdf0e10cSrcweir  * for some file formats, we'd have to introduce a controlling parameter to
1983cdf0e10cSrcweir  * this method here then.
1984cdf0e10cSrcweir */
1985cdf0e10cSrcweir 
1986cdf0e10cSrcweir         // If the cell was alsready dirty because of CalcAfterLoad,
1987cdf0e10cSrcweir         // FormulaTracking has to take place.
1988cdf0e10cSrcweir         if ( p->GetCellType() == CELLTYPE_FORMULA && p->GetDirty() )
1989cdf0e10cSrcweir             p->SetDirty();
1990cdf0e10cSrcweir #endif
1991cdf0e10cSrcweir 	}
1992cdf0e10cSrcweir 	pDocument->SetAutoCalc( bOldAutoCalc );
1993cdf0e10cSrcweir }
1994cdf0e10cSrcweir 
1995cdf0e10cSrcweir 
SetRelNameDirty()1996cdf0e10cSrcweir void ScColumn::SetRelNameDirty()
1997cdf0e10cSrcweir {
1998cdf0e10cSrcweir 	sal_Bool bOldAutoCalc = pDocument->GetAutoCalc();
1999cdf0e10cSrcweir 	pDocument->SetAutoCalc( sal_False );	// Mehrfachberechnungen vermeiden
2000cdf0e10cSrcweir 	for (SCSIZE i=0; i<nCount; i++)
2001cdf0e10cSrcweir 	{
2002cdf0e10cSrcweir 		ScFormulaCell* p = (ScFormulaCell*) pItems[i].pCell;
2003cdf0e10cSrcweir 		if( p->GetCellType() == CELLTYPE_FORMULA && p->HasRelNameReference() )
2004cdf0e10cSrcweir 			p->SetDirty();
2005cdf0e10cSrcweir 	}
2006cdf0e10cSrcweir 	pDocument->SetAutoCalc( bOldAutoCalc );
2007cdf0e10cSrcweir }
2008cdf0e10cSrcweir 
2009cdf0e10cSrcweir 
CalcAll()2010cdf0e10cSrcweir void ScColumn::CalcAll()
2011cdf0e10cSrcweir {
2012cdf0e10cSrcweir 	if (pItems)
2013cdf0e10cSrcweir 		for (SCSIZE i=0; i<nCount; i++)
2014cdf0e10cSrcweir 		{
2015cdf0e10cSrcweir 			ScBaseCell* pCell = pItems[i].pCell;
2016cdf0e10cSrcweir 			if (pCell->GetCellType() == CELLTYPE_FORMULA)
2017cdf0e10cSrcweir 			{
2018cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
2019cdf0e10cSrcweir 				// nach F9 ctrl-F9: ueberprueft die Berechnung per FormulaTree
2020cdf0e10cSrcweir 				ScFormulaCell* pFCell = (ScFormulaCell*)pCell;
2021cdf0e10cSrcweir 				double nOldVal, nNewVal;
2022cdf0e10cSrcweir 				nOldVal = pFCell->GetValue();
2023cdf0e10cSrcweir #endif
2024cdf0e10cSrcweir 				((ScFormulaCell*)pCell)->Interpret();
2025cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
2026cdf0e10cSrcweir 				if ( pFCell->GetCode()->IsRecalcModeNormal() )
2027cdf0e10cSrcweir 					nNewVal = pFCell->GetValue();
2028cdf0e10cSrcweir 				else
2029cdf0e10cSrcweir 					nNewVal = nOldVal;	// random(), jetzt() etc.
2030cdf0e10cSrcweir 				DBG_ASSERT( nOldVal==nNewVal, "CalcAll: nOldVal != nNewVal" );
2031cdf0e10cSrcweir #endif
2032cdf0e10cSrcweir 			}
2033cdf0e10cSrcweir 		}
2034cdf0e10cSrcweir }
2035cdf0e10cSrcweir 
2036cdf0e10cSrcweir 
CompileAll()2037cdf0e10cSrcweir void ScColumn::CompileAll()
2038cdf0e10cSrcweir {
2039cdf0e10cSrcweir 	if (pItems)
2040cdf0e10cSrcweir 		for (SCSIZE i = 0; i < nCount; i++)
2041cdf0e10cSrcweir 		{
2042cdf0e10cSrcweir 			ScBaseCell* pCell = pItems[i].pCell;
2043cdf0e10cSrcweir 			if ( pCell->GetCellType() == CELLTYPE_FORMULA )
2044cdf0e10cSrcweir 			{
2045cdf0e10cSrcweir 				SCROW nRow = pItems[i].nRow;
2046cdf0e10cSrcweir 				// fuer unbedingtes kompilieren
2047cdf0e10cSrcweir 				// bCompile=sal_True und pCode->nError=0
2048cdf0e10cSrcweir 				((ScFormulaCell*)pCell)->GetCode()->SetCodeError( 0 );
2049cdf0e10cSrcweir 				((ScFormulaCell*)pCell)->SetCompile( sal_True );
2050cdf0e10cSrcweir 				((ScFormulaCell*)pCell)->CompileTokenArray();
2051cdf0e10cSrcweir 				if ( nRow != pItems[i].nRow )
2052cdf0e10cSrcweir 					Search( nRow, i );		// Listener geloescht/eingefuegt?
2053cdf0e10cSrcweir 			}
2054cdf0e10cSrcweir 		}
2055cdf0e10cSrcweir }
2056cdf0e10cSrcweir 
2057cdf0e10cSrcweir 
CompileXML(ScProgress & rProgress)2058cdf0e10cSrcweir void ScColumn::CompileXML( ScProgress& rProgress )
2059cdf0e10cSrcweir {
2060cdf0e10cSrcweir 	if (pItems)
2061cdf0e10cSrcweir 		for (SCSIZE i = 0; i < nCount; i++)
2062cdf0e10cSrcweir 		{
2063cdf0e10cSrcweir 			ScBaseCell* pCell = pItems[i].pCell;
2064cdf0e10cSrcweir 			if ( pCell->GetCellType() == CELLTYPE_FORMULA )
2065cdf0e10cSrcweir 			{
2066cdf0e10cSrcweir 				SCROW nRow = pItems[i].nRow;
2067cdf0e10cSrcweir 				((ScFormulaCell*)pCell)->CompileXML( rProgress );
2068cdf0e10cSrcweir 				if ( nRow != pItems[i].nRow )
2069cdf0e10cSrcweir 					Search( nRow, i );		// Listener geloescht/eingefuegt?
2070cdf0e10cSrcweir 			}
2071cdf0e10cSrcweir 		}
2072cdf0e10cSrcweir }
2073cdf0e10cSrcweir 
2074cdf0e10cSrcweir 
CalcAfterLoad()2075cdf0e10cSrcweir void ScColumn::CalcAfterLoad()
2076cdf0e10cSrcweir {
2077cdf0e10cSrcweir 	if (pItems)
2078cdf0e10cSrcweir 		for (SCSIZE i = 0; i < nCount; i++)
2079cdf0e10cSrcweir 		{
2080cdf0e10cSrcweir 			ScBaseCell* pCell = pItems[i].pCell;
2081cdf0e10cSrcweir 			if ( pCell->GetCellType() == CELLTYPE_FORMULA )
2082cdf0e10cSrcweir 				((ScFormulaCell*)pCell)->CalcAfterLoad();
2083cdf0e10cSrcweir 		}
2084cdf0e10cSrcweir }
2085cdf0e10cSrcweir 
2086cdf0e10cSrcweir 
ResetChanged(SCROW nStartRow,SCROW nEndRow)2087cdf0e10cSrcweir void ScColumn::ResetChanged( SCROW nStartRow, SCROW nEndRow )
2088cdf0e10cSrcweir {
2089cdf0e10cSrcweir 	if (pItems)
2090cdf0e10cSrcweir 	{
2091cdf0e10cSrcweir 		SCSIZE nIndex;
2092cdf0e10cSrcweir 		Search(nStartRow,nIndex);
2093cdf0e10cSrcweir 		while (nIndex<nCount && pItems[nIndex].nRow <= nEndRow)
2094cdf0e10cSrcweir 		{
2095cdf0e10cSrcweir 			ScBaseCell* pCell = pItems[nIndex].pCell;
2096cdf0e10cSrcweir 			if (pCell->GetCellType() == CELLTYPE_FORMULA)
2097cdf0e10cSrcweir 				((ScFormulaCell*)pCell)->ResetChanged();
2098cdf0e10cSrcweir 			++nIndex;
2099cdf0e10cSrcweir 		}
2100cdf0e10cSrcweir 	}
2101cdf0e10cSrcweir }
2102cdf0e10cSrcweir 
2103cdf0e10cSrcweir 
HasEditCells(SCROW nStartRow,SCROW nEndRow,SCROW & rFirst) const2104cdf0e10cSrcweir sal_Bool ScColumn::HasEditCells(SCROW nStartRow, SCROW nEndRow, SCROW& rFirst) const
2105cdf0e10cSrcweir {
2106cdf0e10cSrcweir 	//	used in GetOptimalHeight - ambiguous script type counts as edit cell
2107cdf0e10cSrcweir 
2108cdf0e10cSrcweir     SCROW nRow = 0;
2109cdf0e10cSrcweir 	SCSIZE nIndex;
2110cdf0e10cSrcweir 	Search(nStartRow,nIndex);
2111cdf0e10cSrcweir 	while ( (nIndex < nCount) ? ((nRow=pItems[nIndex].nRow) <= nEndRow) : sal_False )
2112cdf0e10cSrcweir 	{
2113cdf0e10cSrcweir 		ScBaseCell* pCell = pItems[nIndex].pCell;
2114cdf0e10cSrcweir         CellType eCellType = pCell->GetCellType();
2115cdf0e10cSrcweir 		if ( eCellType == CELLTYPE_EDIT ||
2116cdf0e10cSrcweir 			 IsAmbiguousScriptNonZero( pDocument->GetScriptType(nCol, nRow, nTab, pCell) ) ||
2117cdf0e10cSrcweir              ((eCellType == CELLTYPE_FORMULA) && ((ScFormulaCell*)pCell)->IsMultilineResult()) )
2118cdf0e10cSrcweir 		{
2119cdf0e10cSrcweir 			rFirst = nRow;
2120cdf0e10cSrcweir 			return sal_True;
2121cdf0e10cSrcweir 		}
2122cdf0e10cSrcweir 		++nIndex;
2123cdf0e10cSrcweir 	}
2124cdf0e10cSrcweir 
2125cdf0e10cSrcweir 	return sal_False;
2126cdf0e10cSrcweir }
2127cdf0e10cSrcweir 
2128cdf0e10cSrcweir 
SearchStyle(SCsROW nRow,const ScStyleSheet * pSearchStyle,sal_Bool bUp,sal_Bool bInSelection,const ScMarkData & rMark)2129cdf0e10cSrcweir SCsROW ScColumn::SearchStyle( SCsROW nRow, const ScStyleSheet* pSearchStyle,
2130cdf0e10cSrcweir 								sal_Bool bUp, sal_Bool bInSelection, const ScMarkData& rMark )
2131cdf0e10cSrcweir {
2132cdf0e10cSrcweir 	if (bInSelection)
2133cdf0e10cSrcweir 	{
2134cdf0e10cSrcweir 		if (rMark.IsMultiMarked())
2135cdf0e10cSrcweir 			return pAttrArray->SearchStyle( nRow, pSearchStyle, bUp,
2136cdf0e10cSrcweir 									(ScMarkArray*) rMark.GetArray()+nCol );		//! const
2137cdf0e10cSrcweir 		else
2138cdf0e10cSrcweir 			return -1;
2139cdf0e10cSrcweir 	}
2140cdf0e10cSrcweir 	else
2141cdf0e10cSrcweir 		return pAttrArray->SearchStyle( nRow, pSearchStyle, bUp, NULL );
2142cdf0e10cSrcweir }
2143cdf0e10cSrcweir 
2144cdf0e10cSrcweir 
SearchStyleRange(SCsROW & rRow,SCsROW & rEndRow,const ScStyleSheet * pSearchStyle,sal_Bool bUp,sal_Bool bInSelection,const ScMarkData & rMark)2145cdf0e10cSrcweir sal_Bool ScColumn::SearchStyleRange( SCsROW& rRow, SCsROW& rEndRow, const ScStyleSheet* pSearchStyle,
2146cdf0e10cSrcweir 									sal_Bool bUp, sal_Bool bInSelection, const ScMarkData& rMark )
2147cdf0e10cSrcweir {
2148cdf0e10cSrcweir 	if (bInSelection)
2149cdf0e10cSrcweir 	{
2150cdf0e10cSrcweir 		if (rMark.IsMultiMarked())
2151cdf0e10cSrcweir 			return pAttrArray->SearchStyleRange( rRow, rEndRow, pSearchStyle, bUp,
2152cdf0e10cSrcweir 									(ScMarkArray*) rMark.GetArray()+nCol );		//! const
2153cdf0e10cSrcweir 		else
2154cdf0e10cSrcweir 			return sal_False;
2155cdf0e10cSrcweir 	}
2156cdf0e10cSrcweir 	else
2157cdf0e10cSrcweir 		return pAttrArray->SearchStyleRange( rRow, rEndRow, pSearchStyle, bUp, NULL );
2158cdf0e10cSrcweir }
2159cdf0e10cSrcweir 
2160cdf0e10cSrcweir 
2161