LCOV - code coverage report
Current view: top level - sc/source/core/data - documen4.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 289 624 46.3 %
Date: 2012-08-25 Functions: 21 36 58.3 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 336 1077 31.2 %

           Branch data     Line data    Source code
       1                 :            : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 :            : /*************************************************************************
       3                 :            :  *
       4                 :            :  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       5                 :            :  *
       6                 :            :  * Copyright 2000, 2010 Oracle and/or its affiliates.
       7                 :            :  *
       8                 :            :  * OpenOffice.org - a multi-platform office productivity suite
       9                 :            :  *
      10                 :            :  * This file is part of OpenOffice.org.
      11                 :            :  *
      12                 :            :  * OpenOffice.org is free software: you can redistribute it and/or modify
      13                 :            :  * it under the terms of the GNU Lesser General Public License version 3
      14                 :            :  * only, as published by the Free Software Foundation.
      15                 :            :  *
      16                 :            :  * OpenOffice.org is distributed in the hope that it will be useful,
      17                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      18                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19                 :            :  * GNU Lesser General Public License version 3 for more details
      20                 :            :  * (a copy is included in the LICENSE file that accompanied this code).
      21                 :            :  *
      22                 :            :  * You should have received a copy of the GNU Lesser General Public License
      23                 :            :  * version 3 along with OpenOffice.org.  If not, see
      24                 :            :  * <http://www.openoffice.org/license.html>
      25                 :            :  * for a copy of the LGPLv3 License.
      26                 :            :  *
      27                 :            :  ************************************************************************/
      28                 :            : 
      29                 :            : #include <svl/intitem.hxx>
      30                 :            : #include <svl/zforlist.hxx>
      31                 :            : #include <formula/token.hxx>
      32                 :            : 
      33                 :            : #include "document.hxx"
      34                 :            : #include "table.hxx"
      35                 :            : #include "globstr.hrc"
      36                 :            : #include "subtotal.hxx"
      37                 :            : #include "docoptio.hxx"
      38                 :            : #include "interpre.hxx"
      39                 :            : #include "markdata.hxx"
      40                 :            : #include "validat.hxx"
      41                 :            : #include "scitems.hxx"
      42                 :            : #include "stlpool.hxx"
      43                 :            : #include "poolhelp.hxx"
      44                 :            : #include "detdata.hxx"
      45                 :            : #include "patattr.hxx"
      46                 :            : #include "chgtrack.hxx"
      47                 :            : #include "progress.hxx"
      48                 :            : #include "paramisc.hxx"
      49                 :            : #include "compiler.hxx"
      50                 :            : #include "externalrefmgr.hxx"
      51                 :            : #include "colorscale.hxx"
      52                 :            : 
      53                 :            : using namespace formula;
      54                 :            : 
      55                 :            : // -----------------------------------------------------------------------
      56                 :            : 
      57                 :            : // Nach der Regula Falsi Methode
      58                 :          3 : bool ScDocument::Solver(SCCOL nFCol, SCROW nFRow, SCTAB nFTab,
      59                 :            :                         SCCOL nVCol, SCROW nVRow, SCTAB nVTab,
      60                 :            :                         const rtl::OUString& sValStr, double& nX)
      61                 :            : {
      62                 :          3 :     bool bRet = false;
      63                 :          3 :     nX = 0.0;
      64 [ +  - ][ +  -  :         21 :     if (ValidColRow(nFCol, nFRow) && ValidColRow(nVCol, nVRow) &&
          +  -  +  -  +  
          -  +  -  +  -  
           +  - ][ +  - ]
      65                 :          6 :         VALIDTAB(nFTab) && VALIDTAB(nVTab) &&
      66                 :          6 :         nFTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nFTab] &&
      67                 :          6 :         nVTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nVTab])
      68                 :            :     {
      69                 :            :         CellType eFType, eVType;
      70         [ +  - ]:          3 :         GetCellType(nFCol, nFRow, nFTab, eFType);
      71         [ +  - ]:          3 :         GetCellType(nVCol, nVRow, nVTab, eVType);
      72                 :            :         // CELLTYPE_NOTE: no value, but referenced by formula
      73                 :            :         // #i108005# convert target value to number using default format,
      74                 :            :         // as previously done in ScInterpreter::GetDouble
      75                 :          3 :         double nTargetVal = 0.0;
      76                 :          3 :         sal_uInt32 nFIndex = 0;
      77 [ +  - ][ -  + ]:          9 :         if (eFType == CELLTYPE_FORMULA && (eVType == CELLTYPE_VALUE || eVType == CELLTYPE_NOTE) &&
         [ #  # ][ +  - ]
                 [ +  - ]
      78 [ +  - ][ +  - ]:          6 :             GetFormatTable()->IsNumberFormat(sValStr, nFIndex, nTargetVal))
         [ +  - ][ +  - ]
         [ +  - ][ #  # ]
      79                 :            :         {
      80                 :            :             ScSingleRefData aRefData;
      81                 :          3 :             aRefData.InitFlags();
      82                 :          3 :             aRefData.nCol = nVCol;
      83                 :          3 :             aRefData.nRow = nVRow;
      84                 :          3 :             aRefData.nTab = nVTab;
      85                 :            : 
      86         [ +  - ]:          3 :             ScTokenArray aArr;
      87         [ +  - ]:          3 :             aArr.AddOpCode( ocBackSolver );
      88         [ +  - ]:          3 :             aArr.AddOpCode( ocOpen );
      89         [ +  - ]:          3 :             aArr.AddSingleReference( aRefData );
      90         [ +  - ]:          3 :             aArr.AddOpCode( ocSep );
      91                 :            : 
      92                 :          3 :             aRefData.nCol = nFCol;
      93                 :          3 :             aRefData.nRow = nFRow;
      94                 :          3 :             aRefData.nTab = nFTab;
      95                 :            : 
      96         [ +  - ]:          3 :             aArr.AddSingleReference( aRefData );
      97         [ +  - ]:          3 :             aArr.AddOpCode( ocSep );
      98         [ +  - ]:          3 :             aArr.AddDouble( nTargetVal );
      99         [ +  - ]:          3 :             aArr.AddOpCode( ocClose );
     100         [ +  - ]:          3 :             aArr.AddOpCode( ocStop );
     101                 :            : 
     102 [ +  - ][ +  - ]:          3 :             ScFormulaCell* pCell = new ScFormulaCell( this, ScAddress(), &aArr );
     103                 :            : 
     104         [ +  - ]:          3 :             if (pCell)
     105                 :            :             {
     106                 :            :                 // FIXME FIXME FIXME this might need to be reworked now that we have formula::FormulaErrorToken and ScFormulaResult, double check !!!
     107                 :            :                 OSL_FAIL("ScDocument::Solver: -> ScFormulaCell::GetValueAlways might need reimplementation");
     108         [ +  - ]:          3 :                 pCell->Interpret();
     109         [ +  - ]:          3 :                 sal_uInt16 nErrCode = pCell->GetErrCode();
     110         [ +  - ]:          3 :                 nX = pCell->GetValueAlways();
     111         [ +  + ]:          3 :                 if (nErrCode == 0)                  // kein fehler beim Rechnen
     112                 :          2 :                     bRet = true;
     113 [ +  - ][ +  - ]:          3 :                 delete pCell;
     114         [ +  - ]:          3 :             }
     115                 :            :         }
     116                 :            :     }
     117                 :          3 :     return bRet;
     118                 :            : }
     119                 :            : 
     120                 :         84 : void ScDocument::InsertMatrixFormula(SCCOL nCol1, SCROW nRow1,
     121                 :            :                                      SCCOL nCol2, SCROW nRow2,
     122                 :            :                                      const ScMarkData& rMark,
     123                 :            :                                      const rtl::OUString& rFormula,
     124                 :            :                                      const ScTokenArray* pArr,
     125                 :            :                                      const formula::FormulaGrammar::Grammar eGram )
     126                 :            : {
     127                 :         84 :     PutInOrder(nCol1, nCol2);
     128                 :         84 :     PutInOrder(nRow1, nRow2);
     129                 :            :     SCTAB i, nTab1;
     130                 :            :     SCCOL j;
     131                 :            :     SCROW k;
     132                 :         84 :     i = 0;
     133                 :         84 :     bool bStop = false;
     134                 :         84 :     SCTAB nMax = static_cast<SCTAB>(maTabs.size());
     135 [ +  - ][ +  - ]:         84 :     ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
     136 [ #  # ][ +  - ]:         84 :     for (; itr != itrEnd && *itr < nMax; ++itr)
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     137                 :            :     {
     138         [ +  - ]:         84 :         if (maTabs[i])
     139                 :            :         {
     140         [ +  - ]:         84 :             i = *itr;
     141                 :         84 :             bStop = true;
     142                 :         84 :             break;
     143                 :            :         }
     144                 :            :     }
     145                 :         84 :     nTab1 = i;
     146         [ +  - ]:         84 :     if (!bStop)
     147                 :            :     {
     148                 :            :         OSL_FAIL("ScDocument::InsertMatrixFormula Keine Tabelle markiert");
     149                 :         84 :         return;
     150                 :            :     }
     151                 :            : 
     152                 :            :     ScFormulaCell* pCell;
     153                 :         84 :     ScAddress aPos( nCol1, nRow1, nTab1 );
     154         [ +  - ]:         84 :     if (pArr)
     155 [ +  - ][ +  - ]:         84 :         pCell = new ScFormulaCell( this, aPos, pArr, eGram, MM_FORMULA );
     156                 :            :     else
     157 [ #  # ][ #  # ]:          0 :         pCell = new ScFormulaCell( this, aPos, rFormula, eGram, MM_FORMULA );
     158         [ +  - ]:         84 :     pCell->SetMatColsRows( nCol2 - nCol1 + 1, nRow2 - nRow1 + 1 );
     159         [ +  - ]:         84 :     itr = rMark.begin();
     160 [ +  - ][ +  - ]:        168 :     for (; itr != itrEnd && *itr < nMax; ++itr)
         [ +  + ][ +  - ]
         [ +  - ][ +  + ]
     161                 :            :     {
     162 [ +  - ][ +  - ]:         84 :         if (maTabs[*itr])
     163                 :            :         {
     164 [ +  - ][ +  - ]:         84 :             if (*itr == nTab1)
     165 [ +  - ][ +  - ]:         84 :                 maTabs[*itr]->PutCell(nCol1, nRow1, pCell);
                 [ +  - ]
     166                 :            :             else
     167 [ #  # ][ #  # ]:          0 :                 maTabs[*itr]->PutCell(nCol1, nRow1, pCell->Clone(*this, ScAddress( nCol1, nRow1, *itr), SC_CLONECELL_STARTLISTENING));
         [ #  # ][ #  # ]
     168                 :            :         }
     169                 :            :     }
     170                 :            : 
     171                 :            :     ScSingleRefData aRefData;
     172                 :         84 :     aRefData.InitFlags();
     173                 :         84 :     aRefData.nCol = nCol1;
     174                 :         84 :     aRefData.nRow = nRow1;
     175                 :         84 :     aRefData.nTab = nTab1;
     176                 :         84 :     aRefData.SetColRel( true );
     177                 :         84 :     aRefData.SetRowRel( true );
     178                 :         84 :     aRefData.SetTabRel( true );
     179         [ +  - ]:         84 :     aRefData.CalcRelFromAbs( ScAddress( nCol1, nRow1, nTab1 ) );
     180                 :            : 
     181         [ +  - ]:         84 :     ScTokenArray aArr;
     182         [ +  - ]:         84 :     ScToken* t = static_cast<ScToken*>(aArr.AddMatrixSingleReference( aRefData));
     183                 :            : 
     184         [ +  - ]:         84 :     itr = rMark.begin();
     185 [ +  - ][ +  - ]:        168 :     for (; itr != itrEnd && *itr < nMax; ++itr)
         [ +  + ][ +  - ]
         [ +  - ][ +  + ]
     186                 :            :     {
     187 [ +  - ][ +  - ]:         84 :         if (maTabs[*itr])
     188                 :            :         {
     189 [ +  - ][ +  - ]:         84 :             maTabs[*itr]->DoColResize( nCol1, nCol2, static_cast<SCSIZE>(nRow2 - nRow1 + 1) );
     190 [ +  - ][ -  + ]:         84 :             if (*itr != nTab1)
     191                 :            :             {
     192         [ #  # ]:          0 :                 aRefData.nTab = *itr;
     193         [ #  # ]:          0 :                 aRefData.nRelTab = *itr - nTab1;
     194         [ #  # ]:          0 :                 t->GetSingleRef() = aRefData;
     195                 :            :             }
     196         [ +  + ]:        252 :             for (j = nCol1; j <= nCol2; j++)
     197                 :            :             {
     198         [ +  + ]:        466 :                 for (k = nRow1; k <= nRow2; k++)
     199                 :            :                 {
     200 [ +  + ][ +  + ]:        298 :                     if (j != nCol1 || k != nRow1)       // nicht in der ersten Zelle
     201                 :            :                     {
     202                 :            :                         // Array muss geklont werden, damit jede
     203                 :            :                         // Zelle ein eigenes Array erhaelt!
     204         [ +  - ]:        214 :                         aPos = ScAddress( j, k, *itr );
     205         [ +  - ]:        214 :                         t->CalcRelFromAbs( aPos );
     206 [ +  - ][ +  - ]:        214 :                         pCell = new ScFormulaCell( this, aPos, aArr.Clone(), eGram, MM_REFERENCE );
                 [ +  - ]
     207 [ +  - ][ +  - ]:        214 :                         maTabs[*itr]->PutCell(j, k, (ScBaseCell*) pCell);
                 [ +  - ]
     208                 :            :                     }
     209                 :            :                 }
     210                 :            :             }
     211                 :            :         }
     212         [ +  - ]:         84 :     }
     213                 :            : }
     214                 :            : 
     215                 :          6 : void ScDocument::InsertTableOp(const ScTabOpParam& rParam,      // Mehrfachoperation
     216                 :            :                                SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
     217                 :            :                                const ScMarkData& rMark)
     218                 :            : {
     219                 :          6 :     PutInOrder(nCol1, nCol2);
     220                 :          6 :     PutInOrder(nRow1, nRow2);
     221                 :            :     SCTAB i, nTab1;
     222                 :            :     SCCOL j;
     223                 :            :     SCROW k;
     224                 :          6 :     i = 0;
     225                 :          6 :     bool bStop = false;
     226                 :          6 :     SCTAB nMax = static_cast<SCTAB>(maTabs.size());
     227 [ +  - ][ +  - ]:          6 :     ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
     228 [ #  # ][ +  - ]:          6 :     for (; itr != itrEnd && *itr < nMax; ++itr)
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     229                 :            :     {
     230 [ +  - ][ +  - ]:          6 :         if (maTabs[*itr])
     231                 :            :         {
     232         [ +  - ]:          6 :             i = *itr;
     233                 :          6 :             bStop = true;
     234                 :          6 :             break;
     235                 :            :         }
     236                 :            :     }
     237                 :          6 :     nTab1 = i;
     238         [ +  - ]:          6 :     if (!bStop)
     239                 :            :     {
     240                 :            :         OSL_FAIL("ScDocument::InsertTableOp: Keine Tabelle markiert");
     241                 :          6 :         return;
     242                 :            :     }
     243                 :            : 
     244                 :          6 :     ScRefAddress aRef;
     245                 :          6 :     rtl::OUStringBuffer aForString('=');
     246 [ +  - ][ +  - ]:          6 :     aForString.append(ScCompiler::GetNativeSymbol(ocTableOp));
                 [ +  - ]
     247 [ +  - ][ +  - ]:          6 :     aForString.append(ScCompiler::GetNativeSymbol( ocOpen));
                 [ +  - ]
     248                 :            : 
     249         [ +  - ]:          6 :     const String& sSep = ScCompiler::GetNativeSymbol( ocSep);
     250         [ +  + ]:          6 :     if (rParam.nMode == 0)                          // nur Spalte
     251                 :            :     {
     252                 :          2 :         aRef.Set( rParam.aRefFormulaCell.GetAddress(), true, false, false );
     253 [ +  - ][ +  - ]:          2 :         aForString.append(aRef.GetRefString(this, nTab1));
         [ +  - ][ +  - ]
     254 [ +  - ][ +  - ]:          2 :         aForString.append(sSep);
     255 [ +  - ][ +  - ]:          2 :         aForString.append(rParam.aRefColCell.GetRefString(this, nTab1));
         [ +  - ][ +  - ]
     256 [ +  - ][ +  - ]:          2 :         aForString.append(sSep);
     257                 :          2 :         aRef.Set( nCol1, nRow1, nTab1, false, true, true );
     258 [ +  - ][ +  - ]:          2 :         aForString.append(aRef.GetRefString(this, nTab1));
         [ +  - ][ +  - ]
     259                 :          2 :         nCol1++;
     260                 :          2 :         nCol2 = Min( nCol2, (SCCOL)(rParam.aRefFormulaEnd.Col() -
     261                 :          2 :                     rParam.aRefFormulaCell.Col() + nCol1 + 1));
     262                 :            :     }
     263         [ +  + ]:          4 :     else if (rParam.nMode == 1)                 // nur zeilenweise
     264                 :            :     {
     265                 :          2 :         aRef.Set( rParam.aRefFormulaCell.GetAddress(), false, true, false );
     266 [ +  - ][ +  - ]:          2 :         aForString.append(aRef.GetRefString(this, nTab1));
         [ +  - ][ +  - ]
     267 [ +  - ][ +  - ]:          2 :         aForString.append(sSep);
     268 [ +  - ][ +  - ]:          2 :         aForString.append(rParam.aRefRowCell.GetRefString(this, nTab1));
         [ +  - ][ +  - ]
     269 [ +  - ][ +  - ]:          2 :         aForString.append(sSep);
     270                 :          2 :         aRef.Set( nCol1, nRow1, nTab1, true, false, true );
     271 [ +  - ][ +  - ]:          2 :         aForString.append(aRef.GetRefString(this, nTab1));
         [ +  - ][ +  - ]
     272                 :          2 :         nRow1++;
     273                 :          2 :         nRow2 = Min( nRow2, (SCROW)(rParam.aRefFormulaEnd.Row() -
     274                 :          2 :                     rParam.aRefFormulaCell.Row() + nRow1 + 1));
     275                 :            :     }
     276                 :            :     else                    // beides
     277                 :            :     {
     278 [ +  - ][ +  - ]:          2 :         aForString.append(rParam.aRefFormulaCell.GetRefString(this, nTab1));
         [ +  - ][ +  - ]
     279 [ +  - ][ +  - ]:          2 :         aForString.append(sSep);
     280 [ +  - ][ +  - ]:          2 :         aForString.append(rParam.aRefColCell.GetRefString(this, nTab1));
         [ +  - ][ +  - ]
     281 [ +  - ][ +  - ]:          2 :         aForString.append(sSep);
     282                 :          2 :         aRef.Set( nCol1, nRow1 + 1, nTab1, false, true, true );
     283 [ +  - ][ +  - ]:          2 :         aForString.append(aRef.GetRefString(this, nTab1));
         [ +  - ][ +  - ]
     284 [ +  - ][ +  - ]:          2 :         aForString.append(sSep);
     285 [ +  - ][ +  - ]:          2 :         aForString.append(rParam.aRefRowCell.GetRefString(this, nTab1));
         [ +  - ][ +  - ]
     286 [ +  - ][ +  - ]:          2 :         aForString.append(sSep);
     287                 :          2 :         aRef.Set( nCol1 + 1, nRow1, nTab1, true, false, true );
     288 [ +  - ][ +  - ]:          2 :         aForString.append(aRef.GetRefString(this, nTab1));
         [ +  - ][ +  - ]
     289                 :          2 :         nCol1++; nRow1++;
     290                 :            :     }
     291 [ +  - ][ +  - ]:          6 :     aForString.append(ScCompiler::GetNativeSymbol( ocClose ));
                 [ +  - ]
     292                 :            : 
     293                 :            :     ScFormulaCell aRefCell( this, ScAddress( nCol1, nRow1, nTab1 ), aForString.makeStringAndClear(),
     294 [ +  - ][ +  - ]:          6 :            formula::FormulaGrammar::GRAM_NATIVE, MM_NONE );
     295         [ +  + ]:         24 :     for( j = nCol1; j <= nCol2; j++ )
     296         [ +  + ]:         73 :         for( k = nRow1; k <= nRow2; k++ )
     297         [ +  + ]:        110 :             for (i = 0; i < static_cast<SCTAB>(maTabs.size()); i++)
     298                 :            :             {
     299         [ +  - ]:         55 :                 itr = rMark.begin();
     300 [ +  - ][ +  - ]:        110 :                 for (; itr != itrEnd && *itr < nMax; ++itr)
         [ +  + ][ +  - ]
         [ +  - ][ +  + ]
     301 [ +  - ][ +  - ]:         55 :                 if( maTabs[*itr] )
     302 [ +  - ][ +  - ]:         55 :                     maTabs[*itr]->PutCell( j, k, aRefCell.Clone( *this, ScAddress( j, k, *itr ), SC_CLONECELL_STARTLISTENING ) );
         [ +  - ][ +  - ]
     303         [ +  - ]:          6 :             }
     304                 :            : }
     305                 :            : 
     306                 :            : namespace {
     307                 :            : 
     308                 :          0 : bool setCacheTableReferenced(ScToken& rToken, ScExternalRefManager& rRefMgr)
     309                 :            : {
     310      [ #  #  # ]:          0 :     switch (rToken.GetType())
     311                 :            :     {
     312                 :            :         case svExternalSingleRef:
     313                 :            :             return rRefMgr.setCacheTableReferenced(
     314 [ #  # ][ #  # ]:          0 :                 rToken.GetIndex(), rToken.GetString(), 1);
     315                 :            :         case svExternalDoubleRef:
     316                 :            :         {
     317                 :          0 :             const ScComplexRefData& rRef = rToken.GetDoubleRef();
     318                 :          0 :             size_t nSheets = rRef.Ref2.nTab - rRef.Ref1.nTab + 1;
     319                 :            :             return rRefMgr.setCacheTableReferenced(
     320 [ #  # ][ #  # ]:          0 :                     rToken.GetIndex(), rToken.GetString(), nSheets);
     321                 :            :         }
     322                 :            :         case svExternalName:
     323                 :            :             /* TODO: external names aren't supported yet, but would
     324                 :            :              * have to be marked as well, if so. Mechanism would be
     325                 :            :              * different. */
     326                 :            :             OSL_FAIL("ScDocument::MarkUsedExternalReferences: implement the svExternalName case!");
     327                 :            :         default:
     328                 :            :             ;
     329                 :            :     }
     330                 :          0 :     return false;
     331                 :            : }
     332                 :            : 
     333                 :            : }
     334                 :            : 
     335                 :          0 : bool ScDocument::MarkUsedExternalReferences( ScTokenArray & rArr )
     336                 :            : {
     337         [ #  # ]:          0 :     if (!rArr.GetLen())
     338                 :          0 :         return false;
     339                 :            : 
     340                 :          0 :     ScExternalRefManager* pRefMgr = NULL;
     341                 :          0 :     rArr.Reset();
     342                 :          0 :     ScToken* t = NULL;
     343                 :          0 :     bool bAllMarked = false;
     344 [ #  # ][ #  # ]:          0 :     while (!bAllMarked && (t = static_cast<ScToken*>(rArr.GetNextReferenceOrName())) != NULL)
                 [ #  # ]
     345                 :            :     {
     346         [ #  # ]:          0 :         if (t->IsExternalRef())
     347                 :            :         {
     348         [ #  # ]:          0 :             if (!pRefMgr)
     349                 :          0 :                 pRefMgr = GetExternalRefManager();
     350                 :            : 
     351                 :          0 :             bAllMarked = setCacheTableReferenced(*t, *pRefMgr);
     352                 :            :         }
     353         [ #  # ]:          0 :         else if (t->GetType() == svIndex)
     354                 :            :         {
     355                 :            :             // this is a named range.  Check if the range contains an external
     356                 :            :             // reference.
     357                 :          0 :             ScRangeData* pRangeData = GetRangeName()->findByIndex(t->GetIndex());
     358         [ #  # ]:          0 :             if (!pRangeData)
     359                 :          0 :                 continue;
     360                 :            : 
     361                 :          0 :             ScTokenArray* pArray = pRangeData->GetCode();
     362         [ #  # ]:          0 :             for (t = static_cast<ScToken*>(pArray->First()); t; t = static_cast<ScToken*>(pArray->Next()))
     363                 :            :             {
     364         [ #  # ]:          0 :                 if (!t->IsExternalRef())
     365                 :          0 :                     continue;
     366                 :            : 
     367         [ #  # ]:          0 :                 if (!pRefMgr)
     368                 :          0 :                     pRefMgr = GetExternalRefManager();
     369                 :            : 
     370                 :          0 :                 bAllMarked = setCacheTableReferenced(*t, *pRefMgr);
     371                 :            :             }
     372                 :            :         }
     373                 :            :     }
     374                 :          0 :     return bAllMarked;
     375                 :            : }
     376                 :            : 
     377                 :          0 : bool ScDocument::GetNextSpellingCell(SCCOL& nCol, SCROW& nRow, SCTAB nTab,
     378                 :            :                         bool bInSel, const ScMarkData& rMark) const
     379                 :            : {
     380 [ #  # ][ #  # ]:          0 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
         [ #  # ][ #  # ]
     381                 :          0 :         return maTabs[nTab]->GetNextSpellingCell( nCol, nRow, bInSel, rMark );
     382                 :            :     else
     383                 :          0 :         return false;
     384                 :            : }
     385                 :            : 
     386                 :          4 : bool ScDocument::GetNextMarkedCell( SCCOL& rCol, SCROW& rRow, SCTAB nTab,
     387                 :            :                                         const ScMarkData& rMark )
     388                 :            : {
     389 [ +  - ][ +  - ]:          4 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
         [ +  - ][ +  - ]
     390                 :          4 :         return maTabs[nTab]->GetNextMarkedCell( rCol, rRow, rMark );
     391                 :            :     else
     392                 :          4 :         return false;
     393                 :            : }
     394                 :            : 
     395                 :          0 : bool ScDocument::ReplaceStyle(const SvxSearchItem& rSearchItem,
     396                 :            :                               SCCOL nCol, SCROW nRow, SCTAB nTab,
     397                 :            :                               ScMarkData& rMark,
     398                 :            :                               bool bIsUndoP)
     399                 :            : {
     400 [ #  # ][ #  # ]:          0 :     if (nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
                 [ #  # ]
     401                 :          0 :         return maTabs[nTab]->ReplaceStyle(rSearchItem, nCol, nRow, rMark, bIsUndoP);
     402                 :            :     else
     403                 :          0 :         return false;
     404                 :            : }
     405                 :            : 
     406                 :         12 : void ScDocument::CompileDBFormula()
     407                 :            : {
     408                 :         12 :     TableContainer::iterator it = maTabs.begin();
     409 [ +  - ][ +  + ]:         28 :     for (;it != maTabs.end(); ++it)
     410                 :            :     {
     411         [ +  - ]:         16 :         if (*it)
     412         [ +  - ]:         16 :             (*it)->CompileDBFormula();
     413                 :            :     }
     414                 :         12 : }
     415                 :            : 
     416                 :         10 : void ScDocument::CompileDBFormula( bool bCreateFormulaString )
     417                 :            : {
     418                 :         10 :     TableContainer::iterator it = maTabs.begin();
     419 [ +  - ][ +  + ]:         20 :     for (;it != maTabs.end(); ++it)
     420                 :            :     {
     421         [ +  - ]:         10 :         if (*it)
     422         [ +  - ]:         10 :             (*it)->CompileDBFormula( bCreateFormulaString );
     423                 :            :     }
     424                 :         10 : }
     425                 :            : 
     426                 :        126 : void ScDocument::CompileNameFormula( bool bCreateFormulaString )
     427                 :            : {
     428                 :        126 :     TableContainer::iterator it = maTabs.begin();
     429 [ +  - ][ +  + ]:        360 :     for (;it != maTabs.end(); ++it)
     430                 :            :     {
     431         [ +  - ]:        234 :         if (*it)
     432         [ +  - ]:        234 :             (*it)->CompileNameFormula( bCreateFormulaString );
     433                 :            :     }
     434                 :        126 : }
     435                 :            : 
     436                 :          7 : void ScDocument::CompileColRowNameFormula()
     437                 :            : {
     438                 :          7 :     TableContainer::iterator it = maTabs.begin();
     439 [ +  - ][ +  + ]:         14 :     for (;it != maTabs.end(); ++it)
     440                 :            :     {
     441         [ +  - ]:          7 :         if (*it)
     442         [ +  - ]:          7 :             (*it)->CompileColRowNameFormula();
     443                 :            :     }
     444                 :          7 : }
     445                 :            : 
     446                 :         78 : void ScDocument::DoColResize( SCTAB nTab, SCCOL nCol1, SCCOL nCol2, SCSIZE nAdd )
     447                 :            : {
     448 [ +  - ][ +  - ]:         78 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
         [ +  - ][ +  - ]
     449                 :         78 :         maTabs[nTab]->DoColResize( nCol1, nCol2, nAdd );
     450                 :            :     else
     451                 :            :     {
     452                 :            :         OSL_FAIL("DoColResize: falsche Tabelle");
     453                 :            :     }
     454                 :         78 : }
     455                 :            : 
     456                 :      10198 : void ScDocument::InvalidateTableArea()
     457                 :            : {
     458                 :      10198 :     TableContainer::iterator it = maTabs.begin();
     459 [ +  - ][ +  + ]:      26829 :     for (;it != maTabs.end() && *it; ++it)
         [ +  - ][ +  - ]
           [ +  +  #  # ]
     460                 :            :     {
     461         [ +  - ]:      16631 :         (*it)->InvalidateTableArea();
     462         [ +  + ]:      16631 :         if ( (*it)->IsScenario() )
     463         [ +  - ]:          1 :             (*it)->InvalidateScenarioRanges();
     464                 :            :     }
     465                 :      10198 : }
     466                 :            : 
     467                 :          0 : sal_Int32 ScDocument::GetMaxStringLen( SCTAB nTab, SCCOL nCol,
     468                 :            :         SCROW nRowStart, SCROW nRowEnd, CharSet eCharSet ) const
     469                 :            : {
     470 [ #  # ][ #  # ]:          0 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
         [ #  # ][ #  # ]
     471                 :          0 :         return maTabs[nTab]->GetMaxStringLen( nCol, nRowStart, nRowEnd, eCharSet );
     472                 :            :     else
     473                 :          0 :         return 0;
     474                 :            : }
     475                 :            : 
     476                 :          0 : xub_StrLen ScDocument::GetMaxNumberStringLen( sal_uInt16& nPrecision, SCTAB nTab,
     477                 :            :                                     SCCOL nCol,
     478                 :            :                                     SCROW nRowStart, SCROW nRowEnd ) const
     479                 :            : {
     480 [ #  # ][ #  # ]:          0 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
         [ #  # ][ #  # ]
     481                 :          0 :         return maTabs[nTab]->GetMaxNumberStringLen( nPrecision, nCol,
     482                 :          0 :             nRowStart, nRowEnd );
     483                 :            :     else
     484                 :          0 :         return 0;
     485                 :            : }
     486                 :            : 
     487                 :        229 : bool ScDocument::GetSelectionFunction( ScSubTotalFunc eFunc,
     488                 :            :                                         const ScAddress& rCursor, const ScMarkData& rMark,
     489                 :            :                                         double& rResult )
     490                 :            : {
     491                 :        229 :     ScFunctionData aData(eFunc);
     492                 :            : 
     493                 :        229 :     ScRange aSingle( rCursor );
     494         [ +  + ]:        229 :     if ( rMark.IsMarked() )
     495         [ +  - ]:          4 :         rMark.GetMarkArea(aSingle);
     496                 :            : 
     497                 :        229 :     SCCOL nStartCol = aSingle.aStart.Col();
     498                 :        229 :     SCROW nStartRow = aSingle.aStart.Row();
     499                 :        229 :     SCCOL nEndCol = aSingle.aEnd.Col();
     500                 :        229 :     SCROW nEndRow = aSingle.aEnd.Row();
     501                 :            : 
     502                 :        229 :     SCTAB nMax = static_cast<SCTAB>(maTabs.size());
     503 [ +  - ][ +  - ]:        229 :     ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
     504 [ +  - ][ +  - ]:        454 :     for (; itr != itrEnd && *itr < nMax && !aData.bError; ++itr)
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  + ]
     505 [ +  - ][ +  - ]:        225 :         if (maTabs[*itr])
     506         [ +  - ]:        225 :             maTabs[*itr]->UpdateSelectionFunction( aData,
     507         [ +  - ]:        225 :                             nStartCol, nStartRow, nEndCol, nEndRow, rMark );
     508                 :            : 
     509                 :            :             //! rMark an UpdateSelectionFunction uebergeben !!!!!
     510                 :            : 
     511         [ +  - ]:        229 :     if (!aData.bError)
     512   [ +  +  -  -  :        229 :         switch (eFunc)
                      - ]
     513                 :            :         {
     514                 :            :             case SUBTOTAL_FUNC_SUM:
     515                 :        222 :                 rResult = aData.nVal;
     516                 :        222 :                 break;
     517                 :            :             case SUBTOTAL_FUNC_CNT:
     518                 :            :             case SUBTOTAL_FUNC_CNT2:
     519                 :          7 :                 rResult = aData.nCount;
     520                 :          7 :                 break;
     521                 :            :             case SUBTOTAL_FUNC_AVE:
     522         [ #  # ]:          0 :                 if (aData.nCount)
     523                 :          0 :                     rResult = aData.nVal / (double) aData.nCount;
     524                 :            :                 else
     525                 :          0 :                     aData.bError = true;
     526                 :          0 :                 break;
     527                 :            :             case SUBTOTAL_FUNC_MAX:
     528                 :            :             case SUBTOTAL_FUNC_MIN:
     529         [ #  # ]:          0 :                 if (aData.nCount)
     530                 :          0 :                     rResult = aData.nVal;
     531                 :            :                 else
     532                 :          0 :                     aData.bError = true;
     533                 :        229 :                 break;
     534                 :            :             default:
     535                 :            :             {
     536                 :            :                 // added to avoid warnings
     537                 :            :             }
     538                 :            :         }
     539                 :            : 
     540         [ -  + ]:        229 :     if (aData.bError)
     541                 :          0 :         rResult = 0.0;
     542                 :            : 
     543                 :        229 :     return !aData.bError;
     544                 :            : }
     545                 :            : 
     546                 :         45 : double ScDocument::RoundValueAsShown( double fVal, sal_uLong nFormat )
     547                 :            : {
     548                 :            :     short nType;
     549 [ +  - ][ +  - ]:         45 :     if ( (nType = GetFormatTable()->GetType( nFormat )) != NUMBERFORMAT_DATE
         [ +  - ][ +  - ]
     550                 :            :       && nType != NUMBERFORMAT_TIME && nType != NUMBERFORMAT_DATETIME )
     551                 :            :     {
     552                 :            :         short nPrecision;
     553         [ -  + ]:         45 :         if ((nFormat % SV_COUNTRY_LANGUAGE_OFFSET) != 0)
     554                 :            :         {
     555                 :          0 :             nPrecision = (short)GetFormatTable()->GetFormatPrecision( nFormat );
     556      [ #  #  # ]:          0 :             switch ( nType )
     557                 :            :             {
     558                 :            :                 case NUMBERFORMAT_PERCENT:      // 0,41% == 0,0041
     559                 :          0 :                     nPrecision += 2;
     560                 :          0 :                     break;
     561                 :            :                 case NUMBERFORMAT_SCIENTIFIC:   // 1,23e-3 == 0,00123
     562                 :            :                 {
     563         [ #  # ]:          0 :                     if ( fVal > 0.0 )
     564                 :          0 :                         nPrecision = sal::static_int_cast<short>( nPrecision - (short)floor( log10( fVal ) ) );
     565         [ #  # ]:          0 :                     else if ( fVal < 0.0 )
     566                 :          0 :                         nPrecision = sal::static_int_cast<short>( nPrecision - (short)floor( log10( -fVal ) ) );
     567                 :          0 :                     break;
     568                 :            :                 }
     569                 :            :             }
     570                 :            :         }
     571                 :            :         else
     572                 :            :         {
     573                 :         45 :             nPrecision = (short)GetDocOptions().GetStdPrecision();
     574                 :            :             // #i115512# no rounding for automatic decimals
     575         [ +  + ]:         45 :             if (nPrecision == static_cast<short>(SvNumberFormatter::UNLIMITED_PRECISION))
     576                 :         15 :                 return fVal;
     577                 :            :         }
     578                 :         30 :         double fRound = ::rtl::math::round( fVal, nPrecision );
     579         [ +  + ]:         30 :         if ( ::rtl::math::approxEqual( fVal, fRound ) )
     580                 :         24 :             return fVal;        // durch Rundung hoechstens Fehler
     581                 :            :         else
     582                 :          6 :             return fRound;
     583                 :            :     }
     584                 :            :     else
     585                 :         45 :         return fVal;
     586                 :            : }
     587                 :            : 
     588                 :            : //
     589                 :            : //          bedingte Formate und Gueltigkeitsbereiche
     590                 :            : //
     591                 :            : 
     592                 :         41 : sal_uLong ScDocument::AddCondFormat( ScConditionalFormat* pNew, SCTAB nTab )
     593                 :            : {
     594         [ -  + ]:         41 :     if(!pNew)
     595                 :          0 :         return 0;
     596                 :            : 
     597 [ +  - ][ +  - ]:         41 :     if(VALIDTAB(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
         [ +  - ][ +  - ]
     598                 :         41 :         return maTabs[nTab]->AddCondFormat( pNew );
     599                 :            : 
     600                 :         41 :     return 0;
     601                 :            : }
     602                 :            : 
     603                 :         54 : sal_uLong ScDocument::AddValidationEntry( const ScValidationData& rNew )
     604                 :            : {
     605         [ -  + ]:         54 :     if (rNew.IsEmpty())
     606                 :          0 :         return 0;                   // leer ist immer 0
     607                 :            : 
     608         [ +  + ]:         54 :     if (!pValidationList)
     609         [ +  - ]:          9 :         pValidationList = new ScValidationDataList;
     610                 :            : 
     611                 :         54 :     sal_uLong nMax = 0;
     612 [ +  - ][ +  - ]:         84 :     for( ScValidationDataList::iterator it = pValidationList->begin(); it != pValidationList->end(); ++it )
                 [ +  + ]
     613                 :            :     {
     614         [ +  - ]:         72 :         const ScValidationData* pData = *it;
     615                 :         72 :         sal_uLong nKey = pData->GetKey();
     616 [ +  + ][ +  - ]:         72 :         if ( pData->EqualEntries( rNew ) )
     617                 :         42 :             return nKey;
     618         [ +  - ]:         30 :         if ( nKey > nMax )
     619                 :         30 :             nMax = nKey;
     620                 :            :     }
     621                 :            : 
     622                 :            :     // Der Aufruf kann aus ScPatternAttr::PutInPool kommen, darum Clone (echte Kopie)
     623                 :            : 
     624                 :         12 :     sal_uLong nNewKey = nMax + 1;
     625                 :         12 :     ScValidationData* pInsert = rNew.Clone(this);
     626                 :         12 :     pInsert->SetKey( nNewKey );
     627                 :         12 :     pValidationList->InsertNew( pInsert );
     628                 :         54 :     return nNewKey;
     629                 :            : }
     630                 :            : 
     631                 :       1983 : const SfxPoolItem* ScDocument::GetEffItem(
     632                 :            :                         SCCOL nCol, SCROW nRow, SCTAB nTab, sal_uInt16 nWhich ) const
     633                 :            : {
     634                 :       1983 :     const ScPatternAttr* pPattern = GetPattern( nCol, nRow, nTab );
     635         [ +  - ]:       1983 :     if ( pPattern )
     636                 :            :     {
     637                 :       1983 :         const SfxItemSet& rSet = pPattern->GetItemSet();
     638                 :            :         const SfxPoolItem* pItem;
     639 [ -  + ][ +  - ]:       1983 :         if ( rSet.GetItemState( ATTR_CONDITIONAL, true, &pItem ) == SFX_ITEM_SET )
     640                 :            :         {
     641                 :          0 :             sal_uLong nIndex = ((const SfxUInt32Item*)pItem)->GetValue();
     642         [ #  # ]:          0 :             ScConditionalFormatList* pCondFormList = GetCondFormList( nTab );
     643 [ #  # ][ #  # ]:          0 :             if (nIndex && pCondFormList)
     644                 :            :             {
     645         [ #  # ]:          0 :                 const ScConditionalFormat* pForm = pCondFormList->GetFormat( nIndex );
     646         [ #  # ]:          0 :                 if ( pForm )
     647                 :            :                 {
     648         [ #  # ]:          0 :                     ScBaseCell* pCell = ((ScDocument*)this)->GetCell(ScAddress(nCol,nRow,nTab));
     649 [ #  # ][ #  # ]:          0 :                     rtl::OUString aStyle = pForm->GetCellStyle( pCell, ScAddress(nCol, nRow, nTab) );
     650         [ #  # ]:          0 :                     if (!aStyle.isEmpty())
     651                 :            :                     {
     652         [ #  # ]:          0 :                         SfxStyleSheetBase* pStyleSheet = xPoolHelper->GetStylePool()->Find(
     653 [ #  # ][ #  # ]:          0 :                                                                 aStyle, SFX_STYLE_FAMILY_PARA );
                 [ #  # ]
     654 [ #  # ][ #  # ]:          0 :                         if ( pStyleSheet && pStyleSheet->GetItemSet().GetItemState(
         [ #  # ][ #  # ]
     655         [ #  # ]:          0 :                                                 nWhich, true, &pItem ) == SFX_ITEM_SET )
     656                 :          0 :                             return pItem;
     657         [ #  # ]:          0 :                     }
     658                 :            :                 }
     659                 :            :             }
     660                 :            :         }
     661         [ +  - ]:       1983 :         return &rSet.Get( nWhich );
     662                 :            :     }
     663                 :            :     OSL_FAIL("kein Pattern");
     664                 :       1983 :     return NULL;
     665                 :            : }
     666                 :            : 
     667                 :       2800 : const SfxItemSet* ScDocument::GetCondResult( SCCOL nCol, SCROW nRow, SCTAB nTab ) const
     668                 :            : {
     669                 :       2800 :     const ScConditionalFormat* pForm = GetCondFormat( nCol, nRow, nTab );
     670         [ +  + ]:       2800 :     if ( pForm )
     671                 :            :     {
     672         [ +  - ]:       2627 :         ScBaseCell* pCell = ((ScDocument*)this)->GetCell(ScAddress(nCol,nRow,nTab));
     673 [ +  - ][ +  - ]:       2627 :         rtl::OUString aStyle = pForm->GetCellStyle( pCell, ScAddress(nCol, nRow, nTab) );
     674         [ +  + ]:       2627 :         if (!aStyle.isEmpty())
     675                 :            :         {
     676 [ +  - ][ +  - ]:         27 :             SfxStyleSheetBase* pStyleSheet = xPoolHelper->GetStylePool()->Find( aStyle, SFX_STYLE_FAMILY_PARA );
         [ +  - ][ +  - ]
     677         [ +  - ]:         27 :             if ( pStyleSheet )
     678         [ +  - ]:       2627 :                 return &pStyleSheet->GetItemSet();
     679                 :            :             // if style is not there, treat like no condition
     680         [ +  + ]:       2627 :         }
     681                 :            :     }
     682                 :       2800 :     return NULL;
     683                 :            : }
     684                 :            : 
     685                 :       2800 : ScConditionalFormat* ScDocument::GetCondFormat(
     686                 :            :                             SCCOL nCol, SCROW nRow, SCTAB nTab ) const
     687                 :            : {
     688                 :       2800 :     sal_uLong nIndex = ((const SfxUInt32Item*)GetAttr(nCol,nRow,nTab,ATTR_CONDITIONAL))->GetValue();
     689         [ +  + ]:       2800 :     if (nIndex)
     690                 :            :     {
     691                 :       2627 :         ScConditionalFormatList* pCondFormList = GetCondFormList(nTab);
     692         [ +  - ]:       2627 :         if (pCondFormList)
     693                 :       2627 :             return pCondFormList->GetFormat( nIndex );
     694                 :            :         else
     695                 :            :         {
     696                 :            :             OSL_FAIL("pCondFormList ist 0");
     697                 :            :         }
     698                 :            :     }
     699                 :            : 
     700                 :       2800 :     return NULL;
     701                 :            : }
     702                 :            : 
     703                 :      64850 : ScConditionalFormatList* ScDocument::GetCondFormList(SCTAB nTab) const
     704                 :            : {
     705 [ +  - ][ +  - ]:      64850 :     if(VALIDTAB(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
         [ +  - ][ +  - ]
     706                 :      64850 :         return maTabs[nTab]->GetCondFormList();
     707                 :            : 
     708                 :      64850 :     return NULL;
     709                 :            : }
     710                 :            : 
     711                 :          3 : void ScDocument::SetCondFormList( ScConditionalFormatList* pList, SCTAB nTab )
     712                 :            : {
     713 [ +  - ][ +  - ]:          3 :     if(VALIDTAB(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
         [ +  - ][ +  - ]
     714                 :          3 :         maTabs[nTab]->SetCondFormList(pList);
     715                 :          3 : }
     716                 :            : 
     717                 :            : 
     718                 :        147 : const ScValidationData* ScDocument::GetValidationEntry( sal_uLong nIndex ) const
     719                 :            : {
     720         [ +  - ]:        147 :     if ( pValidationList )
     721                 :        147 :         return pValidationList->GetData( nIndex );
     722                 :            :     else
     723                 :        147 :         return NULL;
     724                 :            : }
     725                 :            : 
     726                 :          0 : void ScDocument::FindConditionalFormat( sal_uLong nKey, ScRangeList& rRanges, SCTAB nTab )
     727                 :            : {
     728 [ #  # ][ #  # ]:          0 :     if(VALIDTAB(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
         [ #  # ][ #  # ]
     729                 :          0 :         maTabs[nTab]->FindConditionalFormat( nKey, rRanges );
     730                 :          0 : }
     731                 :            : 
     732                 :          0 : void ScDocument::DeleteConditionalFormat(sal_uLong nOldIndex, SCTAB nTab)
     733                 :            : {
     734 [ #  # ][ #  # ]:          0 :     if(VALIDTAB(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
         [ #  # ][ #  # ]
     735                 :          0 :         maTabs[nTab]->DeleteConditionalFormat(nOldIndex);
     736                 :          0 : }
     737                 :            : 
     738                 :            : //------------------------------------------------------------------------
     739                 :            : 
     740                 :          0 : bool ScDocument::HasDetectiveOperations() const
     741                 :            : {
     742 [ #  # ][ #  # ]:          0 :     return pDetOpList && pDetOpList->Count();
     743                 :            : }
     744                 :            : 
     745                 :          1 : void ScDocument::AddDetectiveOperation( const ScDetOpData& rData )
     746                 :            : {
     747         [ +  - ]:          1 :     if (!pDetOpList)
     748         [ +  - ]:          1 :         pDetOpList = new ScDetOpList;
     749                 :            : 
     750                 :          1 :     pDetOpList->Append( new ScDetOpData( rData ) );
     751                 :          1 : }
     752                 :            : 
     753                 :          0 : void ScDocument::ClearDetectiveOperations()
     754                 :            : {
     755         [ #  # ]:          0 :     delete pDetOpList;      // loescht auch die Eintraege
     756                 :          0 :     pDetOpList = NULL;
     757                 :          0 : }
     758                 :            : 
     759                 :          0 : void ScDocument::SetDetOpList(ScDetOpList* pNew)
     760                 :            : {
     761         [ #  # ]:          0 :     delete pDetOpList;      // loescht auch die Eintraege
     762                 :          0 :     pDetOpList = pNew;
     763                 :          0 : }
     764                 :            : 
     765                 :            : //------------------------------------------------------------------------
     766                 :            : //
     767                 :            : //      Vergleich von Dokumenten
     768                 :            : //
     769                 :            : //------------------------------------------------------------------------
     770                 :            : 
     771                 :            : //  Pfriemel-Faktoren
     772                 :            : #define SC_DOCCOMP_MAXDIFF  256
     773                 :            : #define SC_DOCCOMP_MINGOOD  128
     774                 :            : #define SC_DOCCOMP_COLUMNS  10
     775                 :            : #define SC_DOCCOMP_ROWS     100
     776                 :            : 
     777                 :            : 
     778                 :          0 : sal_uInt16 ScDocument::RowDifferences( SCROW nThisRow, SCTAB nThisTab,
     779                 :            :                                     ScDocument& rOtherDoc, SCROW nOtherRow, SCTAB nOtherTab,
     780                 :            :                                     SCCOL nMaxCol, SCCOLROW* pOtherCols )
     781                 :            : {
     782                 :          0 :     sal_uLong nDif = 0;
     783                 :          0 :     sal_uLong nUsed = 0;
     784         [ #  # ]:          0 :     for (SCCOL nThisCol=0; nThisCol<=nMaxCol; nThisCol++)
     785                 :            :     {
     786                 :            :         SCCOL nOtherCol;
     787         [ #  # ]:          0 :         if ( pOtherCols )
     788                 :          0 :             nOtherCol = static_cast<SCCOL>(pOtherCols[nThisCol]);
     789                 :            :         else
     790                 :          0 :             nOtherCol = nThisCol;
     791                 :            : 
     792         [ #  # ]:          0 :         if (ValidCol(nOtherCol))    // nur Spalten vergleichen, die in beiden Dateien sind
     793                 :            :         {
     794         [ #  # ]:          0 :             const ScBaseCell* pThisCell = GetCell( ScAddress( nThisCol, nThisRow, nThisTab ) );
     795         [ #  # ]:          0 :             const ScBaseCell* pOtherCell = rOtherDoc.GetCell( ScAddress( nOtherCol, nOtherRow, nOtherTab ) );
     796         [ #  # ]:          0 :             if (!ScBaseCell::CellEqual( pThisCell, pOtherCell ))
     797                 :            :             {
     798 [ #  # ][ #  # ]:          0 :                 if ( pThisCell && pOtherCell )
     799                 :          0 :                     nDif += 3;
     800                 :            :                 else
     801                 :          0 :                     nDif += 4;      // Inhalt <-> leer zaehlt mehr
     802                 :            :             }
     803                 :            : 
     804 [ #  # ][ #  # ]:          0 :             if ( ( pThisCell  && pThisCell->GetCellType()!=CELLTYPE_NOTE ) ||
           [ #  #  #  # ]
                 [ #  # ]
     805                 :          0 :                  ( pOtherCell && pOtherCell->GetCellType()!=CELLTYPE_NOTE ) )
     806                 :          0 :                 ++nUsed;
     807                 :            :         }
     808                 :            :     }
     809                 :            : 
     810         [ #  # ]:          0 :     if (nUsed > 0)
     811                 :          0 :         return static_cast<sal_uInt16>((nDif*64)/nUsed);            // max.256 (SC_DOCCOMP_MAXDIFF)
     812                 :            : 
     813                 :            :     OSL_ENSURE(!nDif,"Diff ohne Used");
     814                 :          0 :     return 0;
     815                 :            : }
     816                 :            : 
     817                 :          0 : sal_uInt16 ScDocument::ColDifferences( SCCOL nThisCol, SCTAB nThisTab,
     818                 :            :                                     ScDocument& rOtherDoc, SCCOL nOtherCol, SCTAB nOtherTab,
     819                 :            :                                     SCROW nMaxRow, SCCOLROW* pOtherRows )
     820                 :            : {
     821                 :            :     //! optimieren mit Iterator oder so
     822                 :            : 
     823                 :          0 :     sal_uLong nDif = 0;
     824                 :          0 :     sal_uLong nUsed = 0;
     825         [ #  # ]:          0 :     for (SCROW nThisRow=0; nThisRow<=nMaxRow; nThisRow++)
     826                 :            :     {
     827                 :            :         SCROW nOtherRow;
     828         [ #  # ]:          0 :         if ( pOtherRows )
     829                 :          0 :             nOtherRow = pOtherRows[nThisRow];
     830                 :            :         else
     831                 :          0 :             nOtherRow = nThisRow;
     832                 :            : 
     833         [ #  # ]:          0 :         if (ValidRow(nOtherRow))    // nur Zeilen vergleichen, die in beiden Dateien sind
     834                 :            :         {
     835         [ #  # ]:          0 :             const ScBaseCell* pThisCell = GetCell( ScAddress( nThisCol, nThisRow, nThisTab ) );
     836         [ #  # ]:          0 :             const ScBaseCell* pOtherCell = rOtherDoc.GetCell( ScAddress( nOtherCol, nOtherRow, nOtherTab ) );
     837         [ #  # ]:          0 :             if (!ScBaseCell::CellEqual( pThisCell, pOtherCell ))
     838                 :            :             {
     839 [ #  # ][ #  # ]:          0 :                 if ( pThisCell && pOtherCell )
     840                 :          0 :                     nDif += 3;
     841                 :            :                 else
     842                 :          0 :                     nDif += 4;      // Inhalt <-> leer zaehlt mehr
     843                 :            :             }
     844                 :            : 
     845 [ #  # ][ #  # ]:          0 :             if ( ( pThisCell  && pThisCell->GetCellType()!=CELLTYPE_NOTE ) ||
           [ #  #  #  # ]
                 [ #  # ]
     846                 :          0 :                  ( pOtherCell && pOtherCell->GetCellType()!=CELLTYPE_NOTE ) )
     847                 :          0 :                 ++nUsed;
     848                 :            :         }
     849                 :            :     }
     850                 :            : 
     851         [ #  # ]:          0 :     if (nUsed > 0)
     852                 :          0 :         return static_cast<sal_uInt16>((nDif*64)/nUsed);    // max.256
     853                 :            : 
     854                 :            :     OSL_ENSURE(!nDif,"Diff ohne Used");
     855                 :          0 :     return 0;
     856                 :            : }
     857                 :            : 
     858                 :          0 : void ScDocument::FindOrder( SCCOLROW* pOtherRows, SCCOLROW nThisEndRow, SCCOLROW nOtherEndRow,
     859                 :            :                             bool bColumns, ScDocument& rOtherDoc, SCTAB nThisTab, SCTAB nOtherTab,
     860                 :            :                             SCCOLROW nEndCol, SCCOLROW* pTranslate, ScProgress* pProgress, sal_uLong nProAdd )
     861                 :            : {
     862                 :            :     //  bColumns=true: Zeilen sind Spalten und umgekehrt
     863                 :            : 
     864                 :            :     SCCOLROW nMaxCont;                      // wieviel weiter
     865                 :            :     SCCOLROW nMinGood;                      // was ist ein Treffer (incl.)
     866         [ #  # ]:          0 :     if ( bColumns )
     867                 :            :     {
     868                 :          0 :         nMaxCont = SC_DOCCOMP_COLUMNS;      // 10 Spalten
     869                 :          0 :         nMinGood = SC_DOCCOMP_MINGOOD;
     870                 :            :         //! Extra Durchgang mit nMinGood = 0 ????
     871                 :            :     }
     872                 :            :     else
     873                 :            :     {
     874                 :          0 :         nMaxCont = SC_DOCCOMP_ROWS;         // 100 Zeilen
     875                 :          0 :         nMinGood = SC_DOCCOMP_MINGOOD;
     876                 :            :     }
     877 [ #  # ][ #  # ]:          0 :     bool bUseTotal = bColumns && !pTranslate;       // nur beim ersten Durchgang
     878                 :            : 
     879                 :            : 
     880                 :          0 :     SCCOLROW nOtherRow = 0;
     881                 :            :     sal_uInt16 nComp;
     882                 :            :     SCCOLROW nThisRow;
     883                 :          0 :     bool bTotal = false;        // ueber verschiedene nThisRow beibehalten
     884                 :          0 :     SCCOLROW nUnknown = 0;
     885         [ #  # ]:          0 :     for (nThisRow = 0; nThisRow <= nThisEndRow; nThisRow++)
     886                 :            :     {
     887                 :          0 :         SCCOLROW nTempOther = nOtherRow;
     888                 :          0 :         bool bFound = false;
     889                 :          0 :         sal_uInt16 nBest = SC_DOCCOMP_MAXDIFF;
     890                 :          0 :         SCCOLROW nMax = Min( nOtherEndRow, static_cast<SCCOLROW>(( nTempOther + nMaxCont + nUnknown )) );
     891 [ #  # ][ #  # ]:          0 :         for (SCCOLROW i=nTempOther; i<=nMax && nBest>0; i++)    // bei 0 abbrechen
                 [ #  # ]
     892                 :            :         {
     893         [ #  # ]:          0 :             if (bColumns)
     894                 :          0 :                 nComp = ColDifferences( static_cast<SCCOL>(nThisRow), nThisTab, rOtherDoc, static_cast<SCCOL>(i), nOtherTab, nEndCol, pTranslate );
     895                 :            :             else
     896                 :          0 :                 nComp = RowDifferences( nThisRow, nThisTab, rOtherDoc, i, nOtherTab, static_cast<SCCOL>(nEndCol), pTranslate );
     897 [ #  # ][ #  # ]:          0 :             if ( nComp < nBest && ( nComp <= nMinGood || bTotal ) )
                 [ #  # ]
     898                 :            :             {
     899                 :          0 :                 nTempOther = i;
     900                 :          0 :                 nBest = nComp;
     901                 :          0 :                 bFound = true;
     902                 :            :             }
     903 [ #  # ][ #  # ]:          0 :             if ( nComp < SC_DOCCOMP_MAXDIFF || bFound )
     904                 :          0 :                 bTotal = false;
     905 [ #  # ][ #  # ]:          0 :             else if ( i == nTempOther && bUseTotal )
     906                 :          0 :                 bTotal = true;                          // nur ganz oben
     907                 :            :         }
     908         [ #  # ]:          0 :         if ( bFound )
     909                 :            :         {
     910                 :          0 :             pOtherRows[nThisRow] = nTempOther;
     911                 :          0 :             nOtherRow = nTempOther + 1;
     912                 :          0 :             nUnknown = 0;
     913                 :            :         }
     914                 :            :         else
     915                 :            :         {
     916                 :          0 :             pOtherRows[nThisRow] = SCROW_MAX;
     917                 :          0 :             ++nUnknown;
     918                 :            :         }
     919                 :            : 
     920         [ #  # ]:          0 :         if (pProgress)
     921                 :          0 :             pProgress->SetStateOnPercent(nProAdd+static_cast<sal_uLong>(nThisRow));
     922                 :            :     }
     923                 :            : 
     924                 :            :     //  Bloecke ohne Uebereinstimmung ausfuellen
     925                 :            : 
     926                 :          0 :     SCROW nFillStart = 0;
     927                 :          0 :     SCROW nFillPos = 0;
     928                 :          0 :     bool bInFill = false;
     929         [ #  # ]:          0 :     for (nThisRow = 0; nThisRow <= nThisEndRow+1; nThisRow++)
     930                 :            :     {
     931         [ #  # ]:          0 :         SCROW nThisOther = ( nThisRow <= nThisEndRow ) ? pOtherRows[nThisRow] : (nOtherEndRow+1);
     932         [ #  # ]:          0 :         if ( ValidRow(nThisOther) )
     933                 :            :         {
     934         [ #  # ]:          0 :             if ( bInFill )
     935                 :            :             {
     936         [ #  # ]:          0 :                 if ( nThisOther > nFillStart )      // ist was zu verteilen da?
     937                 :            :                 {
     938                 :          0 :                     SCROW nDiff1 = nThisOther - nFillStart;
     939                 :          0 :                     SCROW nDiff2 = nThisRow   - nFillPos;
     940                 :          0 :                     SCROW nMinDiff = Min(nDiff1, nDiff2);
     941         [ #  # ]:          0 :                     for (SCROW i=0; i<nMinDiff; i++)
     942                 :          0 :                         pOtherRows[nFillPos+i] = nFillStart+i;
     943                 :            :                 }
     944                 :            : 
     945                 :          0 :                 bInFill = false;
     946                 :            :             }
     947                 :          0 :             nFillStart = nThisOther + 1;
     948                 :          0 :             nFillPos = nThisRow + 1;
     949                 :            :         }
     950                 :            :         else
     951                 :          0 :             bInFill = true;
     952                 :            :     }
     953                 :          0 : }
     954                 :            : 
     955                 :          0 : void ScDocument::CompareDocument( ScDocument& rOtherDoc )
     956                 :            : {
     957         [ #  # ]:          0 :     if (!pChangeTrack)
     958                 :          0 :         return;
     959                 :            : 
     960         [ #  # ]:          0 :     SCTAB nThisCount = GetTableCount();
     961         [ #  # ]:          0 :     SCTAB nOtherCount = rOtherDoc.GetTableCount();
     962         [ #  # ]:          0 :     SCTAB* pOtherTabs = new SCTAB[nThisCount];
     963                 :            :     SCTAB nThisTab;
     964                 :            : 
     965                 :            :     //  Tabellen mit gleichen Namen vergleichen
     966                 :          0 :     rtl::OUString aThisName;
     967                 :          0 :     rtl::OUString aOtherName;
     968         [ #  # ]:          0 :     for (nThisTab=0; nThisTab<nThisCount; nThisTab++)
     969                 :            :     {
     970                 :          0 :         SCTAB nOtherTab = SCTAB_MAX;
     971 [ #  # ][ #  # ]:          0 :         if (!IsScenario(nThisTab))  // Szenarien weglassen
     972                 :            :         {
     973         [ #  # ]:          0 :             GetName( nThisTab, aThisName );
     974 [ #  # ][ #  # ]:          0 :             for (SCTAB nTemp=0; nTemp<nOtherCount && nOtherTab>MAXTAB; nTemp++)
                 [ #  # ]
     975 [ #  # ][ #  # ]:          0 :                 if (!rOtherDoc.IsScenario(nTemp))
     976                 :            :                 {
     977         [ #  # ]:          0 :                     rOtherDoc.GetName( nTemp, aOtherName );
     978         [ #  # ]:          0 :                     if ( aThisName.equals(aOtherName) )
     979                 :          0 :                         nOtherTab = nTemp;
     980                 :            :                 }
     981                 :            :         }
     982                 :          0 :         pOtherTabs[nThisTab] = nOtherTab;
     983                 :            :     }
     984                 :            :     //  auffuellen, damit einzeln umbenannte Tabellen nicht wegfallen
     985                 :          0 :     SCTAB nFillStart = 0;
     986                 :          0 :     SCTAB nFillPos = 0;
     987                 :          0 :     bool bInFill = false;
     988         [ #  # ]:          0 :     for (nThisTab = 0; nThisTab <= nThisCount; nThisTab++)
     989                 :            :     {
     990         [ #  # ]:          0 :         SCTAB nThisOther = ( nThisTab < nThisCount ) ? pOtherTabs[nThisTab] : nOtherCount;
     991         [ #  # ]:          0 :         if ( ValidTab(nThisOther) )
     992                 :            :         {
     993         [ #  # ]:          0 :             if ( bInFill )
     994                 :            :             {
     995         [ #  # ]:          0 :                 if ( nThisOther > nFillStart )      // ist was zu verteilen da?
     996                 :            :                 {
     997                 :          0 :                     SCTAB nDiff1 = nThisOther - nFillStart;
     998                 :          0 :                     SCTAB nDiff2 = nThisTab   - nFillPos;
     999                 :          0 :                     SCTAB nMinDiff = Min(nDiff1, nDiff2);
    1000         [ #  # ]:          0 :                     for (SCTAB i=0; i<nMinDiff; i++)
    1001 [ #  # ][ #  # ]:          0 :                         if ( !IsScenario(nFillPos+i) && !rOtherDoc.IsScenario(nFillStart+i) )
         [ #  # ][ #  # ]
                 [ #  # ]
    1002                 :          0 :                             pOtherTabs[nFillPos+i] = nFillStart+i;
    1003                 :            :                 }
    1004                 :            : 
    1005                 :          0 :                 bInFill = false;
    1006                 :            :             }
    1007                 :          0 :             nFillStart = nThisOther + 1;
    1008                 :          0 :             nFillPos = nThisTab + 1;
    1009                 :            :         }
    1010                 :            :         else
    1011                 :          0 :             bInFill = true;
    1012                 :            :     }
    1013                 :            : 
    1014                 :            :     //
    1015                 :            :     //  Tabellen in der gefundenen Reihenfolge vergleichen
    1016                 :            :     //
    1017                 :            : 
    1018         [ #  # ]:          0 :     for (nThisTab=0; nThisTab<nThisCount; nThisTab++)
    1019                 :            :     {
    1020                 :          0 :         SCTAB nOtherTab = pOtherTabs[nThisTab];
    1021         [ #  # ]:          0 :         if ( ValidTab(nOtherTab) )
    1022                 :            :         {
    1023                 :          0 :             SCCOL nThisEndCol = 0;
    1024                 :          0 :             SCROW nThisEndRow = 0;
    1025                 :          0 :             SCCOL nOtherEndCol = 0;
    1026                 :          0 :             SCROW nOtherEndRow = 0;
    1027         [ #  # ]:          0 :             GetCellArea( nThisTab, nThisEndCol, nThisEndRow );
    1028         [ #  # ]:          0 :             rOtherDoc.GetCellArea( nOtherTab, nOtherEndCol, nOtherEndRow );
    1029                 :          0 :             SCCOL nEndCol = Max(nThisEndCol, nOtherEndCol);
    1030                 :          0 :             SCROW nEndRow = Max(nThisEndRow, nOtherEndRow);
    1031                 :            :             SCCOL nThisCol;
    1032                 :            :             SCROW nThisRow;
    1033                 :            :             sal_uLong n1,n2;    // fuer AppendDeleteRange
    1034                 :            : 
    1035                 :            :             //! ein Progress ueber alle Tabellen ???
    1036                 :          0 :             rtl::OUString aTabName;
    1037         [ #  # ]:          0 :             GetName( nThisTab, aTabName );
    1038 [ #  # ][ #  # ]:          0 :             rtl::OUString aTemplate = ScGlobal::GetRscString(STR_PROGRESS_COMPARING);
    1039                 :          0 :             sal_Int32 nIndex = 0;
    1040         [ #  # ]:          0 :             rtl::OUStringBuffer aProText = aTemplate.getToken( 0, '#', nIndex );
    1041         [ #  # ]:          0 :             aProText.append(aTabName);
    1042                 :          0 :             nIndex = 0;
    1043         [ #  # ]:          0 :             aProText.append(aTemplate.getToken( 1, '#', nIndex ));
    1044                 :            :             ScProgress aProgress( GetDocumentShell(),
    1045 [ #  # ][ #  # ]:          0 :                                         aProText.makeStringAndClear(), 3*nThisEndRow );  // 2x FindOrder, 1x hier
         [ #  # ][ #  # ]
    1046                 :          0 :             long nProgressStart = 2*nThisEndRow;                    // start fuer hier
    1047                 :            : 
    1048         [ #  # ]:          0 :             SCCOLROW* pTempRows = new SCCOLROW[nThisEndRow+1];
    1049         [ #  # ]:          0 :             SCCOLROW* pOtherRows = new SCCOLROW[nThisEndRow+1];
    1050         [ #  # ]:          0 :             SCCOLROW* pOtherCols = new SCCOLROW[nThisEndCol+1];
    1051                 :            : 
    1052                 :            :             //  eingefuegte/geloeschte Spalten/Zeilen finden:
    1053                 :            :             //  Zwei Versuche:
    1054                 :            :             //  1) Original Zeilen vergleichen                          (pTempRows)
    1055                 :            :             //  2) Original Spalten vergleichen                         (pOtherCols)
    1056                 :            :             //     mit dieser Spaltenreihenfolge Zeilen vergleichen     (pOtherRows)
    1057                 :            : 
    1058                 :            :             //! Spalten vergleichen zweimal mit unterschiedlichem nMinGood ???
    1059                 :            : 
    1060                 :            :             // 1
    1061                 :            :             FindOrder( pTempRows, nThisEndRow, nOtherEndRow, false,
    1062         [ #  # ]:          0 :                         rOtherDoc, nThisTab, nOtherTab, nEndCol, NULL, &aProgress, 0 );
    1063                 :            :             // 2
    1064                 :            :             FindOrder( pOtherCols, nThisEndCol, nOtherEndCol, true,
    1065         [ #  # ]:          0 :                         rOtherDoc, nThisTab, nOtherTab, nEndRow, NULL, NULL, 0 );
    1066                 :            :             FindOrder( pOtherRows, nThisEndRow, nOtherEndRow, false,
    1067                 :            :                         rOtherDoc, nThisTab, nOtherTab, nThisEndCol,
    1068         [ #  # ]:          0 :                         pOtherCols, &aProgress, nThisEndRow );
    1069                 :            : 
    1070                 :          0 :             sal_uLong nMatch1 = 0;  // pTempRows, keine Spalten
    1071         [ #  # ]:          0 :             for (nThisRow = 0; nThisRow<=nThisEndRow; nThisRow++)
    1072         [ #  # ]:          0 :                 if (ValidRow(pTempRows[nThisRow]))
    1073                 :            :                     nMatch1 += SC_DOCCOMP_MAXDIFF -
    1074                 :          0 :                                RowDifferences( nThisRow, nThisTab, rOtherDoc, pTempRows[nThisRow],
    1075         [ #  # ]:          0 :                                                 nOtherTab, nEndCol, NULL );
    1076                 :            : 
    1077                 :          0 :             sal_uLong nMatch2 = 0;  // pOtherRows, pOtherCols
    1078         [ #  # ]:          0 :             for (nThisRow = 0; nThisRow<=nThisEndRow; nThisRow++)
    1079         [ #  # ]:          0 :                 if (ValidRow(pOtherRows[nThisRow]))
    1080                 :            :                     nMatch2 += SC_DOCCOMP_MAXDIFF -
    1081                 :          0 :                                RowDifferences( nThisRow, nThisTab, rOtherDoc, pOtherRows[nThisRow],
    1082         [ #  # ]:          0 :                                                 nOtherTab, nThisEndCol, pOtherCols );
    1083                 :            : 
    1084         [ #  # ]:          0 :             if ( nMatch1 >= nMatch2 )           // ohne Spalten ?
    1085                 :            :             {
    1086                 :            :                 //  Spalten zuruecksetzen
    1087         [ #  # ]:          0 :                 for (nThisCol = 0; nThisCol<=nThisEndCol; nThisCol++)
    1088                 :          0 :                     pOtherCols[nThisCol] = nThisCol;
    1089                 :            : 
    1090                 :            :                 //  Zeilenarrays vertauschen (geloescht werden sowieso beide)
    1091                 :          0 :                 SCCOLROW* pSwap = pTempRows;
    1092                 :          0 :                 pTempRows = pOtherRows;
    1093                 :          0 :                 pOtherRows = pSwap;
    1094                 :            :             }
    1095                 :            :             else
    1096                 :            :             {
    1097                 :            :                 //  bleibt bei pOtherCols, pOtherRows
    1098                 :            :             }
    1099                 :            : 
    1100                 :            : 
    1101                 :            :             //  Change-Actions erzeugen
    1102                 :            :             //  1) Spalten von rechts
    1103                 :            :             //  2) Zeilen von unten
    1104                 :            :             //  3) einzelne Zellen in normaler Reihenfolge
    1105                 :            : 
    1106                 :            :             //  Actions fuer eingefuegte/geloeschte Spalten
    1107                 :            : 
    1108                 :          0 :             SCCOL nLastOtherCol = static_cast<SCCOL>(nOtherEndCol + 1);
    1109                 :            :             //  nThisEndCol ... 0
    1110         [ #  # ]:          0 :             for ( nThisCol = nThisEndCol+1; nThisCol > 0; )
    1111                 :            :             {
    1112                 :          0 :                 --nThisCol;
    1113                 :          0 :                 SCCOL nOtherCol = static_cast<SCCOL>(pOtherCols[nThisCol]);
    1114 [ #  # ][ #  # ]:          0 :                 if ( ValidCol(nOtherCol) && nOtherCol+1 < nLastOtherCol )
                 [ #  # ]
    1115                 :            :                 {
    1116                 :            :                     // Luecke -> geloescht
    1117                 :            :                     ScRange aDelRange( nOtherCol+1, 0, nOtherTab,
    1118                 :          0 :                                         nLastOtherCol-1, MAXROW, nOtherTab );
    1119         [ #  # ]:          0 :                     pChangeTrack->AppendDeleteRange( aDelRange, &rOtherDoc, n1, n2 );
    1120                 :            :                 }
    1121         [ #  # ]:          0 :                 if ( nOtherCol > MAXCOL )                       // eingefuegt
    1122                 :            :                 {
    1123                 :            :                     //  zusammenfassen
    1124 [ #  # ][ #  # ]:          0 :                     if ( nThisCol == nThisEndCol || ValidCol(static_cast<SCCOL>(pOtherCols[nThisCol+1])) )
                 [ #  # ]
    1125                 :            :                     {
    1126                 :          0 :                         SCCOL nFirstNew = static_cast<SCCOL>(nThisCol);
    1127 [ #  # ][ #  # ]:          0 :                         while ( nFirstNew > 0 && pOtherCols[nFirstNew-1] > MAXCOL )
                 [ #  # ]
    1128                 :          0 :                             --nFirstNew;
    1129                 :          0 :                         SCCOL nDiff = nThisCol - nFirstNew;
    1130                 :            :                         ScRange aRange( nLastOtherCol, 0, nOtherTab,
    1131                 :          0 :                                         nLastOtherCol+nDiff, MAXROW, nOtherTab );
    1132         [ #  # ]:          0 :                         pChangeTrack->AppendInsert( aRange );
    1133                 :            :                     }
    1134                 :            :                 }
    1135                 :            :                 else
    1136                 :          0 :                     nLastOtherCol = nOtherCol;
    1137                 :            :             }
    1138         [ #  # ]:          0 :             if ( nLastOtherCol > 0 )                            // ganz oben geloescht
    1139                 :            :             {
    1140                 :            :                 ScRange aDelRange( 0, 0, nOtherTab,
    1141                 :          0 :                                     nLastOtherCol-1, MAXROW, nOtherTab );
    1142         [ #  # ]:          0 :                 pChangeTrack->AppendDeleteRange( aDelRange, &rOtherDoc, n1, n2 );
    1143                 :            :             }
    1144                 :            : 
    1145                 :            :             //  Actions fuer eingefuegte/geloeschte Zeilen
    1146                 :            : 
    1147                 :          0 :             SCROW nLastOtherRow = nOtherEndRow + 1;
    1148                 :            :             //  nThisEndRow ... 0
    1149         [ #  # ]:          0 :             for ( nThisRow = nThisEndRow+1; nThisRow > 0; )
    1150                 :            :             {
    1151                 :          0 :                 --nThisRow;
    1152                 :          0 :                 SCROW nOtherRow = pOtherRows[nThisRow];
    1153 [ #  # ][ #  # ]:          0 :                 if ( ValidRow(nOtherRow) && nOtherRow+1 < nLastOtherRow )
                 [ #  # ]
    1154                 :            :                 {
    1155                 :            :                     // Luecke -> geloescht
    1156                 :            :                     ScRange aDelRange( 0, nOtherRow+1, nOtherTab,
    1157                 :          0 :                                         MAXCOL, nLastOtherRow-1, nOtherTab );
    1158         [ #  # ]:          0 :                     pChangeTrack->AppendDeleteRange( aDelRange, &rOtherDoc, n1, n2 );
    1159                 :            :                 }
    1160         [ #  # ]:          0 :                 if ( nOtherRow > MAXROW )                       // eingefuegt
    1161                 :            :                 {
    1162                 :            :                     //  zusammenfassen
    1163 [ #  # ][ #  # ]:          0 :                     if ( nThisRow == nThisEndRow || ValidRow(pOtherRows[nThisRow+1]) )
                 [ #  # ]
    1164                 :            :                     {
    1165                 :          0 :                         SCROW nFirstNew = nThisRow;
    1166 [ #  # ][ #  # ]:          0 :                         while ( nFirstNew > 0 && pOtherRows[nFirstNew-1] > MAXROW )
                 [ #  # ]
    1167                 :          0 :                             --nFirstNew;
    1168                 :          0 :                         SCROW nDiff = nThisRow - nFirstNew;
    1169                 :            :                         ScRange aRange( 0, nLastOtherRow, nOtherTab,
    1170                 :          0 :                                         MAXCOL, nLastOtherRow+nDiff, nOtherTab );
    1171         [ #  # ]:          0 :                         pChangeTrack->AppendInsert( aRange );
    1172                 :            :                     }
    1173                 :            :                 }
    1174                 :            :                 else
    1175                 :          0 :                     nLastOtherRow = nOtherRow;
    1176                 :            :             }
    1177         [ #  # ]:          0 :             if ( nLastOtherRow > 0 )                            // ganz oben geloescht
    1178                 :            :             {
    1179                 :            :                 ScRange aDelRange( 0, 0, nOtherTab,
    1180                 :          0 :                                     MAXCOL, nLastOtherRow-1, nOtherTab );
    1181         [ #  # ]:          0 :                 pChangeTrack->AppendDeleteRange( aDelRange, &rOtherDoc, n1, n2 );
    1182                 :            :             }
    1183                 :            : 
    1184                 :            :             //  Zeilen durchgehen um einzelne Zellen zu finden
    1185                 :            : 
    1186         [ #  # ]:          0 :             for (nThisRow = 0; nThisRow <= nThisEndRow; nThisRow++)
    1187                 :            :             {
    1188                 :          0 :                 SCROW nOtherRow = pOtherRows[nThisRow];
    1189         [ #  # ]:          0 :                 for (nThisCol = 0; nThisCol <= nThisEndCol; nThisCol++)
    1190                 :            :                 {
    1191                 :          0 :                     SCCOL nOtherCol = static_cast<SCCOL>(pOtherCols[nThisCol]);
    1192                 :          0 :                     ScAddress aThisPos( nThisCol, nThisRow, nThisTab );
    1193         [ #  # ]:          0 :                     const ScBaseCell* pThisCell = GetCell( aThisPos );
    1194                 :          0 :                     const ScBaseCell* pOtherCell = NULL;
    1195 [ #  # ][ #  # ]:          0 :                     if ( ValidCol(nOtherCol) && ValidRow(nOtherRow) )
                 [ #  # ]
    1196                 :            :                     {
    1197                 :          0 :                         ScAddress aOtherPos( nOtherCol, nOtherRow, nOtherTab );
    1198         [ #  # ]:          0 :                         pOtherCell = rOtherDoc.GetCell( aOtherPos );
    1199                 :            :                     }
    1200 [ #  # ][ #  # ]:          0 :                     if ( !ScBaseCell::CellEqual( pThisCell, pOtherCell ) )
    1201                 :            :                     {
    1202                 :          0 :                         ScRange aRange( aThisPos );
    1203 [ #  # ][ #  # ]:          0 :                         ScChangeActionContent* pAction = new ScChangeActionContent( aRange );
    1204         [ #  # ]:          0 :                         pAction->SetOldValue( pOtherCell, &rOtherDoc, this );
    1205         [ #  # ]:          0 :                         pAction->SetNewValue( pThisCell, this );
    1206         [ #  # ]:          0 :                         pChangeTrack->Append( pAction );
    1207                 :            :                     }
    1208                 :            :                 }
    1209         [ #  # ]:          0 :                 aProgress.SetStateOnPercent(nProgressStart+nThisRow);
    1210                 :            :             }
    1211                 :            : 
    1212         [ #  # ]:          0 :             delete[] pOtherCols;
    1213         [ #  # ]:          0 :             delete[] pOtherRows;
    1214 [ #  # ][ #  # ]:          0 :             delete[] pTempRows;
    1215                 :            :         }
    1216                 :            :     }
    1217                 :            : 
    1218                 :            :     //! Inhalt von eingefuegten / geloeschten Tabellen ???
    1219                 :            :     //! Aktionen fuer eingefuegte / geloeschte Tabellen ???
    1220                 :            : 
    1221         [ #  # ]:          0 :     delete[] pOtherTabs;
    1222                 :            : }
    1223                 :            : 
    1224                 :            : 
    1225                 :            : 
    1226                 :            : 
    1227                 :            : 
    1228                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10