/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sc.hxx"



// INCLUDE ---------------------------------------------------------------

#include <map>

#include <svl/poolcach.hxx>
#include <svl/zforlist.hxx>
#include <editeng/scripttypeitem.hxx>
#include <string.h>

#include "scitems.hxx"
#include "column.hxx"
#include "cell.hxx"
#include "document.hxx"
#include "docpool.hxx"
#include "attarray.hxx"
#include "patattr.hxx"
#include "compiler.hxx"
#include "brdcst.hxx"
#include "markdata.hxx"
#include "detfunc.hxx"			// for Notes in Sort/Swap
#include "postit.hxx"

//#pragma optimize ( "", off )
//	nur Search ohne Optimierung!

// STATIC DATA -----------------------------------------------------------
using namespace formula;

inline sal_Bool IsAmbiguousScriptNonZero( sal_uInt8 nScript )
{
	//!	move to a header file
	return ( nScript != SCRIPTTYPE_LATIN &&
			 nScript != SCRIPTTYPE_ASIAN &&
			 nScript != SCRIPTTYPE_COMPLEX &&
			 nScript != 0 );
}

// -----------------------------------------------------------------------------------------


ScColumn::ScColumn() :
	nCol( 0 ),
	nCount( 0 ),
	nLimit( 0 ),
	pItems( NULL ),
    pAttrArray( NULL ),
    pDocument( NULL )
{
}


ScColumn::~ScColumn()
{
	FreeAll();
	if (pAttrArray) delete pAttrArray;
}


void ScColumn::Init(SCCOL nNewCol, SCTAB nNewTab, ScDocument* pDoc)
{
	nCol = nNewCol;
	nTab = nNewTab;
	pDocument = pDoc;
	pAttrArray = new ScAttrArray( nCol, nTab, pDocument );
}


SCsROW ScColumn::GetNextUnprotected( SCROW nRow, sal_Bool bUp ) const
{
	return pAttrArray->GetNextUnprotected(nRow, bUp);
}


sal_uInt16 ScColumn::GetBlockMatrixEdges( SCROW nRow1, SCROW nRow2, sal_uInt16 nMask ) const
{
	// nix:0, mitte:1, unten:2, links:4, oben:8, rechts:16, offen:32
	if ( !pItems )
		return 0;
	if ( nRow1 == nRow2 )
	{
		SCSIZE nIndex;
		if ( Search( nRow1, nIndex ) )
		{
			ScBaseCell* pCell = pItems[nIndex].pCell;
			if ( pCell->GetCellType() == CELLTYPE_FORMULA
				&& ((ScFormulaCell*)pCell)->GetMatrixFlag() )
			{
				ScAddress aOrg( ScAddress::INITIALIZE_INVALID );
				return ((ScFormulaCell*)pCell)->GetMatrixEdge( aOrg );
			}
		}
		return 0;
	}
	else
	{
		ScAddress aOrg( ScAddress::INITIALIZE_INVALID );
		sal_Bool bOpen = sal_False;
		sal_uInt16 nEdges = 0;
		SCSIZE nIndex;
		Search( nRow1, nIndex );
		while ( nIndex < nCount && pItems[nIndex].nRow <= nRow2 )
		{
			ScBaseCell* pCell = pItems[nIndex].pCell;
			if ( pCell->GetCellType() == CELLTYPE_FORMULA
				&& ((ScFormulaCell*)pCell)->GetMatrixFlag() )
			{
				nEdges = ((ScFormulaCell*)pCell)->GetMatrixEdge( aOrg );
				if ( nEdges )
				{
					if ( nEdges & 8 )
						bOpen = sal_True;	// obere Kante oeffnet, weitersehen
					else if ( !bOpen )
						return nEdges | 32;	// es gibt was, was nicht geoeffnet wurde
					else if ( nEdges & 1 )
						return nEdges;	// mittendrin
					// (nMask & 16 und  (4 und nicht 16)) oder
					// (nMask & 4  und (16 und nicht 4))
					if ( ((nMask & 16) && (nEdges & 4)  && !(nEdges & 16))
						|| ((nMask & 4)  && (nEdges & 16) && !(nEdges & 4)) )
						return nEdges;	// nur linke/rechte Kante
					if ( nEdges & 2 )
						bOpen = sal_False;	// untere Kante schliesst
				}
			}
			nIndex++;
		}
		if ( bOpen )
			nEdges |= 32;			// es geht noch weiter
		return nEdges;
	}
}


sal_Bool ScColumn::HasSelectionMatrixFragment(const ScMarkData& rMark) const
{
	if ( rMark.IsMultiMarked() )
	{
		sal_Bool bFound = sal_False;

		ScAddress aOrg( ScAddress::INITIALIZE_INVALID );
		ScAddress aCurOrg( ScAddress::INITIALIZE_INVALID );
		SCROW nTop, nBottom;
		ScMarkArrayIter aMarkIter( rMark.GetArray()+nCol );
		while ( !bFound && aMarkIter.Next( nTop, nBottom ) )
		{
			sal_Bool bOpen = sal_False;
			sal_uInt16 nEdges;
			SCSIZE nIndex;
			Search( nTop, nIndex );
			while ( !bFound && nIndex < nCount && pItems[nIndex].nRow <= nBottom )
			{
				ScBaseCell* pCell = pItems[nIndex].pCell;
				if ( pCell->GetCellType() == CELLTYPE_FORMULA
					&& ((ScFormulaCell*)pCell)->GetMatrixFlag() )
				{
					nEdges = ((ScFormulaCell*)pCell)->GetMatrixEdge( aOrg );
					if ( nEdges )
					{
						if ( nEdges & 8 )
							bOpen = sal_True;	// obere Kante oeffnet, weitersehen
						else if ( !bOpen )
							return sal_True;	// es gibt was, was nicht geoeffnet wurde
						else if ( nEdges & 1 )
							bFound = sal_True;	// mittendrin, alles selektiert?
						// (4 und nicht 16) oder (16 und nicht 4)
						if ( (((nEdges & 4) | 16) ^ ((nEdges & 16) | 4)) )
							bFound = sal_True;	// nur linke/rechte Kante, alles selektiert?
						if ( nEdges & 2 )
							bOpen = sal_False;	// untere Kante schliesst

						if ( bFound )
						{	// alles selektiert?
							if ( aCurOrg != aOrg )
							{	// neue Matrix zu pruefen?
								aCurOrg = aOrg;
								ScFormulaCell* pFCell;
								if ( ((ScFormulaCell*)pCell)->GetMatrixFlag()
										== MM_REFERENCE )
									pFCell = (ScFormulaCell*) pDocument->GetCell( aOrg );
								else
									pFCell = (ScFormulaCell*)pCell;
                                SCCOL nC;
                                SCROW nR;
                                pFCell->GetMatColsRows( nC, nR );
								ScRange aRange( aOrg, ScAddress(
									aOrg.Col() + nC - 1, aOrg.Row() + nR - 1,
									aOrg.Tab() ) );
								if ( rMark.IsAllMarked( aRange ) )
									bFound = sal_False;
							}
							else
								bFound = sal_False;		// war schon
						}
					}
				}
				nIndex++;
			}
			if ( bOpen )
				return sal_True;
		}
		return bFound;
	}
	else
		return sal_False;
}


//UNUSED2009-05 sal_Bool ScColumn::HasLines( SCROW nRow1, SCROW nRow2, Rectangle& rSizes,
//UNUSED2009-05                             sal_Bool bLeft, sal_Bool bRight ) const
//UNUSED2009-05 {
//UNUSED2009-05     return pAttrArray->HasLines( nRow1, nRow2, rSizes, bLeft, bRight );
//UNUSED2009-05 }


bool ScColumn::HasAttrib( SCROW nRow1, SCROW nRow2, sal_uInt16 nMask ) const
{
	return pAttrArray->HasAttrib( nRow1, nRow2, nMask );
}


sal_Bool ScColumn::HasAttribSelection( const ScMarkData& rMark, sal_uInt16 nMask ) const
{
	sal_Bool bFound = sal_False;

	SCROW nTop;
	SCROW nBottom;

	if (rMark.IsMultiMarked())
	{
		ScMarkArrayIter aMarkIter( rMark.GetArray()+nCol );
		while (aMarkIter.Next( nTop, nBottom ) && !bFound)
		{
			if (pAttrArray->HasAttrib( nTop, nBottom, nMask ))
				bFound = sal_True;
		}
	}

	return bFound;
}


sal_Bool ScColumn::ExtendMerge( SCCOL nThisCol, SCROW nStartRow, SCROW nEndRow,
							SCCOL& rPaintCol, SCROW& rPaintRow,
							sal_Bool bRefresh, sal_Bool bAttrs )
{
	return pAttrArray->ExtendMerge( nThisCol, nStartRow, nEndRow, rPaintCol, rPaintRow, bRefresh, bAttrs );
}


void ScColumn::MergeSelectionPattern( ScMergePatternState& rState, const ScMarkData& rMark, sal_Bool bDeep ) const
{
	SCROW nTop;
	SCROW nBottom;

	if ( rMark.IsMultiMarked() )
	{
        const ScMarkArray* pArray = rMark.GetArray() + nCol;
        if ( pArray->HasMarks() )
        {
            ScMarkArrayIter aMarkIter( pArray );
            while (aMarkIter.Next( nTop, nBottom ))
                pAttrArray->MergePatternArea( nTop, nBottom, rState, bDeep );
        }
	}
}


void ScColumn::MergePatternArea( ScMergePatternState& rState, SCROW nRow1, SCROW nRow2, sal_Bool bDeep ) const
{
	pAttrArray->MergePatternArea( nRow1, nRow2, rState, bDeep );
}


void ScColumn::MergeBlockFrame( SvxBoxItem* pLineOuter, SvxBoxInfoItem* pLineInner,
							ScLineFlags& rFlags,
							SCROW nStartRow, SCROW nEndRow, sal_Bool bLeft, SCCOL nDistRight ) const
{
	pAttrArray->MergeBlockFrame( pLineOuter, pLineInner, rFlags, nStartRow, nEndRow, bLeft, nDistRight );
}


