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