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