xref: /AOO41X/main/sc/source/core/data/table4.cxx (revision 8f4c7c28c0e8f794fb1048a19304c40597e0d6b9)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sc.hxx"
26 
27 // System - Includes -----------------------------------------------------
28 
29 
30 
31 #ifdef _MSC_VER
32 #pragma optimize("",off)
33                                         // sonst Absturz Win beim Fuellen
34 #endif
35 
36 // INCLUDE ---------------------------------------------------------------
37 
38 #include "scitems.hxx"
39 #include <svx/algitem.hxx>
40 #include <editeng/boxitem.hxx>
41 #include <editeng/brshitem.hxx>
42 #include <editeng/cntritem.hxx>
43 #include <editeng/colritem.hxx>
44 #include <editeng/crsditem.hxx>
45 #include <editeng/fhgtitem.hxx>
46 #include <editeng/fontitem.hxx>
47 #include <editeng/langitem.hxx>
48 #include <editeng/postitem.hxx>
49 #include <editeng/shdditem.hxx>
50 #include <editeng/udlnitem.hxx>
51 #include <editeng/wghtitem.hxx>
52 #include <svx/rotmodit.hxx>
53 #include <editeng/editobj.hxx>
54 #include <editeng/editeng.hxx>
55 #include <editeng/eeitem.hxx>
56 #include <editeng/escpitem.hxx>
57 #include <svl/zforlist.hxx>
58 #include <vcl/keycodes.hxx>
59 #include <rtl/math.hxx>
60 #include <unotools/charclass.hxx>
61 
62 #include "attrib.hxx"
63 #include "patattr.hxx"
64 #include "cell.hxx"
65 #include "table.hxx"
66 #include "globstr.hrc"
67 #include "global.hxx"
68 #include "document.hxx"
69 #include "autoform.hxx"
70 #include "userlist.hxx"
71 #include "zforauto.hxx"
72 #include "subtotal.hxx"
73 #include "formula/errorcodes.hxx"
74 #include "rangenam.hxx"
75 #include "docpool.hxx"
76 #include "progress.hxx"
77 #include "segmenttree.hxx"
78 
79 #include <math.h>
80 
81 // STATIC DATA -----------------------------------------------------------
82 
83 #define _D_MAX_LONG_  (double) 0x7fffffff
84 
85 extern sal_uInt16 nScFillModeMouseModifier;     // global.cxx
86 
87 // -----------------------------------------------------------------------
88 
lcl_DecompValueString(String & aValue,sal_Int32 & nVal,sal_uInt16 * pMinDigits=NULL)89 short lcl_DecompValueString( String& aValue, sal_Int32& nVal, sal_uInt16* pMinDigits = NULL )
90 {
91     if ( !aValue.Len() )
92     {
93         nVal = 0;
94         return 0;
95     }
96     const sal_Unicode* p = aValue.GetBuffer();
97     xub_StrLen nNeg = 0;
98     xub_StrLen nNum = 0;
99     if ( p[nNum] == '-' )
100         nNum = nNeg = 1;
101     while ( p[nNum] && CharClass::isAsciiNumeric( p[nNum] ) )
102         nNum++;
103 
104     sal_Unicode cNext = p[nNum];            // 0 if at the end
105     sal_Unicode cLast = p[aValue.Len()-1];
106 
107     // #i5550# If there are numbers at the beginning and the end,
108     // prefer the one at the beginning only if it's followed by a space.
109     // Otherwise, use the number at the end, to enable things like IP addresses.
110     if ( nNum > nNeg && ( cNext == 0 || cNext == ' ' || !CharClass::isAsciiNumeric(cLast) ) )
111     {   // number at the beginning
112         nVal = aValue.Copy( 0, nNum ).ToInt32();
113         //  #60893# any number with a leading zero sets the minimum number of digits
114         if ( p[nNeg] == '0' && pMinDigits && ( nNum - nNeg > *pMinDigits ) )
115             *pMinDigits = nNum - nNeg;
116         aValue.Erase( 0, nNum );
117         return -1;
118     }
119     else
120     {
121         nNeg = 0;
122         xub_StrLen nEnd = nNum = aValue.Len() - 1;
123         while ( nNum && CharClass::isAsciiNumeric( p[nNum] ) )
124             nNum--;
125         if ( p[nNum] == '-' )
126         {
127             nNum--;
128             nNeg = 1;
129         }
130         if ( nNum < nEnd - nNeg )
131         {   // number at the end
132             nVal = aValue.Copy( nNum + 1 ).ToInt32();
133             //  #60893# any number with a leading zero sets the minimum number of digits
134             if ( p[nNum+1+nNeg] == '0' && pMinDigits && ( nEnd - nNum - nNeg > *pMinDigits ) )
135                 *pMinDigits = nEnd - nNum - nNeg;
136             aValue.Erase( nNum + 1 );
137             return 1;
138         }
139     }
140     nVal = 0;
141     return 0;
142 }
143 
lcl_ValueString(sal_Int32 nValue,sal_uInt16 nMinDigits)144 String lcl_ValueString( sal_Int32 nValue, sal_uInt16 nMinDigits )
145 {
146     if ( nMinDigits <= 1 )
147         return String::CreateFromInt32( nValue );           // simple case...
148     else
149     {
150         String aStr = String::CreateFromInt32( Abs( nValue ) );
151         if ( aStr.Len() < nMinDigits )
152         {
153             String aZero;
154             aZero.Fill( nMinDigits - aStr.Len(), '0' );
155             aStr.Insert( aZero, 0 );
156         }
157         //  nMinDigits doesn't include the '-' sign -> add after inserting zeros
158         if ( nValue < 0 )
159             aStr.Insert( '-', 0 );
160         return aStr;
161     }
162 }
163 
lcl_getSuffixCell(ScDocument * pDocument,sal_Int32 nValue,sal_uInt16 nDigits,const String & rSuffix,CellType eCellType,sal_Bool bIsOrdinalSuffix)164 static ScBaseCell * lcl_getSuffixCell( ScDocument* pDocument, sal_Int32 nValue,
165         sal_uInt16 nDigits, const String& rSuffix, CellType eCellType,
166         sal_Bool bIsOrdinalSuffix )
167 {
168     String aValue( lcl_ValueString( nValue, nDigits ));
169     if (!bIsOrdinalSuffix)
170         return new ScStringCell( aValue += rSuffix);
171 
172     String aOrdinalSuffix( ScGlobal::GetOrdinalSuffix( nValue));
173     if (eCellType != CELLTYPE_EDIT)
174         return new ScStringCell( aValue += aOrdinalSuffix);
175 
176     EditEngine aEngine( pDocument->GetEnginePool() );
177     SfxItemSet aAttr = aEngine.GetEmptyItemSet();
178     aAttr.Put( SvxEscapementItem( SVX_ESCAPEMENT_SUPERSCRIPT, EE_CHAR_ESCAPEMENT));
179     aEngine.SetText( aValue );
180     aEngine.QuickInsertText( aOrdinalSuffix, ESelection( 0, aValue.Len(), 0,
181                 aValue.Len() + aOrdinalSuffix.Len()));
182     aEngine.QuickSetAttribs( aAttr, ESelection( 0, aValue.Len(), 0, aValue.Len() +
183                 aOrdinalSuffix.Len()));
184     return new ScEditCell( aEngine.CreateTextObject(), pDocument, NULL );
185 }
186 
FillAnalyse(SCCOL nCol1,SCROW nRow1,SCCOL nCol2,SCROW nRow2,FillCmd & rCmd,FillDateCmd & rDateCmd,double & rInc,sal_uInt16 & rMinDigits,ScUserListData * & rListData,sal_uInt16 & rListIndex)187 void ScTable::FillAnalyse( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
188                             FillCmd& rCmd, FillDateCmd& rDateCmd,
189                             double& rInc, sal_uInt16& rMinDigits,
190                             ScUserListData*& rListData, sal_uInt16& rListIndex)
191 {
192     DBG_ASSERT( nCol1==nCol2 || nRow1==nRow2, "FillAnalyse: falscher Bereich" );
193 
194     rInc = 0.0;
195     rMinDigits = 0;
196     rListData = NULL;
197     rCmd = FILL_SIMPLE;
198     if (( nScFillModeMouseModifier & KEY_MOD1 )||IsDataFiltered())  //i89232
199         return ;        // Ctrl-Taste: Copy
200 
201     SCCOL nAddX;
202     SCROW nAddY;
203     SCSIZE nCount;
204     if (nCol1 == nCol2)
205     {
206         nAddX = 0;
207         nAddY = 1;
208         nCount = static_cast<SCSIZE>(nRow2 - nRow1 + 1);
209     }
210     else
211     {
212         nAddX = 1;
213         nAddY = 0;
214         nCount = static_cast<SCSIZE>(nCol2 - nCol1 + 1);
215     }
216 
217     SCCOL nCol = nCol1;
218     SCROW nRow = nRow1;
219 
220     ScBaseCell* pFirstCell = GetCell( nCol, nRow );
221     CellType eCellType = pFirstCell ? pFirstCell->GetCellType() : CELLTYPE_NONE;
222 
223     if (eCellType == CELLTYPE_VALUE)
224     {
225         sal_uInt32 nFormat = ((const SfxUInt32Item*)GetAttr(nCol,nRow,ATTR_VALUE_FORMAT))->GetValue();
226         sal_Bool bDate = ( pDocument->GetFormatTable()->GetType(nFormat) == NUMBERFORMAT_DATE );
227         if (bDate)
228         {
229             if (nCount > 1)
230             {
231                 long nCmpInc = 0;
232                 double nVal;
233                 Date aNullDate = *pDocument->GetFormatTable()->GetNullDate();
234                 Date aDate1 = aNullDate;
235                 nVal = ((ScValueCell*)pFirstCell)->GetValue();
236                 aDate1 += (long)nVal;
237                 Date aDate2 = aNullDate;
238                 nVal = GetValue(nCol+nAddX, nRow+nAddY);
239                 aDate2 += (long)nVal;
240                 if ( aDate1 != aDate2 )
241                 {
242                     FillDateCmd eType;
243                     long nDDiff = aDate2.GetDay()   - (long) aDate1.GetDay();
244                     long nMDiff = aDate2.GetMonth() - (long) aDate1.GetMonth();
245                     long nYDiff = aDate2.GetYear()  - (long) aDate1.GetYear();
246                     if ( nDDiff )
247                     {
248                         eType = FILL_DAY;
249                         nCmpInc = aDate2 - aDate1;
250                     }
251                     else
252                     {
253                         eType = FILL_MONTH;
254                         nCmpInc = nMDiff + 12 * nYDiff;
255                     }
256 
257                     nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
258                     nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
259                     sal_Bool bVal = sal_True;
260                     for (sal_uInt16 i=1; i<nCount && bVal; i++)
261                     {
262                         ScBaseCell* pCell = GetCell(nCol,nRow);
263                         if (pCell && pCell->GetCellType() == CELLTYPE_VALUE)
264                         {
265                             nVal = ((ScValueCell*)pCell)->GetValue();
266                             aDate2 = aNullDate + (long) nVal;
267                             if ( eType == FILL_DAY )
268                             {
269                                 if ( aDate2-aDate1 != nCmpInc )
270                                     bVal = sal_False;
271                             }
272                             else
273                             {
274                                 nDDiff = aDate2.GetDay()   - (long) aDate1.GetDay();
275                                 nMDiff = aDate2.GetMonth() - (long) aDate1.GetMonth();
276                                 nYDiff = aDate2.GetYear()  - (long) aDate1.GetYear();
277                                 if (nDDiff || ( nMDiff + 12 * nYDiff != nCmpInc ))
278                                     bVal = sal_False;
279                             }
280                             aDate1 = aDate2;
281                             nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
282                             nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
283                         }
284                         else
285                             bVal = sal_False;   // #50965# kein Datum passt auch nicht
286                     }
287                     if (bVal)
288                     {
289                         if ( eType == FILL_MONTH && ( nCmpInc % 12 == 0 ) )
290                         {
291                             eType = FILL_YEAR;
292                             nCmpInc /= 12;
293                         }
294                         rCmd = FILL_DATE;
295                         rDateCmd = eType;
296                         rInc = nCmpInc;
297                     }
298                 }
299             }
300             else                            // einzelnes Datum -> Tage hochzaehlen
301             {
302                 rCmd = FILL_DATE;
303                 rDateCmd = FILL_DAY;
304                 rInc = 1.0;
305             }
306         }
307         else
308         {
309             if (nCount > 1)
310             {
311                 double nVal1 = ((ScValueCell*)pFirstCell)->GetValue();
312                 double nVal2 = GetValue(nCol+nAddX, nRow+nAddY);
313                 rInc = nVal2 - nVal1;
314                 nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
315                 nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
316                 sal_Bool bVal = sal_True;
317                 for (sal_uInt16 i=1; i<nCount && bVal; i++)
318                 {
319                     ScBaseCell* pCell = GetCell(nCol,nRow);
320                     if (pCell && pCell->GetCellType() == CELLTYPE_VALUE)
321                     {
322                         nVal2 = ((ScValueCell*)pCell)->GetValue();
323                         double nDiff = nVal2 - nVal1;
324                         if ( !::rtl::math::approxEqual( nDiff, rInc ) )
325                             bVal = sal_False;
326                         nVal1 = nVal2;
327                     }
328                     else
329                         bVal = sal_False;
330                     nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
331                     nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
332                 }
333                 if (bVal)
334                     rCmd = FILL_LINEAR;
335             }
336         }
337     }
338     else if (eCellType == CELLTYPE_STRING || eCellType == CELLTYPE_EDIT)
339     {
340         String aStr;
341         GetString(nCol, nRow, aStr);
342         rListData = (ScUserListData*)(ScGlobal::GetUserList()->GetData(aStr));
343         if (rListData)
344         {
345             rListData->GetSubIndex(aStr, rListIndex);
346             nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
347             nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
348             for (sal_uInt16 i=1; i<nCount && rListData; i++)
349             {
350                 GetString(nCol, nRow, aStr);
351                 if (!rListData->GetSubIndex(aStr, rListIndex))
352                     rListData = NULL;
353                 nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
354                 nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
355             }
356         }
357         else if ( nCount > 1 )
358         {
359             //  pass rMinDigits to all DecompValueString calls
360             //  -> longest number defines rMinDigits
361 
362             sal_Int32 nVal1;
363             short nFlag1 = lcl_DecompValueString( aStr, nVal1, &rMinDigits );
364             if ( nFlag1 )
365             {
366                 sal_Int32 nVal2;
367                 GetString( nCol+nAddX, nRow+nAddY, aStr );
368                 short nFlag2 = lcl_DecompValueString( aStr, nVal2, &rMinDigits );
369                 if ( nFlag1 == nFlag2 )
370                 {
371                     rInc = (double)nVal2 - (double)nVal1;
372                     nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
373                     nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
374                     sal_Bool bVal = sal_True;
375                     for (sal_uInt16 i=1; i<nCount && bVal; i++)
376                     {
377                         ScBaseCell* pCell = GetCell(nCol,nRow);
378                         CellType eType = pCell ? pCell->GetCellType() : CELLTYPE_NONE;
379                         if ( eType == CELLTYPE_STRING || eType == CELLTYPE_EDIT )
380                         {
381                             if ( eType == CELLTYPE_STRING )
382                                 ((ScStringCell*)pCell)->GetString( aStr );
383                             else
384                                 ((ScEditCell*)pCell)->GetString( aStr );
385                             nFlag2 = lcl_DecompValueString( aStr, nVal2, &rMinDigits );
386                             if ( nFlag1 == nFlag2 )
387                             {
388                                 double nDiff = (double)nVal2 - (double)nVal1;
389                                 if ( !::rtl::math::approxEqual( nDiff, rInc ) )
390                                     bVal = sal_False;
391                                 nVal1 = nVal2;
392                             }
393                             else
394                                 bVal = sal_False;
395                         }
396                         else
397                             bVal = sal_False;
398                         nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
399                         nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
400                     }
401                     if (bVal)
402                         rCmd = FILL_LINEAR;
403                 }
404             }
405         }
406         else
407         {
408             //  call DecompValueString to set rMinDigits
409             sal_Int32 nDummy;
410             lcl_DecompValueString( aStr, nDummy, &rMinDigits );
411         }
412     }
413 }
414 
FillFormula(sal_uLong &,sal_Bool,ScFormulaCell * pSrcCell,SCCOL nDestCol,SCROW nDestRow,sal_Bool bLast)415 void ScTable::FillFormula(sal_uLong& /* nFormulaCounter */, sal_Bool /* bFirst */, ScFormulaCell* pSrcCell,
416                           SCCOL nDestCol, SCROW nDestRow, sal_Bool bLast )
417 {
418 /*  sal_uInt16 nTokArrLen = pSrcCell->GetTokenArrayLen();
419     if ( nTokArrLen > 15 )                          // mehr als =A1 oder =67
420     {
421         ScRangeName* pRangeName = pDocument->GetRangeName();
422         String aName("___SC_");                     // Wird dieser String veraendert,
423                                                     // auch in document2 EraseNonUsed...
424                                                     // mitaendern!!
425         aName += pRangeName->GetSharedMaxIndex() + 1;
426         aName += '_';
427         aName += nFormulaCounter;
428         nFormulaCounter++;
429         if (bFirst)
430         {
431             ScRangeData *pAktRange = new ScRangeData(
432                             pDocument, aName, pSrcCell->GetTokenArray(), nTokArrLen,
433                             pSrcCell->GetCol(), pSrcCell->GetRow(), nTab ,RT_SHARED);
434             if (!pRangeName->Insert( pAktRange ))
435                 delete pAktRange;
436             else
437                 bSharedNameInserted = sal_True;
438         }
439         sal_uInt16 nIndex;
440         pRangeName->SearchName(aName, nIndex);
441         if (!pRangeName)
442         {
443             DBG_ERROR("ScTable::FillFormula: Falscher Name");
444             return;
445         }
446         nIndex = ((ScRangeData*) ((*pRangeName)[nIndex]))->GetIndex();
447         ScTokenArray aArr;
448         aArr.AddName(nIndex);
449         aArr.AddOpCode(ocStop);
450         ScFormulaCell* pDestCell = new ScFormulaCell
451             (pDocument, ScAddress( nDestCol, nDestRow, nTab ), aArr );
452         aCol[nDestCol].Insert(nDestRow, pDestCell);
453     }
454     else
455 */  {
456         pDocument->SetNoListening( sal_True );  // noch falsche Referenzen
457         ScAddress aAddr( nDestCol, nDestRow, nTab );
458         ScFormulaCell* pDestCell = new ScFormulaCell( *pSrcCell, *pDocument, aAddr );
459         aCol[nDestCol].Insert(nDestRow, pDestCell);
460 #if 0
461 // mit RelRefs unnoetig
462         pDestCell->UpdateReference(URM_COPY,
463                          ScRange( aAddr, aAddr ),
464                          nDestCol - pSrcCell->aPos.Col(),
465                          nDestRow - pSrcCell->aPos.Row(), 0);
466 #endif
467         if ( bLast && pDestCell->GetMatrixFlag() )
468         {
469             ScAddress aOrg;
470             if ( pDestCell->GetMatrixOrigin( aOrg ) )
471             {
472                 if ( nDestCol >= aOrg.Col() && nDestRow >= aOrg.Row() )
473                 {
474                     ScBaseCell* pOrgCell = pDocument->GetCell( aOrg );
475                     if ( pOrgCell && pOrgCell->GetCellType() == CELLTYPE_FORMULA
476                       && ((ScFormulaCell*)pOrgCell)->GetMatrixFlag() == MM_FORMULA )
477                     {
478                         ((ScFormulaCell*)pOrgCell)->SetMatColsRows(
479                             nDestCol - aOrg.Col() + 1,
480                             nDestRow - aOrg.Row() + 1 );
481                     }
482                     else
483                     {
484                         DBG_ERRORFILE( "FillFormula: MatrixOrigin keine Formelzelle mit MM_FORMULA" );
485                     }
486                 }
487                 else
488                 {
489                     DBG_ERRORFILE( "FillFormula: MatrixOrigin rechts unten" );
490                 }
491             }
492             else
493             {
494                 DBG_ERRORFILE( "FillFormula: kein MatrixOrigin" );
495             }
496         }
497         pDocument->SetNoListening( sal_False );
498         pDestCell->StartListeningTo( pDocument );
499     }
500 }
501 
FillAuto(SCCOL nCol1,SCROW nRow1,SCCOL nCol2,SCROW nRow2,sal_uLong nFillCount,FillDir eFillDir,ScProgress & rProgress)502 void ScTable::FillAuto( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
503                         sal_uLong nFillCount, FillDir eFillDir, ScProgress& rProgress )
504 {
505     if ( (nFillCount == 0) || !ValidColRow(nCol1, nRow1) || !ValidColRow(nCol2, nRow2) )
506         return;
507 
508     //
509     //  Richtung auswerten
510     //
511 
512     sal_Bool bVertical = (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_TOP);
513     sal_Bool bPositive = (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_RIGHT);
514 
515     sal_uLong nCol = 0;
516     sal_uLong nRow = 0;
517     sal_uLong& rInner = bVertical ? nRow : nCol;        // Schleifenvariablen
518     sal_uLong& rOuter = bVertical ? nCol : nRow;
519     sal_uLong nOStart;
520     sal_uLong nOEnd;
521     sal_uLong nIStart;
522     sal_uLong nIEnd;
523     sal_uLong nISrcStart;
524     sal_uLong nISrcEnd;
525 
526     if (bVertical)
527     {
528         nOStart = nCol1;
529         nOEnd = nCol2;
530         if (bPositive)
531         {
532             nISrcStart = nRow1;
533             nISrcEnd = nRow2;
534             nIStart = nRow2 + 1;
535             nIEnd = nRow2 + nFillCount;
536         }
537         else
538         {
539             nISrcStart = nRow2;
540             nISrcEnd = nRow1;
541             nIStart = nRow1 - 1;
542             nIEnd = nRow1 - nFillCount;
543         }
544     }
545     else
546     {
547         nOStart = nRow1;
548         nOEnd = nRow2;
549         if (bPositive)
550         {
551             nISrcStart = nCol1;
552             nISrcEnd = nCol2;
553             nIStart = nCol2 + 1;
554             nIEnd = nCol2 + nFillCount;
555         }
556         else
557         {
558             nISrcStart = nCol2;
559             nISrcEnd = nCol1;
560             nIStart = nCol1 - 1;
561             nIEnd = nCol1 - nFillCount;
562         }
563     }
564     sal_uLong nIMin = nIStart;
565     sal_uLong nIMax = nIEnd;
566     PutInOrder(nIMin,nIMax);
567     sal_Bool bHasFiltered = IsDataFiltered();
568     if (!bHasFiltered)  //modify for i89232
569     {
570         if (bVertical)
571             DeleteArea(nCol1, static_cast<SCROW>(nIMin), nCol2, static_cast<SCROW>(nIMax), IDF_AUTOFILL);
572         else
573             DeleteArea(static_cast<SCCOL>(nIMin), nRow1, static_cast<SCCOL>(nIMax), nRow2, IDF_AUTOFILL);
574     }
575     sal_uLong nProgress = rProgress.GetState();
576 
577     //
578     //  ausfuehren
579     //
580 
581     sal_uLong nActFormCnt = 0;
582     for (rOuter = nOStart; rOuter <= nOEnd; rOuter++)
583     {
584         sal_uLong nMaxFormCnt = 0;                      // fuer Formeln
585 
586         //  Attributierung uebertragen
587 
588         const ScPatternAttr* pSrcPattern = NULL;
589         const ScStyleSheet* pStyleSheet = NULL;
590         sal_uLong nAtSrc = nISrcStart;
591         ScPatternAttr* pNewPattern = NULL;
592         sal_Bool bGetPattern = sal_True;
593         rInner = nIStart;
594         while (true)        // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
595         {
596             if ( bGetPattern )
597             {
598                 if ( pNewPattern )
599                     delete pNewPattern;
600                 if (bVertical)      // rInner&:=nRow, rOuter&:=nCol
601                     pSrcPattern = aCol[nCol].GetPattern(static_cast<SCROW>(nAtSrc));
602                 else                // rInner&:=nCol, rOuter&:=nRow
603                     pSrcPattern = aCol[nAtSrc].GetPattern(static_cast<SCROW>(nRow));
604                 bGetPattern = sal_False;
605                 pStyleSheet = pSrcPattern->GetStyleSheet();
606                 //  Merge/Mergeflag nicht uebernehmen,
607                 const SfxItemSet& rSet = pSrcPattern->GetItemSet();
608                 if ( rSet.GetItemState(ATTR_MERGE, sal_False) == SFX_ITEM_SET
609                   || rSet.GetItemState(ATTR_MERGE_FLAG, sal_False) == SFX_ITEM_SET )
610                 {
611                     pNewPattern = new ScPatternAttr( *pSrcPattern );
612                     SfxItemSet& rNewSet = pNewPattern->GetItemSet();
613                     rNewSet.ClearItem(ATTR_MERGE);
614                     rNewSet.ClearItem(ATTR_MERGE_FLAG);
615                 }
616                 else
617                     pNewPattern = NULL;
618             }
619 
620             if ( bVertical && nISrcStart == nISrcEnd && !bHasFiltered )
621             {
622                 //  Attribute komplett am Stueck setzen
623                 if (pNewPattern || pSrcPattern != pDocument->GetDefPattern())
624                 {
625                     //  Default steht schon da (DeleteArea)
626                     SCROW nY1 = static_cast<SCROW>(Min( nIStart, nIEnd ));
627                     SCROW nY2 = static_cast<SCROW>(Max( nIStart, nIEnd ));
628                     if ( pStyleSheet )
629                         aCol[nCol].ApplyStyleArea( nY1, nY2, *pStyleSheet );
630                     if ( pNewPattern )
631                         aCol[nCol].ApplyPatternArea( nY1, nY2, *pNewPattern );
632                     else
633                         aCol[nCol].ApplyPatternArea( nY1, nY2, *pSrcPattern );
634                 }
635                 break;      // Schleife abbrechen
636             }
637 
638             if ( !RowFiltered(nRow) )
639             {
640                 if ( bHasFiltered )
641                     DeleteArea(static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow),
642                                static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), IDF_AUTOFILL);
643 
644                 if ( pSrcPattern != aCol[nCol].GetPattern( static_cast<SCROW>(nRow) ) )
645                 {
646                     //  Vorlage auch uebernehmen
647                     //! am AttrArray mit ApplyPattern zusammenfassen ??
648                     if ( pStyleSheet )
649                         aCol[nCol].ApplyStyle( static_cast<SCROW>(nRow), *pStyleSheet );
650 
651                     //  ApplyPattern statt SetPattern um alte MergeFlags stehenzulassen
652                     if ( pNewPattern )
653                         aCol[nCol].ApplyPattern( static_cast<SCROW>(nRow), *pNewPattern );
654                     else
655                         aCol[nCol].ApplyPattern( static_cast<SCROW>(nRow), *pSrcPattern );
656                 }
657 
658                 if (nAtSrc==nISrcEnd)
659                 {
660                     if ( nAtSrc != nISrcStart )
661                     {   // mehr als eine Source-Zelle
662                         nAtSrc = nISrcStart;
663                         bGetPattern = sal_True;
664                     }
665                 }
666                 else if (bPositive)
667                 {
668                     ++nAtSrc;
669                     bGetPattern = sal_True;
670                 }
671                 else
672                 {
673                     --nAtSrc;
674                     bGetPattern = sal_True;
675                 }
676             }
677 
678             if (rInner == nIEnd) break;
679             if (bPositive) ++rInner; else --rInner;
680         }
681         if ( pNewPattern )
682             delete pNewPattern;
683 
684         //  Analyse
685 
686         FillCmd eFillCmd;
687         FillDateCmd eDateCmd;
688         double nInc;
689         sal_uInt16 nMinDigits;
690         ScUserListData* pListData = NULL;
691         sal_uInt16 nListIndex;
692         if (bVertical)
693             FillAnalyse(static_cast<SCCOL>(nCol),nRow1,
694                     static_cast<SCCOL>(nCol),nRow2, eFillCmd,eDateCmd,
695                     nInc,nMinDigits, pListData,nListIndex);
696         else
697             FillAnalyse(nCol1,static_cast<SCROW>(nRow),
698                     nCol2,static_cast<SCROW>(nRow), eFillCmd,eDateCmd,
699                     nInc,nMinDigits, pListData,nListIndex);
700 
701         if (bVertical)
702             aCol[nCol].Resize( aCol[nCol].GetCellCount() + nFillCount );
703 
704         if (pListData)
705         {
706             sal_uInt16 nListCount = pListData->GetSubCount();
707             if ( !bPositive )
708             {
709                 //  nListIndex auf FillAnalyse zeigt auf den letzten Eintrag -> anpassen
710                 sal_uLong nSub = nISrcStart - nISrcEnd;
711                 for (sal_uLong i=0; i<nSub; i++)
712                 {
713                     if (nListIndex == 0) nListIndex = nListCount;
714                     --nListIndex;
715                 }
716             }
717 
718             rInner = nIStart;
719             while (true)        // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
720             {
721                 if (bPositive)
722                 {
723                     ++nListIndex;
724                     if (nListIndex >= nListCount) nListIndex = 0;
725                 }
726                 else
727                 {
728                     if (nListIndex == 0) nListIndex = nListCount;
729                     --nListIndex;
730                 }
731                 aCol[nCol].Insert(static_cast<SCROW>(nRow), new ScStringCell(pListData->GetSubStr(nListIndex)));
732 
733                 if (rInner == nIEnd) break;
734                 if (bPositive) ++rInner; else --rInner;
735             }
736             nProgress += nIMax - nIMin + 1;
737             rProgress.SetStateOnPercent( nProgress );
738         }
739         else if (eFillCmd == FILL_SIMPLE)           // Auffuellen mit Muster
740         {
741             sal_uLong nSource = nISrcStart;
742             double nDelta;
743             if (( nScFillModeMouseModifier & KEY_MOD1 )||bHasFiltered) //i89232
744                 nDelta = 0.0;
745             else if ( bPositive )
746                 nDelta = 1.0;
747             else
748                 nDelta = -1.0;
749             double nVal = 0.0;
750             sal_uLong nFormulaCounter = nActFormCnt;
751             sal_Bool bFirst = sal_True;
752             sal_Bool bGetCell = sal_True;
753             sal_uInt16 nCellDigits = 0;
754             short nHeadNoneTail = 0;
755             sal_Int32 nStringValue = 0;
756             String aValue;
757             ScBaseCell* pSrcCell = NULL;
758             CellType eCellType = CELLTYPE_NONE;
759             sal_Bool bIsOrdinalSuffix = sal_False;
760             sal_Bool bRowFiltered = sal_False; //i89232
761 
762             rInner = nIStart;
763             while (true)        // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
764             {
765                 if ( bGetCell )
766                 {
767                     if (bVertical)      // rInner&:=nRow, rOuter&:=nCol
768                         pSrcCell = aCol[nCol].GetCell( static_cast<SCROW>(nSource) );
769                     else                // rInner&:=nCol, rOuter&:=nRow
770                         pSrcCell = aCol[nSource].GetCell( static_cast<SCROW>(nRow) );
771                     bGetCell = sal_False;
772                     if ( pSrcCell )
773                     {
774                         eCellType = pSrcCell->GetCellType();
775                         switch ( eCellType )
776                         {
777                             case CELLTYPE_VALUE:
778                                 nVal = ((ScValueCell*)pSrcCell)->GetValue();
779                             break;
780                             case CELLTYPE_STRING:
781                             case CELLTYPE_EDIT:
782                                 if ( eCellType == CELLTYPE_STRING )
783                                     ((ScStringCell*)pSrcCell)->GetString( aValue );
784                                 else
785                                     ((ScEditCell*)pSrcCell)->GetString( aValue );
786                                 if ( !(nScFillModeMouseModifier & KEY_MOD1) && !bHasFiltered)   //i89232
787                                 {
788                                     nCellDigits = 0;    // look at each source cell individually
789                                     nHeadNoneTail = lcl_DecompValueString(
790                                         aValue, nStringValue, &nCellDigits );
791 
792                                     bIsOrdinalSuffix = aValue.Equals(
793                                             ScGlobal::GetOrdinalSuffix( nStringValue));
794                                 }
795                             break;
796                             default:
797                             {
798                                 // added to avoid warnings
799                             }
800                         }
801                     }
802                     else
803                         eCellType = CELLTYPE_NONE;
804                 }
805 
806                 //Modify for i89232
807                 bRowFiltered = mpFilteredRows->getValue(nRow);
808 
809                 if (!bRowFiltered)
810                 {
811                 //End of i89232
812 
813                     switch (eCellType)
814                     {
815                         case CELLTYPE_VALUE:
816                             aCol[nCol].Insert(static_cast<SCROW>(nRow), new ScValueCell(nVal + nDelta));
817                             break;
818                         case CELLTYPE_STRING:
819                         case CELLTYPE_EDIT:
820                             if ( nHeadNoneTail )
821                             {
822                                 // #i48009# with the "nStringValue+(long)nDelta" expression within the
823                                 // lcl_ValueString calls, gcc 3.4.1 makes wrong optimizations (ok in 3.4.3),
824                                 // so nNextValue is now calculated ahead.
825                                 sal_Int32 nNextValue = nStringValue+(sal_Int32)nDelta;
826 
827                                 String aStr;
828                                 if ( nHeadNoneTail < 0 )
829                                 {
830                                     aCol[nCol].Insert( static_cast<SCROW>(nRow),
831                                             lcl_getSuffixCell( pDocument,
832                                                 nNextValue, nCellDigits, aValue,
833                                                 eCellType, bIsOrdinalSuffix));
834                                 }
835                                 else
836                                 {
837                                     aStr = aValue;
838                                     aStr += lcl_ValueString( nNextValue, nCellDigits );
839                                     aCol[nCol].Insert( static_cast<SCROW>(nRow),
840                                             new ScStringCell( aStr));
841                                 }
842                             }
843                             else
844                             {
845                                 ScAddress aDestPos( static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), nTab );
846                                 switch ( eCellType )
847                                 {
848                                     case CELLTYPE_STRING:
849                                     case CELLTYPE_EDIT:
850                                         aCol[nCol].Insert( aDestPos.Row(), pSrcCell->CloneWithoutNote( *pDocument ) );
851                                     break;
852                                     default:
853                                     {
854                                         // added to avoid warnings
855                                     }
856                                 }
857                             }
858                             break;
859                         case CELLTYPE_FORMULA :
860                             FillFormula( nFormulaCounter, bFirst,
861                                     (ScFormulaCell*) pSrcCell,
862                                     static_cast<SCCOL>(nCol),
863                                     static_cast<SCROW>(nRow), (rInner == nIEnd) );
864                             if (nFormulaCounter - nActFormCnt > nMaxFormCnt)
865                                 nMaxFormCnt = nFormulaCounter - nActFormCnt;
866                             break;
867                         default:
868                         {
869                             // added to avoid warnings
870                         }
871                     }
872 
873                     if (nSource==nISrcEnd)
874                     {
875                         if ( nSource != nISrcStart )
876                         {   // mehr als eine Source-Zelle
877                             nSource = nISrcStart;
878                             bGetCell = sal_True;
879                         }
880                         if ( !(nScFillModeMouseModifier & KEY_MOD1) && !bHasFiltered ) //i89232
881                         {
882                             if ( bPositive )
883                                 nDelta += 1.0;
884                             else
885                                 nDelta -= 1.0;
886                         }
887                         nFormulaCounter = nActFormCnt;
888                         bFirst = sal_False;
889                     }
890                     else if (bPositive)
891                     {
892                         ++nSource;
893                         bGetCell = sal_True;
894                     }
895                     else
896                     {
897                         --nSource;
898                         bGetCell = sal_True;
899                     }
900                 }
901 
902                 //  Progress in der inneren Schleife nur bei teuren Zellen,
903                 //  und auch dann nicht fuer jede einzelne
904 
905                 ++nProgress;
906                 if ( eCellType == CELLTYPE_FORMULA || eCellType == CELLTYPE_EDIT )
907                     rProgress.SetStateOnPercent( nProgress );
908 
909                 if (rInner == nIEnd) break;
910                 if (bPositive) ++rInner; else --rInner;
911             }
912             rProgress.SetStateOnPercent( nProgress );
913         }
914         else
915         {
916             if (!bPositive)
917                 nInc = -nInc;
918             double nEndVal = (nInc>=0.0) ? MAXDOUBLE : -MAXDOUBLE;
919             if (bVertical)
920                 FillSeries( static_cast<SCCOL>(nCol), nRow1,
921                         static_cast<SCCOL>(nCol), nRow2, nFillCount, eFillDir,
922                         eFillCmd, eDateCmd, nInc, nEndVal, nMinDigits, sal_False,
923                         rProgress );
924             else
925                 FillSeries( nCol1, static_cast<SCROW>(nRow), nCol2,
926                         static_cast<SCROW>(nRow), nFillCount, eFillDir,
927                         eFillCmd, eDateCmd, nInc, nEndVal, nMinDigits, sal_False,
928                         rProgress );
929             nProgress = rProgress.GetState();
930         }
931 
932         nActFormCnt += nMaxFormCnt;
933     }
934 }
935 
GetAutoFillPreview(const ScRange & rSource,SCCOL nEndX,SCROW nEndY)936 String ScTable::GetAutoFillPreview( const ScRange& rSource, SCCOL nEndX, SCROW nEndY )
937 {
938     String aValue;
939 
940     SCCOL nCol1 = rSource.aStart.Col();
941     SCROW nRow1 = rSource.aStart.Row();
942     SCCOL nCol2 = rSource.aEnd.Col();
943     SCROW nRow2 = rSource.aEnd.Row();
944     sal_Bool bOk = sal_True;
945     long nIndex = 0;
946     sal_uLong nSrcCount = 0;
947     FillDir eFillDir = FILL_TO_BOTTOM;
948     if ( nEndX == nCol2 && nEndY == nRow2 )     // leer
949         bOk = sal_False;
950     else if ( nEndX == nCol2 )                  // nach oben/unten
951     {
952         nEndX = nCol2 = nCol1;                  // nur erste Spalte ansehen
953         nSrcCount = nRow2 - nRow1 + 1;
954         nIndex = ((long)nEndY) - nRow1;         // kann negativ werden
955         if ( nEndY >= nRow1 )
956             eFillDir = FILL_TO_BOTTOM;
957         else
958             eFillDir = FILL_TO_TOP;
959     }
960     else if ( nEndY == nRow2 )                  // nach links/rechts
961     {
962         nEndY = nRow2 = nRow1;                  // nur erste Zeile ansehen
963         nSrcCount = nCol2 - nCol1 + 1;
964         nIndex = ((long)nEndX) - nCol1;         // kann negativ werden
965         if ( nEndX >= nCol1 )
966             eFillDir = FILL_TO_RIGHT;
967         else
968             eFillDir = FILL_TO_LEFT;
969     }
970     else                                        // Richtung nicht eindeutig
971         bOk = sal_False;
972 
973     if ( bOk )
974     {
975         FillCmd eFillCmd;
976         FillDateCmd eDateCmd;
977         double nInc;
978         sal_uInt16 nMinDigits;
979         ScUserListData* pListData = NULL;
980         sal_uInt16 nListIndex;
981 
982         FillAnalyse(nCol1,nRow1, nCol2,nRow2, eFillCmd,eDateCmd, nInc,nMinDigits, pListData,nListIndex);
983 
984         if ( pListData )                            // benutzerdefinierte Liste
985         {
986             sal_uInt16 nListCount = pListData->GetSubCount();
987             if ( nListCount )
988             {
989                 sal_uLong nSub = nSrcCount - 1; //  nListIndex ist vom letzten Source-Eintrag
990                 while ( nIndex < sal::static_int_cast<long>(nSub) )
991                     nIndex += nListCount;
992                 sal_uLong nPos = ( nListIndex + nIndex - nSub ) % nListCount;
993                 aValue = pListData->GetSubStr(sal::static_int_cast<sal_uInt16>(nPos));
994             }
995         }
996         else if ( eFillCmd == FILL_SIMPLE )         // Auffuellen mit Muster
997         {
998             //Add for i89232
999             if ((eFillDir == FILL_TO_BOTTOM)||(eFillDir == FILL_TO_TOP))
1000             {
1001                 long nBegin = 0;
1002                 long nEnd = 0;
1003                 if (nEndY > nRow1)
1004                 {
1005                     nBegin = nRow2+1;
1006                     nEnd = nEndY;
1007                 }
1008                 else
1009                 {
1010                     nBegin = nEndY;
1011                     nEnd = nRow1 -1;
1012                 }
1013                 long nNonFiltered = CountNonFilteredRows(nBegin, nEnd);
1014                 long nFiltered = nEnd + 1 - nBegin - nNonFiltered;
1015                 if (nIndex >0)
1016                     nIndex = nIndex - nFiltered;
1017                 else
1018                     nIndex = nIndex + nFiltered;
1019             }
1020             //End of i89232
1021 
1022             long nPosIndex = nIndex;
1023             while ( nPosIndex < 0 )
1024                 nPosIndex += nSrcCount;
1025             sal_uLong nPos = nPosIndex % nSrcCount;
1026             SCCOL nSrcX = nCol1;
1027             SCROW nSrcY = nRow1;
1028             if ( eFillDir == FILL_TO_TOP || eFillDir == FILL_TO_BOTTOM )
1029                 nSrcY = sal::static_int_cast<SCROW>( nSrcY + static_cast<SCROW>(nPos) );
1030             else
1031                 nSrcX = sal::static_int_cast<SCCOL>( nSrcX + static_cast<SCCOL>(nPos) );
1032 
1033             ScBaseCell* pCell = GetCell( nSrcX, nSrcY );
1034             if ( pCell )
1035             {
1036                 sal_Int32 nDelta;
1037                 if (nIndex >= 0)
1038                     nDelta = nIndex / nSrcCount;
1039                 else
1040                     nDelta = ( nIndex - nSrcCount + 1 ) / nSrcCount;    // -1 -> -1
1041 
1042                 CellType eType = pCell->GetCellType();
1043                 switch ( eType )
1044                 {
1045                     case CELLTYPE_STRING:
1046                     case CELLTYPE_EDIT:
1047                     {
1048                         if ( eType == CELLTYPE_STRING )
1049                             ((ScStringCell*)pCell)->GetString( aValue );
1050                         else
1051                             ((ScEditCell*)pCell)->GetString( aValue );
1052                         if ( !(nScFillModeMouseModifier & KEY_MOD1) && !IsDataFiltered() )  //i89232
1053                         {
1054                             sal_Int32 nVal;
1055                             sal_uInt16 nCellDigits = 0; // look at each source cell individually
1056                             short nFlag = lcl_DecompValueString( aValue, nVal, &nCellDigits );
1057                             if ( nFlag < 0 )
1058                             {
1059                                 if (aValue.Equals( ScGlobal::GetOrdinalSuffix( nVal)))
1060                                     aValue = ScGlobal::GetOrdinalSuffix( nVal + nDelta);
1061 
1062                                 aValue.Insert( lcl_ValueString( nVal + nDelta, nCellDigits ), 0 );
1063                             }
1064                             else if ( nFlag > 0 )
1065                                 aValue += lcl_ValueString( nVal + nDelta, nCellDigits );
1066                         }
1067                     }
1068                     break;
1069                     case CELLTYPE_VALUE:
1070                     {
1071                         //  dabei kann's keinen Ueberlauf geben...
1072                         double nVal = ((ScValueCell*)pCell)->GetValue();
1073                         if ( !(nScFillModeMouseModifier & KEY_MOD1) && !IsDataFiltered() )  //i89232
1074                             nVal += (double) nDelta;
1075 
1076                         Color* pColor;
1077                         sal_uLong nNumFmt = GetNumberFormat( nSrcX, nSrcY );
1078                         pDocument->GetFormatTable()->
1079                             GetOutputString( nVal, nNumFmt, aValue, &pColor );
1080                     }
1081                     break;
1082                     //  Formeln nicht
1083                     default:
1084                     {
1085                         // added to avoid warnings
1086                     }
1087                 }
1088             }
1089         }
1090         else if ( eFillCmd == FILL_LINEAR || eFillCmd == FILL_DATE )        // Werte
1091         {
1092             sal_Bool bValueOk;
1093             double nStart;
1094             sal_Int32 nVal = 0;
1095             short nHeadNoneTail = 0;
1096             ScBaseCell* pCell = GetCell( nCol1, nRow1 );
1097             if ( pCell )
1098             {
1099                 CellType eType = pCell->GetCellType();
1100                 switch ( eType )
1101                 {
1102                     case CELLTYPE_STRING:
1103                     case CELLTYPE_EDIT:
1104                     {
1105                         if ( eType == CELLTYPE_STRING )
1106                             ((ScStringCell*)pCell)->GetString( aValue );
1107                         else
1108                             ((ScEditCell*)pCell)->GetString( aValue );
1109                         nHeadNoneTail = lcl_DecompValueString( aValue, nVal );
1110                         if ( nHeadNoneTail )
1111                             nStart = (double)nVal;
1112                         else
1113                             nStart = 0.0;
1114                     }
1115                     break;
1116                     case CELLTYPE_VALUE:
1117                         nStart = ((ScValueCell*)pCell)->GetValue();
1118                     break;
1119                     case CELLTYPE_FORMULA:
1120                         nStart = ((ScFormulaCell*)pCell)->GetValue();
1121                     break;
1122                     default:
1123                         nStart = 0.0;
1124                 }
1125             }
1126             else
1127                 nStart = 0.0;
1128             if ( eFillCmd == FILL_LINEAR )
1129             {
1130                 double nAdd = nInc;
1131                 bValueOk = ( SubTotal::SafeMult( nAdd, (double) nIndex ) &&
1132                              SubTotal::SafePlus( nStart, nAdd ) );
1133             }
1134             else        // Datum
1135             {
1136                 bValueOk = sal_True;
1137                 sal_uInt16 nDayOfMonth = 0;
1138                 if ( nIndex < 0 )
1139                 {
1140                     nIndex = -nIndex;
1141                     nInc = -nInc;
1142                 }
1143                 for (long i=0; i<nIndex; i++)
1144                     IncDate( nStart, nDayOfMonth, nInc, eDateCmd );
1145             }
1146 
1147             if (bValueOk)
1148             {
1149                 if ( nHeadNoneTail )
1150                 {
1151                     if ( nHeadNoneTail < 0 )
1152                     {
1153                         if (aValue.Equals( ScGlobal::GetOrdinalSuffix( nVal)))
1154                             aValue = ScGlobal::GetOrdinalSuffix( (sal_Int32)nStart );
1155 
1156                         aValue.Insert( lcl_ValueString( (sal_Int32)nStart, nMinDigits ), 0 );
1157                     }
1158                     else
1159                         aValue += lcl_ValueString( (sal_Int32)nStart, nMinDigits );
1160                 }
1161                 else
1162                 {
1163                     //! Zahlformat je nach Index holen?
1164                     Color* pColor;
1165                     sal_uLong nNumFmt = GetNumberFormat( nCol1, nRow1 );
1166                     pDocument->GetFormatTable()->
1167                         GetOutputString( nStart, nNumFmt, aValue, &pColor );
1168                 }
1169             }
1170         }
1171         else
1172         {
1173             DBG_ERROR("GetAutoFillPreview: falscher Modus");
1174         }
1175     }
1176 
1177     return aValue;
1178 }
1179 
IncDate(double & rVal,sal_uInt16 & nDayOfMonth,double nStep,FillDateCmd eCmd)1180 void ScTable::IncDate(double& rVal, sal_uInt16& nDayOfMonth, double nStep, FillDateCmd eCmd)
1181 {
1182     if (eCmd == FILL_DAY)
1183     {
1184         rVal += nStep;
1185         return;
1186     }
1187 
1188     // class Date Grenzen
1189     const sal_uInt16 nMinYear = 1583;
1190     const sal_uInt16 nMaxYear = 9956;
1191 
1192     long nInc = (long) nStep;       // nach oben/unten begrenzen ?
1193     Date aNullDate = *pDocument->GetFormatTable()->GetNullDate();
1194     Date aDate = aNullDate;
1195     aDate += (long)rVal;
1196     switch (eCmd)
1197     {
1198         case FILL_WEEKDAY:
1199             {
1200                 aDate += nInc;
1201                 DayOfWeek eWeekDay = aDate.GetDayOfWeek();
1202                 if (nInc >= 0)
1203                 {
1204                     if (eWeekDay == SATURDAY)
1205                         aDate += 2;
1206                     else if (eWeekDay == SUNDAY)
1207                         aDate += 1;
1208                 }
1209                 else
1210                 {
1211                     if (eWeekDay == SATURDAY)
1212                         aDate -= 1;
1213                     else if (eWeekDay == SUNDAY)
1214                         aDate -= 2;
1215                 }
1216             }
1217             break;
1218         case FILL_MONTH:
1219             {
1220                 if ( nDayOfMonth == 0 )
1221                     nDayOfMonth = aDate.GetDay();       // init
1222                 long nMonth = aDate.GetMonth();
1223                 long nYear = aDate.GetYear();
1224 
1225                 nMonth += nInc;
1226 
1227                 if (nInc >= 0)
1228                 {
1229                     if (nMonth > 12)
1230                     {
1231                         long nYAdd = (nMonth-1) / 12;
1232                         nMonth -= nYAdd * 12;
1233                         nYear += nYAdd;
1234                     }
1235                 }
1236                 else
1237                 {
1238                     if (nMonth < 1)
1239                     {
1240                         long nYAdd = 1 - nMonth / 12;       // positiv
1241                         nMonth += nYAdd * 12;
1242                         nYear -= nYAdd;
1243                     }
1244                 }
1245 
1246                 if ( nYear < nMinYear )
1247                     aDate = Date( 1,1, nMinYear );
1248                 else if ( nYear > nMaxYear )
1249                     aDate = Date( 31,12, nMaxYear );
1250                 else
1251                 {
1252                     aDate.SetMonth((sal_uInt16) nMonth);
1253                     aDate.SetYear((sal_uInt16) nYear);
1254                     if ( nDayOfMonth > 28 )
1255                         aDate.SetDay( Min( aDate.GetDaysInMonth(), nDayOfMonth ) );
1256                 }
1257             }
1258             break;
1259         case FILL_YEAR:
1260             {
1261                 long nYear = aDate.GetYear();
1262                 nYear += nInc;
1263                 if ( nYear < nMinYear )
1264                     aDate = Date( 1,1, nMinYear );
1265                 else if ( nYear > nMaxYear )
1266                     aDate = Date( 31,12, nMaxYear );
1267                 else
1268                     aDate.SetYear((sal_uInt16) nYear);
1269             }
1270             break;
1271         default:
1272         {
1273             // added to avoid warnings
1274         }
1275     }
1276 
1277     rVal = aDate - aNullDate;
1278 }
1279 
FillSeries(SCCOL nCol1,SCROW nRow1,SCCOL nCol2,SCROW nRow2,sal_uLong nFillCount,FillDir eFillDir,FillCmd eFillCmd,FillDateCmd eFillDateCmd,double nStepValue,double nMaxValue,sal_uInt16 nArgMinDigits,sal_Bool bAttribs,ScProgress & rProgress)1280 void ScTable::FillSeries( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
1281                     sal_uLong nFillCount, FillDir eFillDir, FillCmd eFillCmd, FillDateCmd eFillDateCmd,
1282                     double nStepValue, double nMaxValue, sal_uInt16 nArgMinDigits,
1283                     sal_Bool bAttribs, ScProgress& rProgress )
1284 {
1285     //
1286     //  Richtung auswerten
1287     //
1288 
1289     sal_Bool bVertical = (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_TOP);
1290     sal_Bool bPositive = (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_RIGHT);
1291 
1292     sal_uLong nCol = 0;
1293     sal_uLong nRow = 0;
1294     sal_uLong& rInner = bVertical ? nRow : nCol;        // Schleifenvariablen
1295     sal_uLong& rOuter = bVertical ? nCol : nRow;
1296     sal_uLong nOStart;
1297     sal_uLong nOEnd;
1298     sal_uLong nIStart;
1299     sal_uLong nIEnd;
1300     sal_uLong nISource;
1301 
1302     if (bVertical)
1303     {
1304         nFillCount += (nRow2 - nRow1);
1305         if (nFillCount == 0)
1306             return;
1307         nOStart = nCol1;
1308         nOEnd = nCol2;
1309         if (bPositive)
1310         {
1311             nISource = nRow1;
1312             nIStart = nRow1 + 1;
1313             nIEnd = nRow1 + nFillCount;
1314         }
1315         else
1316         {
1317             nISource = nRow2;
1318             nIStart = nRow2 - 1;
1319             nIEnd = nRow2 - nFillCount;
1320         }
1321     }
1322     else
1323     {
1324         nFillCount += (nCol2 - nCol1);
1325         if (nFillCount == 0)
1326             return;
1327         nOStart = nRow1;
1328         nOEnd = nRow2;
1329         if (bPositive)
1330         {
1331             nISource = nCol1;
1332             nIStart = nCol1 + 1;
1333             nIEnd = nCol1 + nFillCount;
1334         }
1335         else
1336         {
1337             nISource = nCol2;
1338             nIStart = nCol2 - 1;
1339             nIEnd = nCol2 - nFillCount;
1340         }
1341     }
1342 
1343     sal_uLong nIMin = nIStart;
1344     sal_uLong nIMax = nIEnd;
1345     PutInOrder(nIMin,nIMax);
1346     sal_uInt16 nDel = bAttribs ? IDF_AUTOFILL : (IDF_AUTOFILL & IDF_CONTENTS);
1347     if (bVertical)
1348         DeleteArea(nCol1, static_cast<SCROW>(nIMin), nCol2, static_cast<SCROW>(nIMax), nDel);
1349     else
1350         DeleteArea(static_cast<SCCOL>(nIMin), nRow1, static_cast<SCCOL>(nIMax), nRow2, nDel);
1351 
1352     sal_uLong nProgress = rProgress.GetState();
1353 
1354     //
1355     //  ausfuehren
1356     //
1357 
1358     sal_uLong nActFormCnt = 0;
1359     for (rOuter = nOStart; rOuter <= nOEnd; rOuter++)
1360     {
1361         sal_Bool bFirst = sal_True;
1362         rInner = nISource;
1363         ScBaseCell* pSrcCell = aCol[nCol].GetCell(static_cast<SCROW>(nRow));
1364 
1365         if (bVertical && bAttribs)
1366             aCol[nCol].Resize( aCol[nCol].GetCellCount() + nFillCount );
1367 
1368         if (bAttribs)
1369         {
1370             const ScPatternAttr* pSrcPattern = aCol[nCol].GetPattern(static_cast<SCROW>(nRow));
1371             if (bVertical)
1372                 aCol[nCol].SetPatternArea( static_cast<SCROW>(nIMin),
1373                         static_cast<SCROW>(nIMax), *pSrcPattern, sal_True );
1374             else
1375                 for (SCCOL nAtCol = static_cast<SCCOL>(nIMin); nAtCol <= sal::static_int_cast<SCCOL>(nIMax); nAtCol++)
1376                     aCol[nAtCol].SetPattern(static_cast<SCROW>(nRow), *pSrcPattern, sal_True);
1377         }
1378 
1379         if (pSrcCell)
1380         {
1381             CellType eCellType = pSrcCell->GetCellType();
1382 
1383             if (eFillCmd == FILL_SIMPLE)                // kopieren
1384             {
1385                 if (eCellType == CELLTYPE_FORMULA)
1386                 {
1387                     for (rInner = nIMin; rInner <= nIMax; rInner++)
1388                     {
1389                         sal_uLong nInd = nActFormCnt;
1390                         FillFormula(nInd, bFirst, (ScFormulaCell*)pSrcCell,
1391                             static_cast<SCCOL>(nCol), nRow, (rInner == nIEnd) );
1392                         bFirst = sal_False;
1393                         rProgress.SetStateOnPercent( ++nProgress );
1394                     }
1395                 }
1396                 else if (eCellType != CELLTYPE_NOTE)
1397                 {
1398                     for (rInner = nIMin; rInner <= nIMax; rInner++)
1399                     {
1400                         ScAddress aDestPos( static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), nTab );
1401                         aCol[nCol].Insert( aDestPos.Row(), pSrcCell->CloneWithoutNote( *pDocument ) );
1402                     }
1403                     nProgress += nIMax - nIMin + 1;
1404                     rProgress.SetStateOnPercent( nProgress );
1405                 }
1406             }
1407             else if (eCellType == CELLTYPE_VALUE || eCellType == CELLTYPE_FORMULA)
1408             {
1409                 double nStartVal;
1410                 if (eCellType == CELLTYPE_VALUE)
1411                     nStartVal = ((ScValueCell*)pSrcCell)->GetValue();
1412                 else
1413                     nStartVal = ((ScFormulaCell*)pSrcCell)->GetValue();
1414                 double nVal = nStartVal;
1415                 long nIndex = 0;
1416 
1417                 sal_Bool bError = sal_False;
1418                 sal_Bool bOverflow = sal_False;
1419 
1420                 sal_uInt16 nDayOfMonth = 0;
1421                 rInner = nIStart;
1422                 while (true)        // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
1423                 {
1424                     if (!bError && !bOverflow)
1425                     {
1426                         switch (eFillCmd)
1427                         {
1428                             case FILL_LINEAR:
1429                                 {
1430                                     //  #86365# use multiplication instead of repeated addition
1431                                     //  to avoid accumulating rounding errors
1432                                     nVal = nStartVal;
1433                                     double nAdd = nStepValue;
1434                                     if ( !SubTotal::SafeMult( nAdd, (double) ++nIndex ) ||
1435                                          !SubTotal::SafePlus( nVal, nAdd ) )
1436                                         bError = sal_True;
1437                                 }
1438                                 break;
1439                             case FILL_GROWTH:
1440                                 if (!SubTotal::SafeMult(nVal, nStepValue))
1441                                     bError = sal_True;
1442                                 break;
1443                             case FILL_DATE:
1444                                 if (fabs(nVal) > _D_MAX_LONG_)
1445                                     bError = sal_True;
1446                                 else
1447                                     IncDate(nVal, nDayOfMonth, nStepValue, eFillDateCmd);
1448                                 break;
1449                             default:
1450                             {
1451                                 // added to avoid warnings
1452                             }
1453                         }
1454 
1455                         if (nStepValue >= 0)
1456                         {
1457                             if (nVal > nMaxValue)           // Zielwert erreicht?
1458                             {
1459                                 nVal = nMaxValue;
1460                                 bOverflow = sal_True;
1461                             }
1462                         }
1463                         else
1464                         {
1465                             if (nVal < nMaxValue)
1466                             {
1467                                 nVal = nMaxValue;
1468                                 bOverflow = sal_True;
1469                             }
1470                         }
1471                     }
1472 
1473                     if (bError)
1474                         aCol[nCol].SetError(static_cast<SCROW>(nRow), errNoValue);
1475                     else if (!bOverflow)
1476                         aCol[nCol].SetValue(static_cast<SCROW>(nRow), nVal);
1477 
1478                     if (rInner == nIEnd) break;
1479                     if (bPositive) ++rInner; else --rInner;
1480                 }
1481                 nProgress += nIMax - nIMin + 1;
1482                 rProgress.SetStateOnPercent( nProgress );
1483             }
1484             else if (eCellType == CELLTYPE_STRING || eCellType == CELLTYPE_EDIT)
1485             {
1486                 if ( nStepValue >= 0 )
1487                 {
1488                     if ( nMaxValue >= (double)LONG_MAX )
1489                         nMaxValue = (double)LONG_MAX - 1;
1490                 }
1491                 else
1492                 {
1493                     if ( nMaxValue <= (double)LONG_MIN )
1494                         nMaxValue = (double)LONG_MIN + 1;
1495                 }
1496                 String aValue;
1497                 if (eCellType == CELLTYPE_STRING)
1498                     ((ScStringCell*)pSrcCell)->GetString( aValue );
1499                 else
1500                     ((ScEditCell*)pSrcCell)->GetString( aValue );
1501                 sal_Int32 nStringValue;
1502                 sal_uInt16 nMinDigits = nArgMinDigits;
1503                 short nHeadNoneTail = lcl_DecompValueString( aValue, nStringValue, &nMinDigits );
1504                 if ( nHeadNoneTail )
1505                 {
1506                     double nStartVal = (double)nStringValue;
1507                     double nVal = nStartVal;
1508                     long nIndex = 0;
1509                     sal_Bool bError = sal_False;
1510                     sal_Bool bOverflow = sal_False;
1511 
1512                     sal_Bool bIsOrdinalSuffix = aValue.Equals( ScGlobal::GetOrdinalSuffix(
1513                                 (sal_Int32)nStartVal));
1514 
1515                     rInner = nIStart;
1516                     while (true)        // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
1517                     {
1518                         if (!bError && !bOverflow)
1519                         {
1520                             switch (eFillCmd)
1521                             {
1522                                 case FILL_LINEAR:
1523                                     {
1524                                         //  #86365# use multiplication instead of repeated addition
1525                                         //  to avoid accumulating rounding errors
1526                                         nVal = nStartVal;
1527                                         double nAdd = nStepValue;
1528                                         if ( !SubTotal::SafeMult( nAdd, (double) ++nIndex ) ||
1529                                              !SubTotal::SafePlus( nVal, nAdd ) )
1530                                             bError = sal_True;
1531                                     }
1532                                     break;
1533                                 case FILL_GROWTH:
1534                                     if (!SubTotal::SafeMult(nVal, nStepValue))
1535                                         bError = sal_True;
1536                                     break;
1537                                 default:
1538                                 {
1539                                     // added to avoid warnings
1540                                 }
1541                             }
1542 
1543                             if (nStepValue >= 0)
1544                             {
1545                                 if (nVal > nMaxValue)           // Zielwert erreicht?
1546                                 {
1547                                     nVal = nMaxValue;
1548                                     bOverflow = sal_True;
1549                                 }
1550                             }
1551                             else
1552                             {
1553                                 if (nVal < nMaxValue)
1554                                 {
1555                                     nVal = nMaxValue;
1556                                     bOverflow = sal_True;
1557                                 }
1558                             }
1559                         }
1560 
1561                         if (bError)
1562                             aCol[nCol].SetError(static_cast<SCROW>(nRow), errNoValue);
1563                         else if (!bOverflow)
1564                         {
1565                             nStringValue = (sal_Int32)nVal;
1566                             String aStr;
1567                             if ( nHeadNoneTail < 0 )
1568                             {
1569                                 aCol[nCol].Insert( static_cast<SCROW>(nRow),
1570                                         lcl_getSuffixCell( pDocument,
1571                                             nStringValue, nMinDigits, aValue,
1572                                             eCellType, bIsOrdinalSuffix ));
1573                             }
1574                             else
1575                             {
1576                                 aStr = aValue;
1577                                 aStr += lcl_ValueString( nStringValue, nMinDigits );
1578                                 ScStringCell* pCell = new ScStringCell( aStr );
1579                                 aCol[nCol].Insert( static_cast<SCROW>(nRow), pCell );
1580                             }
1581                         }
1582 
1583                         if (rInner == nIEnd) break;
1584                         if (bPositive) ++rInner; else --rInner;
1585                     }
1586                 }
1587                 nProgress += nIMax - nIMin + 1;
1588                 rProgress.SetStateOnPercent( nProgress );
1589             }
1590         }
1591         else
1592         {
1593             nProgress += nIMax - nIMin + 1;
1594             rProgress.SetStateOnPercent( nProgress );
1595         }
1596         ++nActFormCnt;
1597     }
1598 }
1599 
Fill(SCCOL nCol1,SCROW nRow1,SCCOL nCol2,SCROW nRow2,sal_uLong nFillCount,FillDir eFillDir,FillCmd eFillCmd,FillDateCmd eFillDateCmd,double nStepValue,double nMaxValue)1600 void ScTable::Fill( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
1601                     sal_uLong nFillCount, FillDir eFillDir, FillCmd eFillCmd, FillDateCmd eFillDateCmd,
1602                     double nStepValue, double nMaxValue)
1603 {
1604     sal_uLong nProgCount;
1605     if (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_TOP)
1606         nProgCount = nCol2 - nCol1 + 1;
1607     else
1608         nProgCount = nRow2 - nRow1 + 1;
1609     nProgCount *= nFillCount;
1610     ScProgress aProgress( pDocument->GetDocumentShell(),
1611                             ScGlobal::GetRscString(STR_FILL_SERIES_PROGRESS), nProgCount );
1612 
1613     bSharedNameInserted = sal_False;
1614 
1615     if (eFillCmd == FILL_AUTO)
1616         FillAuto(nCol1, nRow1, nCol2, nRow2, nFillCount, eFillDir, aProgress);
1617     else
1618         FillSeries(nCol1, nRow1, nCol2, nRow2, nFillCount, eFillDir,
1619                     eFillCmd, eFillDateCmd, nStepValue, nMaxValue, 0, sal_True, aProgress);
1620 
1621     if (bSharedNameInserted)                        // Wurde Shared-Name eingefuegt?
1622         pDocument->GetRangeName()->SetSharedMaxIndex(
1623             pDocument->GetRangeName()->GetSharedMaxIndex()+1);  // dann hochzaehlen
1624 }
1625 
1626 
AutoFormatArea(SCCOL nStartCol,SCROW nStartRow,SCCOL nEndCol,SCROW nEndRow,const ScPatternAttr & rAttr,sal_uInt16 nFormatNo)1627 void ScTable::AutoFormatArea(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
1628                                 const ScPatternAttr& rAttr, sal_uInt16 nFormatNo)
1629 {
1630     ScAutoFormat* pAutoFormat = ScGlobal::GetAutoFormat();
1631     if (pAutoFormat)
1632     {
1633         ScAutoFormatData* pData = (*pAutoFormat)[nFormatNo];
1634         if (pData)
1635         {
1636 //          ScPatternAttr aPattern(pDocument->GetPool());
1637 //            pData->FillToItemSet(nIndex, aPattern.GetItemSet(), *pDocument);
1638             ApplyPatternArea(nStartCol, nStartRow, nEndCol, nEndRow, rAttr);
1639         }
1640     }
1641 }
1642 
AutoFormat(SCCOL nStartCol,SCROW nStartRow,SCCOL nEndCol,SCROW nEndRow,sal_uInt16 nFormatNo)1643 void ScTable::AutoFormat( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
1644                             sal_uInt16 nFormatNo )
1645 {
1646     if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
1647     {
1648         ScAutoFormat* pAutoFormat = ScGlobal::GetAutoFormat();
1649         if (pAutoFormat)
1650         {
1651             ScAutoFormatData* pData = (*pAutoFormat)[nFormatNo];
1652             if (pData)
1653             {
1654                 ScPatternAttr* pPatternAttrs[16];
1655                 for (sal_uInt8 i = 0; i < 16; ++i)
1656                 {
1657                     pPatternAttrs[i] = new ScPatternAttr(pDocument->GetPool());
1658                     pData->FillToItemSet(i, pPatternAttrs[i]->GetItemSet(), *pDocument);
1659                 }
1660 
1661                 SCCOL nCol = nStartCol;
1662                 SCROW nRow = nStartRow;
1663                 sal_uInt16 nIndex = 0;
1664                 // Linke obere Ecke
1665                 AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1666                 // Linke Spalte
1667                 if (pData->IsEqualData(4, 8))
1668                     AutoFormatArea(nStartCol, nStartRow + 1, nStartCol, nEndRow - 1, *pPatternAttrs[4], nFormatNo);
1669                 else
1670                 {
1671                     nIndex = 4;
1672                     for (nRow = nStartRow + 1; nRow < nEndRow; nRow++)
1673                     {
1674                         AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1675                         if (nIndex == 4)
1676                             nIndex = 8;
1677                         else
1678                             nIndex = 4;
1679                     }
1680                 }
1681                 // Linke untere Ecke
1682                 nRow = nEndRow;
1683                 nIndex = 12;
1684                 AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1685                 // Rechte obere Ecke
1686                 nCol = nEndCol;
1687                 nRow = nStartRow;
1688                 nIndex = 3;
1689                 AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1690                 // Rechte Spalte
1691                 if (pData->IsEqualData(7, 11))
1692                     AutoFormatArea(nEndCol, nStartRow + 1, nEndCol, nEndRow - 1, *pPatternAttrs[7], nFormatNo);
1693                 else
1694                 {
1695                     nIndex = 7;
1696                     for (nRow = nStartRow + 1; nRow < nEndRow; nRow++)
1697                     {
1698                         AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1699                         if (nIndex == 7)
1700                             nIndex = 11;
1701                         else
1702                             nIndex = 7;
1703                     }
1704                 }
1705                 // Rechte untere Ecke
1706                 nRow = nEndRow;
1707                 nIndex = 15;
1708                 AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1709                 nRow = nStartRow;
1710                 nIndex = 1;
1711                 for (nCol = nStartCol + 1; nCol < nEndCol; nCol++)
1712                 {
1713                     AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1714                     if (nIndex == 1)
1715                         nIndex = 2;
1716                     else
1717                         nIndex = 1;
1718                 }
1719                 // Untere Zeile
1720                 nRow = nEndRow;
1721                 nIndex = 13;
1722                 for (nCol = nStartCol + 1; nCol < nEndCol; nCol++)
1723                 {
1724                     AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1725                     if (nIndex == 13)
1726                         nIndex = 14;
1727                     else
1728                         nIndex = 13;
1729                 }
1730                 // Boddy
1731                 if ((pData->IsEqualData(5, 6)) && (pData->IsEqualData(9, 10)) && (pData->IsEqualData(5, 9)))
1732                     AutoFormatArea(nStartCol + 1, nStartRow + 1, nEndCol-1, nEndRow - 1, *pPatternAttrs[5], nFormatNo);
1733                 else
1734                 {
1735                     if ((pData->IsEqualData(5, 9)) && (pData->IsEqualData(6, 10)))
1736                     {
1737                         nIndex = 5;
1738                         for (nCol = nStartCol + 1; nCol < nEndCol; nCol++)
1739                         {
1740                             AutoFormatArea(nCol, nStartRow + 1, nCol, nEndRow - 1, *pPatternAttrs[nIndex], nFormatNo);
1741                             if (nIndex == 5)
1742                                 nIndex = 6;
1743                             else
1744                                 nIndex = 5;
1745                         }
1746                     }
1747                     else
1748                     {
1749                         nIndex = 5;
1750                         for (nCol = nStartCol + 1; nCol < nEndCol; nCol++)
1751                         {
1752                             for (nRow = nStartRow + 1; nRow < nEndRow; nRow++)
1753                             {
1754                                 AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1755                                 if ((nIndex == 5) || (nIndex == 9))
1756                                 {
1757                                     if (nIndex == 5)
1758                                         nIndex = 9;
1759                                     else
1760                                         nIndex = 5;
1761                                 }
1762                                 else
1763                                 {
1764                                     if (nIndex == 6)
1765                                         nIndex = 10;
1766                                     else
1767                                         nIndex = 6;
1768                                 }
1769                             } // for nRow
1770                             if ((nIndex == 5) || (nIndex == 9))
1771                                 nIndex = 6;
1772                             else
1773                                 nIndex = 5;
1774                         } // for nCol
1775                     } // if not equal Column
1776                 } // if not all equal
1777 
1778                 for (sal_uInt8 j = 0; j < 16; ++j)
1779                     delete pPatternAttrs[j];
1780             } // if AutoFormatData != NULL
1781         } // if AutoFormat != NULL
1782     } // if ValidColRow
1783 }
1784 
GetAutoFormatAttr(SCCOL nCol,SCROW nRow,sal_uInt16 nIndex,ScAutoFormatData & rData)1785 void ScTable::GetAutoFormatAttr(SCCOL nCol, SCROW nRow, sal_uInt16 nIndex, ScAutoFormatData& rData)
1786 {
1787     sal_uInt32 nFormatIndex = GetNumberFormat( nCol, nRow );
1788     ScNumFormatAbbrev   aNumFormat( nFormatIndex, *pDocument->GetFormatTable() );
1789     rData.GetFromItemSet( nIndex, GetPattern( nCol, nRow )->GetItemSet(), aNumFormat );
1790 }
1791 
1792 #define LF_LEFT         1
1793 #define LF_TOP          2
1794 #define LF_RIGHT        4
1795 #define LF_BOTTOM       8
1796 #define LF_ALL          (LF_LEFT | LF_TOP | LF_RIGHT | LF_BOTTOM)
1797 
GetAutoFormatFrame(SCCOL nCol,SCROW nRow,sal_uInt16 nFlags,sal_uInt16 nIndex,ScAutoFormatData & rData)1798 void ScTable::GetAutoFormatFrame(SCCOL nCol, SCROW nRow, sal_uInt16 nFlags, sal_uInt16 nIndex, ScAutoFormatData& rData)
1799 {
1800     const SvxBoxItem* pTheBox = (SvxBoxItem*)GetAttr(nCol, nRow, ATTR_BORDER);
1801     const SvxBoxItem* pLeftBox = (SvxBoxItem*)GetAttr(nCol - 1, nRow, ATTR_BORDER);
1802     const SvxBoxItem* pTopBox = (SvxBoxItem*)GetAttr(nCol, nRow - 1, ATTR_BORDER);
1803     const SvxBoxItem* pRightBox = (SvxBoxItem*)GetAttr(nCol + 1, nRow, ATTR_BORDER);
1804     const SvxBoxItem* pBottomBox = (SvxBoxItem*)GetAttr(nCol, nRow + 1, ATTR_BORDER);
1805 
1806     SvxBoxItem aBox( ATTR_BORDER );
1807     if (nFlags & LF_LEFT)
1808     {
1809         if (pLeftBox)
1810         {
1811             if (ScHasPriority(pTheBox->GetLeft(), pLeftBox->GetRight()))
1812                 aBox.SetLine(pTheBox->GetLeft(), BOX_LINE_LEFT);
1813             else
1814                 aBox.SetLine(pLeftBox->GetRight(), BOX_LINE_LEFT);
1815         }
1816         else
1817             aBox.SetLine(pTheBox->GetLeft(), BOX_LINE_LEFT);
1818     }
1819     if (nFlags & LF_TOP)
1820     {
1821         if (pTopBox)
1822         {
1823             if (ScHasPriority(pTheBox->GetTop(), pTopBox->GetBottom()))
1824                 aBox.SetLine(pTheBox->GetTop(), BOX_LINE_TOP);
1825             else
1826                 aBox.SetLine(pTopBox->GetBottom(), BOX_LINE_TOP);
1827         }
1828         else
1829             aBox.SetLine(pTheBox->GetTop(), BOX_LINE_TOP);
1830     }
1831     if (nFlags & LF_RIGHT)
1832     {
1833         if (pRightBox)
1834         {
1835             if (ScHasPriority(pTheBox->GetRight(), pRightBox->GetLeft()))
1836                 aBox.SetLine(pTheBox->GetRight(), BOX_LINE_RIGHT);
1837             else
1838                 aBox.SetLine(pRightBox->GetLeft(), BOX_LINE_RIGHT);
1839         }
1840         else
1841             aBox.SetLine(pTheBox->GetRight(), BOX_LINE_RIGHT);
1842     }
1843     if (nFlags & LF_BOTTOM)
1844     {
1845         if (pBottomBox)
1846         {
1847             if (ScHasPriority(pTheBox->GetBottom(), pBottomBox->GetTop()))
1848                 aBox.SetLine(pTheBox->GetBottom(), BOX_LINE_BOTTOM);
1849             else
1850                 aBox.SetLine(pBottomBox->GetTop(), BOX_LINE_BOTTOM);
1851         }
1852         else
1853             aBox.SetLine(pTheBox->GetBottom(), BOX_LINE_BOTTOM);
1854     }
1855     rData.PutItem( nIndex, aBox );
1856 }
1857 
GetAutoFormatData(SCCOL nStartCol,SCROW nStartRow,SCCOL nEndCol,SCROW nEndRow,ScAutoFormatData & rData)1858 void ScTable::GetAutoFormatData(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, ScAutoFormatData& rData)
1859 {
1860     if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
1861     {
1862         if ((nEndCol - nStartCol >= 3) && (nEndRow - nStartRow >= 3))
1863         {
1864             // Linke obere Ecke
1865             GetAutoFormatAttr(nStartCol, nStartRow, 0, rData);
1866             GetAutoFormatFrame(nStartCol, nStartRow, LF_ALL, 0, rData);
1867             // Linke Spalte
1868             GetAutoFormatAttr(nStartCol, nStartRow + 1, 4, rData);
1869             GetAutoFormatAttr(nStartCol, nStartRow + 2, 8, rData);
1870             GetAutoFormatFrame(nStartCol, nStartRow + 1, LF_LEFT | LF_RIGHT | LF_BOTTOM, 4, rData);
1871             if (nEndRow - nStartRow >= 4)
1872                 GetAutoFormatFrame(nStartCol, nStartRow + 2, LF_LEFT | LF_RIGHT | LF_BOTTOM, 8, rData);
1873             else
1874                 rData.CopyItem( 8, 4, ATTR_BORDER );
1875             // Linke untere Ecke
1876             GetAutoFormatAttr(nStartCol, nEndRow, 12, rData);
1877             GetAutoFormatFrame(nStartCol, nEndRow, LF_ALL, 12, rData);
1878             // Rechte obere Ecke
1879             GetAutoFormatAttr(nEndCol, nStartRow, 3, rData);
1880             GetAutoFormatFrame(nEndCol, nStartRow, LF_ALL, 3, rData);
1881             // Rechte Spalte
1882             GetAutoFormatAttr(nEndCol, nStartRow + 1, 7, rData);
1883             GetAutoFormatAttr(nEndCol, nStartRow + 2, 11, rData);
1884             GetAutoFormatFrame(nEndCol, nStartRow + 1, LF_LEFT | LF_RIGHT | LF_BOTTOM, 7, rData);
1885             if (nEndRow - nStartRow >= 4)
1886                 GetAutoFormatFrame(nEndCol, nStartRow + 2, LF_LEFT | LF_RIGHT | LF_BOTTOM, 11, rData);
1887             else
1888                 rData.CopyItem( 11, 7, ATTR_BORDER );
1889             // Rechte untere Ecke
1890             GetAutoFormatAttr(nEndCol, nEndRow, 15, rData);
1891             GetAutoFormatFrame(nEndCol, nEndRow, LF_ALL, 15, rData);
1892             // Ober Zeile
1893             GetAutoFormatAttr(nStartCol + 1, nStartRow, 1, rData);
1894             GetAutoFormatAttr(nStartCol + 2, nStartRow, 2, rData);
1895             GetAutoFormatFrame(nStartCol + 1, nStartRow, LF_TOP | LF_BOTTOM | LF_RIGHT, 1, rData);
1896             if (nEndCol - nStartCol >= 4)
1897                 GetAutoFormatFrame(nStartCol + 2, nStartRow, LF_TOP | LF_BOTTOM | LF_RIGHT, 2, rData);
1898             else
1899                 rData.CopyItem( 2, 1, ATTR_BORDER );
1900             // Untere Zeile
1901             GetAutoFormatAttr(nStartCol + 1, nEndRow, 13, rData);
1902             GetAutoFormatAttr(nStartCol + 2, nEndRow, 14, rData);
1903             GetAutoFormatFrame(nStartCol + 1, nEndRow, LF_TOP | LF_BOTTOM | LF_RIGHT, 13, rData);
1904             if (nEndCol - nStartCol >= 4)
1905                 GetAutoFormatFrame(nStartCol + 2, nEndRow, LF_TOP | LF_BOTTOM | LF_RIGHT, 14, rData);
1906             else
1907                 rData.CopyItem( 14, 13, ATTR_BORDER );
1908             // Body
1909             GetAutoFormatAttr(nStartCol + 1, nStartRow + 1, 5, rData);
1910             GetAutoFormatAttr(nStartCol + 2, nStartRow + 1, 6, rData);
1911             GetAutoFormatAttr(nStartCol + 1, nStartRow + 2, 9, rData);
1912             GetAutoFormatAttr(nStartCol + 2, nStartRow + 2, 10, rData);
1913             GetAutoFormatFrame(nStartCol + 1, nStartRow + 1, LF_RIGHT | LF_BOTTOM, 5, rData);
1914             if ((nEndCol - nStartCol >= 4) && (nEndRow - nStartRow >= 4))
1915             {
1916                 GetAutoFormatFrame(nStartCol + 2, nStartRow + 1, LF_RIGHT | LF_BOTTOM, 6, rData);
1917                 GetAutoFormatFrame(nStartCol + 1, nStartRow + 2, LF_RIGHT | LF_BOTTOM, 9, rData);
1918                 GetAutoFormatFrame(nStartCol + 2, nStartRow + 2, LF_RIGHT | LF_BOTTOM, 10, rData);
1919             }
1920             else
1921             {
1922                 rData.CopyItem( 6, 5, ATTR_BORDER );
1923                 rData.CopyItem( 9, 5, ATTR_BORDER );
1924                 rData.CopyItem( 10, 5, ATTR_BORDER );
1925             }
1926         }
1927     }
1928 }
1929 
SetError(SCCOL nCol,SCROW nRow,sal_uInt16 nError)1930 void ScTable::SetError( SCCOL nCol, SCROW nRow, sal_uInt16 nError)
1931 {
1932     if (ValidColRow(nCol, nRow))
1933         aCol[nCol].SetError( nRow, nError );
1934 }
1935 
UpdateInsertTabAbs(SCTAB nTable)1936 void ScTable::UpdateInsertTabAbs(SCTAB nTable)
1937 {
1938     for (SCCOL i=0; i <= MAXCOL; i++)
1939         aCol[i].UpdateInsertTabAbs(nTable);
1940 }
1941 
1942 //UNUSED2008-05  sal_uInt16 ScTable::GetErrorData( SCCOL nCol, SCROW nRow ) const
1943 //UNUSED2008-05  {
1944 //UNUSED2008-05      if (ValidColRow(nCol,nRow))
1945 //UNUSED2008-05          return aCol[nCol].GetErrorData( nRow );
1946 //UNUSED2008-05      else
1947 //UNUSED2008-05          return 0;
1948 //UNUSED2008-05  }
1949 
GetNextSpellingCell(SCCOL & rCol,SCROW & rRow,sal_Bool bInSel,const ScMarkData & rMark) const1950 sal_Bool ScTable::GetNextSpellingCell(SCCOL& rCol, SCROW& rRow, sal_Bool bInSel,
1951                                     const ScMarkData& rMark) const
1952 {
1953     if (rRow == MAXROW+2)                       // Tabellenende
1954     {
1955         rRow = 0;
1956         rCol = 0;
1957     }
1958     else
1959     {
1960         rRow++;
1961         if (rRow == MAXROW+1)
1962         {
1963             rCol++;
1964             rRow = 0;
1965         }
1966     }
1967     if (rCol == MAXCOL+1)
1968         return sal_True;
1969     else
1970     {
1971         sal_Bool bStop = sal_False;
1972         while (!bStop)
1973         {
1974             if (ValidCol(rCol))
1975             {
1976                 bStop = aCol[rCol].GetNextSpellingCell(rRow, bInSel, rMark);
1977                 if (bStop)
1978                     return sal_True;
1979                 else /*if (rRow == MAXROW+1) */
1980                 {
1981                     rCol++;
1982                     rRow = 0;
1983                 }
1984             }
1985             else
1986                 return sal_True;
1987         }
1988     }
1989     return sal_False;
1990 }
1991 
RemoveAutoSpellObj()1992 void ScTable::RemoveAutoSpellObj()
1993 {
1994     for (SCCOL i=0; i <= MAXCOL; i++)
1995         aCol[i].RemoveAutoSpellObj();
1996 }
1997 
TestTabRefAbs(SCTAB nTable)1998 sal_Bool ScTable::TestTabRefAbs(SCTAB nTable)
1999 {
2000     sal_Bool bRet = sal_False;
2001     for (SCCOL i=0; i <= MAXCOL; i++)
2002         if (aCol[i].TestTabRefAbs(nTable))
2003             bRet = sal_True;
2004     return bRet;
2005 }
2006 
CompileDBFormula()2007 void ScTable::CompileDBFormula()
2008 {
2009     for (SCCOL i=0; i<=MAXCOL; i++) aCol[i].CompileDBFormula();
2010 }
2011 
CompileDBFormula(sal_Bool bCreateFormulaString)2012 void ScTable::CompileDBFormula( sal_Bool bCreateFormulaString )
2013 {
2014     for (SCCOL i=0; i<=MAXCOL; i++) aCol[i].CompileDBFormula( bCreateFormulaString );
2015 }
2016 
CompileNameFormula(sal_Bool bCreateFormulaString)2017 void ScTable::CompileNameFormula( sal_Bool bCreateFormulaString )
2018 {
2019     for (SCCOL i=0; i<=MAXCOL; i++) aCol[i].CompileNameFormula( bCreateFormulaString );
2020 }
2021 
CompileColRowNameFormula()2022 void ScTable::CompileColRowNameFormula()
2023 {
2024     for (SCCOL i=0; i<=MAXCOL; i++) aCol[i].CompileColRowNameFormula();
2025 }
2026 
GetPatternCount(SCCOL nCol)2027 SCSIZE ScTable::GetPatternCount( SCCOL nCol )
2028 {
2029     if( ValidCol( nCol ) )
2030         return aCol[nCol].GetPatternCount();
2031     else
2032         return 0;
2033 }
2034 
GetPatternCount(SCCOL nCol,SCROW nRw1,SCROW nRw2)2035 SCSIZE ScTable::GetPatternCount( SCCOL nCol, SCROW nRw1, SCROW nRw2 )
2036 {
2037     if( ValidCol( nCol ) && ValidRow( nRw1 ) && ValidRow( nRw2 ) )
2038         return aCol[nCol].GetPatternCount( nRw1, nRw2 );
2039     else
2040         return 0;
2041 }
2042 
ReservedPatternCount(SCCOL nCol,SCSIZE nReserved)2043 bool ScTable::ReservedPatternCount( SCCOL nCol, SCSIZE nReserved )
2044 {
2045     if( ValidCol( nCol ) )
2046         return aCol[nCol].ReservedPatternCount( nReserved );
2047     else
2048         return false;
2049 }
2050