void ScColumn::ApplyBlockFrame( const SvxBoxItem* pLineOuter, const SvxBoxInfoItem* pLineInner,
							SCROW nStartRow, SCROW nEndRow, sal_Bool bLeft, SCCOL nDistRight )
{
	pAttrArray->ApplyBlockFrame( pLineOuter, pLineInner, nStartRow, nEndRow, bLeft, nDistRight );
}


const ScPatternAttr* ScColumn::GetPattern( SCROW nRow ) const
{
	return pAttrArray->GetPattern( nRow );
}

const ScPatternAttr* ScColumn::GetPatternRange( SCROW& rStartRow, SCROW& rEndRow, SCROW nRow ) const
{
	return pAttrArray->GetPatternRange( rStartRow, rEndRow, nRow );
}

const SfxPoolItem* ScColumn::GetAttr( SCROW nRow, sal_uInt16 nWhich ) const
{
	return &pAttrArray->GetPattern( nRow )->GetItemSet().Get(nWhich);
}


const ScPatternAttr* ScColumn::GetMostUsedPattern( SCROW nStartRow, SCROW nEndRow ) const
{
    ::std::map< const ScPatternAttr*, size_t > aAttrMap;
    const ScPatternAttr* pMaxPattern = 0;
    size_t nMaxCount = 0;

    ScAttrIterator aAttrIter( pAttrArray, nStartRow, nEndRow );
    const ScPatternAttr* pPattern;
    SCROW nAttrRow1 = 0, nAttrRow2 = 0;

    while( (pPattern = aAttrIter.Next( nAttrRow1, nAttrRow2 )) != 0 )
    {
        size_t& rnCount = aAttrMap[ pPattern ];
        rnCount += (nAttrRow2 - nAttrRow1 + 1);
        if( rnCount > nMaxCount )
        {
            pMaxPattern = pPattern;
            nMaxCount = rnCount;
        }
    }

    return pMaxPattern;
}


sal_uLong ScColumn::GetNumberFormat( SCROW nRow ) const
{
	return pAttrArray->GetPattern( nRow )->GetNumberFormat( pDocument->GetFormatTable() );
}


SCsROW ScColumn::ApplySelectionCache( SfxItemPoolCache* pCache, const ScMarkData& rMark )
{
    SCROW nTop = 0;
    SCROW nBottom = 0;
	sal_Bool bFound = sal_False;

	if ( rMark.IsMultiMarked() )
	{
		ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol );
		while (aMarkIter.Next( nTop, nBottom ))
		{
			pAttrArray->ApplyCacheArea( nTop, nBottom, pCache );
			bFound = sal_True;
		}
	}

	if (!bFound)
		return -1;
	else if (nTop==0 && nBottom==MAXROW)
		return 0;
	else
		return nBottom;
}


void ScColumn::ChangeSelectionIndent( sal_Bool bIncrement, const ScMarkData& rMark )
{
	SCROW nTop;
	SCROW nBottom;

	if ( pAttrArray && rMark.IsMultiMarked() )
	{
		ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol );
		while (aMarkIter.Next( nTop, nBottom ))
			pAttrArray->ChangeIndent(nTop, nBottom, bIncrement);
	}
}


void ScColumn::ClearSelectionItems( const sal_uInt16* pWhich,const ScMarkData& rMark )
{
	SCROW nTop;
	SCROW nBottom;

	if ( pAttrArray && rMark.IsMultiMarked() )
	{
		ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol );
		while (aMarkIter.Next( nTop, nBottom ))
			pAttrArray->ClearItems(nTop, nBottom, pWhich);
	}
}


void ScColumn::DeleteSelection( sal_uInt16 nDelFlag, const ScMarkData& rMark )
{
	SCROW nTop;
	SCROW nBottom;

	if ( rMark.IsMultiMarked() )
	{
		ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol );
		while (aMarkIter.Next( nTop, nBottom ))
            DeleteArea(nTop, nBottom, nDelFlag);
	}
}


void ScColumn::ApplyPattern( SCROW nRow, const ScPatternAttr& rPatAttr )
{
	const SfxItemSet* pSet = &rPatAttr.GetItemSet();
	SfxItemPoolCache aCache( pDocument->GetPool(), pSet );

	const ScPatternAttr* pPattern = pAttrArray->GetPattern( nRow );

	//	sal_True = alten Eintrag behalten

	ScPatternAttr* pNewPattern = (ScPatternAttr*) &aCache.ApplyTo( *pPattern, sal_True );
	ScDocumentPool::CheckRef( *pPattern );
	ScDocumentPool::CheckRef( *pNewPattern );

	if (pNewPattern != pPattern)
	  pAttrArray->SetPattern( nRow, pNewPattern );
}


void ScColumn::ApplyPatternArea( SCROW nStartRow, SCROW nEndRow, const ScPatternAttr& rPatAttr )
{
	const SfxItemSet* pSet = &rPatAttr.GetItemSet();
	SfxItemPoolCache aCache( pDocument->GetPool(), pSet );
	pAttrArray->ApplyCacheArea( nStartRow, nEndRow, &aCache );
}


void ScColumn::ApplyPatternIfNumberformatIncompatible( const ScRange& rRange,
		const ScPatternAttr& rPattern, short nNewType )
{
	const SfxItemSet* pSet = &rPattern.GetItemSet();
	SfxItemPoolCache aCache( pDocument->GetPool(), pSet );
	SvNumberFormatter* pFormatter = pDocument->GetFormatTable();
	SCROW nEndRow = rRange.aEnd.Row();
	for ( SCROW nRow = rRange.aStart.Row(); nRow <= nEndRow; nRow++ )
	{
		SCROW nRow1, nRow2;
		const ScPatternAttr* pPattern = pAttrArray->GetPatternRange(
			nRow1, nRow2, nRow );
		sal_uLong nFormat = pPattern->GetNumberFormat( pFormatter );
		short nOldType = pFormatter->GetType( nFormat );
		if ( nOldType == nNewType || pFormatter->IsCompatible( nOldType, nNewType ) )
			nRow = nRow2;
		else
		{
			SCROW nNewRow1 = Max( nRow1, nRow );
			SCROW nNewRow2 = Min( nRow2, nEndRow );
			pAttrArray->ApplyCacheArea( nNewRow1, nNewRow2, &aCache );
			nRow = nNewRow2;
		}
	}
}


void ScColumn::ApplyStyle( SCROW nRow, const ScStyleSheet& rStyle )
{
	const ScPatternAttr* pPattern = pAttrArray->GetPattern(nRow);
	ScPatternAttr* pNewPattern = new ScPatternAttr(*pPattern);
	if (pNewPattern)
	{
		pNewPattern->SetStyleSheet((ScStyleSheet*)&rStyle);
		pAttrArray->SetPattern(nRow, pNewPattern, sal_True);
		delete pNewPattern;
	}
}


void ScColumn::ApplyStyleArea( SCROW nStartRow, SCROW nEndRow, const ScStyleSheet& rStyle )
{
	pAttrArray->ApplyStyleArea(nStartRow, nEndRow, (ScStyleSheet*)&rStyle);
}


void ScColumn::ApplySelectionStyle(const ScStyleSheet& rStyle, const ScMarkData& rMark)
{
	SCROW nTop;
	SCROW nBottom;

	if ( rMark.IsMultiMarked() )
	{
		ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol );
		while (aMarkIter.Next( nTop, nBottom ))
			pAttrArray->ApplyStyleArea(nTop, nBottom, (ScStyleSheet*)&rStyle);
	}
}


void ScColumn::ApplySelectionLineStyle( const ScMarkData& rMark,
									const SvxBorderLine* pLine, sal_Bool bColorOnly )
{
	if ( bColorOnly && !pLine )
		return;

	SCROW nTop;
	SCROW nBottom;

	if (rMark.IsMultiMarked())
	{
		ScMarkArrayIter aMarkIter( rMark.GetArray()+nCol );
		while (aMarkIter.Next( nTop, nBottom ))
			pAttrArray->ApplyLineStyleArea(nTop, nBottom, pLine, bColorOnly );
	}
}


const ScStyleSheet* ScColumn::GetStyle( SCROW nRow ) const
{
	return pAttrArray->GetPattern( nRow )->GetStyleSheet();
}


const ScStyleSheet* ScColumn::GetSelectionStyle( const ScMarkData& rMark, sal_Bool& rFound ) const
{
	rFound = sal_False;
	if (!rMark.IsMultiMarked())
	{
		DBG_ERROR("ScColumn::GetSelectionStyle ohne Selektion");
		return NULL;
	}

	sal_Bool bEqual = sal_True;

	const ScStyleSheet* pStyle = NULL;
	const ScStyleSheet* pNewStyle;

	ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol );
	SCROW nTop;
	SCROW nBottom;
	while (bEqual && aMarkIter.Next( nTop, nBottom ))
	{
		ScAttrIterator aAttrIter( pAttrArray, nTop, nBottom );
		SCROW nRow;
		SCROW nDummy;
		const ScPatternAttr* pPattern;
        while (bEqual && ( pPattern = aAttrIter.Next( nRow, nDummy ) ) != NULL)
		{
			pNewStyle = pPattern->GetStyleSheet();
			rFound = sal_True;
			if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) )
				bEqual = sal_False;												// unterschiedliche
			pStyle = pNewStyle;
		}
	}

	return bEqual ? pStyle : NULL;
}


