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