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