const ScStyleSheet*	ScColumn::GetAreaStyle( sal_Bool& rFound, SCROW nRow1, SCROW nRow2 ) const
{
	rFound = sal_False;

	sal_Bool bEqual = sal_True;

	const ScStyleSheet* pStyle = NULL;
	const ScStyleSheet* pNewStyle;

	ScAttrIterator aAttrIter( pAttrArray, nRow1, nRow2 );
	SCROW nRow;
	SCROW nDummy;
	const ScPatternAttr* pPattern;
    while (bEqual && ( pPattern = aAttrIter.Next( nRow, nDummy ) ) != NULL)
	{
		pNewStyle = pPattern->GetStyleSheet();
		rFound = sal_True;
		if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) )
			bEqual = sal_False;												// unterschiedliche
		pStyle = pNewStyle;
	}

	return bEqual ? pStyle : NULL;
}

void ScColumn::FindStyleSheet( const SfxStyleSheetBase* pStyleSheet, ScFlatBoolRowSegments& rUsedRows, bool bReset )
{
    pAttrArray->FindStyleSheet( pStyleSheet, rUsedRows, bReset );
}

sal_Bool ScColumn::IsStyleSheetUsed( const ScStyleSheet& rStyle, sal_Bool bGatherAllStyles ) const
{
	return pAttrArray->IsStyleSheetUsed( rStyle, bGatherAllStyles );
}


sal_Bool ScColumn::ApplyFlags( SCROW nStartRow, SCROW nEndRow, sal_Int16 nFlags )
{
	return pAttrArray->ApplyFlags( nStartRow, nEndRow, nFlags );
}


sal_Bool ScColumn::RemoveFlags( SCROW nStartRow, SCROW nEndRow, sal_Int16 nFlags )
{
	return pAttrArray->RemoveFlags( nStartRow, nEndRow, nFlags );
}


void ScColumn::ClearItems( SCROW nStartRow, SCROW nEndRow, const sal_uInt16* pWhich )
{
	pAttrArray->ClearItems( nStartRow, nEndRow, pWhich );
}


void ScColumn::SetPattern( SCROW nRow, const ScPatternAttr& rPatAttr, sal_Bool bPutToPool )
{
	pAttrArray->SetPattern( nRow, &rPatAttr, bPutToPool );
}


void ScColumn::SetPatternArea( SCROW nStartRow, SCROW nEndRow,
								const ScPatternAttr& rPatAttr, sal_Bool bPutToPool )
{
	pAttrArray->SetPatternArea( nStartRow, nEndRow, &rPatAttr, bPutToPool );
}


void ScColumn::ApplyAttr( SCROW nRow, const SfxPoolItem& rAttr )
{
	//	um nur ein neues SetItem zu erzeugen, brauchen wir keinen SfxItemPoolCache.
	//!	Achtung: der SfxItemPoolCache scheint zuviele Refs fuer das neue SetItem zu erzeugen ??

	ScDocumentPool* pDocPool = pDocument->GetPool();

	const ScPatternAttr* pOldPattern = pAttrArray->GetPattern( nRow );
	ScPatternAttr* pTemp = new ScPatternAttr(*pOldPattern);
	pTemp->GetItemSet().Put(rAttr);
	const ScPatternAttr* pNewPattern = (const ScPatternAttr*) &pDocPool->Put( *pTemp );

	if ( pNewPattern != pOldPattern )
		pAttrArray->SetPattern( nRow, pNewPattern );
	else
		pDocPool->Remove( *pNewPattern );		// ausser Spesen nichts gewesen

	delete pTemp;

		// alte Version mit SfxItemPoolCache:
#if 0
	SfxItemPoolCache aCache( pDocument->GetPool(), &rAttr );

	const ScPatternAttr* pPattern = pAttrArray->GetPattern( nRow );

	//	sal_True = alten Eintrag behalten

	ScPatternAttr* pNewPattern = (ScPatternAttr*) &aCache.ApplyTo( *pPattern, sal_True );
	ScDocumentPool::CheckRef( *pPattern );
	ScDocumentPool::CheckRef( *pNewPattern );

	if (pNewPattern != pPattern)
	  pAttrArray->SetPattern( nRow, pNewPattern );
#endif
}

#ifdef _MSC_VER
#pragma optimize ( "", off )
#endif


sal_Bool ScColumn::Search( SCROW nRow, SCSIZE& nIndex ) const
{
	if ( !pItems || !nCount )
	{
		nIndex = 0;
		return sal_False;
	}
	SCROW nMinRow = pItems[0].nRow;
	if ( nRow <= nMinRow )
	{
		nIndex = 0;
		return nRow == nMinRow;
	}
	SCROW nMaxRow = pItems[nCount-1].nRow;
	if ( nRow >= nMaxRow )
	{
		if ( nRow == nMaxRow )
		{
			nIndex = nCount - 1;
			return sal_True;
		}
		else
		{
			nIndex = nCount;
			return sal_False;
		}
	}

	long nOldLo, nOldHi;
	long	nLo 	= nOldLo = 0;
    long	nHi 	= nOldHi = Min(static_cast<long>(nCount)-1, static_cast<long>(nRow) );
	long	i		= 0;
	sal_Bool	bFound	= sal_False;
	// quite continuous distribution? => interpolating search
	sal_Bool	bInterpol = (static_cast<SCSIZE>(nMaxRow - nMinRow) < nCount * 2);
	SCROW	nR;

	while ( !bFound && nLo <= nHi )
	{
		if ( !bInterpol || nHi - nLo < 3 )
			i = (nLo+nHi) / 2;			// no effort, no division by zero
		else
		{	// interpolating search
			long nLoRow = pItems[nLo].nRow;		// no unsigned underflow upon subtraction
			i = nLo + (long)((long)(nRow - nLoRow) * (nHi - nLo)
				/ (pItems[nHi].nRow - nLoRow));
			if ( i < 0 || static_cast<SCSIZE>(i) >= nCount )
			{	// oops ...
				i = (nLo+nHi) / 2;
				bInterpol = sal_False;
			}
		}
		nR = pItems[i].nRow;
		if ( nR < nRow )
		{
			nLo = i+1;
			if ( bInterpol )
			{
				if ( nLo <= nOldLo )
					bInterpol = sal_False;
				else
					nOldLo = nLo;
			}
		}
		else
		{
			if ( nR > nRow )
			{
				nHi = i-1;
				if ( bInterpol )
				{
					if ( nHi >= nOldHi )
						bInterpol = sal_False;
					else
						nOldHi = nHi;
				}
			}
			else
				bFound = sal_True;
		}
	}
	if (bFound)
		nIndex = static_cast<SCSIZE>(i);
	else
		nIndex = static_cast<SCSIZE>(nLo); // rear index
	return bFound;
}

#ifdef _MSC_VER
#pragma optimize ( "", on )
#endif


ScBaseCell* ScColumn::GetCell( SCROW nRow ) const
{
	SCSIZE nIndex;
	if (Search(nRow, nIndex))
		return pItems[nIndex].pCell;
	return NULL;
}


void ScColumn::Resize( SCSIZE nSize )
{
    if (nSize > sal::static_int_cast<SCSIZE>(MAXROWCOUNT))
		nSize = MAXROWCOUNT;
	if (nSize < nCount)
		nSize = nCount;

	ColEntry* pNewItems;
	if (nSize)
	{
		SCSIZE nNewSize = nSize + COLUMN_DELTA - 1;
		nNewSize -= nNewSize % COLUMN_DELTA;
		nLimit = nNewSize;
		pNewItems = new ColEntry[nLimit];
	}
	else
	{
		nLimit = 0;
		pNewItems = NULL;
	}
	if (pItems)
	{
		if (pNewItems)
			memmove( pNewItems, pItems, nCount * sizeof(ColEntry) );
		delete[] pItems;
	}
	pItems = pNewItems;
}

//	SwapRow zum Sortieren

namespace {

/** Moves broadcaster from old cell to new cell if exists, otherwise creates a new note cell. */
void lclTakeBroadcaster( ScBaseCell*& rpCell, SvtBroadcaster* pBC )
{
    if( pBC )
    {
        if( rpCell )
            rpCell->TakeBroadcaster( pBC );
        else
            rpCell = new ScNoteCell( pBC );
    }
}

} // namespace

