/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifdef _MSC_VER
#pragma hdrstop
#endif

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

#include "scitems.hxx"
#include <tools/urlobj.hxx>
#include <math.h>
#include <bf_svtools/PasswordHelper.hxx>
#include <unotools/transliterationwrapper.hxx>

#include "patattr.hxx"
#include "docpool.hxx"
#include "document.hxx"
#include "drwlayer.hxx"
#include "olinetab.hxx"
#include "rechead.hxx"
#include "stlpool.hxx"
#include "attarray.hxx"     // Iterator
#include "markdata.hxx"
#include "progress.hxx"
#include "dociter.hxx"
#include "conditio.hxx"
#include "chartlis.hxx"
#include "globstr.hrc"
#include "bf_so3/staticbaseurl.hxx"
namespace binfilter {

// STATIC DATA -----------------------------------------------------------

void lcl_LoadRange( SvStream& rStream, ScRange** ppRange );

/*N*/ BOOL ScTable::SetOutlineTable( const ScOutlineTable* pNewOutline )
/*N*/ {
/*N*/   USHORT nOldSizeX = 0;
/*N*/   USHORT nOldSizeY = 0;
/*N*/   USHORT nNewSizeX = 0;
/*N*/   USHORT nNewSizeY = 0;
/*N*/
/*N*/   if (pNewOutline)
/*N*/   {
/*N*/       pOutlineTable = new ScOutlineTable( *pNewOutline );
/*N*/       nNewSizeX = pOutlineTable->GetColArray()->GetDepth();
/*N*/       nNewSizeY = pOutlineTable->GetRowArray()->GetDepth();
/*N*/   }
/*N*/   else
/*N*/       pOutlineTable = NULL;
/*N*/
/*N*/   return ( nNewSizeX != nOldSizeX || nNewSizeY != nOldSizeY );        // Groesse geaendert ?
/*N*/ }


/*N*/ void ScTable::StartOutlineTable()
/*N*/ {
/*N*/   if (!pOutlineTable)
/*N*/       pOutlineTable = new ScOutlineTable;
/*N*/ }


/*N*/ BOOL ScTable::TestInsertRow( USHORT nStartCol, USHORT nEndCol, USHORT nSize )
/*N*/ {
/*N*/   BOOL bTest = TRUE;
/*N*/
/*N*/   if ( nStartCol==0 && nEndCol==MAXCOL && pOutlineTable )
/*N*/       bTest = pOutlineTable->TestInsertRow(nSize);
/*N*/
/*N*/   for (USHORT i=nStartCol; (i<=nEndCol) && bTest; i++)
/*N*/       bTest = aCol[i].TestInsertRow( nSize );
/*N*/
/*N*/   return bTest;
/*N*/ }


/*N*/ void ScTable::InsertRow( USHORT nStartCol, USHORT nEndCol, USHORT nStartRow, USHORT nSize )
/*N*/ {
/*N*/   USHORT i;
/*N*/   nRecalcLvl++;
/*N*/   if (nStartCol==0 && nEndCol==MAXCOL)
/*N*/   {
/*N*/       if (pRowHeight && pRowFlags)
/*N*/       {
/*N*/             memmove( &pRowHeight[nStartRow+nSize], &pRowHeight[nStartRow],
/*N*/                     (MAXROW - nStartRow + 1 - nSize) * sizeof(pRowHeight[0]) );
/*N*/             memmove( &pRowFlags[nStartRow+nSize], &pRowFlags[nStartRow],
/*N*/                     (MAXROW - nStartRow + 1 - nSize) * sizeof(pRowFlags[0]) );
/*N*/
/*N*/           //  #67451# copy row height from row above
/*N*/           USHORT nSourceRow = ( nStartRow > 0 ) ? ( nStartRow - 1 ) : 0;
/*N*/           BYTE nNewFlags = pRowFlags[nSourceRow] & CR_MANUALSIZE;
/*N*/           USHORT nNewHeight = pRowHeight[nSourceRow];
/*N*/           for (i=nStartRow; i<nStartRow+nSize; i++)
/*N*/           {
/*N*/               pRowHeight[i] = nNewHeight;
/*N*/               pRowFlags[i] = nNewFlags;
/*N*/           }
/*N*/       }
/*N*/       if (pOutlineTable)
/*N*/           pOutlineTable->InsertRow( nStartRow, nSize );
/*N*/   }
/*N*/
/*N*/   for (i=nStartCol; i<=nEndCol; i++)
/*N*/       aCol[i].InsertRow( nStartRow, nSize );
/*N*/   if( !--nRecalcLvl )
/*N*/       SetDrawPageSize();
/*N*/ }


/*N*/ void ScTable::DeleteRow( USHORT nStartCol, USHORT nEndCol, USHORT nStartRow, USHORT nSize,
/*N*/                           BOOL* pUndoOutline )
/*N*/ {
/*N*/   USHORT i;
/*N*/   nRecalcLvl++;
/*N*/   if (nStartCol==0 && nEndCol==MAXCOL)
/*N*/   {
/*N*/       if (pRowHeight && pRowFlags)
/*N*/         {
/*N*/             memmove( &pRowHeight[nStartRow], &pRowHeight[nStartRow+nSize],
/*N*/                     (MAXROW - nStartRow + 1 - nSize) * sizeof(pRowHeight[0]) );
/*N*/             memmove( &pRowFlags[nStartRow], &pRowFlags[nStartRow+nSize],
/*N*/                     (MAXROW - nStartRow + 1 - nSize) * sizeof(pRowFlags[0]) );
/*N*/         }
/*N*/       if (pOutlineTable)
/*N*/           if (pOutlineTable->DeleteRow( nStartRow, nSize ))
/*N*/               if (pUndoOutline)
/*N*/                   *pUndoOutline = TRUE;
/*N*/   }
/*N*/
/*N*/   for (i=nStartCol; i<=nEndCol; i++)
/*N*/       aCol[i].DeleteRow( nStartRow, nSize );
/*N*/   if( !--nRecalcLvl )
/*N*/       SetDrawPageSize();
/*N*/ }


/*N*/ BOOL ScTable::TestInsertCol( USHORT nStartRow, USHORT nEndRow, USHORT nSize )
/*N*/ {
/*N*/   BOOL bTest = TRUE;
/*N*/
/*N*/   if ( nStartRow==0 && nEndRow==MAXROW && pOutlineTable )
/*N*/       bTest = pOutlineTable->TestInsertCol(nSize);
/*N*/
/*N*/   if ( nSize > MAXCOL )
/*N*/       bTest = FALSE;
/*N*/
/*N*/   for (USHORT i=MAXCOL; (i+nSize>MAXCOL) && bTest; i--)
/*N*/       bTest = aCol[i].TestInsertCol(nStartRow, nEndRow);
/*N*/
/*N*/   return bTest;
/*N*/ }


/*N*/ void ScTable::InsertCol( USHORT nStartCol, USHORT nStartRow, USHORT nEndRow, USHORT nSize )
/*N*/ {
/*N*/   USHORT i;
/*N*/   nRecalcLvl++;
/*N*/   if (nStartRow==0 && nEndRow==MAXROW)
/*N*/   {
/*N*/       if (pColWidth && pColFlags)
/*N*/         {
/*N*/             memmove( &pColWidth[nStartCol+nSize], &pColWidth[nStartCol],
/*N*/                     (MAXCOL - nStartCol + 1 - nSize) * sizeof(pColWidth[0]) );
/*N*/             memmove( &pColFlags[nStartCol+nSize], &pColFlags[nStartCol],
/*N*/                     (MAXCOL - nStartCol + 1 - nSize) * sizeof(pColFlags[0]) );
/*N*/         }
/*N*/       if (pOutlineTable)
/*N*/           pOutlineTable->InsertCol( nStartCol, nSize );
/*N*/   }
/*N*/
/*N*/
/*N*/   if ((nStartRow == 0) && (nEndRow == MAXROW))
/*N*/   {
/*N*/       for (i=0; i < nSize; i++)
/*N*/           for (USHORT nCol = MAXCOL; nCol > nStartCol; nCol--)
/*N*/               aCol[nCol].SwapCol(aCol[nCol-1]);
/*N*/   }
/*N*/   else
/*N*/   {
/*N*/       for (i=0; i+nSize+nStartCol <= MAXCOL; i++)
/*N*/           aCol[MAXCOL - nSize - i].MoveTo(nStartRow, nEndRow, aCol[MAXCOL - i]);
/*N*/   }
/*N*/
/*N*/   if (nStartCol>0)                        // copy old attributes
/*N*/   {
/*N*/       USHORT nWhichArray[2];
/*N*/       nWhichArray[0] = ATTR_MERGE;
/*N*/       nWhichArray[1] = 0;
/*N*/
/*N*/       for (i=0; i<nSize; i++)
/*N*/       {
/*N*/           aCol[nStartCol-1].CopyToColumn( nStartRow, nEndRow, IDF_ATTRIB,
/*N*/                                               FALSE, aCol[nStartCol+i] );
/*N*/           aCol[nStartCol+i].RemoveFlags( nStartRow, nEndRow,
/*N*/                                               SC_MF_HOR | SC_MF_VER | SC_MF_AUTO );
/*N*/           aCol[nStartCol+i].ClearItems( nStartRow, nEndRow, nWhichArray );
/*N*/       }
/*N*/   }
/*N*/   if( !--nRecalcLvl )
/*N*/       SetDrawPageSize();
/*N*/ }


/*N*/ void ScTable::DeleteCol( USHORT nStartCol, USHORT nStartRow, USHORT nEndRow, USHORT nSize,
/*N*/                           BOOL* pUndoOutline )
/*N*/ {
/*N*/   USHORT i;
/*N*/   nRecalcLvl++;
/*N*/   if (nStartRow==0 && nEndRow==MAXROW)
/*N*/   {
/*N*/       if (pColWidth && pColFlags)
/*N*/         {
/*N*/             memmove( &pColWidth[nStartCol], &pColWidth[nStartCol+nSize],
/*N*/                     (MAXCOL - nStartCol + 1 - nSize) * sizeof(pColWidth[0]) );
/*N*/             memmove( &pColFlags[nStartCol], &pColFlags[nStartCol+nSize],
/*N*/                     (MAXCOL - nStartCol + 1 - nSize) * sizeof(pColFlags[0]) );
/*N*/         }
/*N*/       if (pOutlineTable)
/*N*/           if (pOutlineTable->DeleteCol( nStartCol, nSize ))
/*N*/               if (pUndoOutline)
/*N*/                   *pUndoOutline = TRUE;
/*N*/   }
/*N*/
/*N*/
/*N*/   for (i = 0; i < nSize; i++)
/*N*/       aCol[nStartCol + i].DeleteArea(nStartRow, nEndRow, IDF_ALL);
/*N*/
/*N*/   if ((nStartRow == 0) && (nEndRow == MAXROW))
/*N*/   {
/*N*/       for (i=0; i < nSize; i++)
/*N*/           for (USHORT nCol = nStartCol; nCol < MAXCOL; nCol++)
/*N*/               aCol[nCol].SwapCol(aCol[nCol+1]);
/*N*/   }
/*N*/   else
/*N*/   {
/*N*/       for (i=0; i+nSize+nStartCol <= MAXCOL; i++)
/*N*/           aCol[nStartCol + nSize + i].MoveTo(nStartRow, nEndRow, aCol[nStartCol + i]);
/*N*/   }
/*N*/   if( !--nRecalcLvl )
/*N*/       SetDrawPageSize();
/*N*/ }


/*N*/ void ScTable::DeleteArea(USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2, USHORT nDelFlag)
/*N*/ {
/*N*/   if (nCol2 > MAXCOL) nCol2 = MAXCOL;
/*N*/   if (nRow2 > MAXROW) nRow2 = MAXROW;
/*N*/   if (ValidColRow(nCol1, nRow1) && ValidColRow(nCol2, nRow2))
/*N*/   {
/*N*/ //        nRecalcLvl++;
/*N*/
/*N*/       for (USHORT i = nCol1; i <= nCol2; i++)
/*N*/           aCol[i].DeleteArea(nRow1, nRow2, nDelFlag);
/*N*/
/*N*/           //
/*N*/           // Zellschutz auf geschuetzter Tabelle nicht setzen
/*N*/           //
/*N*/
/*N*/       if ( bProtected && (nDelFlag & IDF_ATTRIB) )
/*N*/       {
/*N*/           ScPatternAttr aPattern(pDocument->GetPool());
/*N*/           aPattern.GetItemSet().Put( ScProtectionAttr( FALSE ) );
/*N*/           ApplyPatternArea( nCol1, nRow1, nCol2, nRow2, aPattern );
/*N*/       }
/*N*/
/*      if( !--nRecalcLvl )
            SetDrawPageSize();
*/
/*N*/   }
/*N*/ }




//  pTable = Clipboard






//  Markierung von diesem Dokument




/*N*/ void ScTable::StartAllListeners()
/*N*/ {
/*N*/   for (USHORT i=0; i<=MAXCOL; i++)
/*N*/       aCol[i].StartAllListeners();
/*N*/ }


/*N*/ void ScTable::StartNameListeners( BOOL bOnlyRelNames )
/*N*/ {
/*N*/   for (USHORT i=0; i<=MAXCOL; i++)
/*N*/         aCol[i].StartNameListeners( bOnlyRelNames );
/*N*/ }






/*N*/ void ScTable::CopyToTable(USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2,
/*N*/                           USHORT nFlags, BOOL bMarked, ScTable* pDestTab,
/*N*/                           const ScMarkData* pMarkData,
/*N*/                           BOOL bAsLink, BOOL bColRowFlags)
/*N*/ {
/*N*/   if (ValidColRow(nCol1, nRow1) && ValidColRow(nCol2, nRow2))
/*N*/   {
/*N*/       USHORT i;
/*N*/
/*N*/       if (nFlags)
/*N*/           for (i = nCol1; i <= nCol2; i++)
/*N*/               aCol[i].CopyToColumn(nRow1, nRow2, nFlags, bMarked,
/*N*/                               pDestTab->aCol[i], pMarkData, bAsLink);
/*N*/
/*N*/       if (bColRowFlags)       // Spaltenbreiten/Zeilenhoehen/Flags
/*N*/       {
/*N*/           //  Charts muessen beim Ein-/Ausblenden angepasst werden
/*N*/           ScChartListenerCollection* pCharts = pDestTab->pDocument->GetChartListenerCollection();
/*N*/           if ( pCharts && !pCharts->GetCount() )
/*N*/               pCharts = NULL;
/*N*/
/*N*/           if (nRow1==0 && nRow2==MAXROW && pColWidth && pDestTab->pColWidth)
/*N*/               for (i=nCol1; i<=nCol2; i++)
/*N*/               {
/*N*/                   pDestTab->pColWidth[i] = pColWidth[i];
/*N*/                   pDestTab->pColFlags[i] = pColFlags[i];
/*N*/               }
/*N*/
/*N*/           if (nCol1==0 && nCol2==MAXCOL && pRowHeight && pDestTab->pRowHeight)
/*N*/               for (i=nRow1; i<=nRow2; i++)
/*N*/               {
/*N*/                   pDestTab->pRowHeight[i] = pRowHeight[i];
/*N*/                   pDestTab->pRowFlags[i]  = pRowFlags[i];
/*N*/               }
/*N*/
/*N*/           pDestTab->SetOutlineTable( pOutlineTable );     // auch nur wenn bColRowFlags
/*N*/       }
/*N*/   }
/*N*/ }







/*N*/ void ScTable::MarkScenarioIn( ScMarkData& rDestMark, USHORT nNeededBits ) const
/*N*/ {
/*N*/   DBG_ASSERT( bScenario, "bScenario == FALSE" );
/*N*/
/*N*/   if ( ( nScenarioFlags & nNeededBits ) != nNeededBits )  // alle Bits gesetzt?
/*N*/       return;
/*N*/
/*N*/   for (USHORT i=0; i<=MAXCOL; i++)
/*N*/       aCol[i].MarkScenarioIn( rDestMark );
/*N*/ }


/*N*/ void ScTable::InvalidateScenarioRanges()
/*N*/ {
/*N*/   delete pScenarioRanges;
/*N*/   pScenarioRanges = NULL;
/*N*/ }

/*N*/ const ScRangeList* ScTable::GetScenarioRanges() const
/*N*/ {
/*N*/   DBG_ASSERT( bScenario, "bScenario == FALSE" );
/*N*/
/*N*/   if (!pScenarioRanges)
/*N*/   {
/*N*/       ((ScTable*)this)->pScenarioRanges = new ScRangeList;
/*N*/       ScMarkData aMark;
/*N*/       MarkScenarioIn( aMark, 0 );     // immer
/*N*/       aMark.FillRangeListWithMarks( pScenarioRanges, FALSE );
/*N*/   }
/*N*/   return pScenarioRanges;
/*N*/ }


/*N*/ void ScTable::PutCell( USHORT nCol, USHORT nRow, ScBaseCell* pCell )
/*N*/ {
/*N*/   if (ValidColRow(nCol,nRow))
/*N*/   {
/*N*/       if (pCell)
/*N*/           aCol[nCol].Insert( nRow, pCell );
/*N*/   }
/*N*/ }


/*N*/ void ScTable::PutCell( USHORT nCol, USHORT nRow, ULONG nFormatIndex, ScBaseCell* pCell )
/*N*/ {
/*N*/   if (ValidColRow(nCol,nRow))
/*N*/   {
/*N*/       if (pCell)
/*N*/           aCol[nCol].Insert( nRow, nFormatIndex, pCell );
/*N*/   }
/*N*/ }


/*N*/ void ScTable::PutCell( const ScAddress& rPos, ScBaseCell* pCell )
/*N*/ {
/*N*/   if (pCell)
/*N*/       aCol[rPos.Col()].Insert( rPos.Row(), pCell );
/*N*/ }


/*N*/ BOOL ScTable::SetString( USHORT nCol, USHORT nRow, USHORT nInTab, const String& rString )
/*N*/ {
/*N*/   if (ValidColRow(nCol,nRow))
/*N*/       return aCol[nCol].SetString( nRow, nInTab, rString );
/*N*/   else
/*N*/       return FALSE;
/*N*/ }


/*N*/ void ScTable::SetValue( USHORT nCol, USHORT nRow, const double& rVal )
/*N*/ {
/*N*/   if (ValidColRow(nCol, nRow))
/*N*/       aCol[nCol].SetValue( nRow, rVal );
/*N*/ }


/*N*/ void ScTable::SetNote( USHORT nCol, USHORT nRow, const ScPostIt& rNote)
/*N*/ {
/*N*/   if (ValidColRow(nCol, nRow))
/*N*/       aCol[nCol].SetNote(nRow, rNote);
/*N*/ }


/*N*/ void ScTable::GetString( USHORT nCol, USHORT nRow, String& rString )
/*N*/ {
/*N*/   if (ValidColRow(nCol,nRow))
/*N*/       aCol[nCol].GetString( nRow, rString );
/*N*/   else
/*N*/       rString.Erase();
/*N*/ }


/*N*/ void ScTable::GetInputString( USHORT nCol, USHORT nRow, String& rString )
/*N*/ {
/*N*/   if (ValidColRow(nCol,nRow))
/*N*/       aCol[nCol].GetInputString( nRow, rString );
/*N*/   else
/*N*/       rString.Erase();
/*N*/ }

/*N*/ BOOL ScTable::GetNote( USHORT nCol, USHORT nRow, ScPostIt& rNote)
/*N*/ {
/*N*/   BOOL bHasNote = FALSE;
/*N*/
/*N*/   if (ValidColRow(nCol,nRow))
/*N*/       bHasNote = aCol[nCol].GetNote( nRow, rNote );
/*N*/   else
/*?*/       rNote.Clear();
/*N*/
/*N*/   return bHasNote;
/*N*/ }


/*N*/ CellType ScTable::GetCellType( USHORT nCol, USHORT nRow ) const
/*N*/ {
/*N*/   if (ValidColRow( nCol, nRow ))
/*N*/       return aCol[nCol].GetCellType( nRow );
/*N*/   return CELLTYPE_NONE;
/*N*/ }


/*N*/ ScBaseCell* ScTable::GetCell( USHORT nCol, USHORT nRow ) const
/*N*/ {
/*N*/   if (ValidColRow( nCol, nRow ))
/*N*/       return aCol[nCol].GetCell( nRow );
/*N*/
/*N*/   OSL_FAIL("GetCell ausserhalb");
/*N*/   return NULL;
/*N*/ }




/*N*/ BOOL ScTable::HasData( USHORT nCol, USHORT nRow )
/*N*/ {
/*N*/   if (ValidColRow(nCol,nRow))
/*N*/       return aCol[nCol].HasDataAt( nRow );
/*N*/   else
/*N*/       return FALSE;
/*N*/ }


/*N*/ BOOL ScTable::HasStringData( USHORT nCol, USHORT nRow )
/*N*/ {
/*N*/   if (ValidColRow(nCol,nRow))
/*N*/       return aCol[nCol].HasStringData( nRow );
/*N*/   else
/*N*/       return FALSE;
/*N*/ }


/*N*/ BOOL ScTable::HasValueData( USHORT nCol, USHORT nRow )
/*N*/ {
/*N*/   if (ValidColRow(nCol,nRow))
/*N*/       return aCol[nCol].HasValueData( nRow );
/*N*/   else
/*N*/       return FALSE;
/*N*/ }

/*N*/ void ScTable::SetDirtyVar()
/*N*/ {
/*N*/   for (USHORT i=0; i<=MAXCOL; i++)
/*N*/       aCol[i].SetDirtyVar();
/*N*/ }


/*N*/ void ScTable::SetDirty()
/*N*/ {
/*N*/   BOOL bOldAutoCalc = pDocument->GetAutoCalc();
/*N*/   pDocument->SetAutoCalc( FALSE );    // Mehrfachberechnungen vermeiden
/*N*/   for (USHORT i=0; i<=MAXCOL; i++)
/*N*/       aCol[i].SetDirty();
/*N*/   pDocument->SetAutoCalc( bOldAutoCalc );
/*N*/ }


/*N*/  void ScTable::SetTableOpDirty( const ScRange& rRange )
/*N*/  {
/*N*/   BOOL bOldAutoCalc = pDocument->GetAutoCalc();
/*N*/   pDocument->SetAutoCalc( FALSE );    // no multiple recalculation
/*N*/   USHORT nCol2 = rRange.aEnd.Col();
/*N*/   for (USHORT i=rRange.aStart.Col(); i<=nCol2; i++)
/*N*/       aCol[i].SetTableOpDirty( rRange );
/*N*/   pDocument->SetAutoCalc( bOldAutoCalc );
/*N*/  }


/*N*/ void ScTable::SetDirtyAfterLoad()
/*N*/ {
/*N*/   BOOL bOldAutoCalc = pDocument->GetAutoCalc();
/*N*/   pDocument->SetAutoCalc( FALSE );    // Mehrfachberechnungen vermeiden
/*N*/   for (USHORT i=0; i<=MAXCOL; i++)
/*N*/       aCol[i].SetDirtyAfterLoad();
/*N*/   pDocument->SetAutoCalc( bOldAutoCalc );
/*N*/ }


/*N*/ void ScTable::SetRelNameDirty()
/*N*/ {
/*N*/   BOOL bOldAutoCalc = pDocument->GetAutoCalc();
/*N*/   pDocument->SetAutoCalc( FALSE );    // Mehrfachberechnungen vermeiden
/*N*/   for (USHORT i=0; i<=MAXCOL; i++)
/*N*/       aCol[i].SetRelNameDirty();
/*N*/   pDocument->SetAutoCalc( bOldAutoCalc );
/*N*/ }


/*N*/ void ScTable::CalcAll()
/*N*/ {
/*N*/   for (USHORT i=0; i<=MAXCOL; i++) aCol[i].CalcAll();
/*N*/ }


/*N*/ void ScTable::CompileAll()
/*N*/ {
/*N*/   for (USHORT i=0; i <= MAXCOL; i++) aCol[i].CompileAll();
/*N*/ }


/*N*/ void ScTable::CompileXML( ScProgress& rProgress )
/*N*/ {
/*N*/   for (USHORT i=0; i <= MAXCOL; i++)
/*N*/   {
/*N*/       aCol[i].CompileXML( rProgress );
/*N*/   }
/*N*/ }


/*N*/ void ScTable::CalcAfterLoad()
/*N*/ {
/*N*/   for (USHORT i=0; i <= MAXCOL; i++) aCol[i].CalcAfterLoad();
/*N*/ }


/*N*/ void ScTable::ResetChanged( const ScRange& rRange )
/*N*/ {
/*N*/   USHORT nStartCol = rRange.aStart.Col();
/*N*/   USHORT nStartRow = rRange.aStart.Row();
/*N*/   USHORT nEndCol = rRange.aEnd.Col();
/*N*/   USHORT nEndRow = rRange.aEnd.Row();
/*N*/
/*N*/   for (USHORT nCol=nStartCol; nCol<=nEndCol; nCol++)
/*N*/       aCol[nCol].ResetChanged(nStartRow, nEndRow);
/*N*/ }

//  Attribute

/*N*/ const SfxPoolItem* ScTable::GetAttr( USHORT nCol, USHORT nRow, USHORT nWhich ) const
/*N*/ {
/*N*/   if (ValidColRow(nCol,nRow))
/*N*/       return aCol[nCol].GetAttr( nRow, nWhich );
/*N*/   else
/*N*/       return NULL;
/*N*/ }


/*N*/ ULONG ScTable::GetNumberFormat( USHORT nCol, USHORT nRow ) const
/*N*/ {
/*N*/   if (ValidColRow(nCol,nRow))
/*N*/       return aCol[nCol].GetNumberFormat( nRow );
/*N*/   else
/*N*/       return 0;
/*N*/ }


/*N*/ const ScPatternAttr* ScTable::GetPattern( USHORT nCol, USHORT nRow ) const
/*N*/ {
/*N*/   if (ValidColRow(nCol,nRow))
/*N*/       return aCol[nCol].GetPattern( nRow );
/*N*/   else
/*N*/       return NULL;
/*N*/ }


/*N*/ BOOL ScTable::HasAttrib( USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2, USHORT nMask ) const
/*N*/ {
/*N*/   BOOL bFound=FALSE;
/*N*/   for (USHORT i=nCol1; i<=nCol2 && !bFound; i++)
/*N*/       bFound |= aCol[i].HasAttrib( nRow1, nRow2, nMask );
/*N*/   return bFound;
/*N*/ }






/*N*/ BOOL ScTable::ExtendMerge( USHORT nStartCol, USHORT nStartRow,
/*N*/                          USHORT& rEndCol, USHORT& rEndRow,
/*N*/                          BOOL bRefresh, BOOL bAttrs )
/*N*/ {
/*N*/   BOOL bFound=FALSE;
/*N*/   USHORT nOldEndX = rEndCol;
/*N*/   USHORT nOldEndY = rEndRow;
/*N*/   for (USHORT i=nStartCol; i<=nOldEndX; i++)
/*N*/       bFound |= aCol[i].ExtendMerge( i, nStartRow, nOldEndY, rEndCol, rEndRow, bRefresh, bAttrs );
/*N*/   return bFound;
/*N*/ }

/*N*/ BOOL ScTable::HasBlockMatrixFragment( USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2 ) const
/*N*/ {
/*N*/   // nix:0, mitte:1, unten:2, links:4, oben:8, rechts:16, offen:32
/*N*/   USHORT nEdges;
/*N*/
/*N*/   if ( nCol1 == nCol2 )
/*N*/   {   // linke und rechte Spalte
/*N*/       const USHORT n = 4 | 16;
/*N*/       nEdges = aCol[nCol1].GetBlockMatrixEdges( nRow1, nRow2, n );
/*N*/       // nicht (4 und 16) oder 1 oder 32
/*N*/       if ( nEdges && (((nEdges & n) != n) || (nEdges & 33)) )
/*N*/           return TRUE;        // linke oder rechte Kante fehlt oder offen
/*N*/   }
/*N*/   else
/*N*/   {   // linke Spalte
/*N*/       nEdges = aCol[nCol1].GetBlockMatrixEdges( nRow1, nRow2, 4 );
/*N*/       // nicht 4 oder 1 oder 32
/*N*/       if ( nEdges && (((nEdges & 4) != 4) || (nEdges & 33)) )
/*N*/           return TRUE;        // linke Kante fehlt oder offen
/*N*/       // rechte Spalte
/*N*/       nEdges = aCol[nCol2].GetBlockMatrixEdges( nRow1, nRow2, 16 );
/*N*/       // nicht 16 oder 1 oder 32
/*N*/       if ( nEdges && (((nEdges & 16) != 16) || (nEdges & 33)) )
/*N*/           return TRUE;        // rechte Kante fehlt oder offen
/*N*/   }
/*N*/
/*N*/   if ( nRow1 == nRow2 )
/*N*/   {   // obere und untere Zeile
/*N*/       USHORT i;
/*N*/       BOOL bOpen = FALSE;
/*N*/       const USHORT n = 2 | 8;
/*N*/       for ( i=nCol1; i<=nCol2; i++)
/*N*/       {
/*N*/           nEdges = aCol[i].GetBlockMatrixEdges( nRow1, nRow1, n );
/*N*/           if ( nEdges )
/*N*/           {
/*N*/               if ( (nEdges & n) != n )
/*N*/                   return TRUE;        // obere oder untere Kante fehlt
/*N*/               if ( nEdges & 4 )
/*N*/                   bOpen = TRUE;       // linke Kante oeffnet, weitersehen
/*N*/               else if ( !bOpen )
/*N*/                   return TRUE;        // es gibt was, was nicht geoeffnet wurde
/*N*/               if ( nEdges & 16 )
/*N*/                   bOpen = FALSE;      // rechte Kante schliesst
/*N*/           }
/*N*/       }
/*N*/       if ( bOpen )
/*N*/           return TRUE;                // es geht noch weiter
/*N*/   }
/*N*/   else
/*N*/   {
/*N*/       USHORT j, nR, n, i;
/*N*/       // erst obere Zeile, dann untere Zeile
/*N*/       for ( j=0, nR=nRow1, n=8; j<2; j++, nR=nRow2, n=2 )
/*N*/       {
/*N*/           BOOL bOpen = FALSE;
/*N*/           for ( i=nCol1; i<=nCol2; i++)
/*N*/           {
/*N*/               nEdges = aCol[i].GetBlockMatrixEdges( nR, nR, n );
/*N*/               if ( nEdges )
/*N*/               {
/*N*/                   // in oberere Zeile keine obere Kante bzw.
/*N*/                   // in unterer Zeile keine untere Kante
/*N*/                   if ( (nEdges & n) != n )
/*N*/                       return TRUE;
/*N*/                   if ( nEdges & 4 )
/*N*/                       bOpen = TRUE;       // linke Kante oeffnet, weitersehen
/*N*/                   else if ( !bOpen )
/*N*/                       return TRUE;        // es gibt was, was nicht geoeffnet wurde
/*N*/                   if ( nEdges & 16 )
/*N*/                       bOpen = FALSE;      // rechte Kante schliesst
/*N*/               }
/*N*/           }
/*N*/           if ( bOpen )
/*N*/               return TRUE;                // es geht noch weiter
/*N*/       }
/*N*/   }
/*N*/   return FALSE;
/*N*/ }


/*N*/ BOOL ScTable::HasSelectionMatrixFragment( const ScMarkData& rMark ) const
/*N*/ {
/*N*/   BOOL bFound=FALSE;
/*N*/   for (USHORT i=0; i<=MAXCOL && !bFound; i++)
/*N*/       bFound |= aCol[i].HasSelectionMatrixFragment(rMark);
/*N*/   return bFound;
/*N*/ }


/*N*/ BOOL ScTable::IsBlockEditable( USHORT nCol1, USHORT nRow1, USHORT nCol2,
/*N*/           USHORT nRow2, BOOL* pOnlyNotBecauseOfMatrix /* = NULL */ ) const
/*N*/ {
/*N*/   BOOL bIsEditable;
/*N*/   if ( nLockCount )
/*N*/       bIsEditable = FALSE;
/*N*/   else if ( bProtected )
/*N*/       bIsEditable = !HasAttrib( nCol1, nRow1, nCol2, nRow2, HASATTR_PROTECTED );
/*N*/   else
/*N*/       bIsEditable = TRUE;
/*N*/   if ( bIsEditable )
/*N*/   {
/*N*/       if ( HasBlockMatrixFragment( nCol1, nRow1, nCol2, nRow2 ) )
/*N*/       {
/*N*/           bIsEditable = FALSE;
/*N*/           if ( pOnlyNotBecauseOfMatrix )
/*N*/               *pOnlyNotBecauseOfMatrix = TRUE;
/*N*/       }
/*N*/       else if ( pOnlyNotBecauseOfMatrix )
/*N*/           *pOnlyNotBecauseOfMatrix = FALSE;
/*N*/   }
/*N*/   else if ( pOnlyNotBecauseOfMatrix )
/*N*/       *pOnlyNotBecauseOfMatrix = FALSE;
/*N*/   return bIsEditable;
/*N*/ }


BOOL ScTable::IsSelectionEditable(
    const ScMarkData& rMark,
    BOOL* pOnlyNotBecauseOfMatrix /* = NULL */
) const
{
    BOOL bIsEditable;
    if ( nLockCount )
        bIsEditable = FALSE;
    else if ( bProtected )
    {
        bIsEditable = FALSE;
    }
    else
        bIsEditable = TRUE;

    if ( bIsEditable )
    {
        if ( HasSelectionMatrixFragment( rMark ) )
        {
            bIsEditable = FALSE;
            if ( pOnlyNotBecauseOfMatrix )
                *pOnlyNotBecauseOfMatrix = TRUE;
        }
        else if ( pOnlyNotBecauseOfMatrix )
            *pOnlyNotBecauseOfMatrix = FALSE;
    }
    else if ( pOnlyNotBecauseOfMatrix )
        *pOnlyNotBecauseOfMatrix = FALSE;

    return bIsEditable;
}



/*N*/ void ScTable::LockTable()
/*N*/ {
/*N*/   ++nLockCount;
/*N*/ }


/*N*/ void ScTable::UnlockTable()
/*N*/ {
/*N*/   if (nLockCount)
/*N*/       --nLockCount;
/*N*/   else
/*N*/       OSL_FAIL("UnlockTable ohne LockTable");
/*N*/ }


/*N*/ void ScTable::MergeSelectionPattern( SfxItemSet** ppSet, const ScMarkData& rMark, BOOL bDeep ) const
/*N*/ {
/*N*/   for (USHORT i=0; i<=MAXCOL; i++)
/*N*/       aCol[i].MergeSelectionPattern( ppSet, rMark, bDeep );
/*N*/ }


/*N*/ void ScTable::MergePatternArea( SfxItemSet** ppSet, USHORT nCol1, USHORT nRow1,
/*N*/                                                   USHORT nCol2, USHORT nRow2, BOOL bDeep ) const
/*N*/ {
/*N*/   for (USHORT i=nCol1; i<=nCol2; i++)
/*N*/       aCol[i].MergePatternArea( ppSet, nRow1, nRow2, bDeep );
/*N*/ }


/*N*/ void ScTable::ApplyPatternArea( USHORT nStartCol, USHORT nStartRow, USHORT nEndCol, USHORT nEndRow,
/*N*/                                    const ScPatternAttr& rAttr )
/*N*/ {
/*N*/   if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
/*N*/   {
/*N*/       PutInOrder(nStartCol, nEndCol);
/*N*/       PutInOrder(nStartRow, nEndRow);
/*N*/       for (USHORT i = nStartCol; i <= nEndCol; i++)
/*N*/           aCol[i].ApplyPatternArea(nStartRow, nEndRow, rAttr);
/*N*/   }
/*N*/ }






/*N*/ void ScTable::ApplyStyleArea( USHORT nStartCol, USHORT nStartRow, USHORT nEndCol, USHORT nEndRow, const ScStyleSheet& rStyle )
/*N*/ {
/*N*/   if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
/*N*/   {
/*N*/       PutInOrder(nStartCol, nEndCol);
/*N*/       PutInOrder(nStartRow, nEndRow);
/*N*/       for (USHORT i = nStartCol; i <= nEndCol; i++)
/*N*/           aCol[i].ApplyStyleArea(nStartRow, nEndRow, rStyle);
/*N*/   }
/*N*/ }

/*N*/ void ScTable::ApplySelectionStyle(const ScStyleSheet& rStyle, const ScMarkData& rMark)
/*N*/ {
/*N*/   for (USHORT i=0; i<=MAXCOL; i++)
/*N*/       aCol[i].ApplySelectionStyle( rStyle, rMark );
/*N*/ }

/*N*/ const ScStyleSheet* ScTable::GetSelectionStyle( const ScMarkData& rMark, BOOL& rFound ) const
/*N*/ {
/*N*/   rFound = FALSE;
/*N*/
/*N*/   BOOL    bEqual = TRUE;
/*N*/   BOOL    bColFound;
/*N*/   USHORT  i;
/*N*/
/*N*/   const ScStyleSheet* pStyle = NULL;
/*N*/   const ScStyleSheet* pNewStyle;
/*N*/
/*N*/   for (i=0; i<=MAXCOL && bEqual; i++)
/*N*/       if (rMark.HasMultiMarks(i))
/*N*/       {
/*N*/           pNewStyle = aCol[i].GetSelectionStyle( rMark, bColFound );
/*N*/           if (bColFound)
/*N*/           {
/*N*/               rFound = TRUE;
/*N*/               if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) )
/*N*/                   bEqual = FALSE;                                             // unterschiedliche
/*N*/               pStyle = pNewStyle;
/*N*/           }
/*N*/       }
/*N*/
/*N*/   return bEqual ? pStyle : NULL;
/*N*/ }


