xref: /AOO41X/main/sc/source/core/data/column2.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 
28 
29 // INCLUDE ---------------------------------------------------------------
30 
31 #include "scitems.hxx"
32 #include <editeng/eeitem.hxx>
33 
34 #include <svx/algitem.hxx>
35 #include <editeng/editobj.hxx>
36 #include <editeng/editstat.hxx>
37 #include <editeng/emphitem.hxx>
38 #include <editeng/fhgtitem.hxx>
39 #include <editeng/forbiddencharacterstable.hxx>
40 #include <svx/rotmodit.hxx>
41 #include <editeng/scripttypeitem.hxx>
42 #include <editeng/unolingu.hxx>
43 #include <svl/zforlist.hxx>
44 #include <svl/broadcast.hxx>
45 #include <svl/listeneriter.hxx>
46 #include <vcl/outdev.hxx>
47 
48 #include "column.hxx"
49 #include "cell.hxx"
50 #include "document.hxx"
51 #include "docpool.hxx"
52 #include "attarray.hxx"
53 #include "patattr.hxx"
54 #include "cellform.hxx"
55 #include "collect.hxx"
56 #include "stlsheet.hxx"
57 #include "rechead.hxx"
58 #include "brdcst.hxx"
59 #include "editutil.hxx"
60 #include "subtotal.hxx"
61 #include "markdata.hxx"
62 #include "compiler.hxx"         // ScTokenArray GetCodeLen
63 #include "dbcolect.hxx"
64 #include "fillinfo.hxx"
65 #include "segmenttree.hxx"
66 
67 #include <math.h>
68 
69 // -----------------------------------------------------------------------
70 
71 // factor from font size to optimal cell height (text width)
72 #define SC_ROT_BREAK_FACTOR     6
73 
74 // -----------------------------------------------------------------------
75 
IsAmbiguousScript(sal_uInt8 nScript)76 inline sal_Bool IsAmbiguousScript( sal_uInt8 nScript )
77 {
78     //! move to a header file
79     return ( nScript != SCRIPTTYPE_LATIN &&
80              nScript != SCRIPTTYPE_ASIAN &&
81              nScript != SCRIPTTYPE_COMPLEX );
82 }
83 
84 // -----------------------------------------------------------------------------------------
85 
86 //
87 //  Datei-Operationen
88 //
89 
90 // -----------------------------------------------------------------------------------------
91 
92 //UNUSED2008-05  SCROW ScColumn::NoteCount( SCROW nMaxRow ) const
93 //UNUSED2008-05  {
94 //UNUSED2008-05      SCROW nNoteCount = 0;
95 //UNUSED2008-05      SCSIZE i;
96 //UNUSED2008-05
97 //UNUSED2008-05      for (i=0; i<nCount; i++)
98 //UNUSED2008-05          if ( pItems[i].pCell->GetNotePtr() && pItems[i].nRow<=nMaxRow )
99 //UNUSED2008-05              ++nNoteCount;
100 //UNUSED2008-05
101 //UNUSED2008-05      return nNoteCount;
102 //UNUSED2008-05  }
103 
104 // -----------------------------------------------------------------------------------------
105 
106 //UNUSED2008-05  void ScColumn::CorrectSymbolCells( CharSet eStreamCharSet )
107 //UNUSED2008-05  {
108 //UNUSED2008-05      //  #99139# find and correct string cells that are formatted with a symbol font,
109 //UNUSED2008-05      //  but are not in the LoadedSymbolStringCellsList
110 //UNUSED2008-05      //  (because CELLTYPE_SYMBOLS wasn't written in the file)
111 //UNUSED2008-05
112 //UNUSED2008-05      ScFontToSubsFontConverter_AutoPtr xFontConverter;
113 //UNUSED2008-05      const sal_uLong nFontConverterFlags = FONTTOSUBSFONT_EXPORT | FONTTOSUBSFONT_ONLYOLDSOSYMBOLFONTS;
114 //UNUSED2008-05
115 //UNUSED2008-05      sal_Bool bListInitialized = sal_False;
116 //UNUSED2008-05      ScSymbolStringCellEntry* pCurrentEntry = NULL;
117 //UNUSED2008-05
118 //UNUSED2008-05      ScAttrIterator aAttrIter( pAttrArray, 0, MAXROW );
119 //UNUSED2008-05      SCROW nStt, nEnd;
120 //UNUSED2008-05      const ScPatternAttr* pAttr = aAttrIter.Next( nStt, nEnd );
121 //UNUSED2008-05      while ( pAttr )
122 //UNUSED2008-05      {
123 //UNUSED2008-05          if ( (xFontConverter = pAttr->GetSubsFontConverter( nFontConverterFlags )) ||
124 //UNUSED2008-05                  pAttr->IsSymbolFont() )
125 //UNUSED2008-05          {
126 //UNUSED2008-05              ScColumnIterator aCellIter( this, nStt, nEnd );
127 //UNUSED2008-05              SCROW nRow;
128 //UNUSED2008-05              ScBaseCell* pCell;
129 //UNUSED2008-05              while ( aCellIter.Next( nRow, pCell ) )
130 //UNUSED2008-05              {
131 //UNUSED2008-05                  if ( pCell->GetCellType() == CELLTYPE_STRING )
132 //UNUSED2008-05                  {
133 //UNUSED2008-05                      List& rList = pDocument->GetLoadedSymbolStringCellsList();
134 //UNUSED2008-05                      if (!bListInitialized)
135 //UNUSED2008-05                      {
136 //UNUSED2008-05                          pCurrentEntry = (ScSymbolStringCellEntry*)rList.First();
137 //UNUSED2008-05                          bListInitialized = sal_True;
138 //UNUSED2008-05                      }
139 //UNUSED2008-05
140 //UNUSED2008-05                      while ( pCurrentEntry && pCurrentEntry->nRow < nRow )
141 //UNUSED2008-05                          pCurrentEntry = (ScSymbolStringCellEntry*)rList.Next();
142 //UNUSED2008-05
143 //UNUSED2008-05                      if ( pCurrentEntry && pCurrentEntry->nRow == nRow )
144 //UNUSED2008-05                      {
145 //UNUSED2008-05                          //  found
146 //UNUSED2008-05                      }
147 //UNUSED2008-05                      else
148 //UNUSED2008-05                      {
149 //UNUSED2008-05                          //  not in list -> convert and put into list
150 //UNUSED2008-05
151 //UNUSED2008-05                          ScStringCell* pStrCell = (ScStringCell*)pCell;
152 //UNUSED2008-05                          String aOldStr;
153 //UNUSED2008-05                          pStrCell->GetString( aOldStr );
154 //UNUSED2008-05
155 //UNUSED2008-05                          //  convert back to stream character set (get original data)
156 //UNUSED2008-05                          ByteString aByteStr( aOldStr, eStreamCharSet );
157 //UNUSED2008-05
158 //UNUSED2008-05                          //  convert using symbol encoding, as for CELLTYPE_SYMBOLS cells
159 //UNUSED2008-05                          String aNewStr( aByteStr, RTL_TEXTENCODING_SYMBOL );
160 //UNUSED2008-05                          pStrCell->SetString( aNewStr );
161 //UNUSED2008-05
162 //UNUSED2008-05                          ScSymbolStringCellEntry * pEntry = new ScSymbolStringCellEntry;
163 //UNUSED2008-05                          pEntry->pCell = pStrCell;
164 //UNUSED2008-05                          pEntry->nRow = nRow;
165 //UNUSED2008-05
166 //UNUSED2008-05                          if ( pCurrentEntry )
167 //UNUSED2008-05                              rList.Insert( pEntry );     // before current entry - pCurrentEntry stays valid
168 //UNUSED2008-05                          else
169 //UNUSED2008-05                              rList.Insert( pEntry, LIST_APPEND );    // append if already behind last entry
170 //UNUSED2008-05                      }
171 //UNUSED2008-05                  }
172 //UNUSED2008-05              }
173 //UNUSED2008-05          }
174 //UNUSED2008-05
175 //UNUSED2008-05          pAttr = aAttrIter.Next( nStt, nEnd );
176 //UNUSED2008-05      }
177 //UNUSED2008-05  }
178 
179 // -----------------------------------------------------------------------------------------
180 
181                                     //  GetNeededSize: optimale Hoehe / Breite in Pixeln
182 
GetNeededSize(SCROW nRow,OutputDevice * pDev,double nPPTX,double nPPTY,const Fraction & rZoomX,const Fraction & rZoomY,sal_Bool bWidth,const ScNeededSizeOptions & rOptions)183 long ScColumn::GetNeededSize( SCROW nRow, OutputDevice* pDev,
184                               double nPPTX, double nPPTY,
185                               const Fraction& rZoomX, const Fraction& rZoomY,
186                               sal_Bool bWidth, const ScNeededSizeOptions& rOptions )
187 {
188     long nValue=0;
189     SCSIZE nIndex;
190     double nPPT = bWidth ? nPPTX : nPPTY;
191     if (Search(nRow,nIndex))
192     {
193         ScBaseCell* pCell = pItems[nIndex].pCell;
194         const ScPatternAttr* pPattern = rOptions.pPattern;
195         if (!pPattern)
196             pPattern = pAttrArray->GetPattern( nRow );
197 
198         //      zusammengefasst?
199         //      Merge nicht in bedingter Formatierung
200 
201         const ScMergeAttr*      pMerge = (const ScMergeAttr*)&pPattern->GetItem(ATTR_MERGE);
202         const ScMergeFlagAttr*  pFlag = (const ScMergeFlagAttr*)&pPattern->GetItem(ATTR_MERGE_FLAG);
203 
204         if ( bWidth )
205         {
206             if ( pFlag->IsHorOverlapped() )
207                 return 0;
208             if ( rOptions.bSkipMerged && pMerge->GetColMerge() > 1 )
209                 return 0;
210         }
211         else
212         {
213             if ( pFlag->IsVerOverlapped() )
214                 return 0;
215             if ( rOptions.bSkipMerged && pMerge->GetRowMerge() > 1 )
216                 return 0;
217         }
218 
219         //      bedingte Formatierung
220         const SfxItemSet* pCondSet = NULL;
221         if ( ((const SfxUInt32Item&)pPattern->GetItem(ATTR_CONDITIONAL)).GetValue() )
222             pCondSet = pDocument->GetCondResult( nCol, nRow, nTab );
223 
224         //  Zeilenumbruch?
225 
226         const SfxPoolItem* pCondItem;
227         SvxCellHorJustify eHorJust;
228         if (pCondSet &&
229                 pCondSet->GetItemState(ATTR_HOR_JUSTIFY, sal_True, &pCondItem) == SFX_ITEM_SET)
230             eHorJust = (SvxCellHorJustify)((const SvxHorJustifyItem*)pCondItem)->GetValue();
231         else
232             eHorJust = (SvxCellHorJustify)((const SvxHorJustifyItem&)
233                                             pPattern->GetItem( ATTR_HOR_JUSTIFY )).GetValue();
234         bool bBreak;
235         if ( eHorJust == SVX_HOR_JUSTIFY_BLOCK )
236             bBreak = true;
237         else if ( pCondSet &&
238                     pCondSet->GetItemState(ATTR_LINEBREAK, sal_True, &pCondItem) == SFX_ITEM_SET)
239             bBreak = ((const SfxBoolItem*)pCondItem)->GetValue();
240         else
241             bBreak = ((const SfxBoolItem&)pPattern->GetItem(ATTR_LINEBREAK)).GetValue();
242 
243         SvNumberFormatter* pFormatter = pDocument->GetFormatTable();
244         sal_uLong nFormat = pPattern->GetNumberFormat( pFormatter, pCondSet );
245         // #i111387# #o11817313# disable automatic line breaks only for "General" number format
246         if ( bBreak && pCell->HasValueData() && ( nFormat % SV_COUNTRY_LANGUAGE_OFFSET ) == 0 )
247         {
248             // also take formula result type into account for number format
249             if ( pCell->GetCellType() != CELLTYPE_FORMULA ||
250                  ( static_cast<ScFormulaCell*>(pCell)->GetStandardFormat(*pFormatter, nFormat) % SV_COUNTRY_LANGUAGE_OFFSET ) == 0 )
251                 bBreak = false;
252         }
253 
254         //  get other attributes from pattern and conditional formatting
255 
256         SvxCellOrientation eOrient = pPattern->GetCellOrientation( pCondSet );
257         sal_Bool bAsianVertical = ( eOrient == SVX_ORIENTATION_STACKED &&
258                 ((const SfxBoolItem&)pPattern->GetItem( ATTR_VERTICAL_ASIAN, pCondSet )).GetValue() );
259         if ( bAsianVertical )
260             bBreak = false;
261 
262         if ( bWidth && bBreak )     // after determining bAsianVertical (bBreak may be reset)
263             return 0;
264 
265         long nRotate = 0;
266         SvxRotateMode eRotMode = SVX_ROTATE_MODE_STANDARD;
267         if ( eOrient == SVX_ORIENTATION_STANDARD )
268         {
269             if (pCondSet &&
270                     pCondSet->GetItemState(ATTR_ROTATE_VALUE, sal_True, &pCondItem) == SFX_ITEM_SET)
271                 nRotate = ((const SfxInt32Item*)pCondItem)->GetValue();
272             else
273                 nRotate = ((const SfxInt32Item&)pPattern->GetItem(ATTR_ROTATE_VALUE)).GetValue();
274             if ( nRotate )
275             {
276                 if (pCondSet &&
277                         pCondSet->GetItemState(ATTR_ROTATE_MODE, sal_True, &pCondItem) == SFX_ITEM_SET)
278                     eRotMode = (SvxRotateMode)((const SvxRotateModeItem*)pCondItem)->GetValue();
279                 else
280                     eRotMode = (SvxRotateMode)((const SvxRotateModeItem&)
281                                                 pPattern->GetItem(ATTR_ROTATE_MODE)).GetValue();
282 
283                 if ( nRotate == 18000 )
284                     eRotMode = SVX_ROTATE_MODE_STANDARD;    // keinen Ueberlauf
285             }
286         }
287 
288         if ( eHorJust == SVX_HOR_JUSTIFY_REPEAT )
289         {
290             // ignore orientation/rotation if "repeat" is active
291             eOrient = SVX_ORIENTATION_STANDARD;
292             nRotate = 0;
293             bAsianVertical = sal_False;
294         }
295 
296         const SvxMarginItem* pMargin;
297         if (pCondSet &&
298                 pCondSet->GetItemState(ATTR_MARGIN, sal_True, &pCondItem) == SFX_ITEM_SET)
299             pMargin = (const SvxMarginItem*) pCondItem;
300         else
301             pMargin = (const SvxMarginItem*) &pPattern->GetItem(ATTR_MARGIN);
302         sal_uInt16 nIndent = 0;
303         if ( eHorJust == SVX_HOR_JUSTIFY_LEFT )
304         {
305             if (pCondSet &&
306                     pCondSet->GetItemState(ATTR_INDENT, sal_True, &pCondItem) == SFX_ITEM_SET)
307                 nIndent = ((const SfxUInt16Item*)pCondItem)->GetValue();
308             else
309                 nIndent = ((const SfxUInt16Item&)pPattern->GetItem(ATTR_INDENT)).GetValue();
310         }
311 
312         sal_uInt8 nScript = pDocument->GetScriptType( nCol, nRow, nTab, pCell );
313         if (nScript == 0) nScript = ScGlobal::GetDefaultScriptType();
314 
315         //  also call SetFont for edit cells, because bGetFont may be set only once
316         //  bGetFont is set also if script type changes
317         if (rOptions.bGetFont)
318         {
319             Fraction aFontZoom = ( eOrient == SVX_ORIENTATION_STANDARD ) ? rZoomX : rZoomY;
320             Font aFont;
321             // font color doesn't matter here
322             pPattern->GetFont( aFont, SC_AUTOCOL_BLACK, pDev, &aFontZoom, pCondSet, nScript );
323             pDev->SetFont(aFont);
324         }
325 
326         sal_Bool bAddMargin = sal_True;
327         CellType eCellType = pCell->GetCellType();
328 
329         sal_Bool bEditEngine = ( eCellType == CELLTYPE_EDIT ||
330                                 eOrient == SVX_ORIENTATION_STACKED ||
331                                 IsAmbiguousScript( nScript ) ||
332                                 ((eCellType == CELLTYPE_FORMULA) && ((ScFormulaCell*)pCell)->IsMultilineResult()) );
333 
334         if (!bEditEngine)                                   // direkte Ausgabe
335         {
336             String aValStr;
337             Color* pColor;
338             ScCellFormat::GetString( pCell, nFormat, aValStr, &pColor,
339                                         *pFormatter,
340                                         sal_True, rOptions.bFormula, ftCheck );
341             if (aValStr.Len())
342             {
343                 //  SetFont ist nach oben verschoben
344 
345                 Size aSize( pDev->GetTextWidth( aValStr ), pDev->GetTextHeight() );
346                 if ( eOrient != SVX_ORIENTATION_STANDARD )
347                 {
348                     long nTemp = aSize.Width();
349                     aSize.Width() = aSize.Height();
350                     aSize.Height() = nTemp;
351                 }
352                 else if ( nRotate )
353                 {
354                     //! unterschiedliche Skalierung X/Y beruecksichtigen
355 
356                     double nRealOrient = nRotate * F_PI18000;   // nRotate sind 1/100 Grad
357                     double nCosAbs = fabs( cos( nRealOrient ) );
358                     double nSinAbs = fabs( sin( nRealOrient ) );
359                     long nHeight = (long)( aSize.Height() * nCosAbs + aSize.Width() * nSinAbs );
360                     long nWidth;
361                     if ( eRotMode == SVX_ROTATE_MODE_STANDARD )
362                         nWidth  = (long)( aSize.Width() * nCosAbs + aSize.Height() * nSinAbs );
363                     else if ( rOptions.bTotalSize )
364                     {
365                         nWidth = (long) ( pDocument->GetColWidth( nCol,nTab ) * nPPT );
366                         bAddMargin = sal_False;
367                         //  nur nach rechts:
368                         //! unterscheiden nach Ausrichtung oben/unten (nur Text/ganze Hoehe)
369                         if ( pPattern->GetRotateDir( pCondSet ) == SC_ROTDIR_RIGHT )
370                             nWidth += (long)( pDocument->GetRowHeight( nRow,nTab ) *
371                                                 nPPT * nCosAbs / nSinAbs );
372                     }
373                     else
374                         nWidth  = (long)( aSize.Height() / nSinAbs );   //! begrenzen?
375 
376                     if ( bBreak && !rOptions.bTotalSize )
377                     {
378                         //  #47744# limit size for line break
379                         long nCmp = pDev->GetFont().GetSize().Height() * SC_ROT_BREAK_FACTOR;
380                         if ( nHeight > nCmp )
381                             nHeight = nCmp;
382                     }
383 
384                     aSize = Size( nWidth, nHeight );
385                 }
386                 nValue = bWidth ? aSize.Width() : aSize.Height();
387 
388                 if ( bAddMargin )
389                 {
390                     if (bWidth)
391                     {
392                         nValue += (long) ( pMargin->GetLeftMargin() * nPPT ) +
393                                   (long) ( pMargin->GetRightMargin() * nPPT );
394                         if ( nIndent )
395                             nValue += (long) ( nIndent * nPPT );
396                     }
397                     else
398                         nValue += (long) ( pMargin->GetTopMargin() * nPPT ) +
399                                   (long) ( pMargin->GetBottomMargin() * nPPT );
400                 }
401 
402                                                 //  Zeilenumbruch ausgefuehrt ?
403 
404                 if ( bBreak && !bWidth )
405                 {
406                     //  Test mit EditEngine zur Sicherheit schon bei 90%
407                     //  (wegen Rundungsfehlern und weil EditEngine teilweise anders formatiert)
408 
409                     long nDocPixel = (long) ( ( pDocument->GetColWidth( nCol,nTab ) -
410                                         pMargin->GetLeftMargin() - pMargin->GetRightMargin() -
411                                         nIndent )
412                                         * nPPT );
413                     nDocPixel = (nDocPixel * 9) / 10;           // zur Sicherheit
414                     if ( aSize.Width() > nDocPixel )
415                         bEditEngine = sal_True;
416                 }
417             }
418         }
419 
420         if (bEditEngine)
421         {
422             //  der Font wird bei !bEditEngine nicht jedesmal neu gesetzt
423             Font aOldFont = pDev->GetFont();
424 
425             MapMode aHMMMode( MAP_100TH_MM, Point(), rZoomX, rZoomY );
426 
427             // am Dokument speichern ?
428             ScFieldEditEngine* pEngine = pDocument->CreateFieldEditEngine();
429 
430             pEngine->SetUpdateMode( sal_False );
431             sal_Bool bTextWysiwyg = ( pDev->GetOutDevType() == OUTDEV_PRINTER );
432             sal_uInt32 nCtrl = pEngine->GetControlWord();
433             if ( bTextWysiwyg )
434                 nCtrl |= EE_CNTRL_FORMAT100;
435             else
436                 nCtrl &= ~EE_CNTRL_FORMAT100;
437             pEngine->SetControlWord( nCtrl );
438             MapMode aOld = pDev->GetMapMode();
439             pDev->SetMapMode( aHMMMode );
440             pEngine->SetRefDevice( pDev );
441             pDocument->ApplyAsianEditSettings( *pEngine );
442             SfxItemSet* pSet = new SfxItemSet( pEngine->GetEmptyItemSet() );
443             pPattern->FillEditItemSet( pSet, pCondSet );
444 
445 //          no longer needed, are setted with the text (is faster)
446 //          pEngine->SetDefaults( pSet );
447 
448             if ( ((const SfxBoolItem&)pSet->Get(EE_PARA_HYPHENATE)).GetValue() ) {
449 
450                 com::sun::star::uno::Reference<com::sun::star::linguistic2::XHyphenator> xXHyphenator( LinguMgr::GetHyphenator() );
451                 pEngine->SetHyphenator( xXHyphenator );
452             }
453 
454             Size aPaper = Size( 1000000, 1000000 );
455             if ( eOrient==SVX_ORIENTATION_STACKED && !bAsianVertical )
456                 aPaper.Width() = 1;
457             else if (bBreak)
458             {
459                 double fWidthFactor = nPPTX;
460                 if ( bTextWysiwyg )
461                 {
462                     //  #95593# if text is formatted for printer, don't use PixelToLogic,
463                     //  to ensure the exact same paper width (and same line breaks) as in
464                     //  ScEditUtil::GetEditArea, used for output.
465 
466                     fWidthFactor = HMM_PER_TWIPS;
467                 }
468 
469                 // use original width for hidden columns:
470                 long nDocWidth = (long) ( pDocument->GetOriginalWidth(nCol,nTab) * fWidthFactor );
471                 SCCOL nColMerge = pMerge->GetColMerge();
472                 if (nColMerge > 1)
473                     for (SCCOL nColAdd=1; nColAdd<nColMerge; nColAdd++)
474                         nDocWidth += (long) ( pDocument->GetColWidth(nCol+nColAdd,nTab) * fWidthFactor );
475                 nDocWidth -= (long) ( pMargin->GetLeftMargin() * fWidthFactor )
476                            + (long) ( pMargin->GetRightMargin() * fWidthFactor )
477                            + 1;     // Ausgabebereich ist Breite-1 Pixel (wegen Gitterlinien)
478                 if ( nIndent )
479                     nDocWidth -= (long) ( nIndent * fWidthFactor );
480 
481                 // space for AutoFilter button:  20 * nZoom/100
482                 if ( pFlag->HasAutoFilter() && !bTextWysiwyg )
483                     nDocWidth -= (rZoomX.GetNumerator()*20)/rZoomX.GetDenominator();
484 
485                 aPaper.Width() = nDocWidth;
486 
487                 if ( !bTextWysiwyg )
488                     aPaper = pDev->PixelToLogic( aPaper, aHMMMode );
489             }
490             pEngine->SetPaperSize(aPaper);
491 
492             if ( pCell->GetCellType() == CELLTYPE_EDIT )
493             {
494                 const EditTextObject* pData;
495                 ((ScEditCell*)pCell)->GetData(pData);
496                 pEngine->SetTextNewDefaults(*pData, pSet);
497             }
498             else
499             {
500                 Color* pColor;
501                 String aString;
502                 ScCellFormat::GetString( pCell, nFormat, aString, &pColor,
503                                             *pFormatter,
504                                             sal_True, rOptions.bFormula, ftCheck );
505                 if (aString.Len())
506                     pEngine->SetTextNewDefaults(aString, pSet);
507                 else
508                     pEngine->SetDefaults(pSet);
509             }
510 
511             sal_Bool bEngineVertical = pEngine->IsVertical();
512             pEngine->SetVertical( bAsianVertical );
513             pEngine->SetUpdateMode( sal_True );
514 
515             sal_Bool bEdWidth = bWidth;
516             if ( eOrient != SVX_ORIENTATION_STANDARD && eOrient != SVX_ORIENTATION_STACKED )
517                 bEdWidth = !bEdWidth;
518             if ( nRotate )
519             {
520                 //! unterschiedliche Skalierung X/Y beruecksichtigen
521 
522                 Size aSize( pEngine->CalcTextWidth(), pEngine->GetTextHeight() );
523                 double nRealOrient = nRotate * F_PI18000;   // nRotate sind 1/100 Grad
524                 double nCosAbs = fabs( cos( nRealOrient ) );
525                 double nSinAbs = fabs( sin( nRealOrient ) );
526                 long nHeight = (long)( aSize.Height() * nCosAbs + aSize.Width() * nSinAbs );
527                 long nWidth;
528                 if ( eRotMode == SVX_ROTATE_MODE_STANDARD )
529                     nWidth  = (long)( aSize.Width() * nCosAbs + aSize.Height() * nSinAbs );
530                 else if ( rOptions.bTotalSize )
531                 {
532                     nWidth = (long) ( pDocument->GetColWidth( nCol,nTab ) * nPPT );
533                     bAddMargin = sal_False;
534                     if ( pPattern->GetRotateDir( pCondSet ) == SC_ROTDIR_RIGHT )
535                         nWidth += (long)( pDocument->GetRowHeight( nRow,nTab ) *
536                                             nPPT * nCosAbs / nSinAbs );
537                 }
538                 else
539                     nWidth  = (long)( aSize.Height() / nSinAbs );   //! begrenzen?
540                 aSize = Size( nWidth, nHeight );
541 
542                 Size aPixSize = pDev->LogicToPixel( aSize, aHMMMode );
543                 if ( bEdWidth )
544                     nValue = aPixSize.Width();
545                 else
546                 {
547                     nValue = aPixSize.Height();
548 
549                     if ( bBreak && !rOptions.bTotalSize )
550                     {
551                         //  #47744# limit size for line break
552                         long nCmp = aOldFont.GetSize().Height() * SC_ROT_BREAK_FACTOR;
553                         if ( nValue > nCmp )
554                             nValue = nCmp;
555                     }
556                 }
557             }
558             else if ( bEdWidth )
559             {
560                 if (bBreak)
561                     nValue = 0;
562                 else
563                     nValue = pDev->LogicToPixel(Size( pEngine->CalcTextWidth(), 0 ),
564                                         aHMMMode).Width();
565             }
566             else            // Hoehe
567             {
568                 nValue = pDev->LogicToPixel(Size( 0, pEngine->GetTextHeight() ),
569                                     aHMMMode).Height();
570 
571                 // With non-100% zoom and several lines or paragraphs, don't shrink below the result with FORMAT100 set
572                 if ( !bTextWysiwyg && ( rZoomY.GetNumerator() != 1 || rZoomY.GetDenominator() != 1 ) &&
573                      ( pEngine->GetParagraphCount() > 1 || ( bBreak && pEngine->GetLineCount(0) > 1 ) ) )
574                 {
575                     pEngine->SetControlWord( nCtrl | EE_CNTRL_FORMAT100 );
576                     pEngine->QuickFormatDoc( sal_True );
577                     long nSecondValue = pDev->LogicToPixel(Size( 0, pEngine->GetTextHeight() ), aHMMMode).Height();
578                     if ( nSecondValue > nValue )
579                         nValue = nSecondValue;
580                 }
581             }
582 
583             if ( nValue && bAddMargin )
584             {
585                 if (bWidth)
586                 {
587                     nValue += (long) ( pMargin->GetLeftMargin() * nPPT ) +
588                               (long) ( pMargin->GetRightMargin() * nPPT );
589                     if (nIndent)
590                         nValue += (long) ( nIndent * nPPT );
591                 }
592                 else
593                 {
594                     nValue += (long) ( pMargin->GetTopMargin() * nPPT ) +
595                               (long) ( pMargin->GetBottomMargin() * nPPT );
596 
597                     if ( bAsianVertical && pDev->GetOutDevType() != OUTDEV_PRINTER )
598                     {
599                         //  add 1pt extra (default margin value) for line breaks with SetVertical
600                         nValue += (long) ( 20 * nPPT );
601                     }
602                 }
603             }
604 
605             //  EditEngine is cached and re-used, so the old vertical flag must be restored
606             pEngine->SetVertical( bEngineVertical );
607 
608             pDocument->DisposeFieldEditEngine(pEngine);
609 
610             pDev->SetMapMode( aOld );
611             pDev->SetFont( aOldFont );
612         }
613 
614         if (bWidth)
615         {
616             //      Platz fuer Autofilter-Button
617             //      20 * nZoom/100
618             //      bedingte Formatierung hier nicht interessant
619 
620             sal_Int16 nFlags = ((const ScMergeFlagAttr&)pPattern->GetItem(ATTR_MERGE_FLAG)).GetValue();
621             if (nFlags & SC_MF_AUTO)
622                 nValue += (rZoomX.GetNumerator()*20)/rZoomX.GetDenominator();
623         }
624     }
625     return nValue;
626 }
627 
GetSimpleTextNeededSize(SCSIZE nIndex,OutputDevice * pDev,sal_Bool bWidth)628 long ScColumn::GetSimpleTextNeededSize( SCSIZE nIndex, OutputDevice* pDev,
629         sal_Bool bWidth )
630 {
631     long nValue=0;
632     if ( nIndex < nCount )
633     {
634         SCROW nRow = pItems[nIndex].nRow;
635         const ScPatternAttr* pPattern = pAttrArray->GetPattern( nRow );
636         ScBaseCell* pCell = pItems[nIndex].pCell;
637         String aValStr;
638         Color* pColor;
639         SvNumberFormatter* pFormatter = pDocument->GetFormatTable();
640         sal_uLong nFormat = pPattern->GetNumberFormat( pFormatter );
641         ScCellFormat::GetString( pCell, nFormat, aValStr, &pColor,
642                                     *pFormatter, sal_True, sal_False, ftCheck );
643         if ( aValStr.Len() )
644         {
645             if ( bWidth )
646                 nValue = pDev->GetTextWidth( aValStr );
647             else
648                 nValue = pDev->GetTextHeight();
649         }
650     }
651     return nValue;
652 }
653 
GetOptimalColWidth(OutputDevice * pDev,double nPPTX,double nPPTY,const Fraction & rZoomX,const Fraction & rZoomY,sal_Bool bFormula,sal_uInt16 nOldWidth,const ScMarkData * pMarkData,sal_Bool bSimpleTextImport)654 sal_uInt16 ScColumn::GetOptimalColWidth( OutputDevice* pDev, double nPPTX, double nPPTY,
655                                         const Fraction& rZoomX, const Fraction& rZoomY,
656                                         sal_Bool bFormula, sal_uInt16 nOldWidth,
657                                         const ScMarkData* pMarkData,
658                                         sal_Bool bSimpleTextImport )
659 {
660     if (nCount == 0)
661         return nOldWidth;
662 
663     sal_uInt16  nWidth = (sal_uInt16) (nOldWidth * nPPTX);
664     sal_Bool    bFound = sal_False;
665 
666     SCSIZE nIndex;
667     ScMarkedDataIter aDataIter(this, pMarkData, sal_True);
668     if ( bSimpleTextImport )
669     {   // alles eins bis auf NumberFormate
670         const ScPatternAttr* pPattern = GetPattern( 0 );
671         Font aFont;
672         // font color doesn't matter here
673         pPattern->GetFont( aFont, SC_AUTOCOL_BLACK, pDev, &rZoomX, NULL );
674         pDev->SetFont( aFont );
675         const SvxMarginItem* pMargin = (const SvxMarginItem*) &pPattern->GetItem(ATTR_MARGIN);
676         long nMargin = (long) ( pMargin->GetLeftMargin() * nPPTX ) +
677                         (long) ( pMargin->GetRightMargin() * nPPTX );
678 
679         while (aDataIter.Next( nIndex ))
680         {
681             sal_uInt16 nThis = (sal_uInt16) (GetSimpleTextNeededSize( nIndex, pDev,
682                 sal_True ) + nMargin);
683             if (nThis)
684             {
685                 if (nThis>nWidth || !bFound)
686                 {
687                     nWidth = nThis;
688                     bFound = sal_True;
689                 }
690             }
691         }
692     }
693     else
694     {
695         ScNeededSizeOptions aOptions;
696         aOptions.bFormula = bFormula;
697         const ScPatternAttr* pOldPattern = NULL;
698         sal_uInt8 nOldScript = 0;
699 
700         while (aDataIter.Next( nIndex ))
701         {
702             SCROW nRow = pItems[nIndex].nRow;
703 
704             sal_uInt8 nScript = pDocument->GetScriptType( nCol, nRow, nTab, pItems[nIndex].pCell );
705             if (nScript == 0) nScript = ScGlobal::GetDefaultScriptType();
706 
707             const ScPatternAttr* pPattern = GetPattern( nRow );
708             aOptions.pPattern = pPattern;
709             aOptions.bGetFont = (pPattern != pOldPattern || nScript != nOldScript);
710             sal_uInt16 nThis = (sal_uInt16) GetNeededSize( nRow, pDev, nPPTX, nPPTY,
711                 rZoomX, rZoomY, sal_True, aOptions );
712             pOldPattern = pPattern;
713             if (nThis)
714             {
715                 if (nThis>nWidth || !bFound)
716                 {
717                     nWidth = nThis;
718                     bFound = sal_True;
719                 }
720             }
721         }
722     }
723 
724     if (bFound)
725     {
726         nWidth += 2;
727         sal_uInt16 nTwips = (sal_uInt16) (nWidth / nPPTX);
728         return nTwips;
729     }
730     else
731         return nOldWidth;
732 }
733 
lcl_GetAttribHeight(const ScPatternAttr & rPattern,sal_uInt16 nFontHeightId)734 sal_uInt16 lcl_GetAttribHeight( const ScPatternAttr& rPattern, sal_uInt16 nFontHeightId )
735 {
736     sal_uInt16 nHeight = (sal_uInt16) ((const SvxFontHeightItem&) rPattern.GetItem(nFontHeightId)).GetHeight();
737     const SvxMarginItem* pMargin = (const SvxMarginItem*) &rPattern.GetItem(ATTR_MARGIN);
738     nHeight += nHeight / 5;
739     //  gibt bei 10pt 240
740 
741     if ( ((const SvxEmphasisMarkItem&)rPattern.
742             GetItem(ATTR_FONT_EMPHASISMARK)).GetEmphasisMark() != EMPHASISMARK_NONE )
743     {
744         //  add height for emphasis marks
745         //! font metrics should be used instead
746         nHeight += nHeight / 4;
747     }
748 
749     if ( nHeight + 240 > ScGlobal::nDefFontHeight )
750     {
751         nHeight = sal::static_int_cast<sal_uInt16>( nHeight + ScGlobal::nDefFontHeight );
752         nHeight -= 240;
753     }
754 
755     //  Standard-Hoehe: TextHeight + Raender - 23
756     //  -> 257 unter Windows
757 
758     if (nHeight > STD_ROWHEIGHT_DIFF)
759         nHeight -= STD_ROWHEIGHT_DIFF;
760 
761     nHeight += pMargin->GetTopMargin() + pMargin->GetBottomMargin();
762 
763     return nHeight;
764 }
765 
766 //  pHeight in Twips
767 //  nMinHeight, nMinStart zur Optimierung: ab nRow >= nMinStart ist mindestens nMinHeight
768 //  (wird nur bei bStdAllowed ausgewertet)
769 
GetOptimalHeight(SCROW nStartRow,SCROW nEndRow,sal_uInt16 * pHeight,OutputDevice * pDev,double nPPTX,double nPPTY,const Fraction & rZoomX,const Fraction & rZoomY,sal_Bool bShrink,sal_uInt16 nMinHeight,SCROW nMinStart)770 void ScColumn::GetOptimalHeight( SCROW nStartRow, SCROW nEndRow, sal_uInt16* pHeight,
771                                 OutputDevice* pDev,
772                                 double nPPTX, double nPPTY,
773                                 const Fraction& rZoomX, const Fraction& rZoomY,
774                                 sal_Bool bShrink, sal_uInt16 nMinHeight, SCROW nMinStart )
775 {
776     ScAttrIterator aIter( pAttrArray, nStartRow, nEndRow );
777 
778     SCROW nStart = -1;
779     SCROW nEnd = -1;
780     SCROW nEditPos = 0;
781     SCROW nNextEnd = 0;
782 
783     //  bei bedingter Formatierung werden immer die einzelnen Zellen angesehen
784 
785     const ScPatternAttr* pPattern = aIter.Next(nStart,nEnd);
786     while ( pPattern )
787     {
788         const ScMergeAttr*      pMerge = (const ScMergeAttr*)&pPattern->GetItem(ATTR_MERGE);
789         const ScMergeFlagAttr*  pFlag = (const ScMergeFlagAttr*)&pPattern->GetItem(ATTR_MERGE_FLAG);
790         if ( pMerge->GetRowMerge() > 1 || pFlag->IsOverlapped() )
791         {
792             //  nix - vertikal bei der zusammengefassten und den ueberdeckten,
793             //        horizontal nur bei den ueberdeckten (unsichtbaren) -
794             //        eine nur horizontal zusammengefasste wird aber beruecksichtigt
795         }
796         else
797         {
798             SCROW nRow = 0;
799             sal_Bool bStdAllowed = (pPattern->GetCellOrientation() == SVX_ORIENTATION_STANDARD);
800             sal_Bool bStdOnly = sal_False;
801             if (bStdAllowed)
802             {
803                 sal_Bool bBreak = ((SfxBoolItem&)pPattern->GetItem(ATTR_LINEBREAK)).GetValue() ||
804                                 ((SvxCellHorJustify)((const SvxHorJustifyItem&)pPattern->
805                                     GetItem( ATTR_HOR_JUSTIFY )).GetValue() ==
806                                     SVX_HOR_JUSTIFY_BLOCK);
807                 bStdOnly = !bBreak;
808 
809                 // bedingte Formatierung: Zellen durchgehen
810                 if ( bStdOnly && ((const SfxUInt32Item&)pPattern->
811                                     GetItem(ATTR_CONDITIONAL)).GetValue() )
812                     bStdOnly = sal_False;
813 
814                 // gedrehter Text: Zellen durchgehen
815                 if ( bStdOnly && ((const SfxInt32Item&)pPattern->
816                                     GetItem(ATTR_ROTATE_VALUE)).GetValue() )
817                     bStdOnly = sal_False;
818             }
819 
820             if (bStdOnly)
821                 if (HasEditCells(nStart,nEnd,nEditPos))     // includes mixed script types
822                 {
823                     if (nEditPos == nStart)
824                     {
825                         bStdOnly = sal_False;
826                         if (nEnd > nEditPos)
827                             nNextEnd = nEnd;
828                         nEnd = nEditPos;                // einzeln ausrechnen
829                         bStdAllowed = sal_False;            // wird auf jeden Fall per Zelle berechnet
830                     }
831                     else
832                     {
833                         nNextEnd = nEnd;
834                         nEnd = nEditPos - 1;            // Standard - Teil
835                     }
836                 }
837 
838             if (bStdAllowed)
839             {
840                 sal_uInt16 nLatHeight = 0;
841                 sal_uInt16 nCjkHeight = 0;
842                 sal_uInt16 nCtlHeight = 0;
843                 sal_uInt16 nDefHeight;
844                 sal_uInt8 nDefScript = ScGlobal::GetDefaultScriptType();
845                 if ( nDefScript == SCRIPTTYPE_ASIAN )
846                     nDefHeight = nCjkHeight = lcl_GetAttribHeight( *pPattern, ATTR_CJK_FONT_HEIGHT );
847                 else if ( nDefScript == SCRIPTTYPE_COMPLEX )
848                     nDefHeight = nCtlHeight = lcl_GetAttribHeight( *pPattern, ATTR_CTL_FONT_HEIGHT );
849                 else
850                     nDefHeight = nLatHeight = lcl_GetAttribHeight( *pPattern, ATTR_FONT_HEIGHT );
851 
852                 //  if everything below is already larger, the loop doesn't have to
853                 //  be run again
854                 SCROW nStdEnd = nEnd;
855                 if ( nDefHeight <= nMinHeight && nStdEnd >= nMinStart )
856                     nStdEnd = (nMinStart>0) ? nMinStart-1 : 0;
857 
858                 for (nRow=nStart; nRow<=nStdEnd; nRow++)
859                     if (nDefHeight > pHeight[nRow-nStartRow])
860                         pHeight[nRow-nStartRow] = nDefHeight;
861 
862                 if ( bStdOnly )
863                 {
864                     //  if cells are not handled individually below,
865                     //  check for cells with different script type
866 
867                     SCSIZE nIndex;
868                     Search(nStart,nIndex);
869                     while ( nIndex < nCount && (nRow=pItems[nIndex].nRow) <= nEnd )
870                     {
871                         sal_uInt8 nScript = pDocument->GetScriptType( nCol, nRow, nTab, pItems[nIndex].pCell );
872                         if ( nScript != nDefScript )
873                         {
874                             if ( nScript == SCRIPTTYPE_ASIAN )
875                             {
876                                 if ( nCjkHeight == 0 )
877                                     nCjkHeight = lcl_GetAttribHeight( *pPattern, ATTR_CJK_FONT_HEIGHT );
878                                 if (nCjkHeight > pHeight[nRow-nStartRow])
879                                     pHeight[nRow-nStartRow] = nCjkHeight;
880                             }
881                             else if ( nScript == SCRIPTTYPE_COMPLEX )
882                             {
883                                 if ( nCtlHeight == 0 )
884                                     nCtlHeight = lcl_GetAttribHeight( *pPattern, ATTR_CTL_FONT_HEIGHT );
885                                 if (nCtlHeight > pHeight[nRow-nStartRow])
886                                     pHeight[nRow-nStartRow] = nCtlHeight;
887                             }
888                             else
889                             {
890                                 if ( nLatHeight == 0 )
891                                     nLatHeight = lcl_GetAttribHeight( *pPattern, ATTR_FONT_HEIGHT );
892                                 if (nLatHeight > pHeight[nRow-nStartRow])
893                                     pHeight[nRow-nStartRow] = nLatHeight;
894                             }
895                         }
896                         ++nIndex;
897                     }
898                 }
899             }
900 
901             if (!bStdOnly)                      // belegte Zellen suchen
902             {
903                 ScNeededSizeOptions aOptions;
904 
905                 SCSIZE nIndex;
906                 Search(nStart,nIndex);
907                 while ( (nIndex < nCount) ? ((nRow=pItems[nIndex].nRow) <= nEnd) : sal_False )
908                 {
909                     //  Zellhoehe nur berechnen, wenn sie spaeter auch gebraucht wird (#37928#)
910 
911                     if ( bShrink || !(pDocument->GetRowFlags(nRow, nTab) & CR_MANUALSIZE) )
912                     {
913                         aOptions.pPattern = pPattern;
914                         sal_uInt16 nHeight = (sal_uInt16)
915                                 ( GetNeededSize( nRow, pDev, nPPTX, nPPTY,
916                                                     rZoomX, rZoomY, sal_False, aOptions ) / nPPTY );
917                         if (nHeight > pHeight[nRow-nStartRow])
918                             pHeight[nRow-nStartRow] = nHeight;
919                     }
920                     ++nIndex;
921                 }
922             }
923         }
924 
925         if (nNextEnd > 0)
926         {
927             nStart = nEnd + 1;
928             nEnd = nNextEnd;
929             nNextEnd = 0;
930         }
931         else
932             pPattern = aIter.Next(nStart,nEnd);
933     }
934 }
935 
GetNextSpellingCell(SCROW & nRow,sal_Bool bInSel,const ScMarkData & rData) const936 sal_Bool ScColumn::GetNextSpellingCell(SCROW& nRow, sal_Bool bInSel, const ScMarkData& rData) const
937 {
938     sal_Bool bStop = sal_False;
939     CellType eCellType;
940     SCSIZE nIndex;
941     if (!bInSel && Search(nRow, nIndex))
942     {
943         eCellType = GetCellType(nRow);
944         if ( (eCellType == CELLTYPE_STRING || eCellType == CELLTYPE_EDIT) &&
945              !(HasAttrib( nRow, nRow, HASATTR_PROTECTED) &&
946                pDocument->IsTabProtected(nTab)) )
947                 return sal_True;
948     }
949     while (!bStop)
950     {
951         if (bInSel)
952         {
953             nRow = rData.GetNextMarked(nCol, nRow, sal_False);
954             if (!ValidRow(nRow))
955             {
956                 nRow = MAXROW+1;
957                 bStop = sal_True;
958             }
959             else
960             {
961                 eCellType = GetCellType(nRow);
962                 if ( (eCellType == CELLTYPE_STRING || eCellType == CELLTYPE_EDIT) &&
963                      !(HasAttrib( nRow, nRow, HASATTR_PROTECTED) &&
964                        pDocument->IsTabProtected(nTab)) )
965                         return sal_True;
966                 else
967                     nRow++;
968             }
969         }
970         else if (GetNextDataPos(nRow))
971         {
972             eCellType = GetCellType(nRow);
973             if ( (eCellType == CELLTYPE_STRING || eCellType == CELLTYPE_EDIT) &&
974                  !(HasAttrib( nRow, nRow, HASATTR_PROTECTED) &&
975                    pDocument->IsTabProtected(nTab)) )
976                     return sal_True;
977             else
978                 nRow++;
979         }
980         else
981         {
982             nRow = MAXROW+1;
983             bStop = sal_True;
984         }
985     }
986     return sal_False;
987 }
988 
989 // =========================================================================================
990 
RemoveAutoSpellObj()991 void ScColumn::RemoveAutoSpellObj()
992 {
993     ScTabEditEngine* pEngine = NULL;
994 
995     for (SCSIZE i=0; i<nCount; i++)
996         if ( pItems[i].pCell->GetCellType() == CELLTYPE_EDIT )
997         {
998             ScEditCell* pOldCell = (ScEditCell*) pItems[i].pCell;
999             const EditTextObject* pData = pOldCell->GetData();
1000             //  keine Abfrage auf HasOnlineSpellErrors, damit es auch
1001             //  nach dem Laden funktioniert
1002 
1003             //  Fuer den Test auf harte Formatierung (ScEditAttrTester) sind die Defaults
1004             //  in der EditEngine unwichtig. Wenn der Tester spaeter einmal gleiche
1005             //  Attribute in Default und harter Formatierung erkennen und weglassen sollte,
1006             //  muessten an der EditEngine zu jeder Zelle die richtigen Defaults gesetzt
1007             //  werden!
1008 
1009             //  auf Attribute testen
1010             if ( !pEngine )
1011                 pEngine = new ScTabEditEngine(pDocument);
1012             pEngine->SetText( *pData );
1013             ScEditAttrTester aTester( pEngine );
1014             if ( aTester.NeedsObject() )                    // nur Spell-Errors entfernen
1015             {
1016                 EditTextObject* pNewData = pEngine->CreateTextObject(); // ohne BIGOBJ
1017                 pOldCell->SetData( pNewData, pEngine->GetEditTextObjectPool() );
1018                 delete pNewData;
1019             }
1020             else                                            // String erzeugen
1021             {
1022                 String aText = ScEditUtil::GetSpaceDelimitedString( *pEngine );
1023                 ScBaseCell* pNewCell = new ScStringCell( aText );
1024                 pNewCell->TakeBroadcaster( pOldCell->ReleaseBroadcaster() );
1025                 pNewCell->TakeNote( pOldCell->ReleaseNote() );
1026                 pItems[i].pCell = pNewCell;
1027                 delete pOldCell;
1028             }
1029         }
1030 
1031     delete pEngine;
1032 }
1033 
RemoveEditAttribs(SCROW nStartRow,SCROW nEndRow)1034 void ScColumn::RemoveEditAttribs( SCROW nStartRow, SCROW nEndRow )
1035 {
1036     ScFieldEditEngine* pEngine = NULL;
1037 
1038     SCSIZE i;
1039     Search( nStartRow, i );
1040     for (; i<nCount && pItems[i].nRow <= nEndRow; i++)
1041         if ( pItems[i].pCell->GetCellType() == CELLTYPE_EDIT )
1042         {
1043             ScEditCell* pOldCell = (ScEditCell*) pItems[i].pCell;
1044             const EditTextObject* pData = pOldCell->GetData();
1045 
1046             //  Fuer den Test auf harte Formatierung (ScEditAttrTester) sind die Defaults
1047             //  in der EditEngine unwichtig. Wenn der Tester spaeter einmal gleiche
1048             //  Attribute in Default und harter Formatierung erkennen und weglassen sollte,
1049             //  muessten an der EditEngine zu jeder Zelle die richtigen Defaults gesetzt
1050             //  werden!
1051 
1052             //  auf Attribute testen
1053             if ( !pEngine )
1054             {
1055                 //pEngine = new ScTabEditEngine(pDocument);
1056                 pEngine = new ScFieldEditEngine( pDocument->GetEditPool() );
1057                 //  EE_CNTRL_ONLINESPELLING falls schon Fehler drin sind
1058                 pEngine->SetControlWord( pEngine->GetControlWord() | EE_CNTRL_ONLINESPELLING );
1059                 pDocument->ApplyAsianEditSettings( *pEngine );
1060             }
1061             pEngine->SetText( *pData );
1062             sal_uInt16 nParCount = pEngine->GetParagraphCount();
1063             for (sal_uInt16 nPar=0; nPar<nParCount; nPar++)
1064             {
1065                 pEngine->QuickRemoveCharAttribs( nPar );
1066                 const SfxItemSet& rOld = pEngine->GetParaAttribs( nPar );
1067                 if ( rOld.Count() )
1068                 {
1069                     SfxItemSet aNew( *rOld.GetPool(), rOld.GetRanges() );   // leer
1070                     pEngine->SetParaAttribs( nPar, aNew );
1071                 }
1072             }
1073             //  URL-Felder in Text wandeln (andere gibt's nicht, darum pType=0)
1074             pEngine->RemoveFields( sal_True );
1075 
1076             sal_Bool bSpellErrors = pEngine->HasOnlineSpellErrors();
1077             sal_Bool bNeedObject = bSpellErrors || nParCount>1;         // Errors/Absaetze behalten
1078             //  ScEditAttrTester nicht mehr noetig, Felder sind raus
1079 
1080             if ( bNeedObject )                                      // bleibt Edit-Zelle
1081             {
1082                 sal_uLong nCtrl = pEngine->GetControlWord();
1083                 sal_uLong nWantBig = bSpellErrors ? EE_CNTRL_ALLOWBIGOBJS : 0;
1084                 if ( ( nCtrl & EE_CNTRL_ALLOWBIGOBJS ) != nWantBig )
1085                     pEngine->SetControlWord( (nCtrl & ~EE_CNTRL_ALLOWBIGOBJS) | nWantBig );
1086                 EditTextObject* pNewData = pEngine->CreateTextObject();
1087                 pOldCell->SetData( pNewData, pEngine->GetEditTextObjectPool() );
1088                 delete pNewData;
1089             }
1090             else                                            // String erzeugen
1091             {
1092                 String aText = ScEditUtil::GetSpaceDelimitedString( *pEngine );
1093                 ScBaseCell* pNewCell = new ScStringCell( aText );
1094                 pNewCell->TakeBroadcaster( pOldCell->ReleaseBroadcaster() );
1095                 pNewCell->TakeNote( pOldCell->ReleaseNote() );
1096                 pItems[i].pCell = pNewCell;
1097                 delete pOldCell;
1098             }
1099         }
1100 
1101     delete pEngine;
1102 }
1103 
1104 // =========================================================================================
1105 
TestTabRefAbs(SCTAB nTable)1106 sal_Bool ScColumn::TestTabRefAbs(SCTAB nTable)
1107 {
1108     sal_Bool bRet = sal_False;
1109     if (pItems)
1110         for (SCSIZE i = 0; i < nCount; i++)
1111             if ( pItems[i].pCell->GetCellType() == CELLTYPE_FORMULA )
1112                 if (((ScFormulaCell*)pItems[i].pCell)->TestTabRefAbs(nTable))
1113                     bRet = sal_True;
1114     return bRet;
1115 }
1116 
1117 // =========================================================================================
1118 
ScColumnIterator(const ScColumn * pCol,SCROW nStart,SCROW nEnd)1119 ScColumnIterator::ScColumnIterator( const ScColumn* pCol, SCROW nStart, SCROW nEnd ) :
1120     pColumn( pCol ),
1121     nTop( nStart ),
1122     nBottom( nEnd )
1123 {
1124     pColumn->Search( nTop, nPos );
1125 }
1126 
~ScColumnIterator()1127 ScColumnIterator::~ScColumnIterator()
1128 {
1129 }
1130 
Next(SCROW & rRow,ScBaseCell * & rpCell)1131 sal_Bool ScColumnIterator::Next( SCROW& rRow, ScBaseCell*& rpCell )
1132 {
1133     if ( nPos < pColumn->nCount )
1134     {
1135         rRow = pColumn->pItems[nPos].nRow;
1136         if ( rRow <= nBottom )
1137         {
1138             rpCell = pColumn->pItems[nPos].pCell;
1139             ++nPos;
1140             return sal_True;
1141         }
1142     }
1143 
1144     rRow = 0;
1145     rpCell = NULL;
1146     return sal_False;
1147 }
1148 
GetIndex() const1149 SCSIZE ScColumnIterator::GetIndex() const           // Index zur letzen abgefragten Zelle
1150 {
1151     return nPos - 1;        // bei Next ist Pos hochgezaehlt worden
1152 }
1153 
1154 // -----------------------------------------------------------------------------------------
1155 
ScMarkedDataIter(const ScColumn * pCol,const ScMarkData * pMarkData,sal_Bool bAllIfNone)1156 ScMarkedDataIter::ScMarkedDataIter( const ScColumn* pCol, const ScMarkData* pMarkData,
1157                                     sal_Bool bAllIfNone ) :
1158     pColumn( pCol ),
1159     pMarkIter( NULL ),
1160     bNext( sal_True ),
1161     bAll( bAllIfNone )
1162 {
1163     if (pMarkData && pMarkData->IsMultiMarked())
1164         pMarkIter = new ScMarkArrayIter( pMarkData->GetArray() + pCol->GetCol() );
1165 }
1166 
~ScMarkedDataIter()1167 ScMarkedDataIter::~ScMarkedDataIter()
1168 {
1169     delete pMarkIter;
1170 }
1171 
Next(SCSIZE & rIndex)1172 sal_Bool ScMarkedDataIter::Next( SCSIZE& rIndex )
1173 {
1174     sal_Bool bFound = sal_False;
1175     do
1176     {
1177         if (bNext)
1178         {
1179             if (!pMarkIter || !pMarkIter->Next( nTop, nBottom ))
1180             {
1181                 if (bAll)                   // ganze Spalte
1182                 {
1183                     nTop    = 0;
1184                     nBottom = MAXROW;
1185                 }
1186                 else
1187                     return sal_False;
1188             }
1189             pColumn->Search( nTop, nPos );
1190             bNext = sal_False;
1191             bAll  = sal_False;                  // nur beim ersten Versuch
1192         }
1193 
1194         if ( nPos >= pColumn->nCount )
1195             return sal_False;
1196 
1197         if ( pColumn->pItems[nPos].nRow <= nBottom )
1198             bFound = sal_True;
1199         else
1200             bNext = sal_True;
1201     }
1202     while (!bFound);
1203 
1204     rIndex = nPos++;
1205     return sal_True;
1206 }
1207 
1208 //UNUSED2009-05 sal_uInt16 ScColumn::GetErrorData( SCROW nRow ) const
1209 //UNUSED2009-05 {
1210 //UNUSED2009-05     SCSIZE  nIndex;
1211 //UNUSED2009-05     if (Search(nRow, nIndex))
1212 //UNUSED2009-05     {
1213 //UNUSED2009-05         ScBaseCell* pCell = pItems[nIndex].pCell;
1214 //UNUSED2009-05         switch (pCell->GetCellType())
1215 //UNUSED2009-05         {
1216 //UNUSED2009-05             case CELLTYPE_FORMULA :
1217 //UNUSED2009-05                 return ((ScFormulaCell*)pCell)->GetErrCode();
1218 //UNUSED2009-05 //            break;
1219 //UNUSED2009-05             default:
1220 //UNUSED2009-05             return 0;
1221 //UNUSED2009-05         }
1222 //UNUSED2009-05     }
1223 //UNUSED2009-05     return 0;
1224 //UNUSED2009-05 }
1225 
1226 //------------
1227 
IsEmptyData() const1228 sal_Bool ScColumn::IsEmptyData() const
1229 {
1230     return (nCount == 0);
1231 }
1232 
IsEmptyVisData(sal_Bool bNotes) const1233 sal_Bool ScColumn::IsEmptyVisData(sal_Bool bNotes) const
1234 {
1235     if (!pItems || nCount == 0)
1236         return sal_True;
1237     else
1238     {
1239         sal_Bool bVisData = sal_False;
1240         SCSIZE i;
1241         for (i=0; i<nCount && !bVisData; i++)
1242         {
1243             ScBaseCell* pCell = pItems[i].pCell;
1244             if ( pCell->GetCellType() != CELLTYPE_NOTE || (bNotes && pCell->HasNote()) )
1245                 bVisData = sal_True;
1246         }
1247         return !bVisData;
1248     }
1249 }
1250 
VisibleCount(SCROW nStartRow,SCROW nEndRow) const1251 SCSIZE ScColumn::VisibleCount( SCROW nStartRow, SCROW nEndRow ) const
1252 {
1253     //  Notizen werden nicht mitgezaehlt
1254 
1255     SCSIZE nVisCount = 0;
1256     SCSIZE nIndex;
1257     Search( nStartRow, nIndex );
1258     while ( nIndex < nCount && pItems[nIndex].nRow <= nEndRow )
1259     {
1260         if ( pItems[nIndex].nRow >= nStartRow &&
1261              pItems[nIndex].pCell->GetCellType() != CELLTYPE_NOTE )
1262         {
1263             ++nVisCount;
1264         }
1265         ++nIndex;
1266     }
1267     return nVisCount;
1268 }
1269 
GetLastVisDataPos(sal_Bool bNotes) const1270 SCROW ScColumn::GetLastVisDataPos(sal_Bool bNotes) const
1271 {
1272     SCROW nRet = 0;
1273     if (pItems)
1274     {
1275         SCSIZE i;
1276         sal_Bool bFound = sal_False;
1277         for (i=nCount; i>0 && !bFound; )
1278         {
1279             --i;
1280             ScBaseCell* pCell = pItems[i].pCell;
1281             if ( pCell->GetCellType() != CELLTYPE_NOTE || (bNotes && pCell->HasNote()) )
1282             {
1283                 bFound = sal_True;
1284                 nRet = pItems[i].nRow;
1285             }
1286         }
1287     }
1288     return nRet;
1289 }
1290 
GetFirstVisDataPos(sal_Bool bNotes) const1291 SCROW ScColumn::GetFirstVisDataPos(sal_Bool bNotes) const
1292 {
1293     SCROW nRet = 0;
1294     if (pItems)
1295     {
1296         SCSIZE i;
1297         sal_Bool bFound = sal_False;
1298         for (i=0; i<nCount && !bFound; i++)
1299         {
1300             ScBaseCell* pCell = pItems[i].pCell;
1301             if ( pCell->GetCellType() != CELLTYPE_NOTE || (bNotes && pCell->HasNote()) )
1302             {
1303                 bFound = sal_True;
1304                 nRet = pItems[i].nRow;
1305             }
1306         }
1307     }
1308     return nRet;
1309 }
1310 
HasVisibleDataAt(SCROW nRow) const1311 sal_Bool ScColumn::HasVisibleDataAt(SCROW nRow) const
1312 {
1313     SCSIZE nIndex;
1314     if (Search(nRow, nIndex))
1315         if (!pItems[nIndex].pCell->IsBlank())
1316             return sal_True;
1317 
1318     return sal_False;
1319 }
1320 
IsEmptyAttr() const1321 sal_Bool ScColumn::IsEmptyAttr() const
1322 {
1323     if (pAttrArray)
1324         return pAttrArray->IsEmpty();
1325     else
1326         return sal_True;
1327 }
1328 
IsEmpty() const1329 sal_Bool ScColumn::IsEmpty() const
1330 {
1331     return (IsEmptyData() && IsEmptyAttr());
1332 }
1333 
IsEmptyBlock(SCROW nStartRow,SCROW nEndRow,bool bIgnoreNotes) const1334 sal_Bool ScColumn::IsEmptyBlock(SCROW nStartRow, SCROW nEndRow, bool bIgnoreNotes) const
1335 {
1336     if ( nCount == 0 || !pItems )
1337         return sal_True;
1338 
1339     SCSIZE nIndex;
1340     Search( nStartRow, nIndex );
1341     while ( nIndex < nCount && pItems[nIndex].nRow <= nEndRow )
1342     {
1343         if ( !pItems[nIndex].pCell->IsBlank( bIgnoreNotes ) )   // found a cell
1344             return sal_False;                           // not empty
1345         ++nIndex;
1346     }
1347     return sal_True;                                    // no cell found
1348 }
1349 
GetEmptyLinesInBlock(SCROW nStartRow,SCROW nEndRow,ScDirection eDir) const1350 SCSIZE ScColumn::GetEmptyLinesInBlock( SCROW nStartRow, SCROW nEndRow, ScDirection eDir ) const
1351 {
1352     SCSIZE nLines = 0;
1353     sal_Bool bFound = sal_False;
1354     SCSIZE i;
1355     if (pItems && (nCount > 0))
1356     {
1357         if (eDir == DIR_BOTTOM)
1358         {
1359             i = nCount;
1360             while (!bFound && (i > 0))
1361             {
1362                 i--;
1363                 if ( pItems[i].nRow < nStartRow )
1364                     break;
1365                 bFound = pItems[i].nRow <= nEndRow && !pItems[i].pCell->IsBlank();
1366             }
1367             if (bFound)
1368                 nLines = static_cast<SCSIZE>(nEndRow - pItems[i].nRow);
1369             else
1370                 nLines = static_cast<SCSIZE>(nEndRow - nStartRow);
1371         }
1372         else if (eDir == DIR_TOP)
1373         {
1374             i = 0;
1375             while (!bFound && (i < nCount))
1376             {
1377                 if ( pItems[i].nRow > nEndRow )
1378                     break;
1379                 bFound = pItems[i].nRow >= nStartRow && !pItems[i].pCell->IsBlank();
1380                 i++;
1381             }
1382             if (bFound)
1383                 nLines = static_cast<SCSIZE>(pItems[i-1].nRow - nStartRow);
1384             else
1385                 nLines = static_cast<SCSIZE>(nEndRow - nStartRow);
1386         }
1387     }
1388     else
1389         nLines = static_cast<SCSIZE>(nEndRow - nStartRow);
1390     return nLines;
1391 }
1392 
GetFirstDataPos() const1393 SCROW ScColumn::GetFirstDataPos() const
1394 {
1395     if (nCount)
1396         return pItems[0].nRow;
1397     else
1398         return 0;
1399 }
1400 
GetLastDataPos() const1401 SCROW ScColumn::GetLastDataPos() const
1402 {
1403     if (nCount)
1404         return pItems[nCount-1].nRow;
1405     else
1406         return 0;
1407 }
1408 
GetPrevDataPos(SCROW & rRow) const1409 sal_Bool ScColumn::GetPrevDataPos(SCROW& rRow) const
1410 {
1411     sal_Bool bFound = sal_False;
1412     SCSIZE i = nCount;
1413     while (!bFound && (i > 0))
1414     {
1415         --i;
1416         bFound = (pItems[i].nRow < rRow);
1417         if (bFound)
1418             rRow = pItems[i].nRow;
1419     }
1420     return bFound;
1421 }
1422 
GetNextDataPos(SCROW & rRow) const1423 sal_Bool ScColumn::GetNextDataPos(SCROW& rRow) const        // greater than rRow
1424 {
1425     SCSIZE nIndex;
1426     if (Search( rRow, nIndex ))
1427         ++nIndex;                   // next cell
1428 
1429     sal_Bool bMore = ( nIndex < nCount );
1430     if ( bMore )
1431         rRow = pItems[nIndex].nRow;
1432     return bMore;
1433 }
1434 
FindDataAreaPos(SCROW & rRow,long nMovY) const1435 void ScColumn::FindDataAreaPos(SCROW& rRow, long nMovY) const
1436 {
1437     if (!nMovY) return;
1438     sal_Bool bForward = (nMovY>0);
1439 
1440     SCSIZE nIndex;
1441     sal_Bool bThere = Search(rRow, nIndex);
1442     if (bThere && pItems[nIndex].pCell->IsBlank())
1443         bThere = sal_False;
1444 
1445     if (bThere)
1446     {
1447         SCROW nLast = rRow;
1448         SCSIZE nOldIndex = nIndex;
1449         if (bForward)
1450         {
1451             if (nIndex<nCount-1)
1452             {
1453                 ++nIndex;
1454                 while (nIndex<nCount-1 && pItems[nIndex].nRow==nLast+1
1455                                         && !pItems[nIndex].pCell->IsBlank())
1456                 {
1457                     ++nIndex;
1458                     ++nLast;
1459                 }
1460                 if (nIndex==nCount-1)
1461                     if (pItems[nIndex].nRow==nLast+1 && !pItems[nIndex].pCell->IsBlank())
1462                         ++nLast;
1463             }
1464         }
1465         else
1466         {
1467             if (nIndex>0)
1468             {
1469                 --nIndex;
1470                 while (nIndex>0 && pItems[nIndex].nRow+1==nLast
1471                                         && !pItems[nIndex].pCell->IsBlank())
1472                 {
1473                     --nIndex;
1474                     --nLast;
1475                 }
1476                 if (nIndex==0)
1477                     if (pItems[nIndex].nRow+1==nLast && !pItems[nIndex].pCell->IsBlank())
1478                         --nLast;
1479             }
1480         }
1481         if (nLast==rRow)
1482         {
1483             bThere = sal_False;
1484             nIndex = bForward ? nOldIndex+1 : nOldIndex;
1485         }
1486         else
1487             rRow = nLast;
1488     }
1489 
1490     if (!bThere)
1491     {
1492         if (bForward)
1493         {
1494             while (nIndex<nCount && pItems[nIndex].pCell->IsBlank())
1495                 ++nIndex;
1496             if (nIndex<nCount)
1497                 rRow = pItems[nIndex].nRow;
1498             else
1499                 rRow = MAXROW;
1500         }
1501         else
1502         {
1503             while (nIndex>0 && pItems[nIndex-1].pCell->IsBlank())
1504                 --nIndex;
1505             if (nIndex>0)
1506                 rRow = pItems[nIndex-1].nRow;
1507             else
1508                 rRow = 0;
1509         }
1510     }
1511 }
1512 
HasDataAt(SCROW nRow) const1513 sal_Bool ScColumn::HasDataAt(SCROW nRow) const
1514 {
1515 /*  SCSIZE nIndex;
1516     return Search( nRow, nIndex );
1517 */
1518         //  immer nur sichtbare interessant ?
1519         //! dann HasVisibleDataAt raus
1520 
1521     SCSIZE nIndex;
1522     if (Search(nRow, nIndex))
1523         if (!pItems[nIndex].pCell->IsBlank())
1524             return sal_True;
1525 
1526     return sal_False;
1527 
1528 }
1529 
IsAllAttrEqual(const ScColumn & rCol,SCROW nStartRow,SCROW nEndRow) const1530 sal_Bool ScColumn::IsAllAttrEqual( const ScColumn& rCol, SCROW nStartRow, SCROW nEndRow ) const
1531 {
1532     if (pAttrArray && rCol.pAttrArray)
1533         return pAttrArray->IsAllEqual( *rCol.pAttrArray, nStartRow, nEndRow );
1534     else
1535         return !pAttrArray && !rCol.pAttrArray;
1536 }
1537 
IsVisibleAttrEqual(const ScColumn & rCol,SCROW nStartRow,SCROW nEndRow) const1538 sal_Bool ScColumn::IsVisibleAttrEqual( const ScColumn& rCol, SCROW nStartRow, SCROW nEndRow ) const
1539 {
1540     if (pAttrArray && rCol.pAttrArray)
1541         return pAttrArray->IsVisibleEqual( *rCol.pAttrArray, nStartRow, nEndRow );
1542     else
1543         return !pAttrArray && !rCol.pAttrArray;
1544 }
1545 
GetFirstVisibleAttr(SCROW & rFirstRow) const1546 sal_Bool ScColumn::GetFirstVisibleAttr( SCROW& rFirstRow ) const
1547 {
1548     if (pAttrArray)
1549         return pAttrArray->GetFirstVisibleAttr( rFirstRow );
1550     else
1551         return sal_False;
1552 }
1553 
GetLastVisibleAttr(SCROW & rLastRow) const1554 sal_Bool ScColumn::GetLastVisibleAttr( SCROW& rLastRow ) const
1555 {
1556     if (pAttrArray)
1557     {
1558         // row of last cell is needed
1559         SCROW nLastData = GetLastVisDataPos( sal_True );    // always including notes, 0 if none
1560 
1561         return pAttrArray->GetLastVisibleAttr( rLastRow, nLastData );
1562     }
1563     else
1564         return sal_False;
1565 }
1566 
GetLastAttr(SCROW & rLastRow) const1567 sal_Bool ScColumn::GetLastAttr( SCROW& rLastRow ) const
1568 {
1569     if ( pAttrArray )
1570     {
1571         // Row of last cell is needed, always including notes, 0 if none.
1572         SCROW nLastData = GetLastVisDataPos( sal_True );
1573         return pAttrArray->GetLastAttr( rLastRow, nLastData );
1574     }
1575     else
1576     {
1577         return sal_False;
1578     }
1579 }
HasVisibleAttrIn(SCROW nStartRow,SCROW nEndRow) const1580 sal_Bool ScColumn::HasVisibleAttrIn( SCROW nStartRow, SCROW nEndRow ) const
1581 {
1582     if (pAttrArray)
1583         return pAttrArray->HasVisibleAttrIn( nStartRow, nEndRow );
1584     else
1585         return sal_False;
1586 }
1587 
FindUsed(SCROW nStartRow,SCROW nEndRow,sal_Bool * pUsed) const1588 void ScColumn::FindUsed( SCROW nStartRow, SCROW nEndRow, sal_Bool* pUsed ) const
1589 {
1590     SCROW nRow = 0;
1591     SCSIZE nIndex;
1592     Search( nStartRow, nIndex );
1593     while ( (nIndex < nCount) ? ((nRow=pItems[nIndex].nRow) <= nEndRow) : sal_False )
1594     {
1595         pUsed[nRow-nStartRow] = sal_True;
1596         ++nIndex;
1597     }
1598 }
1599 
StartListening(SvtListener & rLst,SCROW nRow)1600 void ScColumn::StartListening( SvtListener& rLst, SCROW nRow )
1601 {
1602     SvtBroadcaster* pBC = NULL;
1603     ScBaseCell* pCell;
1604 
1605     SCSIZE nIndex;
1606     if (Search(nRow,nIndex))
1607     {
1608         pCell = pItems[nIndex].pCell;
1609         pBC = pCell->GetBroadcaster();
1610     }
1611     else
1612     {
1613         pCell = new ScNoteCell;
1614         Insert(nRow, pCell);
1615     }
1616 
1617     if (!pBC)
1618     {
1619         pBC = new SvtBroadcaster;
1620         pCell->TakeBroadcaster(pBC);
1621     }
1622     rLst.StartListening(*pBC);
1623 }
1624 
MoveListeners(SvtBroadcaster & rSource,SCROW nDestRow)1625 void ScColumn::MoveListeners( SvtBroadcaster& rSource, SCROW nDestRow )
1626 {
1627     SvtBroadcaster* pBC = NULL;
1628     ScBaseCell* pCell;
1629 
1630     SCSIZE nIndex;
1631     if (Search(nDestRow,nIndex))
1632     {
1633         pCell = pItems[nIndex].pCell;
1634         pBC = pCell->GetBroadcaster();
1635     }
1636     else
1637     {
1638         pCell = new ScNoteCell;
1639         Insert(nDestRow, pCell);
1640     }
1641 
1642     if (!pBC)
1643     {
1644         pBC = new SvtBroadcaster;
1645         pCell->TakeBroadcaster(pBC);
1646     }
1647 
1648     if (rSource.HasListeners())
1649     {
1650         SvtListenerIter aIter( rSource);
1651         for (SvtListener* pLst = aIter.GoStart(); pLst; pLst = aIter.GoNext())
1652         {
1653             pLst->StartListening( *pBC);
1654             pLst->EndListening( rSource);
1655         }
1656     }
1657 }
1658 
EndListening(SvtListener & rLst,SCROW nRow)1659 void ScColumn::EndListening( SvtListener& rLst, SCROW nRow )
1660 {
1661     SCSIZE nIndex;
1662     if (Search(nRow,nIndex))
1663     {
1664         ScBaseCell* pCell = pItems[nIndex].pCell;
1665         SvtBroadcaster* pBC = pCell->GetBroadcaster();
1666         if (pBC)
1667         {
1668             rLst.EndListening(*pBC);
1669 
1670             if (!pBC->HasListeners())
1671             {
1672                 if (pCell->IsBlank())
1673                     DeleteAtIndex(nIndex);
1674                 else
1675                     pCell->DeleteBroadcaster();
1676             }
1677         }
1678 //      else
1679 //          DBG_ERROR("ScColumn::EndListening - kein Broadcaster");
1680     }
1681 //  else
1682 //      DBG_ERROR("ScColumn::EndListening - keine Zelle");
1683 }
1684 
CompileDBFormula()1685 void ScColumn::CompileDBFormula()
1686 {
1687     if (pItems)
1688         for (SCSIZE i = 0; i < nCount; i++)
1689         {
1690             ScBaseCell* pCell = pItems[i].pCell;
1691             if ( pCell->GetCellType() == CELLTYPE_FORMULA )
1692                 ((ScFormulaCell*) pCell)->CompileDBFormula();
1693         }
1694 }
1695 
CompileDBFormula(sal_Bool bCreateFormulaString)1696 void ScColumn::CompileDBFormula( sal_Bool bCreateFormulaString )
1697 {
1698     if (pItems)
1699         for (SCSIZE i = 0; i < nCount; i++)
1700         {
1701             ScBaseCell* pCell = pItems[i].pCell;
1702             if ( pCell->GetCellType() == CELLTYPE_FORMULA )
1703                 ((ScFormulaCell*) pCell)->CompileDBFormula( bCreateFormulaString );
1704         }
1705 }
1706 
CompileNameFormula(sal_Bool bCreateFormulaString)1707 void ScColumn::CompileNameFormula( sal_Bool bCreateFormulaString )
1708 {
1709     if (pItems)
1710         for (SCSIZE i = 0; i < nCount; i++)
1711         {
1712             ScBaseCell* pCell = pItems[i].pCell;
1713             if ( pCell->GetCellType() == CELLTYPE_FORMULA )
1714                 ((ScFormulaCell*) pCell)->CompileNameFormula( bCreateFormulaString );
1715         }
1716 }
1717 
CompileColRowNameFormula()1718 void ScColumn::CompileColRowNameFormula()
1719 {
1720     if (pItems)
1721         for (SCSIZE i = 0; i < nCount; i++)
1722         {
1723             ScBaseCell* pCell = pItems[i].pCell;
1724             if ( pCell->GetCellType() == CELLTYPE_FORMULA )
1725                 ((ScFormulaCell*) pCell)->CompileColRowNameFormula();
1726         }
1727 }
1728 
lcl_UpdateSubTotal(ScFunctionData & rData,ScBaseCell * pCell)1729 void lcl_UpdateSubTotal( ScFunctionData& rData, ScBaseCell* pCell )
1730 {
1731     double nValue = 0.0;
1732     sal_Bool bVal = sal_False;
1733     sal_Bool bCell = sal_True;
1734     switch (pCell->GetCellType())
1735     {
1736         case CELLTYPE_VALUE:
1737             nValue = ((ScValueCell*)pCell)->GetValue();
1738             bVal = sal_True;
1739             break;
1740         case CELLTYPE_FORMULA:
1741             {
1742                 if ( rData.eFunc != SUBTOTAL_FUNC_CNT2 )        // da interessiert's nicht
1743                 {
1744                     ScFormulaCell* pFC = (ScFormulaCell*)pCell;
1745                     if ( pFC->GetErrCode() )
1746                     {
1747                         if ( rData.eFunc != SUBTOTAL_FUNC_CNT ) // fuer Anzahl einfach weglassen
1748                             rData.bError = sal_True;
1749                     }
1750                     else if (pFC->IsValue())
1751                     {
1752                         nValue = pFC->GetValue();
1753                         bVal = sal_True;
1754                     }
1755                     // sonst Text
1756                 }
1757             }
1758             break;
1759         case CELLTYPE_NOTE:
1760             bCell = sal_False;
1761             break;
1762         // bei Strings nichts
1763         default:
1764         {
1765             // added to avoid warnings
1766         }
1767     }
1768 
1769     if (!rData.bError)
1770     {
1771         switch (rData.eFunc)
1772         {
1773             case SUBTOTAL_FUNC_SUM:
1774             case SUBTOTAL_FUNC_AVE:
1775                 if (bVal)
1776                 {
1777                     ++rData.nCount;
1778                     if (!SubTotal::SafePlus( rData.nVal, nValue ))
1779                         rData.bError = sal_True;
1780                 }
1781                 break;
1782             case SUBTOTAL_FUNC_CNT:             // nur Werte
1783                 if (bVal)
1784                     ++rData.nCount;
1785                 break;
1786             case SUBTOTAL_FUNC_CNT2:            // alle
1787                 if (bCell)
1788                     ++rData.nCount;
1789                 break;
1790             case SUBTOTAL_FUNC_MAX:
1791                 if (bVal)
1792                     if (++rData.nCount == 1 || nValue > rData.nVal )
1793                         rData.nVal = nValue;
1794                 break;
1795             case SUBTOTAL_FUNC_MIN:
1796                 if (bVal)
1797                     if (++rData.nCount == 1 || nValue < rData.nVal )
1798                         rData.nVal = nValue;
1799                 break;
1800             default:
1801             {
1802                 // added to avoid warnings
1803             }
1804         }
1805     }
1806 }
1807 
1808 //  Mehrfachselektion:
UpdateSelectionFunction(const ScMarkData & rMark,ScFunctionData & rData,ScFlatBoolRowSegments & rHiddenRows,sal_Bool bDoExclude,SCROW nExStartRow,SCROW nExEndRow)1809 void ScColumn::UpdateSelectionFunction( const ScMarkData& rMark,
1810                                         ScFunctionData& rData,
1811                                         ScFlatBoolRowSegments& rHiddenRows,
1812                                         sal_Bool bDoExclude, SCROW nExStartRow, SCROW nExEndRow )
1813 {
1814     SCSIZE nIndex;
1815     ScMarkedDataIter aDataIter(this, &rMark, sal_False);
1816     while (aDataIter.Next( nIndex ))
1817     {
1818         SCROW nRow = pItems[nIndex].nRow;
1819         bool bRowHidden = rHiddenRows.getValue(nRow);
1820         if ( !bRowHidden )
1821             if ( !bDoExclude || nRow < nExStartRow || nRow > nExEndRow )
1822                 lcl_UpdateSubTotal( rData, pItems[nIndex].pCell );
1823     }
1824 }
1825 
1826 //  bei bNoMarked die Mehrfachselektion weglassen
UpdateAreaFunction(ScFunctionData & rData,ScFlatBoolRowSegments & rHiddenRows,SCROW nStartRow,SCROW nEndRow)1827 void ScColumn::UpdateAreaFunction( ScFunctionData& rData,
1828                                    ScFlatBoolRowSegments& rHiddenRows,
1829                                     SCROW nStartRow, SCROW nEndRow )
1830 {
1831     SCSIZE nIndex;
1832     Search( nStartRow, nIndex );
1833     while ( nIndex<nCount && pItems[nIndex].nRow<=nEndRow )
1834     {
1835         SCROW nRow = pItems[nIndex].nRow;
1836         bool bRowHidden = rHiddenRows.getValue(nRow);
1837         if ( !bRowHidden )
1838             lcl_UpdateSubTotal( rData, pItems[nIndex].pCell );
1839         ++nIndex;
1840     }
1841 }
1842 
GetWeightedCount() const1843 sal_uLong ScColumn::GetWeightedCount() const
1844 {
1845     sal_uLong nTotal = 0;
1846 
1847     //  Notizen werden nicht gezaehlt
1848 
1849     for (SCSIZE i=0; i<nCount; i++)
1850     {
1851         ScBaseCell* pCell = pItems[i].pCell;
1852         switch ( pCell->GetCellType() )
1853         {
1854             case CELLTYPE_VALUE:
1855             case CELLTYPE_STRING:
1856                 ++nTotal;
1857                 break;
1858             case CELLTYPE_FORMULA:
1859                 nTotal += 5 + ((ScFormulaCell*)pCell)->GetCode()->GetCodeLen();
1860                 break;
1861             case CELLTYPE_EDIT:
1862                 nTotal += 50;
1863                 break;
1864             default:
1865             {
1866                 // added to avoid warnings
1867             }
1868         }
1869     }
1870 
1871     return nTotal;
1872 }
1873 
GetCodeCount() const1874 sal_uLong ScColumn::GetCodeCount() const
1875 {
1876     sal_uLong nCodeCount = 0;
1877 
1878     for (SCSIZE i=0; i<nCount; i++)
1879     {
1880         ScBaseCell* pCell = pItems[i].pCell;
1881         if ( pCell->GetCellType() == CELLTYPE_FORMULA )
1882             nCodeCount += ((ScFormulaCell*)pCell)->GetCode()->GetCodeLen();
1883     }
1884 
1885     return nCodeCount;
1886 }
1887 
GetPatternCount()1888 SCSIZE ScColumn::GetPatternCount()
1889 {
1890     return this->pAttrArray ? this->pAttrArray->Count() : 0;
1891 }
1892 
GetPatternCount(SCROW nRw1,SCROW nRw2)1893 SCSIZE ScColumn::GetPatternCount( SCROW nRw1, SCROW nRw2 )
1894 {
1895     return this->pAttrArray ? this->pAttrArray->Count( nRw1, nRw2 ) : 0;
1896 }
1897 
ReservedPatternCount(SCSIZE nReserved)1898 bool ScColumn::ReservedPatternCount( SCSIZE nReserved )
1899 {
1900     return this->pAttrArray ? this->pAttrArray->Reserve( nReserved ) : false;
1901 }
1902