LCOV - code coverage report
Current view: top level - sc/source/core/data - table4.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 455 1160 39.2 %
Date: 2015-06-13 12:38:46 Functions: 17 30 56.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include "scitems.hxx"
      21             : #include <comphelper/string.hxx>
      22             : #include <svx/algitem.hxx>
      23             : #include <editeng/boxitem.hxx>
      24             : #include <editeng/brushitem.hxx>
      25             : #include <editeng/contouritem.hxx>
      26             : #include <editeng/colritem.hxx>
      27             : #include <editeng/crossedoutitem.hxx>
      28             : #include <editeng/fhgtitem.hxx>
      29             : #include <editeng/fontitem.hxx>
      30             : #include <editeng/langitem.hxx>
      31             : #include <editeng/postitem.hxx>
      32             : #include <editeng/shdditem.hxx>
      33             : #include <editeng/udlnitem.hxx>
      34             : #include <editeng/wghtitem.hxx>
      35             : #include <svx/rotmodit.hxx>
      36             : #include <editeng/editobj.hxx>
      37             : #include <editeng/editeng.hxx>
      38             : #include <editeng/eeitem.hxx>
      39             : #include <editeng/escapementitem.hxx>
      40             : #include <svl/zforlist.hxx>
      41             : #include <vcl/keycodes.hxx>
      42             : #include <rtl/math.hxx>
      43             : #include <unotools/charclass.hxx>
      44             : 
      45             : #include "attrib.hxx"
      46             : #include "patattr.hxx"
      47             : #include "formulacell.hxx"
      48             : #include "table.hxx"
      49             : #include "globstr.hrc"
      50             : #include "global.hxx"
      51             : #include "document.hxx"
      52             : #include "autoform.hxx"
      53             : #include "userlist.hxx"
      54             : #include "zforauto.hxx"
      55             : #include "subtotal.hxx"
      56             : #include <formula/errorcodes.hxx>
      57             : #include "rangenam.hxx"
      58             : #include "docpool.hxx"
      59             : #include "progress.hxx"
      60             : #include "segmenttree.hxx"
      61             : #include "conditio.hxx"
      62             : #include "editutil.hxx"
      63             : #include <columnspanset.hxx>
      64             : #include <listenercontext.hxx>
      65             : 
      66             : #include <math.h>
      67             : #include <boost/scoped_ptr.hpp>
      68             : 
      69             : // STATIC DATA -----------------------------------------------------------
      70             : 
      71             : #define _D_MAX_LONG_  (double) 0x7fffffff
      72             : 
      73             : extern sal_uInt16 nScFillModeMouseModifier;     // global.cxx
      74             : 
      75             : namespace {
      76             : 
      77           2 : short lcl_DecompValueString( OUString& rValue, sal_Int32& nVal, sal_uInt16* pMinDigits = NULL )
      78             : {
      79           2 :     if ( rValue.isEmpty() )
      80             :     {
      81           0 :         nVal = 0;
      82           0 :         return 0;
      83             :     }
      84           2 :     const sal_Unicode* p = rValue.getStr();
      85           2 :     sal_Int32 nNeg = 0;
      86           2 :     sal_Int32 nNum = 0;
      87           2 :     if ( p[nNum] == '-' )
      88           0 :         nNum = nNeg = 1;
      89           4 :     while ( p[nNum] && CharClass::isAsciiNumeric( OUString(p[nNum]) ) )
      90           0 :         nNum++;
      91             : 
      92           2 :     sal_Unicode cNext = p[nNum];            // 0 if at the end
      93           2 :     sal_Unicode cLast = p[rValue.getLength()-1];
      94             : 
      95             :     // #i5550# If there are numbers at the beginning and the end,
      96             :     // prefer the one at the beginning only if it's followed by a space.
      97             :     // Otherwise, use the number at the end, to enable things like IP addresses.
      98           2 :     if ( nNum > nNeg && ( cNext == 0 || cNext == ' ' || !CharClass::isAsciiNumeric(OUString(cLast)) ) )
      99             :     {   // number at the beginning
     100           0 :         nVal = rValue.copy( 0, nNum ).toInt32();
     101             :         //  any number with a leading zero sets the minimum number of digits
     102           0 :         if ( p[nNeg] == '0' && pMinDigits && ( nNum - nNeg > *pMinDigits ) )
     103           0 :             *pMinDigits = nNum - nNeg;
     104           0 :         rValue = rValue.copy(nNum);
     105           0 :         return -1;
     106             :     }
     107             :     else
     108             :     {
     109           2 :         nNeg = 0;
     110           2 :         sal_Int32 nEnd = nNum = rValue.getLength() - 1;
     111           4 :         while ( nNum && CharClass::isAsciiNumeric( OUString(p[nNum]) ) )
     112           0 :             nNum--;
     113           2 :         if ( p[nNum] == '-' )
     114             :         {
     115           0 :             nNum--;
     116           0 :             nNeg = 1;
     117             :         }
     118           2 :         if ( nNum < nEnd - nNeg )
     119             :         {   // number at the end
     120           0 :             nVal = rValue.copy( nNum + 1 ).toInt32();
     121             :             //  any number with a leading zero sets the minimum number of digits
     122           0 :             if ( p[nNum+1+nNeg] == '0' && pMinDigits && ( nEnd - nNum - nNeg > *pMinDigits ) )
     123           0 :                 *pMinDigits = nEnd - nNum - nNeg;
     124           0 :             rValue = rValue.copy(0, nNum + 1);
     125           0 :             return 1;
     126             :         }
     127             :     }
     128           2 :     nVal = 0;
     129           2 :     return 0;
     130             : }
     131             : 
     132           0 : OUString lcl_ValueString( sal_Int32 nValue, sal_uInt16 nMinDigits )
     133             : {
     134           0 :     if ( nMinDigits <= 1 )
     135           0 :         return OUString::number( nValue );           // simple case...
     136             :     else
     137             :     {
     138           0 :         OUString aStr = OUString::number( std::abs( nValue ) );
     139           0 :         if ( aStr.getLength() < nMinDigits )
     140             :         {
     141           0 :             OUStringBuffer aZero;
     142           0 :             comphelper::string::padToLength(aZero, nMinDigits - aStr.getLength(), '0');
     143           0 :             aStr = aZero.makeStringAndClear() + aStr;
     144             :         }
     145             :         //  nMinDigits doesn't include the '-' sign -> add after inserting zeros
     146           0 :         if ( nValue < 0 )
     147           0 :             aStr = "-" + aStr;
     148           0 :         return aStr;
     149             :     }
     150             : }
     151             : 
     152           0 : void setSuffixCell(
     153             :     ScColumn& rColumn, SCROW nRow, sal_Int32 nValue, sal_uInt16 nDigits, const OUString& rSuffix,
     154             :     CellType eCellType, bool bIsOrdinalSuffix )
     155             : {
     156           0 :     ScDocument& rDoc = rColumn.GetDoc();
     157           0 :     OUString aValue = lcl_ValueString(nValue, nDigits);
     158           0 :     if (!bIsOrdinalSuffix)
     159             :     {
     160           0 :         rColumn.SetRawString(nRow, aValue += rSuffix);
     161           0 :         return;
     162             :     }
     163             : 
     164           0 :     OUString aOrdinalSuffix = ScGlobal::GetOrdinalSuffix(nValue);
     165           0 :     if (eCellType != CELLTYPE_EDIT)
     166             :     {
     167           0 :         rColumn.SetRawString(nRow, aValue += aOrdinalSuffix);
     168           0 :         return;
     169             :     }
     170             : 
     171           0 :     EditEngine aEngine(rDoc.GetEnginePool());
     172           0 :     aEngine.SetEditTextObjectPool(rDoc.GetEditPool());
     173             : 
     174           0 :     SfxItemSet aAttr = aEngine.GetEmptyItemSet();
     175           0 :     aAttr.Put( SvxEscapementItem( SVX_ESCAPEMENT_SUPERSCRIPT, EE_CHAR_ESCAPEMENT));
     176           0 :     aEngine.SetText( aValue );
     177             :     aEngine.QuickInsertText(
     178             :         aOrdinalSuffix,
     179           0 :         ESelection(0, aValue.getLength(), 0, aValue.getLength() + aOrdinalSuffix.getLength()));
     180             : 
     181             :     aEngine.QuickSetAttribs(
     182             :         aAttr,
     183           0 :         ESelection(0, aValue.getLength(), 0, aValue.getLength() + aOrdinalSuffix.getLength()));
     184             : 
     185             :     // Text object instance will be owned by the cell.
     186           0 :     rColumn.SetEditText(nRow, aEngine.CreateTextObject());
     187             : }
     188             : 
     189             : }
     190             : 
     191          15 : void ScTable::FillAnalyse( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
     192             :                             FillCmd& rCmd, FillDateCmd& rDateCmd,
     193             :                             double& rInc, sal_uInt16& rMinDigits,
     194             :                             ScUserListData*& rListData, sal_uInt16& rListIndex)
     195             : {
     196             :     OSL_ENSURE( nCol1==nCol2 || nRow1==nRow2, "FillAnalyse: invalid range" );
     197             : 
     198          15 :     rInc = 0.0;
     199          15 :     rMinDigits = 0;
     200          15 :     rListData = NULL;
     201          15 :     rCmd = FILL_SIMPLE;
     202          15 :     if ( (nScFillModeMouseModifier & KEY_MOD1) )
     203           1 :         return ;        // Ctrl-key: Copy
     204             : 
     205             :     SCCOL nAddX;
     206             :     SCROW nAddY;
     207             :     SCSIZE nCount;
     208          15 :     if (nCol1 == nCol2)
     209             :     {
     210          15 :         nAddX = 0;
     211          15 :         nAddY = 1;
     212          15 :         nCount = static_cast<SCSIZE>(nRow2 - nRow1 + 1);
     213             :     }
     214             :     else
     215             :     {
     216           0 :         nAddX = 1;
     217           0 :         nAddY = 0;
     218           0 :         nCount = static_cast<SCSIZE>(nCol2 - nCol1 + 1);
     219             :     }
     220             : 
     221          15 :     SCCOL nCol = nCol1;
     222          15 :     SCROW nRow = nRow1;
     223             : 
     224          15 :     ScRefCellValue aFirstCell = GetCellValue(nCol, nRow);
     225          15 :     CellType eCellType = aFirstCell.meType;
     226             : 
     227          15 :     if (eCellType == CELLTYPE_VALUE)
     228             :     {
     229          11 :         sal_uInt32 nFormat = static_cast<const SfxUInt32Item*>(GetAttr(nCol,nRow,ATTR_VALUE_FORMAT))->GetValue();
     230          11 :         bool bDate = ( pDocument->GetFormatTable()->GetType(nFormat) == css::util::NumberFormat::DATE );
     231          11 :         if (bDate)
     232             :         {
     233           0 :             if (nCount > 1)
     234             :             {
     235             :                 double nVal;
     236           0 :                 Date aNullDate = *pDocument->GetFormatTable()->GetNullDate();
     237           0 :                 Date aDate1 = aNullDate;
     238           0 :                 nVal = aFirstCell.mfValue;
     239           0 :                 aDate1 += (long)nVal;
     240           0 :                 Date aDate2 = aNullDate;
     241           0 :                 nVal = GetValue(nCol+nAddX, nRow+nAddY);
     242           0 :                 aDate2 += (long)nVal;
     243           0 :                 if ( aDate1 != aDate2 )
     244             :                 {
     245           0 :                     long nCmpInc = 0;
     246             :                     FillDateCmd eType;
     247           0 :                     long nDDiff = aDate2.GetDay()   - (long) aDate1.GetDay();
     248           0 :                     long nMDiff = aDate2.GetMonth() - (long) aDate1.GetMonth();
     249           0 :                     long nYDiff = aDate2.GetYear()  - (long) aDate1.GetYear();
     250           0 :                     if ( nDDiff )
     251             :                     {
     252           0 :                         eType = FILL_DAY;
     253           0 :                         nCmpInc = aDate2 - aDate1;
     254             :                     }
     255             :                     else
     256             :                     {
     257           0 :                         eType = FILL_MONTH;
     258           0 :                         nCmpInc = nMDiff + 12 * nYDiff;
     259             :                     }
     260             : 
     261           0 :                     nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
     262           0 :                     nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
     263           0 :                     bool bVal = true;
     264           0 :                     for (sal_uInt16 i=1; i<nCount && bVal; i++)
     265             :                     {
     266           0 :                         ScRefCellValue aCell = GetCellValue(nCol,nRow);
     267           0 :                         if (aCell.meType == CELLTYPE_VALUE)
     268             :                         {
     269           0 :                             nVal = aCell.mfValue;
     270           0 :                             aDate2 = aNullDate + (long) nVal;
     271           0 :                             if ( eType == FILL_DAY )
     272             :                             {
     273           0 :                                 if ( aDate2-aDate1 != nCmpInc )
     274           0 :                                     bVal = false;
     275             :                             }
     276             :                             else
     277             :                             {
     278           0 :                                 nDDiff = aDate2.GetDay()   - (long) aDate1.GetDay();
     279           0 :                                 nMDiff = aDate2.GetMonth() - (long) aDate1.GetMonth();
     280           0 :                                 nYDiff = aDate2.GetYear()  - (long) aDate1.GetYear();
     281           0 :                                 if (nDDiff || ( nMDiff + 12 * nYDiff != nCmpInc ))
     282           0 :                                     bVal = false;
     283             :                             }
     284           0 :                             aDate1 = aDate2;
     285           0 :                             nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
     286           0 :                             nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
     287             :                         }
     288             :                         else
     289           0 :                             bVal = false;   // No date is also not ok
     290           0 :                     }
     291           0 :                     if (bVal)
     292             :                     {
     293           0 :                         if ( eType == FILL_MONTH && ( nCmpInc % 12 == 0 ) )
     294             :                         {
     295           0 :                             eType = FILL_YEAR;
     296           0 :                             nCmpInc /= 12;
     297             :                         }
     298           0 :                         rCmd = FILL_DATE;
     299           0 :                         rDateCmd = eType;
     300           0 :                         rInc = nCmpInc;
     301             :                     }
     302             :                 }
     303             :             }
     304             :             else                            // single date -> increment by days
     305             :             {
     306           0 :                 rCmd = FILL_DATE;
     307           0 :                 rDateCmd = FILL_DAY;
     308           0 :                 rInc = 1.0;
     309             :             }
     310             :         }
     311             :         else
     312             :         {
     313          11 :             if (nCount > 1)
     314             :             {
     315           1 :                 double nVal1 = aFirstCell.mfValue;
     316           1 :                 double nVal2 = GetValue(nCol+nAddX, nRow+nAddY);
     317           1 :                 rInc = nVal2 - nVal1;
     318           1 :                 nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
     319           1 :                 nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
     320           1 :                 bool bVal = true;
     321           2 :                 for (sal_uInt16 i=1; i<nCount && bVal; i++)
     322             :                 {
     323           1 :                     ScRefCellValue aCell = GetCellValue(nCol,nRow);
     324           1 :                     if (aCell.meType == CELLTYPE_VALUE)
     325             :                     {
     326           0 :                         nVal2 = aCell.mfValue;
     327           0 :                         double nDiff = nVal2 - nVal1;
     328           0 :                         if ( !::rtl::math::approxEqual( nDiff, rInc, 13 ) )
     329           0 :                             bVal = false;
     330           0 :                         nVal1 = nVal2;
     331             :                     }
     332             :                     else
     333           1 :                         bVal = false;
     334           1 :                     nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
     335           1 :                     nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
     336           1 :                 }
     337           1 :                 if (bVal)
     338           0 :                     rCmd = FILL_LINEAR;
     339             :             }
     340             :         }
     341             :     }
     342           4 :     else if (eCellType == CELLTYPE_STRING || eCellType == CELLTYPE_EDIT)
     343             :     {
     344           2 :         OUString aStr;
     345           2 :         GetString(nCol, nRow, aStr);
     346             : 
     347             :         // fdo#39500 don't deduce increment from multiple equal list entries
     348           2 :         bool bAllSame = true;
     349           5 :         for (SCSIZE i = 0; i < nCount; ++i)
     350             :         {
     351           3 :             OUString aTestStr;
     352           3 :             GetString(static_cast<SCCOL>(nCol + i* nAddX), static_cast<SCROW>(nRow + i * nAddY), aTestStr);
     353           3 :             if(aStr != aTestStr)
     354             :             {
     355           0 :                 bAllSame = false;
     356           0 :                 break;
     357             :             }
     358           3 :         }
     359           2 :         if(bAllSame && nCount > 1)
     360           1 :             return;
     361             : 
     362           1 :         rListData = const_cast<ScUserListData*>(ScGlobal::GetUserList()->GetData(aStr));
     363           1 :         if (rListData)
     364             :         {
     365           1 :             (void)rListData->GetSubIndex(aStr, rListIndex);
     366           1 :             nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
     367           1 :             nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
     368           1 :             for (sal_uInt16 i=1; i<nCount && rListData; i++)
     369             :             {
     370           0 :                 (void)GetString(nCol, nRow, aStr);
     371           0 :                 if (!rListData->GetSubIndex(aStr, rListIndex))
     372           0 :                     rListData = NULL;
     373           0 :                 nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
     374           0 :                 nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
     375             :             }
     376             :         }
     377           0 :         else if ( nCount > 1 )
     378             :         {
     379             :             //  pass rMinDigits to all DecompValueString calls
     380             :             //  -> longest number defines rMinDigits
     381             : 
     382             :             sal_Int32 nVal1;
     383           0 :             short nFlag1 = lcl_DecompValueString( aStr, nVal1, &rMinDigits );
     384           0 :             if ( nFlag1 )
     385             :             {
     386             :                 sal_Int32 nVal2;
     387           0 :                 GetString( nCol+nAddX, nRow+nAddY, aStr );
     388           0 :                 short nFlag2 = lcl_DecompValueString( aStr, nVal2, &rMinDigits );
     389           0 :                 if ( nFlag1 == nFlag2 )
     390             :                 {
     391           0 :                     rInc = (double)nVal2 - (double)nVal1;
     392           0 :                     nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
     393           0 :                     nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
     394           0 :                     bool bVal = true;
     395           0 :                     for (sal_uInt16 i=1; i<nCount && bVal; i++)
     396             :                     {
     397           0 :                         ScRefCellValue aCell = GetCellValue(nCol, nRow);
     398           0 :                         CellType eType = aCell.meType;
     399           0 :                         if ( eType == CELLTYPE_STRING || eType == CELLTYPE_EDIT )
     400             :                         {
     401           0 :                             aStr = aCell.getString(pDocument);
     402           0 :                             nFlag2 = lcl_DecompValueString( aStr, nVal2, &rMinDigits );
     403           0 :                             if ( nFlag1 == nFlag2 )
     404             :                             {
     405           0 :                                 double nDiff = (double)nVal2 - (double)nVal1;
     406           0 :                                 if ( !::rtl::math::approxEqual( nDiff, rInc, 13 ) )
     407           0 :                                     bVal = false;
     408           0 :                                 nVal1 = nVal2;
     409             :                             }
     410             :                             else
     411           0 :                                 bVal = false;
     412             :                         }
     413             :                         else
     414           0 :                             bVal = false;
     415           0 :                         nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
     416           0 :                         nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
     417           0 :                     }
     418           0 :                     if (bVal)
     419           0 :                         rCmd = FILL_LINEAR;
     420             :                 }
     421             :             }
     422             :         }
     423             :         else
     424             :         {
     425             :             //  call DecompValueString to set rMinDigits
     426             :             sal_Int32 nDummy;
     427           0 :             lcl_DecompValueString( aStr, nDummy, &rMinDigits );
     428           1 :         }
     429          14 :     }
     430             : }
     431             : 
     432           6 : void ScTable::FillFormula(
     433             :     ScFormulaCell* pSrcCell, SCCOL nDestCol, SCROW nDestRow, bool bLast )
     434             : {
     435             : 
     436           6 :     pDocument->SetNoListening( true );  // still the wrong reference
     437           6 :     ScAddress aAddr( nDestCol, nDestRow, nTab );
     438           6 :     ScFormulaCell* pDestCell = new ScFormulaCell( *pSrcCell, *pDocument, aAddr );
     439           6 :     aCol[nDestCol].SetFormulaCell(nDestRow, pDestCell);
     440             : 
     441           6 :     if ( bLast && pDestCell->GetMatrixFlag() )
     442             :     {
     443           0 :         ScAddress aOrg;
     444           0 :         if ( pDestCell->GetMatrixOrigin( aOrg ) )
     445             :         {
     446           0 :             if ( nDestCol >= aOrg.Col() && nDestRow >= aOrg.Row() )
     447             :             {
     448           0 :                 ScFormulaCell* pOrgCell = pDocument->GetFormulaCell(aOrg);
     449           0 :                 if (pOrgCell && pOrgCell->GetMatrixFlag() == MM_FORMULA)
     450             :                 {
     451             :                     pOrgCell->SetMatColsRows(
     452           0 :                         nDestCol - aOrg.Col() + 1,
     453           0 :                         nDestRow - aOrg.Row() + 1 );
     454             :                 }
     455             :                 else
     456             :                 {
     457             :                     OSL_FAIL( "FillFormula: MatrixOrigin no forumla cell with MM_FORMULA" );
     458             :                 }
     459             :             }
     460             :             else
     461             :             {
     462             :                 OSL_FAIL( "FillFormula: MatrixOrigin bottom right" );
     463             :             }
     464             :         }
     465             :         else
     466             :         {
     467             :             OSL_FAIL( "FillFormula: no MatrixOrigin" );
     468             :         }
     469             :     }
     470           6 :     pDocument->SetNoListening( false );
     471           6 :     pDestCell->StartListeningTo( pDocument );
     472             : 
     473           6 : }
     474             : 
     475           8 : void ScTable::FillAuto( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
     476             :                         sal_uLong nFillCount, FillDir eFillDir, ScProgress* pProgress )
     477             : {
     478           8 :     if ( (nFillCount == 0) || !ValidColRow(nCol1, nRow1) || !ValidColRow(nCol2, nRow2) )
     479           8 :         return;
     480             : 
     481             :     //  Detect direction
     482             : 
     483           8 :     bool bVertical = (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_TOP);
     484           8 :     bool bPositive = (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_RIGHT);
     485             : 
     486           8 :     SCCOLROW nCol = 0;
     487           8 :     SCCOLROW nRow = 0;
     488           8 :     SCCOLROW& rInner = bVertical ? nRow : nCol;        // loop variables
     489           8 :     SCCOLROW& rOuter = bVertical ? nCol : nRow;
     490             :     SCCOLROW nOStart;
     491             :     SCCOLROW nOEnd;
     492             :     SCCOLROW nIStart;
     493             :     SCCOLROW nIEnd;
     494             :     SCCOLROW nISrcStart;
     495             :     SCCOLROW nISrcEnd;
     496           8 :     ScRange aFillRange;
     497             : 
     498           8 :     if (bVertical)
     499             :     {
     500           7 :         nOStart = nCol1;
     501           7 :         nOEnd = nCol2;
     502           7 :         if (bPositive)
     503             :         {
     504           6 :             nISrcStart = nRow1;
     505           6 :             nISrcEnd = nRow2;
     506           6 :             nIStart = nRow2 + 1;
     507           6 :             nIEnd = nRow2 + nFillCount;
     508           6 :             aFillRange = ScRange(nCol1, nRow2+1, 0, nCol2, nRow2 + nFillCount, 0);
     509             :         }
     510             :         else
     511             :         {
     512           1 :             nISrcStart = nRow2;
     513           1 :             nISrcEnd = nRow1;
     514           1 :             nIStart = nRow1 - 1;
     515           1 :             nIEnd = nRow1 - nFillCount;
     516           1 :             aFillRange = ScRange(nCol1, nRow1-1, 0, nCol2, nRow2 - nFillCount, 0);
     517             :         }
     518             :     }
     519             :     else
     520             :     {
     521           1 :         nOStart = nRow1;
     522           1 :         nOEnd = nRow2;
     523           1 :         if (bPositive)
     524             :         {
     525           1 :             nISrcStart = nCol1;
     526           1 :             nISrcEnd = nCol2;
     527           1 :             nIStart = nCol2 + 1;
     528           1 :             nIEnd = nCol2 + nFillCount;
     529           1 :             aFillRange = ScRange(nCol2 + 1, nRow1, 0, nCol2 + nFillCount, nRow2, 0);
     530             :         }
     531             :         else
     532             :         {
     533           0 :             nISrcStart = nCol2;
     534           0 :             nISrcEnd = nCol1;
     535           0 :             nIStart = nCol1 - 1;
     536           0 :             nIEnd = nCol1 - nFillCount;
     537           0 :             aFillRange = ScRange(nCol1 - 1, nRow1, 0, nCol1 - nFillCount, nRow2, 0);
     538             :         }
     539             :     }
     540           8 :     sal_uLong nIMin = nIStart;
     541           8 :     sal_uLong nIMax = nIEnd;
     542           8 :     PutInOrder(nIMin,nIMax);
     543           8 :     bool bHasFiltered = IsDataFiltered(aFillRange);
     544             : 
     545           8 :     if (!bHasFiltered)
     546             :     {
     547           8 :         if (bVertical)
     548           7 :             DeleteArea(nCol1, static_cast<SCROW>(nIMin), nCol2, static_cast<SCROW>(nIMax), IDF_AUTOFILL);
     549             :         else
     550           1 :             DeleteArea(static_cast<SCCOL>(nIMin), nRow1, static_cast<SCCOL>(nIMax), nRow2, IDF_AUTOFILL);
     551             :     }
     552             : 
     553           8 :     sal_uLong nProgress = 0;
     554           8 :     if (pProgress)
     555           4 :         nProgress = pProgress->GetState();
     556             : 
     557             :     //  execute
     558             : 
     559           8 :     sal_uLong nActFormCnt = 0;
     560          23 :     for (rOuter = nOStart; rOuter <= nOEnd; rOuter++)
     561             :     {
     562          15 :         sal_uLong nMaxFormCnt = 0;                      // for formulas
     563             : 
     564             :         //  transfer attributes
     565             : 
     566          15 :         const ScPatternAttr* pSrcPattern = NULL;
     567          15 :         const ScStyleSheet* pStyleSheet = NULL;
     568          15 :         SCCOLROW nAtSrc = nISrcStart;
     569          15 :         ScPatternAttr* pNewPattern = NULL;
     570          15 :         bool bGetPattern = true;
     571          15 :         rInner = nIStart;
     572             :         while (true)        // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
     573             :         {
     574          31 :             if (!ColHidden(nCol) && !RowHidden(nRow))
     575             :             {
     576          31 :                 if ( bGetPattern )
     577             :                 {
     578          21 :                     delete pNewPattern;
     579          21 :                     if (bVertical)      // rInner&:=nRow, rOuter&:=nCol
     580          16 :                         pSrcPattern = aCol[nCol].GetPattern(static_cast<SCROW>(nAtSrc));
     581             :                     else                // rInner&:=nCol, rOuter&:=nRow
     582           5 :                         pSrcPattern = aCol[nAtSrc].GetPattern(static_cast<SCROW>(nRow));
     583          21 :                     bGetPattern = false;
     584          21 :                     pStyleSheet = pSrcPattern->GetStyleSheet();
     585             :                     //  do not transfer ATTR_MERGE / ATTR_MERGE_FLAG
     586          21 :                     const SfxItemSet& rSet = pSrcPattern->GetItemSet();
     587          42 :                     if ( rSet.GetItemState(ATTR_MERGE, false) == SfxItemState::SET
     588          21 :                             || rSet.GetItemState(ATTR_MERGE_FLAG, false) == SfxItemState::SET )
     589             :                     {
     590           0 :                         pNewPattern = new ScPatternAttr( *pSrcPattern );
     591           0 :                         SfxItemSet& rNewSet = pNewPattern->GetItemSet();
     592           0 :                         rNewSet.ClearItem(ATTR_MERGE);
     593           0 :                         rNewSet.ClearItem(ATTR_MERGE_FLAG);
     594             :                     }
     595             :                     else
     596          21 :                         pNewPattern = NULL;
     597             :                 }
     598             : 
     599          31 :                 const ScCondFormatItem& rCondFormatItem = static_cast<const ScCondFormatItem&>(pSrcPattern->GetItem(ATTR_CONDITIONAL));
     600          31 :                 const std::vector<sal_uInt32>& rCondFormatIndex = rCondFormatItem.GetCondFormatData();
     601             : 
     602          31 :                 if ( bVertical && nISrcStart == nISrcEnd && !bHasFiltered )
     603             :                 {
     604             :                     //  set all attributes at once (en bloc)
     605           8 :                     if (pNewPattern || pSrcPattern != pDocument->GetDefPattern())
     606             :                     {
     607             :                         //  Default is already present (DeleteArea)
     608           0 :                         SCROW nY1 = static_cast<SCROW>(std::min( nIStart, nIEnd ));
     609           0 :                         SCROW nY2 = static_cast<SCROW>(std::max( nIStart, nIEnd ));
     610           0 :                         if ( pStyleSheet )
     611           0 :                             aCol[nCol].ApplyStyleArea( nY1, nY2, *pStyleSheet );
     612           0 :                         if ( pNewPattern )
     613           0 :                             aCol[nCol].ApplyPatternArea( nY1, nY2, *pNewPattern );
     614             :                         else
     615           0 :                             aCol[nCol].ApplyPatternArea( nY1, nY2, *pSrcPattern );
     616             : 
     617           0 :                         for(std::vector<sal_uInt32>::const_iterator itr = rCondFormatIndex.begin(), itrEnd = rCondFormatIndex.end();
     618             :                                                         itr != itrEnd; ++itr)
     619             :                         {
     620           0 :                             ScConditionalFormat* pCondFormat = mpCondFormatList->GetFormat(*itr);
     621           0 :                             ScRangeList aRange = pCondFormat->GetRange();
     622           0 :                             aRange.Join(ScRange(nCol, nY1, nTab, nCol, nY2, nTab));
     623           0 :                             pCondFormat->SetRange(aRange);
     624           0 :                         }
     625             :                     }
     626             : 
     627           8 :                     break;
     628             :                 }
     629             : 
     630          23 :                 if ( bHasFiltered )
     631             :                     DeleteArea(static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow),
     632           0 :                             static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), IDF_AUTOFILL);
     633             : 
     634          23 :                 if ( pSrcPattern != aCol[nCol].GetPattern( static_cast<SCROW>(nRow) ) )
     635             :                 {
     636             :                     // Transfer template too
     637             :                     //TODO: Merge ApplyPattern to AttrArray ??
     638           0 :                     if ( pStyleSheet )
     639           0 :                         aCol[nCol].ApplyStyle( static_cast<SCROW>(nRow), *pStyleSheet );
     640             : 
     641             :                     //  Use ApplyPattern instead of SetPattern to keep old MergeFlags
     642           0 :                     if ( pNewPattern )
     643           0 :                         aCol[nCol].ApplyPattern( static_cast<SCROW>(nRow), *pNewPattern );
     644             :                     else
     645           0 :                         aCol[nCol].ApplyPattern( static_cast<SCROW>(nRow), *pSrcPattern );
     646             : 
     647           0 :                     for(std::vector<sal_uInt32>::const_iterator itr = rCondFormatIndex.begin(), itrEnd = rCondFormatIndex.end();
     648             :                             itr != itrEnd; ++itr)
     649             :                     {
     650           0 :                         ScConditionalFormat* pCondFormat = mpCondFormatList->GetFormat(*itr);
     651           0 :                         ScRangeList aRange = pCondFormat->GetRange();
     652           0 :                         aRange.Join(ScRange(nCol, nRow, nTab, nCol, nRow, nTab));
     653           0 :                         pCondFormat->SetRange(aRange);
     654           0 :                     }
     655             :                 }
     656             : 
     657          23 :                 if (nAtSrc==nISrcEnd)
     658             :                 {
     659          19 :                     if ( nAtSrc != nISrcStart )
     660             :                     {    // More than one source cell
     661           4 :                         nAtSrc = nISrcStart;
     662           4 :                         bGetPattern = true;
     663             :                     }
     664             :                 }
     665           4 :                 else if (bPositive)
     666             :                 {
     667           4 :                     ++nAtSrc;
     668           4 :                     bGetPattern = true;
     669             :                 }
     670             :                 else
     671             :                 {
     672           0 :                     --nAtSrc;
     673           0 :                     bGetPattern = true;
     674             :                 }
     675             :             }
     676             : 
     677          23 :             if (rInner == nIEnd) break;
     678          16 :             if (bPositive) ++rInner; else --rInner;
     679             :         }
     680          15 :         if ( pNewPattern )
     681           0 :             delete pNewPattern;
     682             : 
     683             :         //  Analyse
     684             : 
     685             :         FillCmd eFillCmd;
     686             :         FillDateCmd eDateCmd;
     687             :         double nInc;
     688             :         sal_uInt16 nMinDigits;
     689          15 :         ScUserListData* pListData = NULL;
     690             :         sal_uInt16 nListIndex;
     691          15 :         if (bVertical)
     692             :             FillAnalyse(static_cast<SCCOL>(nCol),nRow1,
     693             :                     static_cast<SCCOL>(nCol),nRow2, eFillCmd,eDateCmd,
     694          10 :                     nInc,nMinDigits, pListData,nListIndex);
     695             :         else
     696             :             FillAnalyse(nCol1,static_cast<SCROW>(nRow),
     697             :                     nCol2,static_cast<SCROW>(nRow), eFillCmd,eDateCmd,
     698           5 :                     nInc,nMinDigits, pListData,nListIndex);
     699             : 
     700          15 :         if (pListData)
     701             :         {
     702           1 :             sal_uInt16 nListCount = pListData->GetSubCount();
     703           1 :             if ( !bPositive )
     704             :             {
     705             :                 //  nListIndex of FillAnalyse points to the last entry -> adjust
     706           0 :                 sal_uLong nSub = nISrcStart - nISrcEnd;
     707           0 :                 for (sal_uLong i=0; i<nSub; i++)
     708             :                 {
     709           0 :                     if (nListIndex == 0) nListIndex = nListCount;
     710           0 :                     --nListIndex;
     711             :                 }
     712             :             }
     713             : 
     714           1 :             rInner = nIStart;
     715             :             while (true)        // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
     716             :             {
     717           2 :                 if(!ColHidden(nCol) && !RowHidden(nRow))
     718             :                 {
     719           2 :                     if (bPositive)
     720             :                     {
     721           2 :                         ++nListIndex;
     722           2 :                         if (nListIndex >= nListCount) nListIndex = 0;
     723             :                     }
     724             :                     else
     725             :                     {
     726           0 :                         if (nListIndex == 0) nListIndex = nListCount;
     727           0 :                         --nListIndex;
     728             :                     }
     729           2 :                     aCol[nCol].SetRawString(static_cast<SCROW>(nRow), pListData->GetSubStr(nListIndex));
     730             :                 }
     731             : 
     732           2 :                 if (rInner == nIEnd) break;
     733           1 :                 if (bPositive) ++rInner; else --rInner;
     734             :             }
     735           1 :             if(pProgress)
     736             :             {
     737           0 :                 nProgress += nIMax - nIMin + 1;
     738           0 :                 pProgress->SetStateOnPercent( nProgress );
     739           1 :             }
     740             :         }
     741          14 :         else if (eFillCmd == FILL_SIMPLE)           // fill with pattern/sample
     742             :         {
     743             :             FillAutoSimple(
     744             :                 nISrcStart, nISrcEnd, nIStart, nIEnd, rInner, nCol, nRow,
     745          14 :                 nActFormCnt, nMaxFormCnt, bHasFiltered, bVertical, bPositive, pProgress, nProgress);
     746             :         }
     747             :         else
     748             :         {
     749           0 :             if (!bPositive)
     750           0 :                 nInc = -nInc;
     751           0 :             double nEndVal = (nInc>=0.0) ? MAXDOUBLE : -MAXDOUBLE;
     752           0 :             if (bVertical)
     753             :                 FillSeries( static_cast<SCCOL>(nCol), nRow1,
     754             :                         static_cast<SCCOL>(nCol), nRow2, nFillCount, eFillDir,
     755             :                         eFillCmd, eDateCmd, nInc, nEndVal, nMinDigits, false,
     756           0 :                         pProgress );
     757             :             else
     758             :                 FillSeries( nCol1, static_cast<SCROW>(nRow), nCol2,
     759             :                         static_cast<SCROW>(nRow), nFillCount, eFillDir,
     760             :                         eFillCmd, eDateCmd, nInc, nEndVal, nMinDigits, false,
     761           0 :                         pProgress );
     762           0 :             if (pProgress)
     763           0 :                 nProgress = pProgress->GetState();
     764             :         }
     765             : 
     766          15 :         nActFormCnt += nMaxFormCnt;
     767          16 :     }
     768             : }
     769             : 
     770           0 : OUString ScTable::GetAutoFillPreview( const ScRange& rSource, SCCOL nEndX, SCROW nEndY )
     771             : {
     772           0 :     OUString aValue;
     773             : 
     774           0 :     SCCOL nCol1 = rSource.aStart.Col();
     775           0 :     SCROW nRow1 = rSource.aStart.Row();
     776           0 :     SCCOL nCol2 = rSource.aEnd.Col();
     777           0 :     SCROW nRow2 = rSource.aEnd.Row();
     778           0 :     bool bOk = true;
     779           0 :     long nIndex = 0;
     780           0 :     sal_uLong nSrcCount = 0;
     781           0 :     FillDir eFillDir = FILL_TO_BOTTOM;
     782           0 :     if ( nEndX == nCol2 && nEndY == nRow2 )     // empty
     783           0 :         bOk = false;
     784           0 :     else if ( nEndX == nCol2 )                  // to up / down
     785             :     {
     786           0 :         nEndX = nCol2 = nCol1;                  // use only first column
     787           0 :         nSrcCount = nRow2 - nRow1 + 1;
     788           0 :         nIndex = ((long)nEndY) - nRow1;         // can be negative
     789           0 :         if ( nEndY >= nRow1 )
     790           0 :             eFillDir = FILL_TO_BOTTOM;
     791             :         else
     792           0 :             eFillDir = FILL_TO_TOP;
     793             :     }
     794           0 :     else if ( nEndY == nRow2 )                  // to left / right
     795             :     {
     796           0 :         nEndY = nRow2 = nRow1;                  // use only first row
     797           0 :         nSrcCount = nCol2 - nCol1 + 1;
     798           0 :         nIndex = ((long)nEndX) - nCol1;         // can be negative
     799           0 :         if ( nEndX >= nCol1 )
     800           0 :             eFillDir = FILL_TO_RIGHT;
     801             :         else
     802           0 :             eFillDir = FILL_TO_LEFT;
     803             :     }
     804             :     else                                        // direction not clear
     805           0 :         bOk = false;
     806             : 
     807           0 :     if ( bOk )
     808             :     {
     809             :         FillCmd eFillCmd;
     810             :         FillDateCmd eDateCmd;
     811             :         double nInc;
     812             :         sal_uInt16 nMinDigits;
     813           0 :         ScUserListData* pListData = NULL;
     814             :         sal_uInt16 nListIndex;
     815             : 
     816           0 :         FillAnalyse(nCol1,nRow1, nCol2,nRow2, eFillCmd,eDateCmd, nInc,nMinDigits, pListData,nListIndex);
     817             : 
     818           0 :         if ( pListData )                            // user defined list
     819             :         {
     820           0 :             sal_uInt16 nListCount = pListData->GetSubCount();
     821           0 :             if ( nListCount )
     822             :             {
     823           0 :                 sal_uLong nSub = nSrcCount - 1; //  nListIndex is from last source entry
     824           0 :                 while ( nIndex < sal::static_int_cast<long>(nSub) )
     825           0 :                     nIndex += nListCount;
     826           0 :                 sal_uLong nPos = ( nListIndex + nIndex - nSub ) % nListCount;
     827           0 :                 aValue = pListData->GetSubStr(sal::static_int_cast<sal_uInt16>(nPos));
     828             :             }
     829             :         }
     830           0 :         else if ( eFillCmd == FILL_SIMPLE )         // fill with pattern/sample
     831             :         {
     832           0 :             if ((eFillDir == FILL_TO_BOTTOM)||(eFillDir == FILL_TO_TOP))
     833             :             {
     834           0 :                 long nBegin = 0;
     835           0 :                 long nEnd = 0;
     836           0 :                 if (nEndY > nRow1)
     837             :                 {
     838           0 :                     nBegin = nRow2+1;
     839           0 :                     nEnd = nEndY;
     840             :                 }
     841             :                 else
     842             :                 {
     843           0 :                     nBegin = nEndY;
     844           0 :                     nEnd = nRow1 -1;
     845             :                 }
     846             : 
     847           0 :                 long nNonFiltered = CountNonFilteredRows(nBegin, nEnd);
     848           0 :                 long nFiltered = nEnd + 1 - nBegin - nNonFiltered;
     849             : 
     850           0 :                 if (nIndex > 0)
     851           0 :                     nIndex = nIndex - nFiltered;
     852             :                 else
     853           0 :                     nIndex = nIndex + nFiltered;
     854             :             }
     855             : 
     856           0 :             long nPosIndex = nIndex;
     857           0 :             while ( nPosIndex < 0 )
     858           0 :                 nPosIndex += nSrcCount;
     859           0 :             sal_uLong nPos = nPosIndex % nSrcCount;
     860           0 :             SCCOL nSrcX = nCol1;
     861           0 :             SCROW nSrcY = nRow1;
     862           0 :             if ( eFillDir == FILL_TO_TOP || eFillDir == FILL_TO_BOTTOM )
     863           0 :                 nSrcY = sal::static_int_cast<SCROW>( nSrcY + static_cast<SCROW>(nPos) );
     864             :             else
     865           0 :                 nSrcX = sal::static_int_cast<SCCOL>( nSrcX + static_cast<SCCOL>(nPos) );
     866             : 
     867           0 :             ScRefCellValue aCell = GetCellValue(nSrcX, nSrcY);
     868           0 :             if (!aCell.isEmpty())
     869             :             {
     870             :                 sal_Int32 nDelta;
     871           0 :                 if (nIndex >= 0)
     872           0 :                     nDelta = nIndex / nSrcCount;
     873             :                 else
     874           0 :                     nDelta = ( nIndex - nSrcCount + 1 ) / nSrcCount;    // -1 -> -1
     875             : 
     876           0 :                 CellType eType = aCell.meType;
     877           0 :                 switch ( eType )
     878             :                 {
     879             :                     case CELLTYPE_STRING:
     880             :                     case CELLTYPE_EDIT:
     881             :                     {
     882           0 :                         aValue = aCell.getString(pDocument);
     883             : 
     884           0 :                         if ( !(nScFillModeMouseModifier & KEY_MOD1) )
     885             :                         {
     886             :                             sal_Int32 nVal;
     887           0 :                             sal_uInt16 nCellDigits = 0; // look at each source cell individually
     888           0 :                             short nFlag = lcl_DecompValueString( aValue, nVal, &nCellDigits );
     889           0 :                             if ( nFlag < 0 )
     890             :                             {
     891           0 :                                 if (aValue.equals( ScGlobal::GetOrdinalSuffix( nVal)))
     892           0 :                                     aValue = ScGlobal::GetOrdinalSuffix( nVal + nDelta);
     893             : 
     894           0 :                                 aValue = lcl_ValueString( nVal + nDelta, nCellDigits ) + aValue;
     895             :                             }
     896           0 :                             else if ( nFlag > 0 )
     897           0 :                                 aValue += lcl_ValueString( nVal + nDelta, nCellDigits );
     898             :                         }
     899             :                     }
     900           0 :                     break;
     901             :                     case CELLTYPE_VALUE:
     902             :                     {
     903             :                         //  overflow is possible...
     904           0 :                         double nVal = aCell.mfValue;
     905           0 :                         if ( !(nScFillModeMouseModifier & KEY_MOD1) )
     906           0 :                             nVal += (double) nDelta;
     907             : 
     908             :                         Color* pColor;
     909           0 :                         sal_uLong nNumFmt = GetNumberFormat( nSrcX, nSrcY );
     910           0 :                         pDocument->GetFormatTable()->GetOutputString( nVal, nNumFmt, aValue, &pColor );
     911             :                     }
     912           0 :                     break;
     913             :                     //  not for formulas
     914             :                     default:
     915             :                     {
     916             :                         // added to avoid warnings
     917             :                     }
     918             :                 }
     919           0 :             }
     920             :         }
     921           0 :         else if ( eFillCmd == FILL_LINEAR || eFillCmd == FILL_DATE )        // values
     922             :         {
     923             :             bool bValueOk;
     924             :             double nStart;
     925           0 :             sal_Int32 nVal = 0;
     926           0 :             short nHeadNoneTail = 0;
     927           0 :             ScRefCellValue aCell = GetCellValue(nCol1, nRow1);
     928           0 :             if (!aCell.isEmpty())
     929             :             {
     930           0 :                 CellType eType = aCell.meType;
     931           0 :                 switch ( eType )
     932             :                 {
     933             :                     case CELLTYPE_STRING:
     934             :                     case CELLTYPE_EDIT:
     935             :                     {
     936           0 :                         aValue = aCell.getString(pDocument);
     937           0 :                         nHeadNoneTail = lcl_DecompValueString( aValue, nVal );
     938           0 :                         if ( nHeadNoneTail )
     939           0 :                             nStart = (double)nVal;
     940             :                         else
     941           0 :                             nStart = 0.0;
     942             :                     }
     943           0 :                     break;
     944             :                     case CELLTYPE_VALUE:
     945           0 :                         nStart = aCell.mfValue;
     946           0 :                     break;
     947             :                     case CELLTYPE_FORMULA:
     948           0 :                         nStart = aCell.mpFormula->GetValue();
     949           0 :                     break;
     950             :                     default:
     951           0 :                         nStart = 0.0;
     952             :                 }
     953             :             }
     954             :             else
     955           0 :                 nStart = 0.0;
     956           0 :             if ( eFillCmd == FILL_LINEAR )
     957             :             {
     958           0 :                 double nAdd = nInc;
     959           0 :                 bValueOk = ( SubTotal::SafeMult( nAdd, (double) nIndex ) &&
     960           0 :                              SubTotal::SafePlus( nStart, nAdd ) );
     961             :             }
     962             :             else        // date
     963             :             {
     964           0 :                 bValueOk = true;
     965           0 :                 sal_uInt16 nDayOfMonth = 0;
     966           0 :                 if ( nIndex < 0 )
     967             :                 {
     968           0 :                     nIndex = -nIndex;
     969           0 :                     nInc = -nInc;
     970             :                 }
     971           0 :                 for (long i=0; i<nIndex; i++)
     972           0 :                     IncDate( nStart, nDayOfMonth, nInc, eDateCmd );
     973             :             }
     974             : 
     975           0 :             if (bValueOk)
     976             :             {
     977           0 :                 if ( nHeadNoneTail )
     978             :                 {
     979           0 :                     if ( nHeadNoneTail < 0 )
     980             :                     {
     981           0 :                         if (aValue.equals( ScGlobal::GetOrdinalSuffix( nVal)))
     982           0 :                             aValue = ScGlobal::GetOrdinalSuffix( (sal_Int32)nStart );
     983             : 
     984           0 :                         aValue = lcl_ValueString( (sal_Int32)nStart, nMinDigits ) + aValue;
     985             :                     }
     986             :                     else
     987           0 :                         aValue += lcl_ValueString( (sal_Int32)nStart, nMinDigits );
     988             :                 }
     989             :                 else
     990             :                 {
     991             :                     //TODO: get number format according to Index?
     992             :                     Color* pColor;
     993           0 :                     sal_uLong nNumFmt = GetNumberFormat( nCol1, nRow1 );
     994           0 :                     pDocument->GetFormatTable()->GetOutputString( nStart, nNumFmt, aValue, &pColor );
     995             :                 }
     996           0 :             }
     997             :         }
     998             :         else
     999             :         {
    1000             :             OSL_FAIL("GetAutoFillPreview: invalid mode");
    1001             :         }
    1002             :     }
    1003             : 
    1004           0 :     return aValue;
    1005             : }
    1006             : 
    1007           0 : void ScTable::IncDate(double& rVal, sal_uInt16& nDayOfMonth, double nStep, FillDateCmd eCmd)
    1008             : {
    1009           0 :     if (eCmd == FILL_DAY)
    1010             :     {
    1011           0 :         rVal += nStep;
    1012           0 :         return;
    1013             :     }
    1014             : 
    1015             :     // class Date limits
    1016           0 :     const sal_uInt16 nMinYear = 1583;
    1017           0 :     const sal_uInt16 nMaxYear = 9956;
    1018             : 
    1019           0 :     long nInc = (long) nStep;       // upper/lower limits ?
    1020           0 :     Date aNullDate = *pDocument->GetFormatTable()->GetNullDate();
    1021           0 :     Date aDate = aNullDate;
    1022           0 :     aDate += (long)rVal;
    1023           0 :     switch (eCmd)
    1024             :     {
    1025             :         case FILL_WEEKDAY:
    1026             :             {
    1027           0 :                 aDate += nInc;
    1028           0 :                 DayOfWeek eWeekDay = aDate.GetDayOfWeek();
    1029           0 :                 if (nInc >= 0)
    1030             :                 {
    1031           0 :                     if (eWeekDay == SATURDAY)
    1032           0 :                         aDate += 2;
    1033           0 :                     else if (eWeekDay == SUNDAY)
    1034           0 :                         aDate += 1;
    1035             :                 }
    1036             :                 else
    1037             :                 {
    1038           0 :                     if (eWeekDay == SATURDAY)
    1039           0 :                         aDate -= 1;
    1040           0 :                     else if (eWeekDay == SUNDAY)
    1041           0 :                         aDate -= 2;
    1042             :                 }
    1043             :             }
    1044           0 :             break;
    1045             :         case FILL_MONTH:
    1046             :             {
    1047           0 :                 if ( nDayOfMonth == 0 )
    1048           0 :                     nDayOfMonth = aDate.GetDay();       // init
    1049           0 :                 long nMonth = aDate.GetMonth();
    1050           0 :                 long nYear = aDate.GetYear();
    1051             : 
    1052           0 :                 nMonth += nInc;
    1053             : 
    1054           0 :                 if (nInc >= 0)
    1055             :                 {
    1056           0 :                     if (nMonth > 12)
    1057             :                     {
    1058           0 :                         long nYAdd = (nMonth-1) / 12;
    1059           0 :                         nMonth -= nYAdd * 12;
    1060           0 :                         nYear += nYAdd;
    1061             :                     }
    1062             :                 }
    1063             :                 else
    1064             :                 {
    1065           0 :                     if (nMonth < 1)
    1066             :                     {
    1067           0 :                         long nYAdd = 1 - nMonth / 12;       // positive
    1068           0 :                         nMonth += nYAdd * 12;
    1069           0 :                         nYear -= nYAdd;
    1070             :                     }
    1071             :                 }
    1072             : 
    1073           0 :                 if ( nYear < nMinYear )
    1074           0 :                     aDate = Date( 1,1, nMinYear );
    1075           0 :                 else if ( nYear > nMaxYear )
    1076           0 :                     aDate = Date( 31,12, nMaxYear );
    1077             :                 else
    1078             :                 {
    1079           0 :                     aDate.SetMonth((sal_uInt16) nMonth);
    1080           0 :                     aDate.SetYear((sal_uInt16) nYear);
    1081           0 :                     aDate.SetDay( std::min( Date::GetDaysInMonth( nMonth, nYear), nDayOfMonth ) );
    1082             :                 }
    1083             :             }
    1084           0 :             break;
    1085             :         case FILL_YEAR:
    1086             :             {
    1087           0 :                 long nYear = aDate.GetYear();
    1088           0 :                 nYear += nInc;
    1089           0 :                 if ( nYear < nMinYear )
    1090           0 :                     aDate = Date( 1,1, nMinYear );
    1091           0 :                 else if ( nYear > nMaxYear )
    1092           0 :                     aDate = Date( 31,12, nMaxYear );
    1093             :                 else
    1094           0 :                     aDate.SetYear((sal_uInt16) nYear);
    1095             :             }
    1096           0 :             break;
    1097             :         default:
    1098             :         {
    1099             :             // added to avoid warnings
    1100             :         }
    1101             :     }
    1102             : 
    1103           0 :     rVal = aDate - aNullDate;
    1104             : }
    1105             : 
    1106             : namespace {
    1107             : 
    1108          39 : bool HiddenRowColumn(ScTable* pTable, SCCOLROW nRowColumn, bool bVertical, SCCOLROW& rLastPos)
    1109             : {
    1110          39 :     bool bHidden = false;
    1111          39 :     if(bVertical)
    1112             :     {
    1113             :         SCROW nLast;
    1114          13 :         bHidden = pTable->RowHidden(nRowColumn, NULL, &nLast);
    1115          13 :         rLastPos = nLast;
    1116             :     }
    1117             :     else
    1118             :     {
    1119             :         SCCOL nLast;
    1120          26 :         bHidden = pTable->ColHidden(static_cast<SCCOL>(nRowColumn), NULL, &nLast);
    1121          26 :         rLastPos = nLast;
    1122             :     }
    1123          39 :     return bHidden;
    1124             : }
    1125             : 
    1126             : }
    1127             : 
    1128           1 : void ScTable::FillFormulaVertical(
    1129             :     const ScFormulaCell& rSrcCell,
    1130             :     SCCOLROW& rInner, SCCOL nCol, SCROW nRow1, SCROW nRow2,
    1131             :     ScProgress* pProgress, sal_uLong& rProgress )
    1132             : {
    1133             :     // rInner is the row position when filling vertically.  Also, when filling
    1134             :     // across hidden regions, it may create multiple dis-jointed spans of
    1135             :     // formula cells.
    1136             : 
    1137           1 :     bool bHidden = false;
    1138           1 :     SCCOLROW nHiddenLast = -1;
    1139             : 
    1140           1 :     SCCOLROW nRowStart = -1, nRowEnd = -1;
    1141           1 :     std::vector<sc::RowSpan> aSpans;
    1142           1 :     PutInOrder(nRow1, nRow2);
    1143          11 :     for (rInner = nRow1; rInner <= nRow2; ++rInner)
    1144             :     {
    1145          10 :         if (rInner > nHiddenLast)
    1146           1 :             bHidden = HiddenRowColumn(this, rInner, true, nHiddenLast);
    1147             : 
    1148          10 :         if (bHidden)
    1149             :         {
    1150           0 :             if (nRowStart >= 0)
    1151             :             {
    1152           0 :                 nRowEnd = rInner - 1;
    1153           0 :                 aSpans.push_back(sc::RowSpan(nRowStart, nRowEnd));
    1154           0 :                 nRowStart = -1;
    1155             :             }
    1156           0 :             rInner = nHiddenLast;
    1157           0 :             continue;
    1158             :         }
    1159             : 
    1160          10 :         if (nRowStart < 0)
    1161           1 :             nRowStart = rInner;
    1162             :     }
    1163             : 
    1164           1 :     if (nRowStart >= 0)
    1165             :     {
    1166           1 :         nRowEnd = rInner - 1;
    1167           1 :         aSpans.push_back(sc::RowSpan(nRowStart, nRowEnd));
    1168             :     }
    1169             : 
    1170           1 :     if (aSpans.empty())
    1171           1 :         return;
    1172             : 
    1173           1 :     aCol[nCol].DeleteRanges(aSpans, IDF_VALUE | IDF_DATETIME | IDF_STRING | IDF_FORMULA | IDF_OUTLINE, false);
    1174           1 :     aCol[nCol].CloneFormulaCell(rSrcCell, sc::CellTextAttr(), aSpans, NULL);
    1175             : 
    1176           2 :     boost::shared_ptr<sc::ColumnBlockPositionSet> pSet(new sc::ColumnBlockPositionSet(*pDocument));
    1177           2 :     sc::StartListeningContext aStartCxt(*pDocument, pSet);
    1178           2 :     sc::EndListeningContext aEndCxt(*pDocument, pSet);
    1179             : 
    1180           1 :     SCROW nStartRow = aSpans.front().mnRow1;
    1181           1 :     SCROW nEndRow = aSpans.back().mnRow2;
    1182           1 :     aCol[nCol].EndListeningFormulaCells(aEndCxt, nStartRow, nEndRow, &nStartRow, &nEndRow);
    1183           1 :     aCol[nCol].StartListeningFormulaCells(aStartCxt, aEndCxt, nStartRow, nEndRow);
    1184             : 
    1185           1 :     std::vector<sc::RowSpan>::const_iterator it = aSpans.begin(), itEnd = aSpans.end();
    1186           2 :     for (; it != itEnd; ++it)
    1187           1 :         aCol[nCol].SetDirty(it->mnRow1, it->mnRow2, ScColumn::BROADCAST_NONE);
    1188             : 
    1189           1 :     rProgress += nRow2 - nRow1 + 1;
    1190           1 :     if (pProgress)
    1191           1 :         pProgress->SetStateOnPercent(rProgress);
    1192             : }
    1193             : 
    1194          38 : void ScTable::FillSeriesSimple(
    1195             :     ScCellValue& rSrcCell, SCCOLROW& rInner, SCCOLROW nIMin, SCCOLROW nIMax,
    1196             :     SCCOLROW& rCol, SCCOLROW& rRow, bool bVertical, ScProgress* pProgress, sal_uLong& rProgress )
    1197             : {
    1198          38 :     bool bHidden = false;
    1199          38 :     SCCOLROW nHiddenLast = -1;
    1200             : 
    1201          38 :     if (bVertical)
    1202             :     {
    1203          12 :         switch (rSrcCell.meType)
    1204             :         {
    1205             :             case CELLTYPE_FORMULA:
    1206             :             {
    1207             :                 FillFormulaVertical(
    1208           0 :                     *rSrcCell.mpFormula, rInner, rCol, nIMin, nIMax, pProgress, rProgress);
    1209             :             }
    1210           0 :             break;
    1211             :             default:
    1212             :             {
    1213          78 :                 for (rInner = nIMin; rInner <= nIMax; ++rInner)
    1214             :                 {
    1215          66 :                     if (rInner > nHiddenLast)
    1216          12 :                         bHidden = HiddenRowColumn(this, rInner, bVertical, nHiddenLast);
    1217             : 
    1218          66 :                     if (bHidden)
    1219             :                     {
    1220           0 :                         rInner = nHiddenLast;
    1221           0 :                         continue;
    1222             :                     }
    1223             : 
    1224          66 :                     ScAddress aDestPos(rCol, rRow, nTab);
    1225          66 :                     rSrcCell.commit(aCol[rCol], aDestPos.Row());
    1226             :                 }
    1227          12 :                 rProgress += nIMax - nIMin + 1;
    1228          12 :                 if (pProgress)
    1229          12 :                     pProgress->SetStateOnPercent(rProgress);
    1230             :             }
    1231             :         }
    1232             :     }
    1233             :     else
    1234             :     {
    1235          26 :         switch (rSrcCell.meType)
    1236             :         {
    1237             :             case CELLTYPE_FORMULA:
    1238             :             {
    1239           0 :                 for (rInner = nIMin; rInner <= nIMax; ++rInner)
    1240             :                 {
    1241           0 :                     if (rInner > nHiddenLast)
    1242           0 :                         bHidden = HiddenRowColumn(this, rInner, bVertical, nHiddenLast);
    1243             : 
    1244           0 :                     if (bHidden)
    1245           0 :                         continue;
    1246             : 
    1247           0 :                     FillFormula(rSrcCell.mpFormula, rCol, rRow, (rInner == nIMax));
    1248           0 :                     if (pProgress)
    1249           0 :                         pProgress->SetStateOnPercent(++rProgress);
    1250             :                 }
    1251             :             }
    1252           0 :             break;
    1253             :             default:
    1254             :             {
    1255         106 :                 for (rInner = nIMin; rInner <= nIMax; ++rInner)
    1256             :                 {
    1257          80 :                     if (rInner > nHiddenLast)
    1258          26 :                         bHidden = HiddenRowColumn(this, rInner, bVertical, nHiddenLast);
    1259             : 
    1260          80 :                     if (bHidden)
    1261           0 :                         continue;
    1262             : 
    1263          80 :                     ScAddress aDestPos(rCol, rRow, nTab);
    1264          80 :                     rSrcCell.commit(aCol[rCol], aDestPos.Row());
    1265             :                 }
    1266          26 :                 rProgress += nIMax - nIMin + 1;
    1267          26 :                 if (pProgress)
    1268          26 :                     pProgress->SetStateOnPercent(rProgress);
    1269             :             }
    1270             :         }
    1271             :     }
    1272          38 : }
    1273             : 
    1274          14 : void ScTable::FillAutoSimple(
    1275             :     SCCOLROW nISrcStart, SCCOLROW nISrcEnd, SCCOLROW nIStart, SCCOLROW nIEnd,
    1276             :     SCCOLROW& rInner, SCCOLROW& rCol, SCCOLROW& rRow, sal_uLong nActFormCnt,
    1277             :     sal_uLong nMaxFormCnt, bool bHasFiltered, bool bVertical, bool bPositive,
    1278             :     ScProgress* pProgress, sal_uLong& rProgress )
    1279             : {
    1280          14 :     SCCOLROW nSource = nISrcStart;
    1281             :     double nDelta;
    1282          14 :     if ( (nScFillModeMouseModifier & KEY_MOD1) )
    1283           0 :         nDelta = 0.0;
    1284          14 :     else if ( bPositive )
    1285          13 :         nDelta = 1.0;
    1286             :     else
    1287           1 :         nDelta = -1.0;
    1288          14 :     sal_uLong nFormulaCounter = nActFormCnt;
    1289          14 :     bool bGetCell = true;
    1290          14 :     sal_uInt16 nCellDigits = 0;
    1291          14 :     short nHeadNoneTail = 0;
    1292          14 :     sal_Int32 nStringValue = 0;
    1293          14 :     OUString aValue;
    1294          27 :     ScCellValue aSrcCell;
    1295          14 :     bool bIsOrdinalSuffix = false;
    1296             : 
    1297          14 :     bool bColHidden = false, bRowHidden = false;
    1298          14 :     SCCOL nColHiddenLast = -1;
    1299          14 :     SCROW nRowHiddenLast = -1;
    1300             : 
    1301          14 :     rInner = nIStart;
    1302             :     while (true)        // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
    1303             :     {
    1304          50 :         if (rCol > nColHiddenLast)
    1305          14 :             bColHidden = ColHidden(rCol, NULL, &nColHiddenLast);
    1306          50 :         if (rRow > nRowHiddenLast)
    1307          14 :             bRowHidden = RowHidden(rRow, NULL, &nRowHiddenLast);
    1308             : 
    1309          50 :         if (!bColHidden && !bRowHidden)
    1310             :         {
    1311          50 :             if ( bGetCell )
    1312             :             {
    1313          20 :                 if (bVertical)      // rInner&:=nRow, rOuter&:=nCol
    1314             :                 {
    1315          15 :                     aSrcCell = aCol[rCol].GetCellValue(nSource);
    1316          15 :                     if (nISrcStart == nISrcEnd && aSrcCell.meType == CELLTYPE_FORMULA)
    1317             :                     {
    1318           1 :                         FillFormulaVertical(*aSrcCell.mpFormula, rInner, rCol, nIStart, nIEnd, pProgress, rProgress);
    1319          15 :                         return;
    1320             :                     }
    1321             :                 }
    1322             :                 else                // rInner&:=nCol, rOuter&:=nRow
    1323           5 :                     aSrcCell = aCol[nSource].GetCellValue(rRow);
    1324             : 
    1325          19 :                 bGetCell = false;
    1326          19 :                 if (!aSrcCell.isEmpty())
    1327             :                 {
    1328          19 :                     switch (aSrcCell.meType)
    1329             :                     {
    1330             :                         case CELLTYPE_STRING:
    1331             :                         case CELLTYPE_EDIT:
    1332           2 :                             if (aSrcCell.meType == CELLTYPE_STRING)
    1333           2 :                                 aValue = aSrcCell.mpString->getString();
    1334             :                             else
    1335           0 :                                 aValue = ScEditUtil::GetString(*aSrcCell.mpEditText, pDocument);
    1336           2 :                             if ( !(nScFillModeMouseModifier & KEY_MOD1) && !bHasFiltered )
    1337             :                             {
    1338           2 :                                 nCellDigits = 0;    // look at each source cell individually
    1339             :                                 nHeadNoneTail = lcl_DecompValueString(
    1340           2 :                                         aValue, nStringValue, &nCellDigits );
    1341             : 
    1342             :                                 bIsOrdinalSuffix = aValue.equals(
    1343           2 :                                         ScGlobal::GetOrdinalSuffix( nStringValue));
    1344             :                             }
    1345           2 :                             break;
    1346             :                         default:
    1347             :                             {
    1348             :                                 // added to avoid warnings
    1349             :                             }
    1350             :                     }
    1351             :                 }
    1352             :             }
    1353             : 
    1354          49 :             switch (aSrcCell.meType)
    1355             :             {
    1356             :                 case CELLTYPE_VALUE:
    1357          41 :                     aCol[rCol].SetValue(rRow, aSrcCell.mfValue + nDelta);
    1358          41 :                     break;
    1359             :                 case CELLTYPE_STRING:
    1360             :                 case CELLTYPE_EDIT:
    1361           2 :                     if ( nHeadNoneTail )
    1362             :                     {
    1363             :                         // #i48009# with the "nStringValue+(long)nDelta" expression within the
    1364             :                         // lcl_ValueString calls, gcc 3.4.1 makes wrong optimizations (ok in 3.4.3),
    1365             :                         // so nNextValue is now calculated ahead.
    1366           0 :                         sal_Int32 nNextValue = nStringValue+(sal_Int32)nDelta;
    1367             : 
    1368           0 :                         OUString aStr;
    1369           0 :                         if ( nHeadNoneTail < 0 )
    1370             :                         {
    1371             :                             setSuffixCell(
    1372           0 :                                 aCol[rCol], rRow,
    1373             :                                 nNextValue, nCellDigits, aValue,
    1374           0 :                                 aSrcCell.meType, bIsOrdinalSuffix);
    1375             :                         }
    1376             :                         else
    1377             :                         {
    1378           0 :                             aStr = aValue + lcl_ValueString( nNextValue, nCellDigits );
    1379           0 :                             aCol[rCol].SetRawString(rRow, aStr);
    1380           0 :                         }
    1381             :                     }
    1382             :                     else
    1383           2 :                         aSrcCell.commit(aCol[rCol], rRow);
    1384             : 
    1385           2 :                     break;
    1386             :                 case CELLTYPE_FORMULA :
    1387             :                     FillFormula(
    1388           6 :                         aSrcCell.mpFormula, rCol, rRow, (rInner == nIEnd));
    1389           6 :                     if (nFormulaCounter - nActFormCnt > nMaxFormCnt)
    1390           0 :                         nMaxFormCnt = nFormulaCounter - nActFormCnt;
    1391           6 :                     break;
    1392             :                 default:
    1393             :                     {
    1394             :                         // added to avoid warnings
    1395             :                     }
    1396             :             }
    1397             : 
    1398          49 :             if (nSource == nISrcEnd)
    1399             :             {
    1400          45 :                 if ( nSource != nISrcStart )
    1401             :                 {   // More than one source cell
    1402           4 :                     nSource = nISrcStart;
    1403           4 :                     bGetCell = true;
    1404             :                 }
    1405          45 :                 if ( !(nScFillModeMouseModifier & KEY_MOD1) )
    1406             :                 {
    1407          45 :                     if ( bPositive )
    1408          45 :                         nDelta += 1.0;
    1409             :                     else
    1410           0 :                         nDelta -= 1.0;
    1411             :                 }
    1412          45 :                 nFormulaCounter = nActFormCnt;
    1413             :             }
    1414           4 :             else if (bPositive)
    1415             :             {
    1416           4 :                 ++nSource;
    1417           4 :                 bGetCell = true;
    1418             :             }
    1419             :             else
    1420             :             {
    1421           0 :                 --nSource;
    1422           0 :                 bGetCell = true;
    1423             :             }
    1424             :         }
    1425             : 
    1426          49 :         if (rInner == nIEnd)
    1427          13 :             break;
    1428          36 :         if (bPositive)
    1429          36 :             ++rInner;
    1430             :         else
    1431           0 :             --rInner;
    1432             : 
    1433             :         //  Progress in inner loop only for expensive cells,
    1434             :         //  and even then not individually for each one
    1435             : 
    1436          36 :         ++rProgress;
    1437          36 :         if ( pProgress && (aSrcCell.meType == CELLTYPE_FORMULA || aSrcCell.meType == CELLTYPE_EDIT) )
    1438           2 :             pProgress->SetStateOnPercent( rProgress );
    1439             : 
    1440             :     }
    1441          13 :     if (pProgress)
    1442          24 :         pProgress->SetStateOnPercent( rProgress );
    1443             : }
    1444             : 
    1445          16 : void ScTable::FillSeries( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
    1446             :                     sal_uLong nFillCount, FillDir eFillDir, FillCmd eFillCmd, FillDateCmd eFillDateCmd,
    1447             :                     double nStepValue, double nMaxValue, sal_uInt16 nArgMinDigits,
    1448             :                     bool bAttribs, ScProgress* pProgress )
    1449             : {
    1450             :     // The term 'inner' here refers to the loop in the filling direction i.e.
    1451             :     // when filling vertically, the inner position is the row position whereas
    1452             :     // when filling horizontally the column position becomes the inner
    1453             :     // position. The term 'outer' refers to the column position when filling
    1454             :     // vertically, or the row position when filling horizontally. The fill is
    1455             :     // performed once in each 'outer' position e.g. when filling vertically,
    1456             :     // we perform the fill once in each column.
    1457             : 
    1458             :     //  Detect direction
    1459             : 
    1460          16 :     bool bVertical = (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_TOP);
    1461          16 :     bool bPositive = (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_RIGHT);
    1462             : 
    1463          16 :     SCCOLROW nCol = 0;
    1464          16 :     SCCOLROW nRow = 0;
    1465          16 :     SCCOLROW& rInner = bVertical ? nRow : nCol;        // loop variables
    1466          16 :     SCCOLROW& rOuter = bVertical ? nCol : nRow;
    1467             :     SCCOLROW nOStart;
    1468             :     SCCOLROW nOEnd;
    1469             :     SCCOLROW nIStart;
    1470             :     SCCOLROW nIEnd;
    1471             :     SCCOLROW nISource;
    1472          16 :     ScRange aFillRange;
    1473             : 
    1474          16 :     if (bVertical)
    1475             :     {
    1476           8 :         nFillCount += (nRow2 - nRow1);
    1477           8 :         if (nFillCount == 0)
    1478           0 :             return;
    1479           8 :         nOStart = nCol1;
    1480           8 :         nOEnd = nCol2;
    1481           8 :         if (bPositive)
    1482             :         {
    1483             :             // downward fill
    1484           6 :             nISource = nRow1; // top row of the source range.
    1485           6 :             nIStart = nRow1 + 1; // first row where we start filling.
    1486           6 :             nIEnd = nRow1 + nFillCount;
    1487           6 :             aFillRange = ScRange(nCol1, nRow1 + 1, nTab, nCol2, nRow1 + nFillCount, nTab);
    1488             :         }
    1489             :         else
    1490             :         {
    1491             :             // upward fill
    1492           2 :             nISource = nRow2;
    1493           2 :             nIStart = nRow2 - 1;
    1494           2 :             nIEnd = nRow2 - nFillCount;
    1495           2 :             aFillRange = ScRange(nCol1, nRow2 -1, nTab, nCol2, nRow2 - nFillCount, nTab);
    1496             :         }
    1497             :     }
    1498             :     else
    1499             :     {
    1500           8 :         nFillCount += (nCol2 - nCol1);
    1501           8 :         if (nFillCount == 0)
    1502           0 :             return;
    1503           8 :         nOStart = nRow1;
    1504           8 :         nOEnd = nRow2;
    1505           8 :         if (bPositive)
    1506             :         {
    1507             :             // to the right
    1508           6 :             nISource = nCol1;
    1509           6 :             nIStart = nCol1 + 1;
    1510           6 :             nIEnd = nCol1 + nFillCount;
    1511           6 :             aFillRange = ScRange(nCol1 + 1, nRow1, nTab, nCol1 + nFillCount, nRow2, nTab);
    1512             :         }
    1513             :         else
    1514             :         {
    1515             :             // to the left
    1516           2 :             nISource = nCol2;
    1517           2 :             nIStart = nCol2 - 1;
    1518           2 :             nIEnd = nCol2 - nFillCount;
    1519           2 :             aFillRange = ScRange(nCol2 - 1, nRow1, nTab, nCol2 - nFillCount, nRow2, nTab);
    1520             :         }
    1521             :     }
    1522             : 
    1523          16 :     SCCOLROW nIMin = nIStart;
    1524          16 :     SCCOLROW nIMax = nIEnd;
    1525          16 :     PutInOrder(nIMin,nIMax);
    1526          16 :     InsertDeleteFlags nDel = bAttribs ? IDF_AUTOFILL : (IDF_AUTOFILL & IDF_CONTENTS);
    1527             : 
    1528          16 :     bool bIsFiltered = IsDataFiltered(aFillRange);
    1529          16 :     if (!bIsFiltered)
    1530             :     {
    1531          14 :         if (bVertical)
    1532           7 :             DeleteArea(nCol1, static_cast<SCROW>(nIMin), nCol2, static_cast<SCROW>(nIMax), nDel);
    1533             :         else
    1534           7 :             DeleteArea(static_cast<SCCOL>(nIMin), nRow1, static_cast<SCCOL>(nIMax), nRow2, nDel);
    1535             :     }
    1536             : 
    1537          16 :     sal_uLong nProgress = 0;
    1538          16 :     if (pProgress)
    1539          13 :         nProgress = pProgress->GetState();
    1540             : 
    1541             :     // Perform the fill once per each 'outer' position i.e. one per column
    1542             :     // when filling vertically.
    1543             : 
    1544          16 :     sal_uLong nActFormCnt = 0;
    1545          88 :     for (rOuter = nOStart; rOuter <= nOEnd; rOuter++)
    1546             :     {
    1547          72 :         rInner = nISource;
    1548             : 
    1549             :         // Source cell value. We need to clone the value since it may be inserted repeatedly.
    1550          72 :         ScCellValue aSrcCell = aCol[nCol].GetCellValue(static_cast<SCROW>(nRow));
    1551             : 
    1552          72 :         if (bAttribs)
    1553             :         {
    1554          72 :             const ScPatternAttr* pSrcPattern = aCol[nCol].GetPattern(static_cast<SCROW>(nRow));
    1555             : 
    1556          72 :             const ScCondFormatItem& rCondFormatItem = static_cast<const ScCondFormatItem&>(pSrcPattern->GetItem(ATTR_CONDITIONAL));
    1557          72 :             const std::vector<sal_uInt32>& rCondFormatIndex = rCondFormatItem.GetCondFormatData();
    1558             : 
    1559          72 :             if (bVertical)
    1560             :             {
    1561             :                 // if not filtered use the faster method
    1562             :                 // hidden cols/rows should be skipped
    1563          26 :                 if(!bIsFiltered)
    1564             :                 {
    1565          25 :                     aCol[nCol].SetPatternArea( static_cast<SCROW>(nIMin),
    1566          50 :                             static_cast<SCROW>(nIMax), *pSrcPattern, true );
    1567             : 
    1568          25 :                     for(std::vector<sal_uInt32>::const_iterator itr = rCondFormatIndex.begin(), itrEnd = rCondFormatIndex.end();
    1569             :                             itr != itrEnd; ++itr)
    1570             :                     {
    1571           0 :                         ScConditionalFormat* pCondFormat = mpCondFormatList->GetFormat(*itr);
    1572           0 :                         ScRangeList aRange = pCondFormat->GetRange();
    1573           0 :                         aRange.Join(ScRange(nCol, nIMin, nTab, nCol, nIMax, nTab));
    1574           0 :                         pCondFormat->SetRange(aRange);
    1575           0 :                     }
    1576             :                 }
    1577             :                 else
    1578             :                 {
    1579           9 :                     for(SCROW nAtRow = static_cast<SCROW>(nIMin); nAtRow <= static_cast<SCROW>(nIMax); ++nAtRow)
    1580             :                     {
    1581           8 :                         if(!RowHidden(nAtRow))
    1582             :                         {
    1583           6 :                             aCol[nCol].SetPatternArea( static_cast<SCROW>(nAtRow),
    1584           6 :                                     static_cast<SCROW>(nAtRow), *pSrcPattern, true);
    1585           6 :                             for(std::vector<sal_uInt32>::const_iterator itr = rCondFormatIndex.begin(), itrEnd = rCondFormatIndex.end();
    1586             :                                     itr != itrEnd; ++itr)
    1587             :                             {
    1588           0 :                                 ScConditionalFormat* pCondFormat = mpCondFormatList->GetFormat(*itr);
    1589           0 :                                 ScRangeList aRange = pCondFormat->GetRange();
    1590           0 :                                 aRange.Join(ScRange(nCol, nAtRow, nTab, nCol, nAtRow, nTab));
    1591           0 :                                 pCondFormat->SetRange(aRange);
    1592           0 :                             }
    1593             :                         }
    1594             :                     }
    1595             : 
    1596             :                 }
    1597             :             }
    1598             :             else
    1599         203 :                 for (SCCOL nAtCol = static_cast<SCCOL>(nIMin); nAtCol <= sal::static_int_cast<SCCOL>(nIMax); nAtCol++)
    1600         157 :                     if(!ColHidden(nAtCol))
    1601             :                     {
    1602         157 :                         aCol[nAtCol].SetPattern(static_cast<SCROW>(nRow), *pSrcPattern, true);
    1603         157 :                         for(std::vector<sal_uInt32>::const_iterator itr = rCondFormatIndex.begin(), itrEnd = rCondFormatIndex.end();
    1604             :                                 itr != itrEnd; ++itr)
    1605             :                         {
    1606           0 :                             ScConditionalFormat* pCondFormat = mpCondFormatList->GetFormat(*itr);
    1607           0 :                             ScRangeList aRange = pCondFormat->GetRange();
    1608           0 :                             aRange.Join(ScRange(nAtCol, static_cast<SCROW>(nRow), nTab, nAtCol, static_cast<SCROW>(nRow), nTab));
    1609           0 :                             pCondFormat->SetRange(aRange);
    1610           0 :                         }
    1611             :                     }
    1612             :         }
    1613             : 
    1614          72 :         if (!aSrcCell.isEmpty())
    1615             :         {
    1616          60 :             CellType eCellType = aSrcCell.meType;
    1617             : 
    1618          60 :             if (eFillCmd == FILL_SIMPLE)                // copy
    1619             :             {
    1620          38 :                 FillSeriesSimple(aSrcCell, rInner, nIMin, nIMax, nCol, nRow, bVertical, pProgress, nProgress);
    1621             :             }
    1622          22 :             else if (eCellType == CELLTYPE_VALUE || eCellType == CELLTYPE_FORMULA)
    1623             :             {
    1624             :                 double nStartVal;
    1625          22 :                 if (eCellType == CELLTYPE_VALUE)
    1626          21 :                     nStartVal = aSrcCell.mfValue;
    1627             :                 else
    1628           1 :                     nStartVal = aSrcCell.mpFormula->GetValue();
    1629          22 :                 double nVal = nStartVal;
    1630          22 :                 long nIndex = 0;
    1631             : 
    1632          22 :                 bool bError = false;
    1633          22 :                 bool bOverflow = false;
    1634             : 
    1635          22 :                 sal_uInt16 nDayOfMonth = 0;
    1636          22 :                 rInner = nIStart;
    1637             :                 while (true)        // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
    1638             :                 {
    1639          99 :                     if(!ColHidden(nCol) && !RowHidden(nRow))
    1640             :                     {
    1641          87 :                         if (!bError && !bOverflow)
    1642             :                         {
    1643          72 :                             switch (eFillCmd)
    1644             :                             {
    1645             :                                 case FILL_LINEAR:
    1646             :                                     {
    1647             :                                         //  use multiplication instead of repeated addition
    1648             :                                         //  to avoid accumulating rounding errors
    1649          58 :                                         nVal = nStartVal;
    1650          58 :                                         double nAdd = nStepValue;
    1651         116 :                                         if ( !SubTotal::SafeMult( nAdd, (double) ++nIndex ) ||
    1652          58 :                                                 !SubTotal::SafePlus( nVal, nAdd ) )
    1653           0 :                                             bError = true;
    1654             :                                     }
    1655          58 :                                     break;
    1656             :                                 case FILL_GROWTH:
    1657          14 :                                     if (!SubTotal::SafeMult(nVal, nStepValue))
    1658           0 :                                         bError = true;
    1659          14 :                                     break;
    1660             :                                 case FILL_DATE:
    1661           0 :                                     if (fabs(nVal) > _D_MAX_LONG_)
    1662           0 :                                         bError = true;
    1663             :                                     else
    1664           0 :                                         IncDate(nVal, nDayOfMonth, nStepValue, eFillDateCmd);
    1665           0 :                                     break;
    1666             :                                 default:
    1667             :                                     {
    1668             :                                         // added to avoid warnings
    1669             :                                     }
    1670             :                             }
    1671             : 
    1672          72 :                             if (nStepValue >= 0)
    1673             :                             {
    1674          72 :                                 if (nVal > nMaxValue)           // target value reached ?
    1675             :                                 {
    1676           9 :                                     nVal = nMaxValue;
    1677           9 :                                     bOverflow = true;
    1678             :                                 }
    1679             :                             }
    1680             :                             else
    1681             :                             {
    1682           0 :                                 if (nVal < nMaxValue)
    1683             :                                 {
    1684           0 :                                     nVal = nMaxValue;
    1685           0 :                                     bOverflow = true;
    1686             :                                 }
    1687             :                             }
    1688             :                         }
    1689             : 
    1690          87 :                         if (bError)
    1691           0 :                             aCol[nCol].SetError(static_cast<SCROW>(nRow), errNoValue);
    1692          87 :                         else if (bOverflow)
    1693          24 :                             aCol[nCol].SetError(static_cast<SCROW>(nRow), errIllegalFPOperation);
    1694             :                         else
    1695          63 :                             aCol[nCol].SetValue(static_cast<SCROW>(nRow), nVal);
    1696             :                     }
    1697             : 
    1698          99 :                     if (rInner == nIEnd)
    1699          22 :                         break;
    1700          77 :                     if (bPositive)
    1701             :                     {
    1702          77 :                         ++rInner;
    1703             :                     }
    1704             :                     else
    1705             :                     {
    1706           0 :                         --rInner;
    1707             :                     }
    1708             :                 }
    1709          22 :                 nProgress += nIMax - nIMin + 1;
    1710          22 :                 if(pProgress)
    1711          88 :                     pProgress->SetStateOnPercent( nProgress );
    1712             :             }
    1713           0 :             else if (eCellType == CELLTYPE_STRING || eCellType == CELLTYPE_EDIT)
    1714             :             {
    1715           0 :                 if ( nStepValue >= 0 )
    1716             :                 {
    1717           0 :                     if ( nMaxValue >= (double)LONG_MAX )
    1718           0 :                         nMaxValue = (double)LONG_MAX - 1;
    1719             :                 }
    1720             :                 else
    1721             :                 {
    1722           0 :                     if ( nMaxValue <= (double)LONG_MIN )
    1723           0 :                         nMaxValue = (double)LONG_MIN + 1;
    1724             :                 }
    1725           0 :                 OUString aValue;
    1726           0 :                 if (eCellType == CELLTYPE_STRING)
    1727           0 :                     aValue = aSrcCell.mpString->getString();
    1728             :                 else
    1729           0 :                     aValue = ScEditUtil::GetString(*aSrcCell.mpEditText, pDocument);
    1730             :                 sal_Int32 nStringValue;
    1731           0 :                 sal_uInt16 nMinDigits = nArgMinDigits;
    1732           0 :                 short nHeadNoneTail = lcl_DecompValueString( aValue, nStringValue, &nMinDigits );
    1733           0 :                 if ( nHeadNoneTail )
    1734             :                 {
    1735           0 :                     double nStartVal = (double)nStringValue;
    1736           0 :                     double nVal = nStartVal;
    1737           0 :                     long nIndex = 0;
    1738           0 :                     bool bError = false;
    1739           0 :                     bool bOverflow = false;
    1740             : 
    1741             :                     bool bIsOrdinalSuffix = aValue.equals( ScGlobal::GetOrdinalSuffix(
    1742           0 :                                 (sal_Int32)nStartVal));
    1743             : 
    1744           0 :                     rInner = nIStart;
    1745             :                     while (true)        // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
    1746             :                     {
    1747           0 :                         if(!ColHidden(nCol) && !RowHidden(nRow))
    1748             :                         {
    1749           0 :                             if (!bError && !bOverflow)
    1750             :                             {
    1751           0 :                                 switch (eFillCmd)
    1752             :                                 {
    1753             :                                     case FILL_LINEAR:
    1754             :                                         {
    1755             :                                             //  use multiplication instead of repeated addition
    1756             :                                             //  to avoid accumulating rounding errors
    1757           0 :                                             nVal = nStartVal;
    1758           0 :                                             double nAdd = nStepValue;
    1759           0 :                                             if ( !SubTotal::SafeMult( nAdd, (double) ++nIndex ) ||
    1760           0 :                                                     !SubTotal::SafePlus( nVal, nAdd ) )
    1761           0 :                                                 bError = true;
    1762             :                                         }
    1763           0 :                                         break;
    1764             :                                     case FILL_GROWTH:
    1765           0 :                                         if (!SubTotal::SafeMult(nVal, nStepValue))
    1766           0 :                                             bError = true;
    1767           0 :                                         break;
    1768             :                                     default:
    1769             :                                         {
    1770             :                                             // added to avoid warnings
    1771             :                                         }
    1772             :                                 }
    1773             : 
    1774           0 :                                 if (nStepValue >= 0)
    1775             :                                 {
    1776           0 :                                     if (nVal > nMaxValue)           // target value reached ?
    1777             :                                     {
    1778           0 :                                         nVal = nMaxValue;
    1779           0 :                                         bOverflow = true;
    1780             :                                     }
    1781             :                                 }
    1782             :                                 else
    1783             :                                 {
    1784           0 :                                     if (nVal < nMaxValue)
    1785             :                                     {
    1786           0 :                                         nVal = nMaxValue;
    1787           0 :                                         bOverflow = true;
    1788             :                                     }
    1789             :                                 }
    1790             :                             }
    1791             : 
    1792           0 :                             if (bError)
    1793           0 :                                 aCol[nCol].SetError(static_cast<SCROW>(nRow), errNoValue);
    1794           0 :                             else if (bOverflow)
    1795           0 :                                 aCol[nCol].SetError(static_cast<SCROW>(nRow), errIllegalFPOperation);
    1796             :                             else
    1797             :                             {
    1798           0 :                                 nStringValue = (sal_Int32)nVal;
    1799           0 :                                 OUString aStr;
    1800           0 :                                 if ( nHeadNoneTail < 0 )
    1801             :                                 {
    1802             :                                     setSuffixCell(
    1803           0 :                                         aCol[nCol], static_cast<SCROW>(nRow),
    1804             :                                         nStringValue, nMinDigits, aValue,
    1805           0 :                                         eCellType, bIsOrdinalSuffix);
    1806             :                                 }
    1807             :                                 else
    1808             :                                 {
    1809           0 :                                     aStr = aValue;
    1810           0 :                                     aStr += lcl_ValueString( nStringValue, nMinDigits );
    1811           0 :                                     aCol[nCol].SetRawString(static_cast<SCROW>(nRow), aStr);
    1812           0 :                                 }
    1813             :                             }
    1814             :                         }
    1815             : 
    1816           0 :                         if (rInner == nIEnd) break;
    1817           0 :                         if (bPositive) ++rInner; else --rInner;
    1818           0 :                     }
    1819             :                 }
    1820           0 :                 if(pProgress)
    1821             :                 {
    1822           0 :                     nProgress += nIMax - nIMin + 1;
    1823           0 :                     pProgress->SetStateOnPercent( nProgress );
    1824           0 :                 }
    1825             :             }
    1826             :         }
    1827          12 :         else if(pProgress)
    1828             :         {
    1829          12 :             nProgress += nIMax - nIMin + 1;
    1830          12 :             pProgress->SetStateOnPercent( nProgress );
    1831             :         }
    1832          72 :         ++nActFormCnt;
    1833          72 :     }
    1834             : }
    1835             : 
    1836          24 : void ScTable::Fill( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
    1837             :                     sal_uLong nFillCount, FillDir eFillDir, FillCmd eFillCmd, FillDateCmd eFillDateCmd,
    1838             :                     double nStepValue, double nMaxValue, ScProgress* pProgress)
    1839             : {
    1840          24 :     if (eFillCmd == FILL_AUTO)
    1841           8 :         FillAuto(nCol1, nRow1, nCol2, nRow2, nFillCount, eFillDir, pProgress);
    1842             :     else
    1843             :         FillSeries(nCol1, nRow1, nCol2, nRow2, nFillCount, eFillDir,
    1844          16 :                     eFillCmd, eFillDateCmd, nStepValue, nMaxValue, 0, true, pProgress);
    1845          24 : }
    1846             : 
    1847           0 : void ScTable::AutoFormatArea(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
    1848             :                                 const ScPatternAttr& rAttr, sal_uInt16 nFormatNo)
    1849             : {
    1850           0 :     ScAutoFormat& rFormat = *ScGlobal::GetOrCreateAutoFormat();
    1851           0 :     ScAutoFormatData* pData = rFormat.findByIndex(nFormatNo);
    1852           0 :     if (pData)
    1853             :     {
    1854           0 :         ApplyPatternArea(nStartCol, nStartRow, nEndCol, nEndRow, rAttr);
    1855             :     }
    1856           0 : }
    1857             : 
    1858           0 : void ScTable::AutoFormat( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
    1859             :                             sal_uInt16 nFormatNo )
    1860             : {
    1861           0 :     if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
    1862             :     {
    1863           0 :         ScAutoFormat& rFormat = *ScGlobal::GetOrCreateAutoFormat();
    1864           0 :         ScAutoFormatData* pData = rFormat.findByIndex(nFormatNo);
    1865           0 :         if (pData)
    1866             :         {
    1867             :             ScPatternAttr* pPatternAttrs[16];
    1868           0 :             for (sal_uInt8 i = 0; i < 16; ++i)
    1869             :             {
    1870           0 :                 pPatternAttrs[i] = new ScPatternAttr(pDocument->GetPool());
    1871           0 :                 pData->FillToItemSet(i, pPatternAttrs[i]->GetItemSet(), *pDocument);
    1872             :             }
    1873             : 
    1874           0 :             SCCOL nCol = nStartCol;
    1875           0 :             SCROW nRow = nStartRow;
    1876           0 :             sal_uInt16 nIndex = 0;
    1877             :             // Left top corner
    1878           0 :             AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
    1879             :             // Left column
    1880           0 :             if (pData->IsEqualData(4, 8))
    1881           0 :                 AutoFormatArea(nStartCol, nStartRow + 1, nStartCol, nEndRow - 1, *pPatternAttrs[4], nFormatNo);
    1882             :             else
    1883             :             {
    1884           0 :                 nIndex = 4;
    1885           0 :                 for (nRow = nStartRow + 1; nRow < nEndRow; nRow++)
    1886             :                 {
    1887           0 :                     AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
    1888           0 :                     if (nIndex == 4)
    1889           0 :                         nIndex = 8;
    1890             :                     else
    1891           0 :                         nIndex = 4;
    1892             :                 }
    1893             :             }
    1894             :             // Left bottom corner
    1895           0 :             nRow = nEndRow;
    1896           0 :             nIndex = 12;
    1897           0 :             AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
    1898             :             // Right top corner
    1899           0 :             nCol = nEndCol;
    1900           0 :             nRow = nStartRow;
    1901           0 :             nIndex = 3;
    1902           0 :             AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
    1903             :             // Right column
    1904           0 :             if (pData->IsEqualData(7, 11))
    1905           0 :                 AutoFormatArea(nEndCol, nStartRow + 1, nEndCol, nEndRow - 1, *pPatternAttrs[7], nFormatNo);
    1906             :             else
    1907             :             {
    1908           0 :                 nIndex = 7;
    1909           0 :                 for (nRow = nStartRow + 1; nRow < nEndRow; nRow++)
    1910             :                 {
    1911           0 :                     AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
    1912           0 :                     if (nIndex == 7)
    1913           0 :                         nIndex = 11;
    1914             :                     else
    1915           0 :                         nIndex = 7;
    1916             :                 }
    1917             :             }
    1918             :             // Right bottom corner
    1919           0 :             nRow = nEndRow;
    1920           0 :             nIndex = 15;
    1921           0 :             AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
    1922           0 :             nRow = nStartRow;
    1923           0 :             nIndex = 1;
    1924           0 :             for (nCol = nStartCol + 1; nCol < nEndCol; nCol++)
    1925             :             {
    1926           0 :                 AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
    1927           0 :                 if (nIndex == 1)
    1928           0 :                     nIndex = 2;
    1929             :                 else
    1930           0 :                     nIndex = 1;
    1931             :             }
    1932             :             // Bottom row
    1933           0 :             nRow = nEndRow;
    1934           0 :             nIndex = 13;
    1935           0 :             for (nCol = nStartCol + 1; nCol < nEndCol; nCol++)
    1936             :             {
    1937           0 :                 AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
    1938           0 :                 if (nIndex == 13)
    1939           0 :                     nIndex = 14;
    1940             :                 else
    1941           0 :                     nIndex = 13;
    1942             :             }
    1943             :             // Boddy
    1944           0 :             if ((pData->IsEqualData(5, 6)) && (pData->IsEqualData(9, 10)) && (pData->IsEqualData(5, 9)))
    1945           0 :                 AutoFormatArea(nStartCol + 1, nStartRow + 1, nEndCol-1, nEndRow - 1, *pPatternAttrs[5], nFormatNo);
    1946             :             else
    1947             :             {
    1948           0 :                 if ((pData->IsEqualData(5, 9)) && (pData->IsEqualData(6, 10)))
    1949             :                 {
    1950           0 :                     nIndex = 5;
    1951           0 :                     for (nCol = nStartCol + 1; nCol < nEndCol; nCol++)
    1952             :                     {
    1953           0 :                         AutoFormatArea(nCol, nStartRow + 1, nCol, nEndRow - 1, *pPatternAttrs[nIndex], nFormatNo);
    1954           0 :                         if (nIndex == 5)
    1955           0 :                             nIndex = 6;
    1956             :                         else
    1957           0 :                             nIndex = 5;
    1958             :                     }
    1959             :                 }
    1960             :                 else
    1961             :                 {
    1962           0 :                     nIndex = 5;
    1963           0 :                     for (nCol = nStartCol + 1; nCol < nEndCol; nCol++)
    1964             :                     {
    1965           0 :                         for (nRow = nStartRow + 1; nRow < nEndRow; nRow++)
    1966             :                         {
    1967           0 :                             AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
    1968           0 :                             if ((nIndex == 5) || (nIndex == 9))
    1969             :                             {
    1970           0 :                                 if (nIndex == 5)
    1971           0 :                                     nIndex = 9;
    1972             :                                 else
    1973           0 :                                     nIndex = 5;
    1974             :                             }
    1975             :                             else
    1976             :                             {
    1977           0 :                                 if (nIndex == 6)
    1978           0 :                                     nIndex = 10;
    1979             :                                 else
    1980           0 :                                     nIndex = 6;
    1981             :                             }
    1982             :                         } // for nRow
    1983           0 :                         if ((nIndex == 5) || (nIndex == 9))
    1984           0 :                             nIndex = 6;
    1985             :                         else
    1986           0 :                             nIndex = 5;
    1987             :                     } // for nCol
    1988             :                 } // if not equal Column
    1989             :             } // if not all equal
    1990             : 
    1991           0 :             for (sal_uInt8 j = 0; j < 16; ++j)
    1992           0 :                 delete pPatternAttrs[j];
    1993             :         } // if AutoFormatData != NULL
    1994             :     } // if ValidColRow
    1995           0 : }
    1996             : 
    1997           0 : void ScTable::GetAutoFormatAttr(SCCOL nCol, SCROW nRow, sal_uInt16 nIndex, ScAutoFormatData& rData)
    1998             : {
    1999           0 :     sal_uInt32 nFormatIndex = GetNumberFormat( nCol, nRow );
    2000           0 :     ScNumFormatAbbrev   aNumFormat( nFormatIndex, *pDocument->GetFormatTable() );
    2001           0 :     rData.GetFromItemSet( nIndex, GetPattern( nCol, nRow )->GetItemSet(), aNumFormat );
    2002           0 : }
    2003             : 
    2004             : #define LF_LEFT         1
    2005             : #define LF_TOP          2
    2006             : #define LF_RIGHT        4
    2007             : #define LF_BOTTOM       8
    2008             : #define LF_ALL          (LF_LEFT | LF_TOP | LF_RIGHT | LF_BOTTOM)
    2009             : 
    2010           0 : void ScTable::GetAutoFormatFrame(SCCOL nCol, SCROW nRow, sal_uInt16 nFlags, sal_uInt16 nIndex, ScAutoFormatData& rData)
    2011             : {
    2012           0 :     const SvxBoxItem* pTheBox = static_cast<const SvxBoxItem*>(GetAttr(nCol, nRow, ATTR_BORDER));
    2013           0 :     const SvxBoxItem* pLeftBox = static_cast<const SvxBoxItem*>(GetAttr(nCol - 1, nRow, ATTR_BORDER));
    2014           0 :     const SvxBoxItem* pTopBox = static_cast<const SvxBoxItem*>(GetAttr(nCol, nRow - 1, ATTR_BORDER));
    2015           0 :     const SvxBoxItem* pRightBox = static_cast<const SvxBoxItem*>(GetAttr(nCol + 1, nRow, ATTR_BORDER));
    2016           0 :     const SvxBoxItem* pBottomBox = static_cast<const SvxBoxItem*>(GetAttr(nCol, nRow + 1, ATTR_BORDER));
    2017             : 
    2018           0 :     SvxBoxItem aBox( ATTR_BORDER );
    2019           0 :     if (nFlags & LF_LEFT)
    2020             :     {
    2021           0 :         if (pLeftBox)
    2022             :         {
    2023           0 :             if (ScHasPriority(pTheBox->GetLeft(), pLeftBox->GetRight()))
    2024           0 :                 aBox.SetLine(pTheBox->GetLeft(), SvxBoxItemLine::LEFT);
    2025             :             else
    2026           0 :                 aBox.SetLine(pLeftBox->GetRight(), SvxBoxItemLine::LEFT);
    2027             :         }
    2028             :         else
    2029           0 :             aBox.SetLine(pTheBox->GetLeft(), SvxBoxItemLine::LEFT);
    2030             :     }
    2031           0 :     if (nFlags & LF_TOP)
    2032             :     {
    2033           0 :         if (pTopBox)
    2034             :         {
    2035           0 :             if (ScHasPriority(pTheBox->GetTop(), pTopBox->GetBottom()))
    2036           0 :                 aBox.SetLine(pTheBox->GetTop(), SvxBoxItemLine::TOP);
    2037             :             else
    2038           0 :                 aBox.SetLine(pTopBox->GetBottom(), SvxBoxItemLine::TOP);
    2039             :         }
    2040             :         else
    2041           0 :             aBox.SetLine(pTheBox->GetTop(), SvxBoxItemLine::TOP);
    2042             :     }
    2043           0 :     if (nFlags & LF_RIGHT)
    2044             :     {
    2045           0 :         if (pRightBox)
    2046             :         {
    2047           0 :             if (ScHasPriority(pTheBox->GetRight(), pRightBox->GetLeft()))
    2048           0 :                 aBox.SetLine(pTheBox->GetRight(), SvxBoxItemLine::RIGHT);
    2049             :             else
    2050           0 :                 aBox.SetLine(pRightBox->GetLeft(), SvxBoxItemLine::RIGHT);
    2051             :         }
    2052             :         else
    2053           0 :             aBox.SetLine(pTheBox->GetRight(), SvxBoxItemLine::RIGHT);
    2054             :     }
    2055           0 :     if (nFlags & LF_BOTTOM)
    2056             :     {
    2057           0 :         if (pBottomBox)
    2058             :         {
    2059           0 :             if (ScHasPriority(pTheBox->GetBottom(), pBottomBox->GetTop()))
    2060           0 :                 aBox.SetLine(pTheBox->GetBottom(), SvxBoxItemLine::BOTTOM);
    2061             :             else
    2062           0 :                 aBox.SetLine(pBottomBox->GetTop(), SvxBoxItemLine::BOTTOM);
    2063             :         }
    2064             :         else
    2065           0 :             aBox.SetLine(pTheBox->GetBottom(), SvxBoxItemLine::BOTTOM);
    2066             :     }
    2067           0 :     rData.PutItem( nIndex, aBox );
    2068           0 : }
    2069             : 
    2070           0 : void ScTable::GetAutoFormatData(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, ScAutoFormatData& rData)
    2071             : {
    2072           0 :     if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
    2073             :     {
    2074           0 :         if ((nEndCol - nStartCol >= 3) && (nEndRow - nStartRow >= 3))
    2075             :         {
    2076             :             // Left top corner
    2077           0 :             GetAutoFormatAttr(nStartCol, nStartRow, 0, rData);
    2078           0 :             GetAutoFormatFrame(nStartCol, nStartRow, LF_ALL, 0, rData);
    2079             :             // Left column
    2080           0 :             GetAutoFormatAttr(nStartCol, nStartRow + 1, 4, rData);
    2081           0 :             GetAutoFormatAttr(nStartCol, nStartRow + 2, 8, rData);
    2082           0 :             GetAutoFormatFrame(nStartCol, nStartRow + 1, LF_LEFT | LF_RIGHT | LF_BOTTOM, 4, rData);
    2083           0 :             if (nEndRow - nStartRow >= 4)
    2084           0 :                 GetAutoFormatFrame(nStartCol, nStartRow + 2, LF_LEFT | LF_RIGHT | LF_BOTTOM, 8, rData);
    2085             :             else
    2086           0 :                 rData.CopyItem( 8, 4, ATTR_BORDER );
    2087             :             // Left bottom corner
    2088           0 :             GetAutoFormatAttr(nStartCol, nEndRow, 12, rData);
    2089           0 :             GetAutoFormatFrame(nStartCol, nEndRow, LF_ALL, 12, rData);
    2090             :             // Right top corner
    2091           0 :             GetAutoFormatAttr(nEndCol, nStartRow, 3, rData);
    2092           0 :             GetAutoFormatFrame(nEndCol, nStartRow, LF_ALL, 3, rData);
    2093             :             // Right column
    2094           0 :             GetAutoFormatAttr(nEndCol, nStartRow + 1, 7, rData);
    2095           0 :             GetAutoFormatAttr(nEndCol, nStartRow + 2, 11, rData);
    2096           0 :             GetAutoFormatFrame(nEndCol, nStartRow + 1, LF_LEFT | LF_RIGHT | LF_BOTTOM, 7, rData);
    2097           0 :             if (nEndRow - nStartRow >= 4)
    2098           0 :                 GetAutoFormatFrame(nEndCol, nStartRow + 2, LF_LEFT | LF_RIGHT | LF_BOTTOM, 11, rData);
    2099             :             else
    2100           0 :                 rData.CopyItem( 11, 7, ATTR_BORDER );
    2101             :             // Right bottom corner
    2102           0 :             GetAutoFormatAttr(nEndCol, nEndRow, 15, rData);
    2103           0 :             GetAutoFormatFrame(nEndCol, nEndRow, LF_ALL, 15, rData);
    2104             :             // Top row
    2105           0 :             GetAutoFormatAttr(nStartCol + 1, nStartRow, 1, rData);
    2106           0 :             GetAutoFormatAttr(nStartCol + 2, nStartRow, 2, rData);
    2107           0 :             GetAutoFormatFrame(nStartCol + 1, nStartRow, LF_TOP | LF_BOTTOM | LF_RIGHT, 1, rData);
    2108           0 :             if (nEndCol - nStartCol >= 4)
    2109           0 :                 GetAutoFormatFrame(nStartCol + 2, nStartRow, LF_TOP | LF_BOTTOM | LF_RIGHT, 2, rData);
    2110             :             else
    2111           0 :                 rData.CopyItem( 2, 1, ATTR_BORDER );
    2112             :             // Bottom row
    2113           0 :             GetAutoFormatAttr(nStartCol + 1, nEndRow, 13, rData);
    2114           0 :             GetAutoFormatAttr(nStartCol + 2, nEndRow, 14, rData);
    2115           0 :             GetAutoFormatFrame(nStartCol + 1, nEndRow, LF_TOP | LF_BOTTOM | LF_RIGHT, 13, rData);
    2116           0 :             if (nEndCol - nStartCol >= 4)
    2117           0 :                 GetAutoFormatFrame(nStartCol + 2, nEndRow, LF_TOP | LF_BOTTOM | LF_RIGHT, 14, rData);
    2118             :             else
    2119           0 :                 rData.CopyItem( 14, 13, ATTR_BORDER );
    2120             :             // Body
    2121           0 :             GetAutoFormatAttr(nStartCol + 1, nStartRow + 1, 5, rData);
    2122           0 :             GetAutoFormatAttr(nStartCol + 2, nStartRow + 1, 6, rData);
    2123           0 :             GetAutoFormatAttr(nStartCol + 1, nStartRow + 2, 9, rData);
    2124           0 :             GetAutoFormatAttr(nStartCol + 2, nStartRow + 2, 10, rData);
    2125           0 :             GetAutoFormatFrame(nStartCol + 1, nStartRow + 1, LF_RIGHT | LF_BOTTOM, 5, rData);
    2126           0 :             if ((nEndCol - nStartCol >= 4) && (nEndRow - nStartRow >= 4))
    2127             :             {
    2128           0 :                 GetAutoFormatFrame(nStartCol + 2, nStartRow + 1, LF_RIGHT | LF_BOTTOM, 6, rData);
    2129           0 :                 GetAutoFormatFrame(nStartCol + 1, nStartRow + 2, LF_RIGHT | LF_BOTTOM, 9, rData);
    2130           0 :                 GetAutoFormatFrame(nStartCol + 2, nStartRow + 2, LF_RIGHT | LF_BOTTOM, 10, rData);
    2131             :             }
    2132             :             else
    2133             :             {
    2134           0 :                 rData.CopyItem( 6, 5, ATTR_BORDER );
    2135           0 :                 rData.CopyItem( 9, 5, ATTR_BORDER );
    2136           0 :                 rData.CopyItem( 10, 5, ATTR_BORDER );
    2137             :             }
    2138             :         }
    2139             :     }
    2140           0 : }
    2141             : 
    2142           1 : void ScTable::SetError( SCCOL nCol, SCROW nRow, sal_uInt16 nError)
    2143             : {
    2144           1 :     if (ValidColRow(nCol, nRow))
    2145           1 :         aCol[nCol].SetError( nRow, nError );
    2146           1 : }
    2147             : 
    2148           7 : void ScTable::UpdateInsertTabAbs(SCTAB nTable)
    2149             : {
    2150        7175 :     for (SCCOL i=0; i <= MAXCOL; i++)
    2151        7168 :         aCol[i].UpdateInsertTabAbs(nTable);
    2152           7 : }
    2153             : 
    2154           0 : bool ScTable::GetNextSpellingCell(SCCOL& rCol, SCROW& rRow, bool bInSel,
    2155             :                                     const ScMarkData& rMark) const
    2156             : {
    2157           0 :     if (rRow == MAXROW+2)                       // end of table
    2158             :     {
    2159           0 :         rRow = 0;
    2160           0 :         rCol = 0;
    2161             :     }
    2162             :     else
    2163             :     {
    2164           0 :         rRow++;
    2165           0 :         if (rRow == MAXROW+1)
    2166             :         {
    2167           0 :             rCol++;
    2168           0 :             rRow = 0;
    2169             :         }
    2170             :     }
    2171           0 :     if (rCol == MAXCOL+1)
    2172           0 :         return true;
    2173             :     else
    2174             :     {
    2175           0 :         bool bStop = false;
    2176           0 :         while (!bStop)
    2177             :         {
    2178           0 :             if (ValidCol(rCol))
    2179             :             {
    2180           0 :                 bStop = aCol[rCol].GetNextSpellingCell(rRow, bInSel, rMark);
    2181           0 :                 if (bStop)
    2182           0 :                     return true;
    2183             :                 else /*if (rRow == MAXROW+1) */
    2184             :                 {
    2185           0 :                     rCol++;
    2186           0 :                     rRow = 0;
    2187             :                 }
    2188             :             }
    2189             :             else
    2190           0 :                 return true;
    2191             :         }
    2192             :     }
    2193           0 :     return false;
    2194             : }
    2195             : 
    2196          11 : bool ScTable::TestTabRefAbs(SCTAB nTable) const
    2197             : {
    2198        1066 :     for (SCCOL i=0; i <= MAXCOL; i++)
    2199        1065 :         if (aCol[i].TestTabRefAbs(nTable))
    2200          10 :             return true;
    2201           1 :     return false;
    2202             : }
    2203             : 
    2204           9 : void ScTable::CompileDBFormula( sc::CompileFormulaContext& rCxt )
    2205             : {
    2206        9225 :     for (SCCOL i = 0; i <= MAXCOL; ++i)
    2207        9216 :         aCol[i].CompileDBFormula(rCxt);
    2208           9 : }
    2209             : 
    2210           7 : void ScTable::CompileColRowNameFormula( sc::CompileFormulaContext& rCxt )
    2211             : {
    2212        7175 :     for (SCCOL i = 0; i <= MAXCOL; ++i)
    2213        7168 :         aCol[i].CompileColRowNameFormula(rCxt);
    2214           7 : }
    2215             : 
    2216           0 : SCSIZE ScTable::GetPatternCount( SCCOL nCol ) const
    2217             : {
    2218           0 :     if( ValidCol( nCol ) )
    2219           0 :         return aCol[nCol].GetPatternCount();
    2220             :     else
    2221           0 :         return 0;
    2222             : }
    2223             : 
    2224           0 : SCSIZE ScTable::GetPatternCount( SCCOL nCol, SCROW nRow1, SCROW nRow2 ) const
    2225             : {
    2226           0 :     if( ValidCol( nCol ) && ValidRow( nRow1 ) && ValidRow( nRow2 ) )
    2227           0 :         return aCol[nCol].GetPatternCount( nRow1, nRow2 );
    2228             :     else
    2229           0 :         return 0;
    2230             : }
    2231             : 
    2232           0 : bool ScTable::ReservePatternCount( SCCOL nCol, SCSIZE nReserve )
    2233             : {
    2234           0 :     if( ValidCol( nCol ) )
    2235           0 :         return aCol[nCol].ReservePatternCount( nReserve );
    2236             :     else
    2237           0 :         return false;
    2238         156 : }
    2239             : 
    2240             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11