/*N*/ const ScStyleSheet*   ScTable::GetAreaStyle( BOOL& rFound, USHORT nCol1, USHORT nRow1,
/*N*/                                                   USHORT nCol2, USHORT nRow2 ) const
/*N*/ {
/*N*/   rFound = FALSE;
/*N*/
/*N*/   BOOL    bEqual = TRUE;
/*N*/   BOOL    bColFound;
/*N*/   USHORT  i;
/*N*/
/*N*/   const ScStyleSheet* pStyle = NULL;
/*N*/   const ScStyleSheet* pNewStyle;
/*N*/
/*N*/   for (i=nCol1; i<=nCol2 && bEqual; i++)
/*N*/   {
/*N*/       pNewStyle = aCol[i].GetAreaStyle(bColFound, nRow1, nRow2);
/*N*/       if (bColFound)
/*N*/       {
/*N*/           rFound = TRUE;
/*N*/           if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) )
/*N*/               bEqual = FALSE;                                             // unterschiedliche
/*N*/           pStyle = pNewStyle;
/*N*/       }
/*N*/   }
/*N*/
/*N*/   return bEqual ? pStyle : NULL;
/*N*/ }


/*N*/ void ScTable::StyleSheetChanged( const SfxStyleSheetBase* pStyleSheet, BOOL bRemoved,
/*N*/                               OutputDevice* pDev,
/*N*/                               double nPPTX, double nPPTY,
/*N*/                               const Fraction& rZoomX, const Fraction& rZoomY )
/*N*/ {
/*N*/   BOOL* pUsed = new BOOL[MAXROW+1];
/*N*/     memset( pUsed, 0, sizeof(BOOL) * (MAXROW+1) );
/*N*/
/*N*/   USHORT nCol;
/*N*/   for (nCol=0; nCol<=MAXCOL; nCol++)
/*N*/       aCol[nCol].FindStyleSheet( pStyleSheet, pUsed, bRemoved );
/*N*/
/*N*/   BOOL bFound = FALSE;
/*N*/   USHORT i;
/*N*/   USHORT nStart(0);
/*N*/   USHORT nEnd(0);
/*N*/   for (i=0; i<=MAXROW; i++)
/*N*/   {
/*N*/       if (pUsed[i])
/*N*/       {
/*N*/           if (!bFound)
/*N*/           {
/*N*/               nStart = i;
/*N*/               bFound = TRUE;
/*N*/           }
/*N*/           nEnd = i;
/*N*/       }
/*N*/       else if (bFound)
/*N*/       {
/*?*/           SetOptimalHeight( nStart, nEnd, 0, pDev, nPPTX, nPPTY, rZoomX, rZoomY, FALSE );
/*?*/           bFound = FALSE;
/*N*/       }
/*N*/   }
/*N*/   if (bFound)
/*N*/       SetOptimalHeight( nStart, nEnd, 0, pDev, nPPTX, nPPTY, rZoomX, rZoomY, FALSE );
/*N*/
/*N*/   delete[] pUsed;
/*N*/ }