void ScColumn::SwapRow(SCROW nRow1, SCROW nRow2)
{
    /*  Simple swap of cell pointers does not work if broadcasters exist (crash
        if cell broadcasts directly or indirectly to itself). While swapping
        the cells, broadcasters have to remain at old positions! */

    /*  While cloning cells, do not clone notes, but move note pointers to new
        cells. This prevents creation of new caption drawing objects for every
        swap operation while sorting. */

	ScBaseCell* pCell1 = 0;
	SCSIZE nIndex1;
	if ( Search( nRow1, nIndex1 ) )
		pCell1 = pItems[nIndex1].pCell;

    ScBaseCell* pCell2 = 0;
	SCSIZE nIndex2;
	if ( Search( nRow2, nIndex2 ) )
		pCell2 = pItems[nIndex2].pCell;

    // no cells found, nothing to do
	if ( !pCell1 && !pCell2 )
		return ;

    // swap variables if first cell is empty, to save some code below
    if ( !pCell1 )
    {
        ::std::swap( nRow1, nRow2 );
        ::std::swap( nIndex1, nIndex2 );
        ::std::swap( pCell1, pCell2 );
    }

    // from here: first cell (pCell1, nIndex1) exists always

    ScAddress aPos1( nCol, nRow1, nTab );
    ScAddress aPos2( nCol, nRow2, nTab );

	CellType eType1 = pCell1->GetCellType();
	CellType eType2 = pCell2 ? pCell2->GetCellType() : CELLTYPE_NONE;

    ScFormulaCell* pFmlaCell1 = (eType1 == CELLTYPE_FORMULA) ? static_cast< ScFormulaCell* >( pCell1 ) : 0;
    ScFormulaCell* pFmlaCell2 = (eType2 == CELLTYPE_FORMULA) ? static_cast< ScFormulaCell* >( pCell2 ) : 0;

    // simple swap if no formula cells present
	if ( !pFmlaCell1 && !pFmlaCell2 )
	{
        // remember cell broadcasters, must remain at old position
        SvtBroadcaster* pBC1 = pCell1->ReleaseBroadcaster();

		if ( pCell2 )
		{
            /*  Both cells exist, no formula cells involved, a simple swap can
                be performed (but keep broadcasters and notes at old position). */
			pItems[nIndex1].pCell = pCell2;
			pItems[nIndex2].pCell = pCell1;

            SvtBroadcaster* pBC2 = pCell2->ReleaseBroadcaster();
            pCell1->TakeBroadcaster( pBC2 );
            pCell2->TakeBroadcaster( pBC1 );
		}
		else
		{
			ScNoteCell* pDummyCell = pBC1 ? new ScNoteCell( pBC1 ) : 0;
			if ( pDummyCell )
			{
                // insert dummy note cell (without note) containing old broadcaster
				pItems[nIndex1].pCell = pDummyCell;
			}
			else
			{
                // remove ColEntry at old position
				--nCount;
				memmove( &pItems[nIndex1], &pItems[nIndex1 + 1], (nCount - nIndex1) * sizeof(ColEntry) );
				pItems[nCount].nRow = 0;
				pItems[nCount].pCell = 0;
			}

            // insert ColEntry at new position
			Insert( nRow2, pCell1 );
		}

		return;
	}

	// from here: at least one of the cells is a formula cell

    /*  Never move any array formulas. Disabling sort if parts of array
        formulas are contained is done at UI. */
    if ( (pFmlaCell1 && (pFmlaCell1->GetMatrixFlag() != 0)) || (pFmlaCell2 && (pFmlaCell2->GetMatrixFlag() != 0)) )
        return;

    // do not swap, if formulas are equal
	if ( pFmlaCell1 && pFmlaCell2 )
	{
		ScTokenArray* pCode1 = pFmlaCell1->GetCode();
		ScTokenArray* pCode2 = pFmlaCell2->GetCode();

		if (pCode1->GetLen() == pCode2->GetLen())		// nicht-UPN
		{
			sal_Bool bEqual = sal_True;
			sal_uInt16 nLen = pCode1->GetLen();
			FormulaToken** ppToken1 = pCode1->GetArray();
			FormulaToken** ppToken2 = pCode2->GetArray();
			for (sal_uInt16 i=0; i<nLen; i++)
            {
                if ( !ppToken1[i]->TextEqual(*(ppToken2[i])) ||
                        ppToken1[i]->Is3DRef() || ppToken2[i]->Is3DRef() )
				{
					bEqual = sal_False;
					break;
				}
            }

            // do not swap formula cells with equal formulas, but swap notes
			if (bEqual)
            {
                ScPostIt* pNote1 = pCell1->ReleaseNote();
                pCell1->TakeNote( pCell2->ReleaseNote() );
                pCell2->TakeNote( pNote1 );
				return;
            }
		}
	}

	//	hier kein UpdateReference wegen #30529# - mitsortiert werden nur noch relative Referenzen
//	long dy = (long)nRow2 - (long)nRow1;

    /*  Create clone of pCell1 at position of pCell2 (pCell1 exists always, see
        variable swapping above). Do not clone the note, but move pointer of
        old note to new cell. */
    ScBaseCell* pNew2 = pCell1->CloneWithoutNote( *pDocument, aPos2, SC_CLONECELL_ADJUST3DREL );
    pNew2->TakeNote( pCell1->ReleaseNote() );

    /*  Create clone of pCell2 at position of pCell1. Do not clone the note,
        but move pointer of old note to new cell. */
	ScBaseCell* pNew1 = 0;
	if ( pCell2 )
	{
        pNew1 = pCell2->CloneWithoutNote( *pDocument, aPos1, SC_CLONECELL_ADJUST3DREL );
        pNew1->TakeNote( pCell2->ReleaseNote() );
	}

    // move old broadcasters new cells at the same old position
    SvtBroadcaster* pBC1 = pCell1->ReleaseBroadcaster();
    lclTakeBroadcaster( pNew1, pBC1 );
    SvtBroadcaster* pBC2 = pCell2 ? pCell2->ReleaseBroadcaster() : 0;
    lclTakeBroadcaster( pNew2, pBC2 );

	/*  Insert the new cells. Old cell has to be deleted, if there is no new
        cell (call to Insert deletes old cell by itself). */
	if ( !pNew1 )
		Delete( nRow1 );            // deletes pCell1
	else
        Insert( nRow1, pNew1 );     // deletes pCell1, inserts pNew1

	if ( pCell2 && !pNew2 )
		Delete( nRow2 );            // deletes pCell2
	else if ( pNew2 )
		Insert( nRow2, pNew2 );     // deletes pCell2 (if existing), inserts pNew2
}


void ScColumn::SwapCell( SCROW nRow, ScColumn& rCol)
{
	ScBaseCell* pCell1 = 0;
	SCSIZE nIndex1;
	if ( Search( nRow, nIndex1 ) )
		pCell1 = pItems[nIndex1].pCell;

    ScBaseCell* pCell2 = 0;
	SCSIZE nIndex2;
	if ( rCol.Search( nRow, nIndex2 ) )
		pCell2 = rCol.pItems[nIndex2].pCell;

    // reverse call if own cell is missing (ensures own existing cell in following code)
    if( !pCell1 )
    {
        if( pCell2 )
            rCol.SwapCell( nRow, *this );
        return;
    }

    // from here: own cell (pCell1, nIndex1) exists always

    ScFormulaCell* pFmlaCell1 = (pCell1->GetCellType() == CELLTYPE_FORMULA) ? static_cast< ScFormulaCell* >( pCell1 ) : 0;
	ScFormulaCell* pFmlaCell2 = (pCell2 && (pCell2->GetCellType() == CELLTYPE_FORMULA)) ? static_cast< ScFormulaCell* >( pCell2 ) : 0;

	if ( pCell2 )
	{
		// Tauschen
		pItems[nIndex1].pCell = pCell2;
		rCol.pItems[nIndex2].pCell = pCell1;
		// Referenzen aktualisieren
		SCsCOL dx = rCol.nCol - nCol;
		if ( pFmlaCell1 )
		{
			ScRange aRange( ScAddress( rCol.nCol, 0, nTab ),
							ScAddress( rCol.nCol, MAXROW, nTab ) );
			pFmlaCell1->aPos.SetCol( rCol.nCol );
			pFmlaCell1->UpdateReference(URM_MOVE, aRange, dx, 0, 0);
		}
		if ( pFmlaCell2 )
		{
			ScRange aRange( ScAddress( nCol, 0, nTab ),
							ScAddress( nCol, MAXROW, nTab ) );
			pFmlaCell2->aPos.SetCol( nCol );
			pFmlaCell2->UpdateReference(URM_MOVE, aRange, -dx, 0, 0);
		}
	}
	else
    {
        // Loeschen
        --nCount;
        memmove( &pItems[nIndex1], &pItems[nIndex1 + 1], (nCount - nIndex1) * sizeof(ColEntry) );
        pItems[nCount].nRow = 0;
        pItems[nCount].pCell = 0;
        // Referenzen aktualisieren
        SCsCOL dx = rCol.nCol - nCol;
        if ( pFmlaCell1 )
        {
            ScRange aRange( ScAddress( rCol.nCol, 0, nTab ),
                            ScAddress( rCol.nCol, MAXROW, nTab ) );
            pFmlaCell1->aPos.SetCol( rCol.nCol );
            pFmlaCell1->UpdateReference(URM_MOVE, aRange, dx, 0, 0);
        }
        // Einfuegen
        rCol.Insert(nRow, pCell1);
    }
}


sal_Bool ScColumn::TestInsertCol( SCROW nStartRow, SCROW nEndRow) const
{
	if (!IsEmpty())
	{
		sal_Bool bTest = sal_True;
		if (pItems)
			for (SCSIZE i=0; (i<nCount) && bTest; i++)
				bTest = (pItems[i].nRow < nStartRow) || (pItems[i].nRow > nEndRow)
                        || pItems[i].pCell->IsBlank();

		//	AttrArray testet nur zusammengefasste

		if ((bTest) && (pAttrArray))
			bTest = pAttrArray->TestInsertCol(nStartRow, nEndRow);

		//!		rausgeschobene Attribute bei Undo beruecksichtigen

		return bTest;
	}
	else
		return sal_True;
}


sal_Bool ScColumn::TestInsertRow( SCSIZE nSize ) const
{
    //  AttrArray only looks for merged cells

	if ( pItems && nCount )
        return ( nSize <= sal::static_int_cast<SCSIZE>(MAXROW) &&
                 pItems[nCount-1].nRow <= MAXROW-(SCROW)nSize && pAttrArray->TestInsertRow( nSize ) );
	else
		return pAttrArray->TestInsertRow( nSize );

#if 0
	//!		rausgeschobene Attribute bei Undo beruecksichtigen

	if ( nSize > static_cast<SCSIZE>(MAXROW) )
		return sal_False;

	SCSIZE nVis = nCount;
    while ( nVis && pItems[nVis-1].pCell->IsBlank() )
		--nVis;

	if ( nVis )
		return ( pItems[nVis-1].nRow <= MAXROW-nSize );
	else
		return sal_True;
#endif
}


