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