/*N*/ BOOL ScTable::ApplyFlags( USHORT nStartCol, USHORT nStartRow, USHORT nEndCol, USHORT nEndRow,
/*N*/                                   INT16 nFlags )
/*N*/ {
/*N*/   BOOL bChanged = FALSE;
/*N*/   if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
/*N*/       for (USHORT i = nStartCol; i <= nEndCol; i++)
/*N*/           bChanged |= aCol[i].ApplyFlags(nStartRow, nEndRow, nFlags);
/*N*/   return bChanged;
/*N*/ }






/*N*/ void ScTable::ApplyAttr( USHORT nCol, USHORT nRow, const SfxPoolItem& rAttr )
/*N*/ {
/*N*/   if (ValidColRow(nCol,nRow))
/*N*/       aCol[nCol].ApplyAttr( nRow, rAttr );
/*N*/ }


/*N*/ void ScTable::ApplySelectionCache( SfxItemPoolCache* pCache, const ScMarkData& rMark )
/*N*/ {
/*N*/   for (USHORT i=0; i<=MAXCOL; i++)
/*N*/       aCol[i].ApplySelectionCache( pCache, rMark );
/*N*/ }






//  Spaltenbreiten / Zeilenhoehen

/*N*/ void ScTable::SetColWidth( USHORT nCol, USHORT nNewWidth )
/*N*/ {
/*N*/   if (VALIDCOL(nCol) && pColWidth)
/*N*/   {
/*N*/       if (!nNewWidth)
/*N*/       {
/*N*/ //            OSL_FAIL("Spaltenbreite 0 in SetColWidth");
/*N*/           nNewWidth = STD_COL_WIDTH;
/*N*/       }
/*N*/
/*N*/       if ( nNewWidth != pColWidth[nCol] )
/*N*/       {
/*N*/           nRecalcLvl++;
/*N*/           ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
/*N*/           if (pDrawLayer)
/*N*/               pDrawLayer->WidthChanged( nTab, nCol, ((long) nNewWidth) - (long) pColWidth[nCol] );
/*N*/           pColWidth[nCol] = nNewWidth;
/*N*/           if( !--nRecalcLvl )
/*N*/               SetDrawPageSize();
/*N*/       }
/*N*/   }
/*N*/   else
/*N*/       OSL_FAIL("Falsche Spaltennummer oder keine Breiten");
/*N*/ }