void ScColumn::InsertRow( SCROW nStartRow, SCSIZE nSize )
{
	pAttrArray->InsertRow( nStartRow, nSize );

	//!	Search

	if ( !pItems || !nCount )
		return;

	SCSIZE i;
	Search( nStartRow, i );
	if ( i >= nCount )
		return ;

	sal_Bool bOldAutoCalc = pDocument->GetAutoCalc();
	pDocument->SetAutoCalc( sal_False );	// Mehrfachberechnungen vermeiden

	SCSIZE nNewCount = nCount;
	sal_Bool bCountChanged = sal_False;
	ScAddress aAdr( nCol, 0, nTab );
    ScHint aHint( SC_HINT_DATACHANGED, aAdr, NULL );    // only areas (ScBaseCell* == NULL)
    ScAddress& rAddress = aHint.GetAddress();
    // for sparse occupation use single broadcasts, not ranges
    sal_Bool bSingleBroadcasts = (((pItems[nCount-1].nRow - pItems[i].nRow) /
                (nCount - i)) > 1);
    if ( bSingleBroadcasts )
    {
        SCROW nLastBroadcast = MAXROW+1;
        for ( ; i < nCount; i++)
        {
            SCROW nOldRow = pItems[i].nRow;
            // #43940# Aenderung Quelle broadcasten
            if ( nLastBroadcast != nOldRow )
            {   // direkt aufeinanderfolgende nicht doppelt broadcasten
                rAddress.SetRow( nOldRow );
                pDocument->AreaBroadcast( aHint );
            }
            SCROW nNewRow = (pItems[i].nRow += nSize);
            // #43940# Aenderung Ziel broadcasten
            rAddress.SetRow( nNewRow );
            pDocument->AreaBroadcast( aHint );
            nLastBroadcast = nNewRow;
            ScBaseCell* pCell = pItems[i].pCell;
            if ( pCell->GetCellType() == CELLTYPE_FORMULA )
                ((ScFormulaCell*)pCell)->aPos.SetRow( nNewRow );
            if ( nNewRow > MAXROW && !bCountChanged )
            {
                nNewCount = i;
                bCountChanged = sal_True;
            }
        }
    }
    else
    {
        rAddress.SetRow( pItems[i].nRow );
        ScRange aRange( rAddress );
        for ( ; i < nCount; i++)
        {
            SCROW nNewRow = (pItems[i].nRow += nSize);
            ScBaseCell* pCell = pItems[i].pCell;
            if ( pCell->GetCellType() == CELLTYPE_FORMULA )
                ((ScFormulaCell*)pCell)->aPos.SetRow( nNewRow );
            if ( nNewRow > MAXROW && !bCountChanged )
            {
                nNewCount = i;
                bCountChanged = sal_True;
                aRange.aEnd.SetRow( MAXROW );
            }
        }
        if ( !bCountChanged )
            aRange.aEnd.SetRow( pItems[nCount-1].nRow );
        pDocument->AreaBroadcastInRange( aRange, aHint );
    }

	if (bCountChanged)
	{
		SCSIZE nDelCount = nCount - nNewCount;
		ScBaseCell** ppDelCells = new ScBaseCell*[nDelCount];
		SCROW* pDelRows = new SCROW[nDelCount];
		for (i = 0; i < nDelCount; i++)
		{
			ppDelCells[i] = pItems[nNewCount+i].pCell;
			pDelRows[i] = pItems[nNewCount+i].nRow;
		}
		nCount = nNewCount;

		for (i = 0; i < nDelCount; i++)
		{
			ScBaseCell* pCell = ppDelCells[i];
            DBG_ASSERT( pCell->IsBlank(), "sichtbare Zelle weggeschoben" );
			SvtBroadcaster* pBC = pCell->GetBroadcaster();
			if (pBC)
			{
				MoveListeners( *pBC, pDelRows[i] - nSize );
                pCell->DeleteBroadcaster();
				pCell->Delete();
			}
		}

		delete [] pDelRows;
		delete [] ppDelCells;
	}

	pDocument->SetAutoCalc( bOldAutoCalc );
}


void ScColumn::CopyToClip(SCROW nRow1, SCROW nRow2, ScColumn& rColumn, sal_Bool bKeepScenarioFlags, sal_Bool bCloneNoteCaptions)
{
	pAttrArray->CopyArea( nRow1, nRow2, 0, *rColumn.pAttrArray,
							bKeepScenarioFlags ? (SC_MF_ALL & ~SC_MF_SCENARIO) : SC_MF_ALL );

	SCSIZE i;
	SCSIZE nBlockCount = 0;
    SCSIZE nStartIndex = 0, nEndIndex = 0;
	for (i = 0; i < nCount; i++)
		if ((pItems[i].nRow >= nRow1) && (pItems[i].nRow <= nRow2))
		{
			if (!nBlockCount)
				nStartIndex = i;
			nEndIndex = i;
			++nBlockCount;

			//	im Clipboard muessen interpretierte Zellen stehen, um andere Formate
			//	(Text, Grafik...) erzueugen zu koennen

			if ( pItems[i].pCell->GetCellType() == CELLTYPE_FORMULA )
			{
				ScFormulaCell* pFCell = (ScFormulaCell*) pItems[i].pCell;
				if (pFCell->GetDirty() && pDocument->GetAutoCalc())
					pFCell->Interpret();
			}
		}

	if (nBlockCount)
	{
        int nCloneFlags = bCloneNoteCaptions ? SC_CLONECELL_DEFAULT : SC_CLONECELL_NOCAPTION;
		rColumn.Resize( rColumn.GetCellCount() + nBlockCount );
        ScAddress aOwnPos( nCol, 0, nTab );
        ScAddress aDestPos( rColumn.nCol, 0, rColumn.nTab );
		for (i = nStartIndex; i <= nEndIndex; i++)
        {
            aOwnPos.SetRow( pItems[i].nRow );
            aDestPos.SetRow( pItems[i].nRow );
            ScBaseCell* pNewCell = pItems[i].pCell->CloneWithNote( aOwnPos, *rColumn.pDocument, aDestPos, nCloneFlags );
            rColumn.Append( aDestPos.Row(), pNewCell );
        }
	}
}


void ScColumn::CopyToColumn(SCROW nRow1, SCROW nRow2, sal_uInt16 nFlags, sal_Bool bMarked,
								ScColumn& rColumn, const ScMarkData* pMarkData, sal_Bool bAsLink )
{
	if (bMarked)
	{
		SCROW nStart, nEnd;
		if (pMarkData && pMarkData->IsMultiMarked())
		{
			ScMarkArrayIter aIter( pMarkData->GetArray()+nCol );

			while ( aIter.Next( nStart, nEnd ) && nStart <= nRow2 )
			{
				if ( nEnd >= nRow1 )
					CopyToColumn( Max(nRow1,nStart), Min(nRow2,nEnd),
									nFlags, sal_False, rColumn, pMarkData, bAsLink );
			}
		}
		else
		{
			DBG_ERROR("CopyToColumn: bMarked, aber keine Markierung");
		}
		return;
	}

	if ( (nFlags & IDF_ATTRIB) != 0 )
	{
		if ( (nFlags & IDF_STYLES) != IDF_STYLES )
		{	// StyleSheets im Zieldokument bleiben erhalten
			// z.B. DIF und RTF Clipboard-Import
			for ( SCROW nRow = nRow1; nRow <= nRow2; nRow++ )
			{
				const ScStyleSheet* pStyle =
					rColumn.pAttrArray->GetPattern( nRow )->GetStyleSheet();
				const ScPatternAttr* pPattern = pAttrArray->GetPattern( nRow );
				ScPatternAttr* pNewPattern = new ScPatternAttr( *pPattern );
				pNewPattern->SetStyleSheet( (ScStyleSheet*)pStyle );
				rColumn.pAttrArray->SetPattern( nRow, pNewPattern, sal_True );
				delete pNewPattern;
			}
		}
		else
			pAttrArray->CopyArea( nRow1, nRow2, 0, *rColumn.pAttrArray);
	}


	if ((nFlags & IDF_CONTENTS) != 0)
	{
		SCSIZE i;
		SCSIZE nBlockCount = 0;
        SCSIZE nStartIndex = 0, nEndIndex = 0;
		for (i = 0; i < nCount; i++)
			if ((pItems[i].nRow >= nRow1) && (pItems[i].nRow <= nRow2))
			{
				if (!nBlockCount)
					nStartIndex = i;
				nEndIndex = i;
				++nBlockCount;
			}

		if (nBlockCount)
		{
			rColumn.Resize( rColumn.GetCellCount() + nBlockCount );
			ScAddress aDestPos( rColumn.nCol, 0, rColumn.nTab );
			for (i = nStartIndex; i <= nEndIndex; i++)
			{
				aDestPos.SetRow( pItems[i].nRow );
				ScBaseCell* pNew = bAsLink ?
                    CreateRefCell( rColumn.pDocument, aDestPos, i, nFlags ) :
                    CloneCell( i, nFlags, *rColumn.pDocument, aDestPos );

				if (pNew)
					rColumn.Insert(pItems[i].nRow, pNew);
			}
		}
	}
}


void ScColumn::UndoToColumn(SCROW nRow1, SCROW nRow2, sal_uInt16 nFlags, sal_Bool bMarked,
								ScColumn& rColumn, const ScMarkData* pMarkData )
{
	if (nRow1 > 0)
		CopyToColumn( 0, nRow1-1, IDF_FORMULA, sal_False, rColumn );

	CopyToColumn( nRow1, nRow2, nFlags, bMarked, rColumn, pMarkData );		//! bMarked ????

	if (nRow2 < MAXROW)
		CopyToColumn( nRow2+1, MAXROW, IDF_FORMULA, sal_False, rColumn );
}


void ScColumn::CopyUpdated( const ScColumn& rPosCol, ScColumn& rDestCol ) const
{
	ScDocument& rDestDoc = *rDestCol.pDocument;
    ScAddress aOwnPos( nCol, 0, nTab );
    ScAddress aDestPos( rDestCol.nCol, 0, rDestCol.nTab );

	SCSIZE nPosCount = rPosCol.nCount;
	for (SCSIZE nPosIndex = 0; nPosIndex < nPosCount; nPosIndex++)
	{
        aOwnPos.SetRow( rPosCol.pItems[nPosIndex].nRow );
        aDestPos.SetRow( aOwnPos.Row() );
		SCSIZE nThisIndex;
		if ( Search( aDestPos.Row(), nThisIndex ) )
		{
            ScBaseCell* pNew = pItems[nThisIndex].pCell->CloneWithNote( aOwnPos, rDestDoc, aDestPos );
			rDestCol.Insert( aDestPos.Row(), pNew );
		}
	}

	//	Dummy:
	//	CopyToColumn( 0,MAXROW, IDF_FORMULA, sal_False, rDestCol, NULL, sal_False );
}