/*N*/ void ScTable::SetRowHeight( USHORT nRow, USHORT nNewHeight )
/*N*/ {
/*N*/   if (VALIDROW(nRow) && pRowHeight)
/*N*/   {
/*N*/       if (!nNewHeight)
/*N*/       {
/*?*/           OSL_FAIL("Zeilenhoehe 0 in SetRowHeight");
/*?*/           nNewHeight = ScGlobal::nStdRowHeight;
/*N*/       }
/*N*/
/*N*/       if ( nNewHeight != pRowHeight[nRow] )
/*N*/       {
/*N*/           nRecalcLvl++;
/*N*/           ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
/*N*/           if (pDrawLayer)
/*N*/               pDrawLayer->HeightChanged( nTab, nRow, ((long) nNewHeight) - (long) pRowHeight[nRow] );
/*N*/           pRowHeight[nRow] = nNewHeight;
/*N*/           if( !--nRecalcLvl )
/*?*/               SetDrawPageSize();
/*N*/       }
/*N*/   }
/*N*/   else
/*N*/       OSL_FAIL("Falsche Zeilennummer oder keine Hoehen");
/*N*/ }


/*N*/ BOOL ScTable::SetRowHeightRange( USHORT nStartRow, USHORT nEndRow, USHORT nNewHeight,
/*N*/                                   double /*nPPTX*/,double nPPTY )
/*N*/ {
/*N*/   BOOL bChanged = FALSE;
/*N*/   if (VALIDROW(nStartRow) && VALIDROW(nEndRow) && pRowHeight)
/*N*/   {
/*N*/       nRecalcLvl++;
/*N*/       if (!nNewHeight)
/*N*/       {
/*?*/           OSL_FAIL("Zeilenhoehe 0 in SetRowHeight");
/*?*/           nNewHeight = ScGlobal::nStdRowHeight;
/*N*/       }
/*N*/
/*N*/       long nNewPix = (long) ( nNewHeight * nPPTY );
/*N*/
/*N*/       BOOL bSingle = FALSE;
/*N*/       ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
/*N*/       if (pDrawLayer)
/*N*/           if (pDrawLayer->HasObjectsInRows( nTab, nStartRow, nEndRow ))
/*N*/               bSingle = TRUE;
/*N*/
/*N*/       USHORT nRow;
/*N*/       if (bSingle)
/*N*/       {
/*N*/           BOOL bDiff = FALSE;
/*N*/           for (nRow=nStartRow; nRow<=nEndRow && !bDiff; nRow++)
/*N*/               bDiff = ( pRowHeight[nRow] != nNewHeight );
/*N*/           if (!bDiff)
/*N*/               bSingle = FALSE;
/*N*/       }
/*N*/       if (bSingle)
/*N*/       {
/*N*/           if (nEndRow-nStartRow < 20)
/*N*/               for (nRow=nStartRow; nRow<=nEndRow; nRow++)
/*N*/               {
/*N*/                   if (!bChanged)
/*N*/                       if ( pRowHeight[nRow] != nNewHeight )
/*N*/                           bChanged = ( nNewPix != (long) ( pRowHeight[nRow] * nPPTY ) );
/*N*/                   SetRowHeight( nRow, nNewHeight );
/*N*/               }
/*N*/           else
/*N*/           {
/*?*/               USHORT nMid = (nStartRow+nEndRow) / 2;
/*?*/               if (SetRowHeightRange( nStartRow, nMid, nNewHeight, 1.0, 1.0 ))
/*?*/                   bChanged = TRUE;
/*?*/               if (SetRowHeightRange( nMid+1, nEndRow, nNewHeight, 1.0, 1.0 ))
/*?*/                   bChanged = TRUE;
/*N*/           }
/*N*/       }
/*N*/       else
/*N*/       {
/*N*/           if (pDrawLayer)
/*N*/           {
/*N*/               long nHeightDif = 0;
/*N*/               for (nRow=nStartRow; nRow<=nEndRow; nRow++)
/*N*/                   nHeightDif += ((long) nNewHeight) - (long) pRowHeight[nRow];
/*N*/               pDrawLayer->HeightChanged( nTab, nEndRow, nHeightDif );
/*N*/           }
/*N*/           for (nRow=nStartRow; nRow<=nEndRow; nRow++)
/*N*/           {
/*N*/               if (!bChanged)
/*N*/                   if ( pRowHeight[nRow] != nNewHeight )
/*N*/                       bChanged = ( nNewPix != (long) ( pRowHeight[nRow] * nPPTY ) );
/*N*/               pRowHeight[nRow] = nNewHeight;
/*N*/           }
/*N*/       }
/*N*/       if( !--nRecalcLvl )
/*N*/           SetDrawPageSize();
/*N*/   }
/*N*/   else
/*N*/       OSL_FAIL("Falsche Zeilennummer oder keine Hoehen");
/*N*/
/*N*/   return bChanged;
/*N*/ }