void ScColumn::CopyScenarioFrom( const ScColumn& rSrcCol )
{
	//	Dies ist die Szenario-Tabelle, die Daten werden hineinkopiert

	ScAttrIterator aAttrIter( pAttrArray, 0, MAXROW );
	SCROW nStart = -1, nEnd = -1;
	const ScPatternAttr* pPattern = aAttrIter.Next( nStart, nEnd );
	while (pPattern)
	{
		if ( ((ScMergeFlagAttr&)pPattern->GetItem( ATTR_MERGE_FLAG )).IsScenario() )
		{
			DeleteArea( nStart, nEnd, IDF_CONTENTS );
			((ScColumn&)rSrcCol).
				CopyToColumn( nStart, nEnd, IDF_CONTENTS, sal_False, *this );

			//	UpdateUsed nicht noetig, schon in TestCopyScenario passiert

			SCsTAB nDz = nTab - rSrcCol.nTab;
			UpdateReference(URM_COPY, nCol, nStart, nTab,
									  nCol, nEnd,   nTab,
									  0, 0, nDz, NULL);
			UpdateCompile();
		}

		//!	CopyToColumn "const" machen !!!

		pPattern = aAttrIter.Next( nStart, nEnd );
	}
}


void ScColumn::CopyScenarioTo( ScColumn& rDestCol ) const
{
	//	Dies ist die Szenario-Tabelle, die Daten werden in die andere kopiert

	ScAttrIterator aAttrIter( pAttrArray, 0, MAXROW );
	SCROW nStart = -1, nEnd = -1;
	const ScPatternAttr* pPattern = aAttrIter.Next( nStart, nEnd );
	while (pPattern)
	{
		if ( ((ScMergeFlagAttr&)pPattern->GetItem( ATTR_MERGE_FLAG )).IsScenario() )
		{
			rDestCol.DeleteArea( nStart, nEnd, IDF_CONTENTS );
			((ScColumn*)this)->
				CopyToColumn( nStart, nEnd, IDF_CONTENTS, sal_False, rDestCol );

			//	UpdateUsed nicht noetig, schon in TestCopyScenario passiert

			SCsTAB nDz = rDestCol.nTab - nTab;
			rDestCol.UpdateReference(URM_COPY, rDestCol.nCol, nStart, rDestCol.nTab,
											   rDestCol.nCol, nEnd,   rDestCol.nTab,
											   0, 0, nDz, NULL);
			rDestCol.UpdateCompile();
		}

		//!	CopyToColumn "const" machen !!!

		pPattern = aAttrIter.Next( nStart, nEnd );
	}
}


sal_Bool ScColumn::TestCopyScenarioTo( const ScColumn& rDestCol ) const
{
	sal_Bool bOk = sal_True;
	ScAttrIterator aAttrIter( pAttrArray, 0, MAXROW );
	SCROW nStart = 0, nEnd = 0;
	const ScPatternAttr* pPattern = aAttrIter.Next( nStart, nEnd );
	while (pPattern && bOk)
	{
		if ( ((ScMergeFlagAttr&)pPattern->GetItem( ATTR_MERGE_FLAG )).IsScenario() )
			if ( rDestCol.pAttrArray->HasAttrib( nStart, nEnd, HASATTR_PROTECTED ) )
				bOk = sal_False;

		pPattern = aAttrIter.Next( nStart, nEnd );
	}
	return bOk;
}


void ScColumn::MarkScenarioIn( ScMarkData& rDestMark ) const
{
	ScRange aRange( nCol, 0, nTab );

	ScAttrIterator aAttrIter( pAttrArray, 0, MAXROW );
	SCROW nStart = -1, nEnd = -1;
	const ScPatternAttr* pPattern = aAttrIter.Next( nStart, nEnd );
	while (pPattern)
	{
		if ( ((ScMergeFlagAttr&)pPattern->GetItem( ATTR_MERGE_FLAG )).IsScenario() )
		{
			aRange.aStart.SetRow( nStart );
			aRange.aEnd.SetRow( nEnd );
			rDestMark.SetMultiMarkArea( aRange, sal_True );
		}

		pPattern = aAttrIter.Next( nStart, nEnd );
	}
}


void ScColumn::SwapCol(ScColumn& rCol)
{
	SCSIZE nTemp;

	nTemp = rCol.nCount;
	rCol.nCount  = nCount;
	nCount = nTemp;

	nTemp = rCol.nLimit;
	rCol.nLimit = nLimit;
	nLimit = nTemp;

	ColEntry* pTempItems = rCol.pItems;
	rCol.pItems = pItems;
	pItems = pTempItems;

	ScAttrArray* pTempAttr = rCol.pAttrArray;
	rCol.pAttrArray = pAttrArray;
	pAttrArray = pTempAttr;

	// #38415# AttrArray muss richtige Spaltennummer haben
	pAttrArray->SetCol(nCol);
	rCol.pAttrArray->SetCol(rCol.nCol);

	SCSIZE i;
	if (pItems)
		for (i = 0; i < nCount; i++)
		{
			ScFormulaCell* pCell = (ScFormulaCell*) pItems[i].pCell;
			if( pCell->GetCellType() == CELLTYPE_FORMULA)
				pCell->aPos.SetCol(nCol);
		}
	if (rCol.pItems)
		for (i = 0; i < rCol.nCount; i++)
		{
			ScFormulaCell* pCell = (ScFormulaCell*) rCol.pItems[i].pCell;
			if( pCell->GetCellType() == CELLTYPE_FORMULA)
				pCell->aPos.SetCol(rCol.nCol);
		}
}


void ScColumn::MoveTo(SCROW nStartRow, SCROW nEndRow, ScColumn& rCol)
{
	pAttrArray->MoveTo(nStartRow, nEndRow, *rCol.pAttrArray);

	if (pItems)
	{
        ::std::vector<SCROW> aRows;
        bool bConsecutive = true;
		SCSIZE i;
        Search( nStartRow, i);  // i points to start row or position thereafter
		SCSIZE nStartPos = i;
		for ( ; i < nCount && pItems[i].nRow <= nEndRow; ++i)
		{
            SCROW nRow = pItems[i].nRow;
            aRows.push_back( nRow);
            rCol.Insert( nRow, pItems[i].pCell);
            if (nRow != pItems[i].nRow)
            {   // Listener inserted
                bConsecutive = false;
                Search( nRow, i);
            }
		}
        SCSIZE nStopPos = i;
		if (nStartPos < nStopPos)
		{
            // Create list of ranges of cell entry positions
            typedef ::std::pair<SCSIZE,SCSIZE> PosPair;
            typedef ::std::vector<PosPair> EntryPosPairs;
            EntryPosPairs aEntries;
            if (bConsecutive)
                aEntries.push_back( PosPair(nStartPos, nStopPos));
            else
            {
                bool bFirst = true;
                nStopPos = 0;
                for (::std::vector<SCROW>::const_iterator it( aRows.begin());
                        it != aRows.end() && nStopPos < nCount; ++it,
                        ++nStopPos)
                {
                    if (!bFirst && *it != pItems[nStopPos].nRow)
                    {
                        aEntries.push_back( PosPair(nStartPos, nStopPos));
                        bFirst = true;
                    }
                    if (bFirst && Search( *it, nStartPos))
                    {
                        bFirst = false;
                        nStopPos = nStartPos;
                    }
                }
                if (!bFirst && nStartPos < nStopPos)
                    aEntries.push_back( PosPair(nStartPos, nStopPos));
            }
			// Broadcast changes
            ScAddress aAdr( nCol, 0, nTab );
            ScHint aHint( SC_HINT_DYING, aAdr, NULL );  // areas only
            ScAddress& rAddress = aHint.GetAddress();
            ScNoteCell* pNoteCell = new ScNoteCell;		// Dummy like in DeleteRange

            // #121990# must iterate backwards, because indexes of following cells become invalid
            for (EntryPosPairs::reverse_iterator it( aEntries.rbegin());
                    it != aEntries.rend(); ++it)
            {
                nStartPos = (*it).first;
                nStopPos = (*it).second;
                for (i=nStartPos; i<nStopPos; ++i)
                    pItems[i].pCell = pNoteCell;
                for (i=nStartPos; i<nStopPos; ++i)
                {
                    rAddress.SetRow( pItems[i].nRow );
                    pDocument->AreaBroadcast( aHint );
                }
                nCount -= nStopPos - nStartPos;
                memmove( &pItems[nStartPos], &pItems[nStopPos],
                        (nCount - nStartPos) * sizeof(ColEntry) );
            }
            delete pNoteCell;
            pItems[nCount].nRow = 0;
            pItems[nCount].pCell = NULL;
		}
	}
}