/*N*/ void ScTable::SetManualHeight( USHORT nStartRow, USHORT nEndRow, BOOL bManual )
/*N*/ {
/*N*/   if (VALIDROW(nStartRow) && VALIDROW(nEndRow) && pRowFlags)
/*N*/   {
/*N*/       USHORT nRow;
/*N*/       if (bManual)
/*N*/           for (nRow=nStartRow; nRow<=nEndRow; nRow++)
/*N*/               pRowFlags[nRow] |= CR_MANUALSIZE;
/*N*/       else
/*N*/           for (nRow=nStartRow; nRow<=nEndRow; nRow++)
/*N*/               pRowFlags[nRow] &= ~CR_MANUALSIZE;
/*N*/   }
/*N*/   else
/*N*/       OSL_FAIL("Falsche Zeilennummer oder keine Zeilenflags");
/*N*/ }


/*N*/ USHORT ScTable::GetColWidth( USHORT nCol ) const
/*N*/ {
/*N*/   DBG_ASSERT(VALIDCOL(nCol),"Falsche Spaltennummer");
/*N*/
/*N*/   if (VALIDCOL(nCol) && pColFlags && pColWidth)
/*N*/   {
/*N*/       if ( pColFlags[nCol] & CR_HIDDEN )
/*N*/           return 0;
/*N*/       else
/*N*/           return pColWidth[nCol];
/*N*/   }
/*N*/   else
/*N*/       return (USHORT) STD_COL_WIDTH;
/*N*/ }