void ScColumn::UpdateReference( UpdateRefMode eUpdateRefMode, SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
			 SCCOL nCol2, SCROW nRow2, SCTAB nTab2, SCsCOL nDx, SCsROW nDy, SCsTAB nDz,
			 ScDocument* pUndoDoc )
{
	if (pItems)
	{
		ScRange aRange( ScAddress( nCol1, nRow1, nTab1 ),
						ScAddress( nCol2, nRow2, nTab2 ) );
		if ( eUpdateRefMode == URM_COPY && nRow1 == nRow2 )
		{	// z.B. eine einzelne Zelle aus dem Clipboard eingefuegt
			SCSIZE nIndex;
			if ( Search( nRow1, nIndex ) )
			{
				ScFormulaCell* pCell = (ScFormulaCell*) pItems[nIndex].pCell;
				if( pCell->GetCellType() == CELLTYPE_FORMULA)
					pCell->UpdateReference(	eUpdateRefMode, aRange, nDx, nDy, nDz, pUndoDoc );
			}
		}
		else
		{
            // #90279# For performance reasons two loop bodies instead of
            // testing for update mode in each iteration.
            // Anyways, this is still a bottleneck on large arrays with few
            // formulas cells.
            if ( eUpdateRefMode == URM_COPY )
            {
                SCSIZE i;
                Search( nRow1, i );
                for ( ; i < nCount; i++ )
                {
                    SCROW nRow = pItems[i].nRow;
                    if ( nRow > nRow2 )
                        break;
                    ScBaseCell* pCell = pItems[i].pCell;
                    if( pCell->GetCellType() == CELLTYPE_FORMULA)
                    {
                        ((ScFormulaCell*)pCell)->UpdateReference( eUpdateRefMode, aRange, nDx, nDy, nDz, pUndoDoc );
                        if ( nRow != pItems[i].nRow )
                            Search( nRow, i );  // Listener removed/inserted?
                    }
                }
            }
            else
            {
                SCSIZE i = 0;
                for ( ; i < nCount; i++ )
                {
                    ScBaseCell* pCell = pItems[i].pCell;
                    if( pCell->GetCellType() == CELLTYPE_FORMULA)
                    {
                        SCROW nRow = pItems[i].nRow;
                        // When deleting rows on several sheets, the formula's position may be updated with the first call,
                        // so the undo position must be passed from here.
                        ScAddress aUndoPos( nCol, nRow, nTab );
                        ((ScFormulaCell*)pCell)->UpdateReference( eUpdateRefMode, aRange, nDx, nDy, nDz, pUndoDoc, &aUndoPos );
                        if ( nRow != pItems[i].nRow )
                            Search( nRow, i );  // Listener removed/inserted?
                    }
                }
            }
		}
	}
}


void ScColumn::UpdateTranspose( const ScRange& rSource, const ScAddress& rDest,
									ScDocument* pUndoDoc )
{
	if (pItems)
		for (SCSIZE i=0; i<nCount; i++)
		{
			ScBaseCell* pCell = pItems[i].pCell;
			if (pCell->GetCellType() == CELLTYPE_FORMULA)
			{
				SCROW nRow = pItems[i].nRow;
				((ScFormulaCell*)pCell)->UpdateTranspose( rSource, rDest, pUndoDoc );
				if ( nRow != pItems[i].nRow )
					Search( nRow, i );				// Listener geloescht/eingefuegt?
			}
		}
}


void ScColumn::UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY )
{
	if (pItems)
		for (SCSIZE i=0; i<nCount; i++)
		{
			ScBaseCell* pCell = pItems[i].pCell;
			if (pCell->GetCellType() == CELLTYPE_FORMULA)
			{
				SCROW nRow = pItems[i].nRow;
				((ScFormulaCell*)pCell)->UpdateGrow( rArea, nGrowX, nGrowY );
				if ( nRow != pItems[i].nRow )
					Search( nRow, i );				// Listener geloescht/eingefuegt?
			}
		}
}


void ScColumn::UpdateInsertTab( SCTAB nTable)
{
    if (nTab >= nTable)
        pAttrArray->SetTab(++nTab);
	if( pItems )
		UpdateInsertTabOnlyCells( nTable );
}


void ScColumn::UpdateInsertTabOnlyCells( SCTAB nTable)
{
	if (pItems)
		for (SCSIZE i = 0; i < nCount; i++)
		{
			ScFormulaCell* pCell = (ScFormulaCell*) pItems[i].pCell;
			if( pCell->GetCellType() == CELLTYPE_FORMULA)
			{
				SCROW nRow = pItems[i].nRow;
				pCell->UpdateInsertTab(nTable);
				if ( nRow != pItems[i].nRow )
					Search( nRow, i );		// Listener geloescht/eingefuegt?
			}
		}
}


void ScColumn::UpdateInsertTabAbs(SCTAB nTable)
{
	if (pItems)
		for (SCSIZE i = 0; i < nCount; i++)
		{
			ScFormulaCell* pCell = (ScFormulaCell*) pItems[i].pCell;
			if( pCell->GetCellType() == CELLTYPE_FORMULA)
			{
				SCROW nRow = pItems[i].nRow;
				pCell->UpdateInsertTabAbs(nTable);
				if ( nRow != pItems[i].nRow )
					Search( nRow, i );		// Listener geloescht/eingefuegt?
			}
		}
}


void ScColumn::UpdateDeleteTab( SCTAB nTable, sal_Bool bIsMove, ScColumn* pRefUndo )
{
	if (nTab > nTable)
		pAttrArray->SetTab(--nTab);

	if (pItems)
		for (SCSIZE i = 0; i < nCount; i++)
			if ( pItems[i].pCell->GetCellType() == CELLTYPE_FORMULA )
			{
				SCROW nRow = pItems[i].nRow;
				ScFormulaCell* pOld = (ScFormulaCell*)pItems[i].pCell;

                /*  Do not copy cell note to the undo document. Undo will copy
                    back the formula cell while keeping the original note. */
                ScBaseCell* pSave = pRefUndo ? pOld->CloneWithoutNote( *pDocument ) : 0;

				sal_Bool bChanged = pOld->UpdateDeleteTab(nTable, bIsMove);
				if ( nRow != pItems[i].nRow )
					Search( nRow, i );		// Listener geloescht/eingefuegt?

				if (pRefUndo)
				{
					if (bChanged)
						pRefUndo->Insert( nRow, pSave );
					else if(pSave)
						pSave->Delete();
				}
			}
}


void ScColumn::UpdateMoveTab( SCTAB nOldPos, SCTAB nNewPos, SCTAB nTabNo )
{
	nTab = nTabNo;
	pAttrArray->SetTab( nTabNo );
	if (pItems)
		for (SCSIZE i = 0; i < nCount; i++)
		{
			ScFormulaCell* pCell = (ScFormulaCell*) pItems[i].pCell;
			if ( pCell->GetCellType() == CELLTYPE_FORMULA )
			{
				SCROW nRow = pItems[i].nRow;
				pCell->UpdateMoveTab( nOldPos, nNewPos, nTabNo );
				if ( nRow != pItems[i].nRow )
					Search( nRow, i );		// Listener geloescht/eingefuegt?
			}
		}
}


void ScColumn::UpdateCompile( sal_Bool bForceIfNameInUse )
{
	if (pItems)
		for (SCSIZE i = 0; i < nCount; i++)
		{
			ScFormulaCell* p = (ScFormulaCell*) pItems[i].pCell;
			if( p->GetCellType() == CELLTYPE_FORMULA )
			{
				SCROW nRow = pItems[i].nRow;
				p->UpdateCompile( bForceIfNameInUse );
				if ( nRow != pItems[i].nRow )
					Search( nRow, i );		// Listener geloescht/eingefuegt?
			}
		}
}


void ScColumn::SetTabNo(SCTAB nNewTab)
{
	nTab = nNewTab;
	pAttrArray->SetTab( nNewTab );
	if (pItems)
		for (SCSIZE i = 0; i < nCount; i++)
		{
			ScFormulaCell* p = (ScFormulaCell*) pItems[i].pCell;
			if( p->GetCellType() == CELLTYPE_FORMULA )
				p->aPos.SetTab( nNewTab );
		}
}


sal_Bool ScColumn::IsRangeNameInUse(SCROW nRow1, SCROW nRow2, sal_uInt16 nIndex) const
{
	sal_Bool bInUse = sal_False;
	if (pItems)
		for (SCSIZE i = 0; !bInUse && (i < nCount); i++)
			if ((pItems[i].nRow >= nRow1) &&
				(pItems[i].nRow <= nRow2) &&
				(pItems[i].pCell->GetCellType() == CELLTYPE_FORMULA))
					bInUse = ((ScFormulaCell*)pItems[i].pCell)->IsRangeNameInUse(nIndex);
	return bInUse;
}

void ScColumn::FindRangeNamesInUse(SCROW nRow1, SCROW nRow2, std::set<sal_uInt16>& rIndexes) const
{
    if (pItems)
        for (SCSIZE i = 0; i < nCount; i++)
            if ((pItems[i].nRow >= nRow1) &&
                (pItems[i].nRow <= nRow2) &&
                (pItems[i].pCell->GetCellType() == CELLTYPE_FORMULA))
                    ((ScFormulaCell*)pItems[i].pCell)->FindRangeNamesInUse(rIndexes);
}

void ScColumn::ReplaceRangeNamesInUse(SCROW nRow1, SCROW nRow2,
                                     const ScRangeData::IndexMap& rMap )
{
    if (pItems)
        for (SCSIZE i = 0; i < nCount; i++)
        {
            if ((pItems[i].nRow >= nRow1) &&
                (pItems[i].nRow <= nRow2) &&
                (pItems[i].pCell->GetCellType() == CELLTYPE_FORMULA))
            {
                SCROW nRow = pItems[i].nRow;
                ((ScFormulaCell*)pItems[i].pCell)->ReplaceRangeNamesInUse( rMap );
                if ( nRow != pItems[i].nRow )
                    Search( nRow, i );      // Listener geloescht/eingefuegt?
            }
        }
}

void ScColumn::SetDirtyVar()
{
	for (SCSIZE i=0; i<nCount; i++)
	{
		ScFormulaCell* p = (ScFormulaCell*) pItems[i].pCell;
		if( p->GetCellType() == CELLTYPE_FORMULA )
			p->SetDirtyVar();
	}
}


void ScColumn::SetDirty()
{
	// wird nur dokumentweit verwendet, kein FormulaTrack
	sal_Bool bOldAutoCalc = pDocument->GetAutoCalc();
	pDocument->SetAutoCalc( sal_False );	// Mehrfachberechnungen vermeiden
	for (SCSIZE i=0; i<nCount; i++)
	{
		ScFormulaCell* p = (ScFormulaCell*) pItems[i].pCell;
		if( p->GetCellType() == CELLTYPE_FORMULA )
		{
			p->SetDirtyVar();
			if ( !pDocument->IsInFormulaTree( p ) )
				pDocument->PutInFormulaTree( p );
		}
	}
	pDocument->SetAutoCalc( bOldAutoCalc );
}