/*N*/ USHORT ScTable::GetOriginalWidth( USHORT nCol ) const     // immer die eingestellte
/*N*/ {
/*N*/   DBG_ASSERT(VALIDCOL(nCol),"Falsche Spaltennummer");
/*N*/
/*N*/   if (VALIDCOL(nCol) && pColWidth)
/*N*/       return pColWidth[nCol];
/*N*/   else
/*N*/       return (USHORT) STD_COL_WIDTH;
/*N*/ }




/*N*/ USHORT ScTable::GetRowHeight( USHORT nRow ) const
/*N*/ {
/*N*/   DBG_ASSERT(VALIDROW(nRow),"Falsche Zeilennummer");
/*N*/
/*N*/   if (VALIDROW(nRow) && pRowFlags && pRowHeight)
/*N*/   {
/*N*/       if ( pRowFlags[nRow] & CR_HIDDEN )
/*N*/           return 0;
/*N*/       else
/*N*/           return pRowHeight[nRow];
/*N*/   }
/*N*/   else
/*N*/       return (USHORT) ScGlobal::nStdRowHeight;
/*N*/ }


/*N*/ USHORT ScTable::GetOriginalHeight( USHORT nRow ) const        // non-0 even if hidden
/*N*/ {
/*N*/   DBG_ASSERT(VALIDROW(nRow),"wrong row number");
/*N*/
/*N*/   if (VALIDROW(nRow) && pRowHeight)
/*N*/       return pRowHeight[nRow];
/*N*/   else
/*N*/       return (USHORT) ScGlobal::nStdRowHeight;
/*N*/ }


//  Spalten-/Zeilen-Flags


/*N*/ USHORT ScTable::GetHiddenRowCount( USHORT nRow ) const
/*N*/ {
/*N*/   USHORT nEndRow = nRow;
/*N*/   if ( pRowFlags )
/*N*/   {
/*N*/       while ( nEndRow <= MAXROW && ( pRowFlags[nEndRow] & CR_HIDDEN ) )
/*N*/           ++nEndRow;
/*N*/   }
/*N*/   return nEndRow - nRow;
/*N*/ }


//!     ShowRows / DBShowRows zusammenfassen

/*N*/ void ScTable::ShowCol(USHORT nCol, BOOL bShow)
/*N*/ {
/*N*/   if (VALIDCOL(nCol) && pColFlags)
/*N*/   {
/*N*/       BOOL bWasVis = ( pColFlags[nCol] & CR_HIDDEN ) == 0;
/*N*/       if (bWasVis != bShow)
/*N*/       {
/*N*/           nRecalcLvl++;
/*N*/           ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
/*N*/           if (pDrawLayer)
/*N*/           {
/*N*/               if (bShow)
/*N*/                   pDrawLayer->WidthChanged( nTab, nCol, (long) pColWidth[nCol] );
/*N*/               else
/*N*/                   pDrawLayer->WidthChanged( nTab, nCol, -(long) pColWidth[nCol] );
/*N*/           }
/*N*/
/*N*/           if (bShow)
/*N*/               pColFlags[nCol] &= ~CR_HIDDEN;
/*N*/           else
/*N*/               pColFlags[nCol] |= CR_HIDDEN;
/*N*/           if( !--nRecalcLvl )
/*?*/               SetDrawPageSize();
/*N*/
/*N*/       }
/*N*/   }
/*N*/   else
/*N*/       OSL_FAIL("Falsche Spaltennummer oder keine Flags");
/*N*/ }


/*N*/ void ScTable::ShowRows(USHORT nRow1, USHORT nRow2, BOOL bShow)
/*N*/ {
/*N*/   USHORT i;
/*N*/   USHORT nStartRow = nRow1;
/*N*/   nRecalcLvl++;
/*N*/   while (nStartRow <= nRow2)
/*N*/   {
/*N*/       USHORT nEndRow = nStartRow;
/*N*/       BYTE nOldFlag = pRowFlags[nStartRow] & CR_HIDDEN;
/*N*/       while ( nEndRow < nRow2 && (pRowFlags[nEndRow+1] & CR_HIDDEN) == nOldFlag )
/*N*/           ++nEndRow;
/*N*/
/*N*/       BOOL bWasVis = ( nOldFlag == 0 );
/*N*/       BOOL bChanged = ( bWasVis != bShow );
/*N*/       if ( bChanged )
/*N*/       {
/*N*/           ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
/*N*/           if (pDrawLayer)
/*N*/           {
/*N*/               long nHeight = 0;
/*N*/               for (i=nStartRow; i<=nEndRow; i++)
/*N*/                   nHeight += pRowHeight[i];
/*N*/
/*N*/               if (bShow)
/*N*/                   pDrawLayer->HeightChanged( nTab, nStartRow, nHeight );
/*N*/               else
/*N*/                   pDrawLayer->HeightChanged( nTab, nStartRow, -nHeight );
/*N*/           }
/*N*/       }
/*N*/
/*N*/       if (bShow)
/*N*/           for (i=nStartRow; i<=nEndRow; i++)
/*N*/               pRowFlags[i] &= ~(CR_HIDDEN | CR_FILTERED);
/*N*/       else
/*N*/           for (i=nStartRow; i<=nEndRow; i++)
/*N*/               pRowFlags[i] |= CR_HIDDEN;
/*N*/
/*N*/       nStartRow = nEndRow + 1;
/*N*/   }
/*N*/   if( !--nRecalcLvl )
/*?*/       SetDrawPageSize();
/*N*/ }


/*N*/ BOOL ScTable::IsFiltered(USHORT nRow) const
/*N*/ {
/*N*/   if (VALIDROW(nRow) && pRowFlags)
/*N*/       return ( pRowFlags[nRow] & CR_FILTERED ) != 0;
/*N*/
/*N*/   OSL_FAIL("Falsche Zeilennummer oder keine Flags");
/*N*/   return FALSE;
/*N*/ }




/*N*/ void ScTable::SetRowFlags( USHORT nRow, BYTE nNewFlags )
/*N*/ {
/*N*/   if (VALIDROW(nRow) && pRowFlags)
/*N*/       pRowFlags[nRow] = nNewFlags;
/*N*/   else
/*N*/       OSL_FAIL("Falsche Zeilennummer oder keine Flags");
/*N*/ }


/*N*/ BYTE ScTable::GetColFlags( USHORT nCol ) const
/*N*/ {
/*N*/   if (VALIDCOL(nCol) && pColFlags)
/*N*/       return pColFlags[nCol];
/*N*/   else
/*N*/       return 0;
/*N*/ }


/*N*/ BYTE ScTable::GetRowFlags( USHORT nRow ) const
/*N*/ {
/*N*/   if (VALIDROW(nRow) && pRowFlags)
/*N*/       return pRowFlags[nRow];
/*N*/   else
/*N*/       return 0;
/*N*/ }






/*N*/ USHORT ScTable::GetLastChangedCol() const
/*N*/ {
/*N*/   if ( !pColFlags )
/*N*/       return 0;
/*N*/
/*N*/   USHORT nLastFound = 0;
/*N*/   for (USHORT nCol = 1; nCol <= MAXCOL; nCol++)
/*N*/       if ((pColFlags[nCol] & ~CR_PAGEBREAK) || (pColWidth[nCol] != STD_COL_WIDTH))
/*N*/           nLastFound = nCol;
/*N*/
/*N*/   return nLastFound;
/*N*/ }


/*N*/ USHORT ScTable::GetLastChangedRow() const
/*N*/ {
/*N*/   if ( !pRowFlags )
/*N*/       return 0;
/*N*/
/*N*/   USHORT nLastFound = 0;
/*N*/   for (USHORT nRow = 1; nRow <= MAXROW; nRow++)
/*N*/       if ((pRowFlags[nRow] & ~CR_PAGEBREAK) || (pRowHeight[nRow] != ScGlobal::nStdRowHeight))
/*N*/           nLastFound = nRow;
/*N*/
/*N*/   return nLastFound;
/*N*/ }


/*N*/ BOOL ScTable::UpdateOutlineRow( USHORT nStartRow, USHORT nEndRow, BOOL bShow )
/*N*/ {
/*N*/   if (pOutlineTable && pRowFlags)
/*N*/       return pOutlineTable->GetRowArray()->ManualAction( nStartRow, nEndRow, bShow, pRowFlags );
/*N*/   else
/*N*/       return FALSE;
/*N*/ }


//  Auto-Outline

/*N*/ inline short DiffSign( USHORT a, USHORT b )
/*N*/ {
/*N*/   return (a<b) ? -1 :
/*N*/           (a>b) ? 1 : 0;
/*N*/ }



//
//  Datei-Operationen
//

//  Laden