void ScColumn::SetDirty( const ScRange& rRange )
{	// broadcastet alles innerhalb eines Range, mit FormulaTrack
	if ( !pItems || !nCount )
		return ;
	sal_Bool bOldAutoCalc = pDocument->GetAutoCalc();
	pDocument->SetAutoCalc( sal_False );	// Mehrfachberechnungen vermeiden
	SCROW nRow2 = rRange.aEnd.Row();
	ScAddress aPos( nCol, 0, nTab );
    ScHint aHint( SC_HINT_DATACHANGED, aPos, NULL );
	SCROW nRow;
	SCSIZE nIndex;
	Search( rRange.aStart.Row(), nIndex );
	while ( nIndex < nCount && (nRow = pItems[nIndex].nRow) <= nRow2 )
	{
		ScBaseCell* pCell = pItems[nIndex].pCell;
		if ( pCell->GetCellType() == CELLTYPE_FORMULA )
			((ScFormulaCell*)pCell)->SetDirty();
		else
		{
			aHint.GetAddress().SetRow( nRow );
            aHint.SetCell( pCell );
			pDocument->Broadcast( aHint );
		}
		nIndex++;
	}
	pDocument->SetAutoCalc( bOldAutoCalc );
}


void ScColumn::SetTableOpDirty( const ScRange& rRange )
{
	if ( !pItems || !nCount )
		return ;
	sal_Bool bOldAutoCalc = pDocument->GetAutoCalc();
	pDocument->SetAutoCalc( sal_False );	// no multiple recalculation
	SCROW nRow2 = rRange.aEnd.Row();
	ScAddress aPos( nCol, 0, nTab );
    ScHint aHint( SC_HINT_TABLEOPDIRTY, aPos, NULL );
	SCROW nRow;
	SCSIZE nIndex;
	Search( rRange.aStart.Row(), nIndex );
	while ( nIndex < nCount && (nRow = pItems[nIndex].nRow) <= nRow2 )
	{
		ScBaseCell* pCell = pItems[nIndex].pCell;
		if ( pCell->GetCellType() == CELLTYPE_FORMULA )
			((ScFormulaCell*)pCell)->SetTableOpDirty();
		else
		{
			aHint.GetAddress().SetRow( nRow );
            aHint.SetCell( pCell );
			pDocument->Broadcast( aHint );
		}
		nIndex++;
	}
	pDocument->SetAutoCalc( bOldAutoCalc );
}


void ScColumn::SetDirtyAfterLoad()
{
	sal_Bool bOldAutoCalc = pDocument->GetAutoCalc();
	pDocument->SetAutoCalc( sal_False );	// Mehrfachberechnungen vermeiden
	for (SCSIZE i=0; i<nCount; i++)
	{
		ScFormulaCell* p = (ScFormulaCell*) pItems[i].pCell;
#if 1
        // Simply set dirty and append to FormulaTree, without broadcasting,
        // which is a magnitude faster. This is used to calculate the entire
        // document, e.g. when loading alien file formats.
        if ( p->GetCellType() == CELLTYPE_FORMULA )
            p->SetDirtyAfterLoad();
#else
/* This was used with the binary file format that stored results, where only
 * newly compiled and volatile functions and their dependents had to be
 * recalculated, which was faster then. Since that was moved to 'binfilter' to
 * convert to an XML file this isn't needed anymore, and not used for other
 * file formats. Kept for reference in case mechanism needs to be reactivated
 * for some file formats, we'd have to introduce a controlling parameter to
 * this method here then.
*/

        // If the cell was alsready dirty because of CalcAfterLoad,
        // FormulaTracking has to take place.
        if ( p->GetCellType() == CELLTYPE_FORMULA && p->GetDirty() )
            p->SetDirty();
#endif
	}
	pDocument->SetAutoCalc( bOldAutoCalc );
}


void ScColumn::SetRelNameDirty()
{
	sal_Bool bOldAutoCalc = pDocument->GetAutoCalc();
	pDocument->SetAutoCalc( sal_False );	// Mehrfachberechnungen vermeiden
	for (SCSIZE i=0; i<nCount; i++)
	{
		ScFormulaCell* p = (ScFormulaCell*) pItems[i].pCell;
		if( p->GetCellType() == CELLTYPE_FORMULA && p->HasRelNameReference() )
			p->SetDirty();
	}
	pDocument->SetAutoCalc( bOldAutoCalc );
}


void ScColumn::CalcAll()
{
	if (pItems)
		for (SCSIZE i=0; i<nCount; i++)
		{
			ScBaseCell* pCell = pItems[i].pCell;
			if (pCell->GetCellType() == CELLTYPE_FORMULA)
			{
#if OSL_DEBUG_LEVEL > 1
				// nach F9 ctrl-F9: ueberprueft die Berechnung per FormulaTree
				ScFormulaCell* pFCell = (ScFormulaCell*)pCell;
				double nOldVal, nNewVal;
				nOldVal = pFCell->GetValue();
#endif
				((ScFormulaCell*)pCell)->Interpret();
#if OSL_DEBUG_LEVEL > 1
				if ( pFCell->GetCode()->IsRecalcModeNormal() )
					nNewVal = pFCell->GetValue();
				else
					nNewVal = nOldVal;	// random(), jetzt() etc.
				DBG_ASSERT( nOldVal==nNewVal, "CalcAll: nOldVal != nNewVal" );
#endif
			}
		}
}


void ScColumn::CompileAll()
{
	if (pItems)
		for (SCSIZE i = 0; i < nCount; i++)
		{
			ScBaseCell* pCell = pItems[i].pCell;
			if ( pCell->GetCellType() == CELLTYPE_FORMULA )
			{
				SCROW nRow = pItems[i].nRow;
				// fuer unbedingtes kompilieren
				// bCompile=sal_True und pCode->nError=0
				((ScFormulaCell*)pCell)->GetCode()->SetCodeError( 0 );
				((ScFormulaCell*)pCell)->SetCompile( sal_True );
				((ScFormulaCell*)pCell)->CompileTokenArray();
				if ( nRow != pItems[i].nRow )
					Search( nRow, i );		// Listener geloescht/eingefuegt?
			}
		}
}


void ScColumn::CompileXML( ScProgress& rProgress )
{
	if (pItems)
		for (SCSIZE i = 0; i < nCount; i++)
		{
			ScBaseCell* pCell = pItems[i].pCell;
			if ( pCell->GetCellType() == CELLTYPE_FORMULA )
			{
				SCROW nRow = pItems[i].nRow;
				((ScFormulaCell*)pCell)->CompileXML( rProgress );
				if ( nRow != pItems[i].nRow )
					Search( nRow, i );		// Listener geloescht/eingefuegt?
			}
		}
}


void ScColumn::CalcAfterLoad()
{
	if (pItems)
		for (SCSIZE i = 0; i < nCount; i++)
		{
			ScBaseCell* pCell = pItems[i].pCell;
			if ( pCell->GetCellType() == CELLTYPE_FORMULA )
				((ScFormulaCell*)pCell)->CalcAfterLoad();
		}
}


void ScColumn::ResetChanged( SCROW nStartRow, SCROW nEndRow )
{
	if (pItems)
	{
		SCSIZE nIndex;
		Search(nStartRow,nIndex);
		while (nIndex<nCount && pItems[nIndex].nRow <= nEndRow)
		{
			ScBaseCell* pCell = pItems[nIndex].pCell;
			if (pCell->GetCellType() == CELLTYPE_FORMULA)
				((ScFormulaCell*)pCell)->ResetChanged();
			++nIndex;
		}
	}
}


sal_Bool ScColumn::HasEditCells(SCROW nStartRow, SCROW nEndRow, SCROW& rFirst) const
{
	//	used in GetOptimalHeight - ambiguous script type counts as edit cell

    SCROW nRow = 0;
	SCSIZE nIndex;
	Search(nStartRow,nIndex);
	while ( (nIndex < nCount) ? ((nRow=pItems[nIndex].nRow) <= nEndRow) : sal_False )
	{
		ScBaseCell* pCell = pItems[nIndex].pCell;
        CellType eCellType = pCell->GetCellType();
		if ( eCellType == CELLTYPE_EDIT ||
			 IsAmbiguousScriptNonZero( pDocument->GetScriptType(nCol, nRow, nTab, pCell) ) ||
             ((eCellType == CELLTYPE_FORMULA) && ((ScFormulaCell*)pCell)->IsMultilineResult()) )
		{
			rFirst = nRow;
			return sal_True;
		}
		++nIndex;
	}

	return sal_False;
}


SCsROW ScColumn::SearchStyle( SCsROW nRow, const ScStyleSheet* pSearchStyle,
								sal_Bool bUp, sal_Bool bInSelection, const ScMarkData& rMark )
{
	if (bInSelection)
	{
		if (rMark.IsMultiMarked())
			return pAttrArray->SearchStyle( nRow, pSearchStyle, bUp,
									(ScMarkArray*) rMark.GetArray()+nCol );		//! const
		else
			return -1;
	}
	else
		return pAttrArray->SearchStyle( nRow, pSearchStyle, bUp, NULL );
}


sal_Bool ScColumn::SearchStyleRange( SCsROW& rRow, SCsROW& rEndRow, const ScStyleSheet* pSearchStyle,
									sal_Bool bUp, sal_Bool bInSelection, const ScMarkData& rMark )
{
	if (bInSelection)
	{
		if (rMark.IsMultiMarked())
			return pAttrArray->SearchStyleRange( rRow, rEndRow, pSearchStyle, bUp,
									(ScMarkArray*) rMark.GetArray()+nCol );		//! const
		else
			return sal_False;
	}
	else
		return pAttrArray->SearchStyleRange( rRow, rEndRow, pSearchStyle, bUp, NULL );
}