/*N*/ BOOL ScTable::Load( SvStream& rStream, USHORT nVersion, ScProgress* pProgress )
/*N*/ {
/*N*/   ScReadHeader aHdr( rStream );
/*N*/   USHORT i;
/*N*/
/*N*/   while (aHdr.BytesLeft() && rStream.GetError() == SVSTREAM_OK)
/*N*/   {
/*N*/       USHORT nID;
/*N*/       rStream >> nID;
/*N*/       switch (nID)
/*N*/       {
/*N*/           case SCID_COLUMNS:                      //  Spalten (Daten)
/*N*/               {
/*N*/                   ScMultipleReadHeader aColHdr( rStream );
/*N*/                   if( nVersion >= SC_DATABYTES )
/*N*/                     while( aColHdr.BytesLeft() )
/*N*/                   {
/*N*/                       BYTE nCol;
/*N*/                       rStream >> nCol;
/*N*/                       aCol[ nCol ].Load(rStream, aColHdr);
/*N*/                       if (pProgress)
/*N*/                           pProgress->SetState( rStream.Tell() );
/*N*/                   }
/*N*/                   else
/*N*/                     for (i=0; i<=MAXCOL; i++)
/*N*/                   {
/*N*/                       aCol[i].Load(rStream, aColHdr);
/*N*/                       if (pProgress)
/*N*/                           pProgress->SetState( rStream.Tell() );
/*N*/                   }
/*N*/               }
/*N*/               break;
/*N*/           case SCID_COLROWFLAGS:                  //  Spalten-/Zeilenflags
/*N*/               {
/*N*/                   ScReadHeader aFlagsHdr( rStream );
/*N*/
/*N*/                   BYTE    nFlags;
/*N*/                   USHORT  nVal;
/*N*/                   short   nRep;
/*N*/
/*N*/                   i=0;
/*N*/                   while (i<=MAXCOL)
/*N*/                   {
/*N*/                       rStream >> nRep;
/*N*/                       rStream >> nVal;
/*N*/                       while (nRep-- && i<=MAXCOL)
/*N*/                           pColWidth[i++] = nVal;
/*N*/                   }
/*N*/                   DBG_ASSERT(nRep==-1, "Fehler bei Spaltenbreiten");
/*N*/                   i=0;
/*N*/                   while (i<=MAXCOL)
/*N*/                   {
/*N*/                       rStream >> nRep;
/*N*/                       rStream >> nFlags;
/*N*/                       while (nRep-- && i<=MAXCOL)
/*N*/                           pColFlags[i++] = nFlags;
/*N*/                   }
/*N*/                   DBG_ASSERT(nRep==-1, "Fehler bei Spaltenflags");
/*N*/                   if (pProgress)
/*N*/                       pProgress->SetState( rStream.Tell() );
/*N*/
/*N*/                   //  aus der Datei immer soviele Zeilen laden, wie gespeichert wurden
/*N*/                   USHORT nSrcMaxRow = pDocument->GetSrcMaxRow();
/*N*/
/*N*/                   i=0;
/*N*/                   while (i<=nSrcMaxRow)       // nSrcMaxRow und MAXROW evtl. unterschiedlich
/*N*/                   {
/*N*/                       rStream >> nRep;
/*N*/                       rStream >> nVal;
/*N*/                       while (nRep--)
/*N*/                       {
/*N*/                           if (i<=MAXROW)
/*N*/                               pRowHeight[i] = nVal;
/*N*/                           ++i;
/*N*/                       }
/*N*/                   }
/*N*/                   DBG_ASSERT(i==nSrcMaxRow+1, "Fehler bei Zeilenhoehen");
/*N*/                   if (pProgress)
/*N*/                       pProgress->SetState( rStream.Tell() );
/*N*/                   i=0;
/*N*/                   while (i<=nSrcMaxRow)       // nSrcMaxRow und MAXROW evtl. unterschiedlich
/*N*/                   {
/*N*/                       rStream >> nRep;
/*N*/                       rStream >> nFlags;
/*N*/                       while (nRep--)
/*N*/                       {
/*N*/                           if (i<=MAXROW)
/*N*/                               pRowFlags[i] = nFlags;
/*N*/                           ++i;
/*N*/                       }
/*N*/                   }
/*N*/                   DBG_ASSERT(i==nSrcMaxRow+1, "Fehler bei Zeilenflags");
/*N*/                   if (pProgress)
/*N*/                       pProgress->SetState( rStream.Tell() );
/*N*/               }
/*N*/               break;
/*N*/           case SCID_TABOPTIONS:                   //  einzelne Einstellungen
/*N*/               {
/*N*/                   ScReadHeader aFlagsHdr( rStream );
/*N*/
/*N*/                   aName = rStream.ReadUniOrByteString( rStream.GetStreamCharSet() );
/*N*/
/*N*/                   rStream >> bScenario;
/*N*/                   aComment = rStream.ReadUniOrByteString( rStream.GetStreamCharSet() );
/*N*/
/*N*/                   rStream >> bProtected;
/*N*/                   String aPass = rStream.ReadUniOrByteString( rStream.GetStreamCharSet() );
/*N*/                   if (aPass.Len())
/*N*/                       SvPasswordHelper::GetHashPassword(aProtectPass, aPass);
/*N*/
/*N*/                   BOOL bOutline;
/*N*/                   rStream >> bOutline;
/*N*/                   if (bOutline)
/*N*/                   {
/*N*/                       StartOutlineTable();
/*N*/                       pOutlineTable->Load( rStream );
/*N*/                   }
/*N*/
/*N*/                   if ( aFlagsHdr.BytesLeft() )
/*N*/                   {
/*N*/                       SfxStyleSheetBasePool* pStylePool =
/*N*/                               pDocument->GetStyleSheetPool();
/*N*/
/*N*/                       aPageStyle = rStream.ReadUniOrByteString( rStream.GetStreamCharSet() );
/*N*/
/*N*/                       if ( !pStylePool->Find( aPageStyle, SFX_STYLE_FAMILY_PAGE ) )
/*N*/                       {
/*N*/                           OSL_TRACE( "PageStyle not found. Using Standard." );
/*N*/                           aPageStyle = ScGlobal::GetRscString(STR_STYLENAME_STANDARD);
/*N*/                       }
/*N*/                   }
/*N*/
/*N*/                   if ( aFlagsHdr.BytesLeft() )
/*N*/                   {
/*N*/                       BOOL bOneRange;                     // einzelner Druckbereich ?
/*N*/                       rStream >> bOneRange;
/*N*/                       if ( bOneRange )
/*N*/                       {
/*N*/                           ScRange aRange;
/*N*/                           rStream >> aRange;
/*N*/                           SetPrintRangeCount( 1 );
/*N*/                           SetPrintRange( 0, aRange );
/*N*/                       }
/*N*/
/*N*/                       lcl_LoadRange( rStream, &pRepeatColRange );
/*N*/                       lcl_LoadRange( rStream, &pRepeatRowRange );
/*N*/                   }
/*N*/
/*N*/                   if ( aFlagsHdr.BytesLeft() )
/*N*/                       rStream >> bVisible;
/*N*/
/*N*/                   if ( aFlagsHdr.BytesLeft() )            // Druckbereiche ab Version 314c
/*N*/                   {
/*N*/                       USHORT nNewCount;
/*N*/                       rStream >> nNewCount;
/*N*/                       if ( nNewCount )
/*N*/                       {
/*?*/                           ScRange aTmp;
/*?*/                           SetPrintRangeCount( nNewCount );
/*?*/                           for (i=0; i<nNewCount; i++)
/*?*/                           {
/*?*/                               rStream >> aTmp;
/*?*/                               SetPrintRange( i, aTmp );
/*?*/                           }
/*?*/                       }
/*N*/                   }
/*N*/
/*N*/                   if ( aFlagsHdr.BytesLeft() )            // erweiterte Szenario-Flags ab 5.0
/*N*/                   {
/*N*/                       rStream >> aScenarioColor;
/*N*/                       rStream >> nScenarioFlags;
/*N*/                       rStream >> bActiveScenario;
/*N*/                   }
/*N*/                   else if ( bScenario )
/*N*/                   {
/*?*/                       //  Default fuer Szenarien aus alten Dateien??
/*?*/                       //  Wenn die alten Szenarien wirklich benutzt wurden,
/*?*/                       //  wuerde der Rahmen wahrscheinlich stoeren.
/*?*/
/*?*/                       nScenarioFlags = SC_SCENARIO_COPYALL;
/*N*/                   }
/*N*/
/*N*/                   if (pProgress)
/*N*/                       pProgress->SetState( rStream.Tell() );
/*N*/               }
/*N*/               break;
/*N*/           case SCID_TABLINK:                      //  Verknuepfung
/*N*/               {
/*N*/                   ScReadHeader aLinkHdr( rStream );
/*N*/
/*N*/                   rStream >> nLinkMode;
/*N*/                   aLinkDoc = rStream.ReadUniOrByteString( rStream.GetStreamCharSet() );
/*N*/                   aLinkDoc = ::binfilter::StaticBaseUrl::RelToAbs( aLinkDoc );
/*N*/                   aLinkFlt = rStream.ReadUniOrByteString( rStream.GetStreamCharSet() );
/*N*/                   aLinkTab = rStream.ReadUniOrByteString( rStream.GetStreamCharSet() );
/*N*/
/*N*/                   BOOL bRelURL;
/*N*/                   if ( aLinkHdr.BytesLeft() )
/*N*/                       rStream >> bRelURL;
/*N*/                   else
/*N*/                       bRelURL = FALSE;
/*N*/                   // externer Tabellenname relativ zu absolut
/*N*/                   if ( nLinkMode == SC_LINK_VALUE && bRelURL )
/*N*/                       aName = ScGlobal::GetDocTabName( aLinkDoc, aLinkTab );
/*N*/
/*N*/                   if ( aLinkHdr.BytesLeft() )     // ab 336 auch Filter-Optionen
/*N*/                       aLinkOpt = rStream.ReadUniOrByteString( rStream.GetStreamCharSet() );
/*N*/               }
/*N*/               break;
/*N*/           default:
/*N*/               {
/*N*/                   OSL_FAIL("unbekannter Sub-Record in ScTable::Load");
/*N*/                   ScReadHeader aDummyHeader( rStream );
/*N*/               }
/*N*/       }
/*N*/   }
/*N*/
/*N*/   //  Neuberechnungen
/*N*/
/*N*/   ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
/*N*/   if (pDrawLayer)
/*?*/       pDrawLayer->ScRenamePage( nTab, aName );
/*N*/
/*N*/   return TRUE;
/*N*/ }

/*N*/ void lcl_LoadRange( SvStream& rStream, ScRange** ppRange )
/*N*/ {
/*N*/   BOOL bIsSet = FALSE;
/*N*/
/*N*/   rStream >> bIsSet;
/*N*/
/*N*/   if ( bIsSet )
/*N*/   {
/*N*/       *ppRange = new ScRange;
/*N*/       rStream >> **ppRange;
/*N*/   }
/*N*/   else
/*N*/       *ppRange = NULL;
/*N*/ }

// Berechnen der Groesse der Tabelle und setzen der Groesse an der DrawPage

/*N*/ void ScTable::SetDrawPageSize()
/*N*/ {
/*N*/   ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
/*N*/   if( pDrawLayer )
/*N*/   {
/*N*/       ULONG x = GetColOffset( MAXCOL + 1 );
/*N*/       ULONG y = GetRowOffset( MAXROW + 1 );
/*N*/       x = (ULONG) ((double) x * HMM_PER_TWIPS);
/*N*/       y = (ULONG) ((double) y * HMM_PER_TWIPS);
/*N*/       pDrawLayer->SetPageSize( nTab, Size( x, y ) );
/*N*/   }
/*N*/ }


/*N*/ ULONG ScTable::GetRowOffset( USHORT nRow ) const
/*N*/ {
/*N*/   ULONG n = 0;
/*N*/   if ( pRowFlags && pRowHeight )
/*N*/   {
/*N*/       USHORT i;
/*N*/       BYTE* pFlags = pRowFlags;
/*N*/       USHORT* pHeight = pRowHeight;
/*N*/       for( i = 0; i < nRow; i++, pFlags++, pHeight++ )
/*N*/           if( !( *pFlags & CR_HIDDEN ) )
/*N*/               n += *pHeight;
/*N*/   }
/*N*/   else
/*N*/       OSL_FAIL("GetRowOffset: Daten fehlen");
/*N*/   return n;
/*N*/ }


/*N*/ ULONG ScTable::GetColOffset( USHORT nCol ) const
/*N*/ {
/*N*/   ULONG n = 0;
/*N*/   if ( pColFlags && pColWidth )
/*N*/   {
/*N*/       USHORT i;
/*N*/       BYTE* pFlags = pColFlags;
/*N*/       USHORT* pWidth = pColWidth;
/*N*/       for( i = 0; i < nCol; i++, pFlags++, pWidth++ )
/*N*/           if( !( *pFlags & CR_HIDDEN ) )
/*N*/               n += *pWidth;
/*N*/   }
/*N*/   else
/*N*/       OSL_FAIL("GetColumnOffset: Daten fehlen");
/*N*/   return n;
/*N*/ }

}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
