xref: /trunk/main/sc/source/core/data/fillinfo.cxx (revision acf6b796)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sc.hxx"
26 
27 
28 
29 // INCLUDE ---------------------------------------------------------------
30 
31 #include "scitems.hxx"
32 #include <editeng/boxitem.hxx>
33 #include <editeng/bolnitem.hxx>
34 #include <editeng/editdata.hxx>		// can be removed if table has a bLayoutRTL flag
35 #include <editeng/shaditem.hxx>
36 
37 #include "fillinfo.hxx"
38 #include "document.hxx"
39 #include "cell.hxx"
40 #include "table.hxx"
41 #include "attrib.hxx"
42 #include "attarray.hxx"
43 #include "markarr.hxx"
44 #include "markdata.hxx"
45 #include "patattr.hxx"
46 #include "poolhelp.hxx"
47 #include "docpool.hxx"
48 #include "conditio.hxx"
49 #include "stlpool.hxx"
50 
51 // -----------------------------------------------------------------------
52 
53 const sal_uInt16 ROWINFO_MAX = 1024;
54 
55 
56 enum FillInfoLinePos
57 	{
58 		FILP_TOP,
59 		FILP_BOTTOM,
60 		FILP_LEFT,
61 		FILP_RIGHT
62 	};
63 
64 
GetNullOrLine(const SvxBoxItem * pBox,FillInfoLinePos eWhich)65 inline const SvxBorderLine* GetNullOrLine( const SvxBoxItem* pBox, FillInfoLinePos eWhich )
66 {
67 	if (pBox)
68 	{
69 		if (eWhich==FILP_TOP)
70 			return pBox->GetTop();
71 		else if (eWhich==FILP_BOTTOM)
72 			return pBox->GetBottom();
73 		else if (eWhich==FILP_LEFT)
74 			return pBox->GetLeft();
75 		else
76 			return pBox->GetRight();
77 	}
78 	else
79 		return NULL;
80 }
81 
82 //	aehnlich wie in output.cxx
83 
lcl_GetMergeRange(SCsCOL nX,SCsROW nY,SCSIZE nArrY,ScDocument * pDoc,RowInfo * pRowInfo,SCCOL nX1,SCROW nY1,SCCOL,SCROW,SCTAB nTab,SCsCOL & rStartX,SCsROW & rStartY,SCsCOL & rEndX,SCsROW & rEndY)84 void lcl_GetMergeRange( SCsCOL nX, SCsROW nY, SCSIZE nArrY,
85 							ScDocument* pDoc, RowInfo* pRowInfo,
86 							SCCOL nX1, SCROW nY1, SCCOL /* nX2 */, SCROW /* nY2 */, SCTAB nTab,
87 							SCsCOL& rStartX, SCsROW& rStartY, SCsCOL& rEndX, SCsROW& rEndY )
88 {
89 	CellInfo* pInfo = &pRowInfo[nArrY].pCellInfo[nX+1];
90 
91 	rStartX = nX;
92 	rStartY = nY;
93 	sal_Bool bHOver = pInfo->bHOverlapped;
94 	sal_Bool bVOver = pInfo->bVOverlapped;
95     SCCOL nLastCol;
96     SCROW nLastRow;
97 
98 	while (bHOver)				// nY konstant
99 	{
100 		--rStartX;
101         if (rStartX >= (SCsCOL) nX1 && !pDoc->ColHidden(rStartX, nTab, nLastCol))
102 		{
103 			bHOver = pRowInfo[nArrY].pCellInfo[rStartX+1].bHOverlapped;
104 			bVOver = pRowInfo[nArrY].pCellInfo[rStartX+1].bVOverlapped;
105 		}
106 		else
107 		{
108 			sal_uInt16 nOverlap = ((ScMergeFlagAttr*)pDoc->GetAttr(
109 								rStartX, rStartY, nTab, ATTR_MERGE_FLAG ))->GetValue();
110 			bHOver = ((nOverlap & SC_MF_HOR) != 0);
111 			bVOver = ((nOverlap & SC_MF_VER) != 0);
112 		}
113 	}
114 
115 	while (bVOver)
116 	{
117 		--rStartY;
118 
119 		if (nArrY>0)
120 			--nArrY;						// lokale Kopie !
121 
122 		if (rStartX >= (SCsCOL) nX1 && rStartY >= (SCsROW) nY1 &&
123             !pDoc->ColHidden(rStartX, nTab, nLastCol) &&
124             !pDoc->RowHidden(rStartY, nTab, nLastRow) &&
125 			(SCsROW) pRowInfo[nArrY].nRowNo == rStartY)
126 		{
127 			bHOver = pRowInfo[nArrY].pCellInfo[rStartX+1].bHOverlapped;
128 			bVOver = pRowInfo[nArrY].pCellInfo[rStartX+1].bVOverlapped;
129 		}
130 		else
131 		{
132 			sal_uInt16 nOverlap = ((ScMergeFlagAttr*)pDoc->GetAttr(
133 								rStartX, rStartY, nTab, ATTR_MERGE_FLAG ))->GetValue();
134 			bHOver = ((nOverlap & SC_MF_HOR) != 0);
135 			bVOver = ((nOverlap & SC_MF_VER) != 0);
136 		}
137 	}
138 
139 	const ScMergeAttr* pMerge;
140 	if (rStartX >= (SCsCOL) nX1 && rStartY >= (SCsROW) nY1 &&
141         !pDoc->ColHidden(rStartX, nTab, nLastCol) &&
142         !pDoc->RowHidden(rStartY, nTab, nLastRow) &&
143 		(SCsROW) pRowInfo[nArrY].nRowNo == rStartY)
144 	{
145 		pMerge = (const ScMergeAttr*) &pRowInfo[nArrY].pCellInfo[rStartX+1].pPatternAttr->
146 										GetItem(ATTR_MERGE);
147 	}
148 	else
149 		pMerge = (const ScMergeAttr*) pDoc->GetAttr(rStartX,rStartY,nTab,ATTR_MERGE);
150 
151 	rEndX = rStartX + pMerge->GetColMerge() - 1;
152 	rEndY = rStartY + pMerge->GetRowMerge() - 1;
153 }
154 
155 #define CELLINFO(x,y) pRowInfo[nArrY+y].pCellInfo[nArrX+x]
156 
FillInfo(ScTableInfo & rTabInfo,SCCOL nX1,SCROW nY1,SCCOL nX2,SCROW nY2,SCTAB nTab,double nScaleX,double nScaleY,sal_Bool bPageMode,sal_Bool bFormulaMode,const ScMarkData * pMarkData)157 void ScDocument::FillInfo( ScTableInfo& rTabInfo, SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2,
158 							SCTAB nTab, double nScaleX, double nScaleY,
159 							sal_Bool bPageMode, sal_Bool bFormulaMode, const ScMarkData* pMarkData )
160 {
161 	DBG_ASSERT( pTab[nTab], "Tabelle existiert nicht" );
162 
163 	sal_Bool bLayoutRTL = IsLayoutRTL( nTab );
164 
165 	ScDocumentPool* pPool = xPoolHelper->GetDocPool();
166 	ScStyleSheetPool* pStlPool = xPoolHelper->GetStylePool();
167 
168     RowInfo* pRowInfo = rTabInfo.mpRowInfo;
169 
170 	const SvxBrushItem* pDefBackground =
171 			(const SvxBrushItem*) &pPool->GetDefaultItem( ATTR_BACKGROUND );
172 	const ScMergeAttr* pDefMerge =
173 			(const ScMergeAttr*) &pPool->GetDefaultItem( ATTR_MERGE );
174 	const SvxShadowItem* pDefShadow =
175 			(const SvxShadowItem*) &pPool->GetDefaultItem( ATTR_SHADOW );
176 
177 	SCROW nThisRow;
178 	SCCOL nX;
179 	SCROW nY;
180 	SCsROW nSignedY;
181 	SCCOL nArrX;
182 	SCSIZE nArrY;
183 	SCSIZE nArrCount;
184 	sal_Bool bAnyMerged = sal_False;
185 	sal_Bool bAnyShadow = sal_False;
186 	sal_Bool bAnyCondition = sal_False;
187 
188 	sal_Bool bTabProtect = IsTabProtected(nTab);
189 
190 												// fuer Blockmarken von zusammengefassten Zellen mit
191 												// versteckter erster Zeile / Spalte
192 	sal_Bool bPaintMarks = sal_False;
193 	sal_Bool bSkipMarks = sal_False;
194     SCCOL nBlockStartX = 0, nBlockEndX = 0;
195     SCROW nBlockEndY = 0, nBlockStartY = 0;
196 	if (pMarkData && pMarkData->IsMarked())
197 	{
198 		ScRange aTmpRange;
199 		pMarkData->GetMarkArea(aTmpRange);
200 		if ( nTab >= aTmpRange.aStart.Tab() && nTab <= aTmpRange.aEnd.Tab() )
201 		{
202 			nBlockStartX = aTmpRange.aStart.Col();
203 			nBlockStartY = aTmpRange.aStart.Row();
204 			nBlockEndX = aTmpRange.aEnd.Col();
205 			nBlockEndY = aTmpRange.aEnd.Row();
206 			ExtendHidden( nBlockStartX, nBlockStartY, nBlockEndX, nBlockEndY, nTab );	//? noetig ?
207 			if (pMarkData->IsMarkNegative())
208 				bSkipMarks = sal_True;
209 			else
210 				bPaintMarks = sal_True;
211 		}
212 	}
213 
214 	//	zuerst nur die Eintraege fuer die ganze Spalte
215 
216 	nArrY=0;
217 	SCROW nYExtra = nY2+1;
218     sal_uInt16 nDocHeight = ScGlobal::nStdRowHeight;
219     SCROW nDocHeightEndRow = -1;
220 	for (nSignedY=((SCsROW)nY1)-1; nSignedY<=(SCsROW)nYExtra; nSignedY++)
221 	{
222 		if (nSignedY >= 0)
223 			nY = (SCROW) nSignedY;
224 		else
225 			nY = MAXROW+1;			// ungueltig
226 
227         if (nY > nDocHeightEndRow)
228         {
229             if (ValidRow(nY))
230                 nDocHeight = GetRowHeight( nY, nTab, NULL, &nDocHeightEndRow );
231             else
232                 nDocHeight = ScGlobal::nStdRowHeight;
233         }
234 
235 		if ( nArrY==0 || nDocHeight || nY > MAXROW )
236 		{
237 			RowInfo* pThisRowInfo = &pRowInfo[nArrY];
238 			pThisRowInfo->pCellInfo = NULL;					// wird unten belegt
239 
240 			sal_uInt16 nHeight = (sal_uInt16) ( nDocHeight * nScaleY );
241 			if (!nHeight)
242 				nHeight = 1;
243 
244 			pThisRowInfo->nRowNo		= nY;				//! Fall < 0 ?
245 			pThisRowInfo->nHeight 		= nHeight;
246 			pThisRowInfo->bEmptyBack	= sal_True;
247 			pThisRowInfo->bEmptyText	= sal_True;
248 			pThisRowInfo->bChanged		= sal_True;
249 			pThisRowInfo->bAutoFilter	= sal_False;
250 			pThisRowInfo->bPushButton	= sal_False;
251 			pThisRowInfo->nRotMaxCol	= SC_ROTMAX_NONE;
252 
253 			++nArrY;
254 			if (nArrY >= ROWINFO_MAX)
255 			{
256 				DBG_ERROR("Zu grosser Bereich bei FillInfo" );
257 				nYExtra = nSignedY;									// Ende
258 				nY2 = nYExtra - 1;									// Bereich anpassen
259 			}
260 		}
261 		else
262 			if (nSignedY==(SCsROW) nYExtra)							// zusaetzliche Zeile verdeckt ?
263 				++nYExtra;
264 	}
265 	nArrCount = nArrY;										// incl. Dummys
266 
267 	//	rotierter Text...
268 
269 	//	Attribut im Dokument ueberhaupt verwendet?
270 	sal_Bool bAnyItem = sal_False;
271 	sal_uInt32 nRotCount = pPool->GetItemCount2( ATTR_ROTATE_VALUE );
272 	for (sal_uInt32 nItem=0; nItem<nRotCount; nItem++)
273 		if (pPool->GetItem2( ATTR_ROTATE_VALUE, nItem ))
274 		{
275 			bAnyItem = sal_True;
276 			break;
277 		}
278 
279 	SCCOL nRotMax = nX2;
280 	if ( bAnyItem && HasAttrib( 0,nY1,nTab, MAXCOL,nY2+1,nTab,
281 								HASATTR_ROTATE | HASATTR_CONDITIONAL ) )
282 	{
283 		//!	Conditionals auch bei HASATTR_ROTATE abfragen ????
284 
285 		DBG_ASSERT( nArrCount>2, "nArrCount zu klein" );
286 //		FindMaxRotCol( nTab, &pRowInfo[1], nArrCount-2, nX1, nX2 );
287 		FindMaxRotCol( nTab, &pRowInfo[1], nArrCount-1, nX1, nX2 );
288 		//	FindMaxRotCol setzt nRotMaxCol
289 
290 		for (nArrY=0; nArrY<nArrCount; nArrY++)
291 			if (pRowInfo[nArrY].nRotMaxCol != SC_ROTMAX_NONE && pRowInfo[nArrY].nRotMaxCol > nRotMax)
292 				nRotMax = pRowInfo[nArrY].nRotMaxCol;
293 	}
294 
295 	//	Zell-Infos erst nach dem Test auf gedrehte allozieren
296 	//	bis nRotMax wegen nRotateDir Flag
297 
298 	for (nArrY=0; nArrY<nArrCount; nArrY++)
299 	{
300 		RowInfo* pThisRowInfo = &pRowInfo[nArrY];
301 		nY = pThisRowInfo->nRowNo;
302 		pThisRowInfo->pCellInfo = new CellInfo[ nRotMax+1+2 ];	// vom Aufrufer zu loeschen !
303 
304 		for (nArrX=0; nArrX<=nRotMax+2; nArrX++)				// Zell-Infos vorbelegen
305 		{
306 			if (nArrX>0)
307 				nX = nArrX-1;
308 			else
309 				nX = MAXCOL+1;		// ungueltig
310 
311 			CellInfo* pInfo = &pThisRowInfo->pCellInfo[nArrX];
312 			pInfo->bEmptyCellText = sal_True;
313 			pInfo->pCell = NULL;
314 			if (bPaintMarks)
315 				pInfo->bMarked = ( nX >= nBlockStartX && nX <= nBlockEndX
316 								&& nY >= nBlockStartY && nY <= nBlockEndY );
317 			else
318 				pInfo->bMarked = sal_False;
319 			pInfo->nWidth = 0;
320 
321 			pInfo->nClipMark	= SC_CLIPMARK_NONE;
322 			pInfo->bMerged		= sal_False;
323 			pInfo->bHOverlapped = sal_False;
324 			pInfo->bVOverlapped = sal_False;
325 			pInfo->bAutoFilter	= sal_False;
326 			pInfo->bPushButton	= sal_False;
327             pInfo->bPopupButton = false;
328             pInfo->bFilterActive = false;
329 			pInfo->nRotateDir	= SC_ROTDIR_NONE;
330 
331 			pInfo->bPrinted		= sal_False;					//	view-intern
332 			pInfo->bHideGrid	= sal_False;					//	view-intern
333 			pInfo->bEditEngine	= sal_False;					//	view-intern
334 
335 			pInfo->pBackground  = NULL;						//! weglassen?
336 			pInfo->pPatternAttr = NULL;
337 			pInfo->pConditionSet= NULL;
338 
339             pInfo->pLinesAttr   = NULL;
340             pInfo->mpTLBRLine   = NULL;
341             pInfo->mpBLTRLine   = NULL;
342 
343 			pInfo->pShadowAttr	  = pDefShadow;
344 			pInfo->pHShadowOrigin = NULL;
345 			pInfo->pVShadowOrigin = NULL;
346 		}
347 	}
348 
349 	for (nArrX=nX2+3; nArrX<=nRotMax+2; nArrX++)			// restliche Breiten eintragen
350 	{
351 		nX = nArrX-1;
352 		if ( ValidCol(nX) )
353 		{
354             if (!ColHidden(nX, nTab))
355 			{
356 				sal_uInt16 nThisWidth = (sal_uInt16) (GetColWidth( nX, nTab ) * nScaleX);
357 				if (!nThisWidth)
358 					nThisWidth = 1;
359 
360 				pRowInfo[0].pCellInfo[nArrX].nWidth = nThisWidth;
361 			}
362 		}
363 	}
364 
365 	for (nArrX=0; nArrX<=nX2+2; nArrX++)					// links & rechts + 1
366 	{
367 		nX = (nArrX>0) ? nArrX-1 : MAXCOL+1;					// negativ -> ungueltig
368 
369 		if ( ValidCol(nX) )
370 		{
371             // #i58049#, #i57939# Hidden columns must be skipped here, or their attributes
372             // will disturb the output
373 
374             // TODO: Optimize this loop.
375             if (!ColHidden(nX, nTab))
376 			{
377 				sal_uInt16 nThisWidth = (sal_uInt16) (GetColWidth( nX, nTab ) * nScaleX);
378                 if (!nThisWidth)
379 					nThisWidth = 1;
380 
381 				pRowInfo[0].pCellInfo[nArrX].nWidth = nThisWidth;			//! dies sollte reichen
382 
383 				ScColumn* pThisCol = &pTab[nTab]->aCol[nX];					// Spalten-Daten
384 
385                 nArrY = 1;
386                 SCSIZE nUIndex;
387                 bool bHiddenRow = true;
388                 SCROW nHiddenEndRow = -1;
389                 (void) pThisCol->Search( nY1, nUIndex );
390                 while ( nUIndex < pThisCol->nCount &&
391                         (nThisRow=pThisCol->pItems[nUIndex].nRow) <= nY2 )
392                 {
393                     if (nThisRow > nHiddenEndRow)
394                         bHiddenRow = RowHidden( nThisRow, nTab, nHiddenEndRow);
395                     if ( !bHiddenRow )
396                     {
397                         while ( pRowInfo[nArrY].nRowNo < nThisRow )
398                             ++nArrY;
399                         DBG_ASSERT( pRowInfo[nArrY].nRowNo == nThisRow, "Zeile nicht gefunden in FillInfo" );
400 
401                         RowInfo* pThisRowInfo = &pRowInfo[nArrY];
402                         CellInfo* pInfo = &pThisRowInfo->pCellInfo[nArrX];
403                         pInfo->pCell = pThisCol->pItems[nUIndex].pCell;
404                         if (pInfo->pCell->GetCellType() != CELLTYPE_NOTE)
405                         {
406                             pThisRowInfo->bEmptyText = sal_False;                   // Zeile nicht leer
407                             pInfo->bEmptyCellText = sal_False;                      // Zelle nicht leer
408                         }
409                         ++nArrY;
410                     }
411                     ++nUIndex;
412                 }
413 
414 				if (nX+1 >= nX1)								// Attribute/Blockmarken ab nX1-1
415 				{
416 					ScAttrArray* pThisAttrArr = pThisCol->pAttrArray;		// Attribute
417 
418 					nArrY = 0;
419 					const ScPatternAttr* pPattern;
420 					SCROW nCurRow=nY1;					// einzelne Zeile
421 					if (nCurRow>0)
422 						--nCurRow;						// oben 1 mehr
423 					else
424 						nArrY = 1;
425 					nThisRow=nCurRow;					// Ende des Bereichs
426 					SCSIZE  nIndex;
427 					(void) pThisAttrArr->Search( nCurRow, nIndex );
428 
429 
430 					do
431 					{
432 						nThisRow=pThisAttrArr->pData[nIndex].nRow;				// Ende des Bereichs
433 						pPattern=pThisAttrArr->pData[nIndex].pPattern;
434 
435 						const SvxBrushItem* pBackground = (const SvxBrushItem*)
436 														&pPattern->GetItem(ATTR_BACKGROUND);
437 						const SvxBoxItem* pLinesAttr = (const SvxBoxItem*)
438 														&pPattern->GetItem(ATTR_BORDER);
439 
440                         const SvxLineItem* pTLBRLine = static_cast< const SvxLineItem* >(
441                             &pPattern->GetItem( ATTR_BORDER_TLBR ) );
442                         const SvxLineItem* pBLTRLine = static_cast< const SvxLineItem* >(
443                             &pPattern->GetItem( ATTR_BORDER_BLTR ) );
444 
445 						const SvxShadowItem* pShadowAttr = (const SvxShadowItem*)
446 														&pPattern->GetItem(ATTR_SHADOW);
447 						if (pShadowAttr != pDefShadow)
448 							bAnyShadow = sal_True;
449 
450 						const ScMergeAttr* pMergeAttr = (const ScMergeAttr*)
451 												&pPattern->GetItem(ATTR_MERGE);
452 						sal_Bool bMerged = ( pMergeAttr != pDefMerge && *pMergeAttr != *pDefMerge );
453 						sal_uInt16 nOverlap = ((const ScMergeFlagAttr*) &pPattern->GetItemSet().
454 														Get(ATTR_MERGE_FLAG))->GetValue();
455 						sal_Bool bHOverlapped = ((nOverlap & SC_MF_HOR) != 0);
456 						sal_Bool bVOverlapped = ((nOverlap & SC_MF_VER) != 0);
457 						sal_Bool bAutoFilter  = ((nOverlap & SC_MF_AUTO) != 0);
458 						sal_Bool bPushButton  = ((nOverlap & SC_MF_BUTTON) != 0);
459 						sal_Bool bScenario	  = ((nOverlap & SC_MF_SCENARIO) != 0);
460                         bool bPopupButton = ((nOverlap & SC_MF_BUTTON_POPUP) != 0);
461                         bool bFilterActive = ((nOverlap & SC_MF_HIDDEN_MEMBER) != 0);
462 						if (bMerged||bHOverlapped||bVOverlapped)
463 							bAnyMerged = sal_True;								// intern
464 
465 						sal_Bool bHidden, bHideFormula;
466 						if (bTabProtect)
467 						{
468 							const ScProtectionAttr& rProtAttr = (const ScProtectionAttr&)
469 														pPattern->GetItem(ATTR_PROTECTION);
470 							bHidden = rProtAttr.GetHideCell();
471 							bHideFormula = rProtAttr.GetHideFormula();
472 						}
473 						else
474 							bHidden = bHideFormula = sal_False;
475 
476 						sal_uLong nConditional = ((const SfxUInt32Item&)pPattern->
477 												GetItem(ATTR_CONDITIONAL)).GetValue();
478 						const ScConditionalFormat* pCondForm = NULL;
479 						if ( nConditional && pCondFormList )
480 							pCondForm = pCondFormList->GetFormat( nConditional );
481 
482 						do
483 						{
484                             SCROW nLastHiddenRow = -1;
485                             bool bRowHidden = RowHidden(nCurRow, nTab, nLastHiddenRow);
486 							if ( nArrY==0 || !bRowHidden )
487 							{
488 								RowInfo* pThisRowInfo = &pRowInfo[nArrY];
489 								if (pBackground != pDefBackground)			// Spalten-HG == Standard ?
490 									pThisRowInfo->bEmptyBack = sal_False;
491 								if (bAutoFilter)
492 									pThisRowInfo->bAutoFilter = sal_True;
493 								if (bPushButton)
494 									pThisRowInfo->bPushButton = sal_True;
495 
496 								CellInfo* pInfo = &pThisRowInfo->pCellInfo[nArrX];
497 								pInfo->pBackground	= pBackground;
498 								pInfo->pPatternAttr	= pPattern;
499 								pInfo->bMerged		= bMerged;
500 								pInfo->bHOverlapped	= bHOverlapped;
501 								pInfo->bVOverlapped	= bVOverlapped;
502 								pInfo->bAutoFilter	= bAutoFilter;
503 								pInfo->bPushButton	= bPushButton;
504                                 pInfo->bPopupButton = bPopupButton;
505                                 pInfo->bFilterActive = bFilterActive;
506 								pInfo->pLinesAttr	= pLinesAttr;
507                                 pInfo->mpTLBRLine   = pTLBRLine;
508                                 pInfo->mpBLTRLine   = pBLTRLine;
509 								pInfo->pShadowAttr	= pShadowAttr;
510 								//	nWidth wird nicht mehr einzeln gesetzt
511 
512                                 sal_Bool bEmbed = sal_False; /*bIsEmbedded &&
513 										nTab	>= aEmbedRange.aStart.Tab() &&
514 										nTab    <= aEmbedRange.aEnd.Tab()   &&
515 										nX		>= aEmbedRange.aStart.Col() &&
516 										nX	    <= aEmbedRange.aEnd.Col()   &&
517 										nCurRow >= aEmbedRange.aStart.Row() &&
518 										nCurRow <= aEmbedRange.aEnd.Row(); */
519 
520 								if (bScenario)
521 								{
522 									pInfo->pBackground = ScGlobal::GetButtonBrushItem();
523 									pThisRowInfo->bEmptyBack = sal_False;
524 								}
525 								else if (bEmbed)
526 								{
527 									pInfo->pBackground = ScGlobal::GetEmbeddedBrushItem();
528 									pThisRowInfo->bEmptyBack = sal_False;
529 								}
530 
531 								if (bHidden || ( bFormulaMode && bHideFormula && pInfo->pCell
532 													&& pInfo->pCell->GetCellType()
533 														== CELLTYPE_FORMULA ))
534 									pInfo->bEmptyCellText = sal_True;
535 
536 								if ( pCondForm )
537 								{
538 									String aStyle = pCondForm->GetCellStyle( pInfo->pCell,
539 														ScAddress( nX, nCurRow, nTab ) );
540 									if (aStyle.Len())
541 									{
542 										SfxStyleSheetBase* pStyleSheet =
543 												pStlPool->Find( aStyle, SFX_STYLE_FAMILY_PARA );
544 										if ( pStyleSheet )
545 										{
546 											//!	Style-Sets cachen !!!
547 											pInfo->pConditionSet = &pStyleSheet->GetItemSet();
548 											bAnyCondition = sal_True;
549 										}
550 										// if style is not there, treat like no condition
551 									}
552 								}
553 
554 								++nArrY;
555 							}
556                             else if (bRowHidden && nLastHiddenRow >= 0)
557                             {
558                                 nCurRow = nLastHiddenRow;
559                                 if (nCurRow > nThisRow)
560                                     nCurRow = nThisRow;
561                             }
562 							++nCurRow;
563 						}
564 						while (nCurRow <= nThisRow && nCurRow <= nYExtra);
565 						++nIndex;
566 					}
567 					while ( nIndex < pThisAttrArr->nCount && nThisRow < nYExtra );
568 
569 
570 					if (pMarkData && pMarkData->IsMultiMarked())
571 					{
572 						//	Blockmarken
573 						const ScMarkArray* pThisMarkArr = pMarkData->GetArray()+nX;
574 						sal_Bool bThisMarked;
575 						nArrY = 1;
576 						nCurRow = nY1;										// einzelne Zeile
577 						nThisRow = nY1;										// Ende des Bereichs
578 
579                         if ( pThisMarkArr->Search( nY1, nIndex ) )
580                         {
581                             do
582                             {
583                                 nThisRow=pThisMarkArr->pData[nIndex].nRow;      // Ende des Bereichs
584                                 bThisMarked=pThisMarkArr->pData[nIndex].bMarked;
585 
586                                 do
587                                 {
588                                     if ( !RowHidden( nCurRow,nTab ) )
589                                     {
590                                         if ( bThisMarked )
591                                         {
592                                             sal_Bool bSkip = bSkipMarks &&
593                                                         nX      >= nBlockStartX &&
594                                                         nX      <= nBlockEndX   &&
595                                                         nCurRow >= nBlockStartY &&
596                                                         nCurRow <= nBlockEndY;
597                                             if (!bSkip)
598                                             {
599                                                 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
600                                                 CellInfo* pInfo = &pThisRowInfo->pCellInfo[nArrX];
601                                                 pInfo->bMarked = sal_True;
602                                             }
603                                         }
604                                         ++nArrY;
605                                     }
606                                     ++nCurRow;
607                                 }
608                                 while (nCurRow <= nThisRow && nCurRow <= nY2);
609                                 ++nIndex;
610                             }
611                             while ( nIndex < pThisMarkArr->nCount && nThisRow < nY2 );
612                         }
613 					}
614 				}
615 				else									// vordere Spalten
616 				{
617 					for (nArrY=1; nArrY+1<nArrCount; nArrY++)
618 					{
619 						RowInfo* pThisRowInfo = &pRowInfo[nArrY];
620 						CellInfo* pInfo = &pThisRowInfo->pCellInfo[nArrX];
621 
622 						pInfo->nWidth		= nThisWidth;			//! oder nur 0 abfragen ??
623 					}
624 				}
625 			}
626 		}
627 		else
628 			pRowInfo[0].pCellInfo[nArrX].nWidth = STD_COL_WIDTH;
629 		// STD_COL_WIDTH ganz links und rechts wird fuer DrawExtraShadow gebraucht
630 	}
631 
632 	//-------------------------------------------------------------------------
633 	//	bedingte Formatierung auswerten
634 
635 	if (bAnyCondition)
636 	{
637 		for (nArrY=0; nArrY<nArrCount; nArrY++)
638 		{
639 			for (nArrX=nX1; nArrX<=nX2+2; nArrX++)					// links und rechts einer mehr
640 			{
641 				CellInfo* pInfo = &pRowInfo[nArrY].pCellInfo[nArrX];
642 				const SfxItemSet* pCondSet = pInfo->pConditionSet;
643 				if (pCondSet)
644 				{
645 					const SfxPoolItem* pItem;
646 
647 							//	Hintergrund
648 					if ( pCondSet->GetItemState( ATTR_BACKGROUND, sal_True, &pItem ) == SFX_ITEM_SET )
649 					{
650 						pInfo->pBackground = (const SvxBrushItem*) pItem;
651 						pRowInfo[nArrY].bEmptyBack = sal_False;
652 					}
653 
654 							//	Umrandung
655 					if ( pCondSet->GetItemState( ATTR_BORDER, sal_True, &pItem ) == SFX_ITEM_SET )
656 						pInfo->pLinesAttr = (const SvxBoxItem*) pItem;
657 
658                     if ( pCondSet->GetItemState( ATTR_BORDER_TLBR, sal_True, &pItem ) == SFX_ITEM_SET )
659                         pInfo->mpTLBRLine = static_cast< const SvxLineItem* >( pItem );
660                     if ( pCondSet->GetItemState( ATTR_BORDER_BLTR, sal_True, &pItem ) == SFX_ITEM_SET )
661                         pInfo->mpBLTRLine = static_cast< const SvxLineItem* >( pItem );
662 
663 							//	Schatten
664 					if ( pCondSet->GetItemState( ATTR_SHADOW, sal_True, &pItem ) == SFX_ITEM_SET )
665 					{
666 						pInfo->pShadowAttr = (const SvxShadowItem*) pItem;
667 						bAnyShadow = sal_True;
668 					}
669 				}
670 			}
671 		}
672 	}
673 
674 	//	bedingte Formatierung Ende
675 	//-------------------------------------------------------------------------
676 
677 				//
678 				//		Daten von zusammengefassten Zellen anpassen
679 				//
680 
681 	if (bAnyMerged)
682 	{
683 		for (nArrY=0; nArrY<nArrCount; nArrY++)
684 		{
685 			RowInfo* pThisRowInfo = &pRowInfo[nArrY];
686             nSignedY = nArrY ? pThisRowInfo->nRowNo : ((SCsROW)nY1)-1;
687 
688 			for (nArrX=nX1; nArrX<=nX2+2; nArrX++)					// links und rechts einer mehr
689 			{
690                 SCsCOL nSignedX = ((SCsCOL) nArrX) - 1;
691 				CellInfo* pInfo = &pThisRowInfo->pCellInfo[nArrX];
692 
693 				if (pInfo->bMerged || pInfo->bHOverlapped || pInfo->bVOverlapped)
694 				{
695 					SCsCOL nStartX;
696 					SCsROW nStartY;
697 					SCsCOL nEndX;
698 					SCsROW nEndY;
699 					lcl_GetMergeRange( nSignedX,nSignedY, nArrY, this,pRowInfo, nX1,nY1,nX2,nY2,nTab,
700 										nStartX,nStartY, nEndX,nEndY );
701 					const ScPatternAttr* pStartPattern = GetPattern( nStartX,nStartY,nTab );
702 					const SfxItemSet* pStartCond = GetCondResult( nStartX,nStartY,nTab );
703 					const SfxPoolItem* pItem;
704 
705 					// Hintergrund kopieren (oder in output.cxx)
706 
707 					if ( !pStartCond || pStartCond->
708 									GetItemState(ATTR_BACKGROUND,sal_True,&pItem) != SFX_ITEM_SET )
709 						pItem = &pStartPattern->GetItem(ATTR_BACKGROUND);
710 					pInfo->pBackground = (const SvxBrushItem*) pItem;
711 					pRowInfo[nArrY].bEmptyBack = sal_False;
712 
713 					// Schatten
714 
715 					if ( !pStartCond || pStartCond->
716 									GetItemState(ATTR_SHADOW,sal_True,&pItem) != SFX_ITEM_SET )
717 						pItem = &pStartPattern->GetItem(ATTR_SHADOW);
718 					pInfo->pShadowAttr = (const SvxShadowItem*) pItem;
719 					if (pInfo->pShadowAttr != pDefShadow)
720 						bAnyShadow = sal_True;
721 
722 					// Blockmarken - wieder mit Original-Merge-Werten
723 
724 					sal_Bool bCellMarked = sal_False;
725 					if (bPaintMarks)
726 						bCellMarked = ( nStartX >= (SCsCOL) nBlockStartX
727 									&& nStartX <= (SCsCOL) nBlockEndX
728 									&& nStartY >= (SCsROW) nBlockStartY
729 									&& nStartY <= (SCsROW) nBlockEndY );
730 					if (pMarkData && pMarkData->IsMultiMarked() && !bCellMarked)
731 					{
732 						const ScMarkArray* pThisMarkArr = pMarkData->GetArray()+nStartX;
733 						SCSIZE nIndex;
734                         if ( pThisMarkArr->Search( nStartY, nIndex ) )
735                             bCellMarked=pThisMarkArr->pData[nIndex].bMarked;
736 					}
737 
738 					pInfo->bMarked = bCellMarked;
739 				}
740 			}
741 		}
742 	}
743 
744 	if (bAnyShadow)								// Schatten verteilen
745 	{
746 		for (nArrY=0; nArrY<nArrCount; nArrY++)
747 		{
748 			sal_Bool bTop = ( nArrY == 0 );
749 			sal_Bool bBottom = ( nArrY+1 == nArrCount );
750 
751 			for (nArrX=nX1; nArrX<=nX2+2; nArrX++)					// links und rechts einer mehr
752 			{
753 				sal_Bool bLeft = ( nArrX == nX1 );
754 				sal_Bool bRight = ( nArrX == nX2+2 );
755 
756 				CellInfo* pInfo = &pRowInfo[nArrY].pCellInfo[nArrX];
757 				const SvxShadowItem* pThisAttr = pInfo->pShadowAttr;
758 				SvxShadowLocation eLoc = pThisAttr ? pThisAttr->GetLocation() : SVX_SHADOW_NONE;
759 				if (eLoc != SVX_SHADOW_NONE)
760 				{
761 					//	oder Test auf != eLoc
762 
763 					SCsCOL nDxPos = 1;
764 					SCsCOL nDxNeg = -1;
765 
766 					while ( nArrX+nDxPos < nX2+2 && pRowInfo[0].pCellInfo[nArrX+nDxPos].nWidth == 0 )
767 						++nDxPos;
768 					while ( nArrX+nDxNeg > nX1 && pRowInfo[0].pCellInfo[nArrX+nDxNeg].nWidth == 0 )
769 						--nDxNeg;
770 
771 					sal_Bool bLeftDiff = !bLeft &&
772 							CELLINFO(nDxNeg,0).pShadowAttr->GetLocation() == SVX_SHADOW_NONE;
773 					sal_Bool bRightDiff = !bRight &&
774 							CELLINFO(nDxPos,0).pShadowAttr->GetLocation() == SVX_SHADOW_NONE;
775 					sal_Bool bTopDiff = !bTop &&
776 							CELLINFO(0,-1).pShadowAttr->GetLocation() == SVX_SHADOW_NONE;
777 					sal_Bool bBottomDiff = !bBottom &&
778 							CELLINFO(0,1).pShadowAttr->GetLocation() == SVX_SHADOW_NONE;
779 
780 					if ( bLayoutRTL )
781 					{
782 						switch (eLoc)
783 						{
784 							case SVX_SHADOW_BOTTOMRIGHT: eLoc = SVX_SHADOW_BOTTOMLEFT;	break;
785 							case SVX_SHADOW_BOTTOMLEFT:	 eLoc = SVX_SHADOW_BOTTOMRIGHT;	break;
786 							case SVX_SHADOW_TOPRIGHT:	 eLoc = SVX_SHADOW_TOPLEFT;		break;
787 							case SVX_SHADOW_TOPLEFT:	 eLoc = SVX_SHADOW_TOPRIGHT;	break;
788                             default:
789                             {
790                                 // added to avoid warnings
791                             }
792 						}
793 					}
794 
795 					switch (eLoc)
796 					{
797 						case SVX_SHADOW_BOTTOMRIGHT:
798 							if (bBottomDiff)
799 							{
800 								CELLINFO(0,1).pHShadowOrigin = pThisAttr;
801 								CELLINFO(0,1).eHShadowPart =
802 												bLeftDiff ? SC_SHADOW_HSTART : SC_SHADOW_HORIZ;
803 							}
804 							if (bRightDiff)
805 							{
806 								CELLINFO(1,0).pVShadowOrigin = pThisAttr;
807 								CELLINFO(1,0).eVShadowPart =
808 												bTopDiff ? SC_SHADOW_VSTART : SC_SHADOW_VERT;
809 							}
810 							if (bBottomDiff && bRightDiff)
811 							{
812 								CELLINFO(1,1).pHShadowOrigin = pThisAttr;
813 								CELLINFO(1,1).eHShadowPart = SC_SHADOW_CORNER;
814 							}
815 							break;
816 
817 						case SVX_SHADOW_BOTTOMLEFT:
818 							if (bBottomDiff)
819 							{
820 								CELLINFO(0,1).pHShadowOrigin = pThisAttr;
821 								CELLINFO(0,1).eHShadowPart =
822 												bRightDiff ? SC_SHADOW_HSTART : SC_SHADOW_HORIZ;
823 							}
824 							if (bLeftDiff)
825 							{
826 								CELLINFO(-1,0).pVShadowOrigin = pThisAttr;
827 								CELLINFO(-1,0).eVShadowPart =
828 												bTopDiff ? SC_SHADOW_VSTART : SC_SHADOW_VERT;
829 							}
830 							if (bBottomDiff && bLeftDiff)
831 							{
832 								CELLINFO(-1,1).pHShadowOrigin = pThisAttr;
833 								CELLINFO(-1,1).eHShadowPart = SC_SHADOW_CORNER;
834 							}
835 							break;
836 
837 						case SVX_SHADOW_TOPRIGHT:
838 							if (bTopDiff)
839 							{
840 								CELLINFO(0,-1).pHShadowOrigin = pThisAttr;
841 								CELLINFO(0,-1).eHShadowPart =
842 												bLeftDiff ? SC_SHADOW_HSTART : SC_SHADOW_HORIZ;
843 							}
844 							if (bRightDiff)
845 							{
846 								CELLINFO(1,0).pVShadowOrigin = pThisAttr;
847 								CELLINFO(1,0).eVShadowPart =
848 												bBottomDiff ? SC_SHADOW_VSTART : SC_SHADOW_VERT;
849 							}
850 							if (bTopDiff && bRightDiff)
851 							{
852 								CELLINFO(1,-1).pHShadowOrigin = pThisAttr;
853 								CELLINFO(1,-1).eHShadowPart = SC_SHADOW_CORNER;
854 							}
855 							break;
856 
857 						case SVX_SHADOW_TOPLEFT:
858 							if (bTopDiff)
859 							{
860 								CELLINFO(0,-1).pHShadowOrigin = pThisAttr;
861 								CELLINFO(0,-1).eHShadowPart =
862 												bRightDiff ? SC_SHADOW_HSTART : SC_SHADOW_HORIZ;
863 							}
864 							if (bLeftDiff)
865 							{
866 								CELLINFO(-1,0).pVShadowOrigin = pThisAttr;
867 								CELLINFO(-1,0).eVShadowPart =
868 												bBottomDiff ? SC_SHADOW_VSTART : SC_SHADOW_VERT;
869 							}
870 							if (bTopDiff && bLeftDiff)
871 							{
872 								CELLINFO(-1,-1).pHShadowOrigin = pThisAttr;
873 								CELLINFO(-1,-1).eHShadowPart = SC_SHADOW_CORNER;
874 							}
875 							break;
876 
877 						default:
878 							DBG_ERROR("falscher Shadow-Enum");
879 					}
880 				}
881 			}
882 		}
883 	}
884 
885     rTabInfo.mnArrCount = sal::static_int_cast<sal_uInt16>(nArrCount);
886     rTabInfo.mbPageMode = bPageMode;
887 
888     // ========================================================================
889     // *** create the frame border array ***
890 
891     // RowInfo structs are filled in the range [ 0 , nArrCount-1 ]
892     // each RowInfo contains CellInfo structs in the range [ nX1-1 , nX2+1 ]
893 
894     size_t nColCount = nX2 - nX1 + 3;
895     size_t nRowCount = nArrCount;
896 
897     svx::frame::Array& rArray = rTabInfo.maArray;
898     rArray.Initialize( nColCount, nRowCount );
899     rArray.SetUseDiagDoubleClipping( false );
900 
901     for( size_t nRow = 0; nRow < nRowCount; ++nRow )
902     {
903         sal_uInt16 nCellInfoY = static_cast< sal_uInt16 >( nRow );
904         RowInfo& rThisRowInfo = pRowInfo[ nCellInfoY ];
905 
906         for( size_t nCol = 0; nCol < nColCount; ++nCol )
907         {
908             sal_uInt16 nCellInfoX = static_cast< sal_uInt16 >( nCol + nX1 );
909             const CellInfo& rInfo = rThisRowInfo.pCellInfo[ nCellInfoX ];
910 
911             const SvxBoxItem* pBox = rInfo.pLinesAttr;
912             const SvxLineItem* pTLBR = rInfo.mpTLBRLine;
913             const SvxLineItem* pBLTR = rInfo.mpBLTRLine;
914 
915             size_t nFirstCol = nCol;
916             size_t nFirstRow = nRow;
917 
918             // *** merged cells *** -------------------------------------------
919 
920             if( !rArray.IsMerged( nCol, nRow ) && (rInfo.bMerged || rInfo.bHOverlapped || rInfo.bVOverlapped) )
921             {
922                 // *** insert merged range in svx::frame::Array ***
923 
924                 /*  #i69369# top-left cell of a merged range may be located in
925                     a hidden column or row. Use lcl_GetMergeRange() to find the
926                     complete merged range, then calculate dimensions and
927                     document position of the visible range. */
928 
929                 // note: document columns are always one less than CellInfoX coords
930                 // note: document rows must be looked up in RowInfo structs
931 
932                 // current column and row in document coordinates
933                 SCCOL nCurrDocCol = static_cast< SCCOL >( nCellInfoX - 1 );
934                 SCROW nCurrDocRow = static_cast< SCROW >( (nCellInfoY > 0) ? rThisRowInfo.nRowNo : (nY1 - 1) );
935 
936                 // find entire merged range in document, returns signed document coordinates
937                 SCsCOL nFirstRealDocColS, nLastRealDocColS;
938                 SCsROW nFirstRealDocRowS, nLastRealDocRowS;
939                 lcl_GetMergeRange( static_cast< SCsCOL >( nCurrDocCol ), static_cast< SCsROW >( nCurrDocRow ),
940                     nCellInfoY, this, pRowInfo, nX1,nY1,nX2,nY2,nTab,
941                     nFirstRealDocColS, nFirstRealDocRowS, nLastRealDocColS, nLastRealDocRowS );
942 
943                 // *complete* merged range in document coordinates
944                 SCCOL nFirstRealDocCol = static_cast< SCCOL >( nFirstRealDocColS );
945                 SCROW nFirstRealDocRow = static_cast< SCROW >( nFirstRealDocRowS );
946                 SCCOL nLastRealDocCol  = static_cast< SCCOL >( nLastRealDocColS );
947                 SCROW nLastRealDocRow  = static_cast< SCROW >( nLastRealDocRowS );
948 
949                 // first visible column (nX1-1 is first processed document column)
950                 SCCOL nFirstDocCol = (nX1 > 0) ? ::std::max< SCCOL >( nFirstRealDocCol, nX1 - 1 ) : nFirstRealDocCol;
951                 sal_uInt16 nFirstCellInfoX = static_cast< sal_uInt16 >( nFirstDocCol + 1 );
952                 nFirstCol = static_cast< size_t >( nFirstCellInfoX - nX1 );
953 
954                 // last visible column (nX2+1 is last processed document column)
955                 SCCOL nLastDocCol = (nX2 < MAXCOL) ? ::std::min< SCCOL >( nLastRealDocCol, nX2 + 1 ) : nLastRealDocCol;
956                 sal_uInt16 nLastCellInfoX = static_cast< sal_uInt16 >( nLastDocCol + 1 );
957                 size_t nLastCol = static_cast< size_t >( nLastCellInfoX - nX1 );
958 
959                 // first visible row
960                 sal_uInt16 nFirstCellInfoY = nCellInfoY;
961                 while( ((nFirstCellInfoY > 1) && (pRowInfo[ nFirstCellInfoY - 1 ].nRowNo >= nFirstRealDocRow)) ||
962                        ((nFirstCellInfoY == 1) && (static_cast< SCROW >( nY1 - 1 ) >= nFirstRealDocRow)) )
963                     --nFirstCellInfoY;
964                 SCROW nFirstDocRow = (nFirstCellInfoY > 0) ? pRowInfo[ nFirstCellInfoY ].nRowNo : static_cast< SCROW >( nY1 - 1 );
965                 nFirstRow = static_cast< size_t >( nFirstCellInfoY );
966 
967                 // last visible row
968                 sal_uInt16 nLastCellInfoY = nCellInfoY;
969                 while( (sal::static_int_cast<SCSIZE>(nLastCellInfoY + 1) < nArrCount) &&
970                             (pRowInfo[ nLastCellInfoY + 1 ].nRowNo <= nLastRealDocRow) )
971                     ++nLastCellInfoY;
972                 SCROW nLastDocRow = (nLastCellInfoY > 0) ? pRowInfo[ nLastCellInfoY ].nRowNo : static_cast< SCROW >( nY1 - 1 );
973                 size_t nLastRow = static_cast< size_t >( nLastCellInfoY );
974 
975                 // insert merged range
976                 rArray.SetMergedRange( nFirstCol, nFirstRow, nLastCol, nLastRow );
977 
978                 // *** find additional size not included in svx::frame::Array ***
979 
980                 // additional space before first column
981                 if( nFirstCol == 0 )
982                 {
983                     long nSize = 0;
984                     for( SCCOL nDocCol = nFirstRealDocCol; nDocCol < nFirstDocCol; ++nDocCol )
985                         nSize += std::max( static_cast< long >( GetColWidth( nDocCol, nTab ) * nScaleX ), 1L );
986                     rArray.SetAddMergedLeftSize( nCol, nRow, nSize );
987                 }
988                 // additional space after last column
989                 if( nLastCol + 1 == nColCount )
990                 {
991                     long nSize = 0;
992                     for( SCCOL nDocCol = nLastDocCol + 1; nDocCol <= nLastRealDocCol; ++nDocCol )
993                         nSize += std::max( static_cast< long >( GetColWidth( nDocCol, nTab ) * nScaleX ), 1L );
994                     rArray.SetAddMergedRightSize( nCol, nRow, nSize );
995                 }
996                 // additional space above first row
997                 if( nFirstRow == 0 )
998                 {
999                     long nSize = 0;
1000                     for( SCROW nDocRow = nFirstRealDocRow; nDocRow < nFirstDocRow; ++nDocRow )
1001                         nSize += std::max( static_cast< long >( GetRowHeight( nDocRow, nTab ) * nScaleY ), 1L );
1002                     rArray.SetAddMergedTopSize( nCol, nRow, nSize );
1003                 }
1004                 // additional space beyond last row
1005                 if( nLastRow + 1 == nRowCount )
1006                 {
1007                     long nSize = 0;
1008                     for( SCROW nDocRow = nLastDocRow + 1; nDocRow <= nLastRealDocRow; ++nDocRow )
1009                         nSize += std::max( static_cast< long >( GetRowHeight( nDocRow, nTab ) * nScaleY ), 1L );
1010                     rArray.SetAddMergedBottomSize( nCol, nRow, nSize );
1011                 }
1012 
1013                 // *** use line attributes from real origin cell ***
1014 
1015                 if( (nFirstRealDocCol != nCurrDocCol) || (nFirstRealDocRow != nCurrDocRow) )
1016                 {
1017                     if( const ScPatternAttr* pPattern = GetPattern( nFirstRealDocCol, nFirstRealDocRow, nTab ) )
1018                     {
1019                         const SfxItemSet* pCond = GetCondResult( nFirstRealDocCol, nFirstRealDocRow, nTab );
1020                         pBox = static_cast< const SvxBoxItem* >( &pPattern->GetItem( ATTR_BORDER, pCond ) );
1021                         pTLBR = static_cast< const SvxLineItem* >( &pPattern->GetItem( ATTR_BORDER_TLBR, pCond ) );
1022                         pBLTR = static_cast< const SvxLineItem* >( &pPattern->GetItem( ATTR_BORDER_BLTR, pCond ) );
1023                     }
1024                     else
1025                     {
1026                         pBox = 0;
1027                         pTLBR = pBLTR = 0;
1028                     }
1029                 }
1030             }
1031 
1032             // *** borders *** ------------------------------------------------
1033 
1034             if( pBox )
1035             {
1036                 rArray.SetCellStyleLeft(   nFirstCol, nFirstRow, svx::frame::Style( pBox->GetLeft(),   nScaleX ) );
1037                 rArray.SetCellStyleRight(  nFirstCol, nFirstRow, svx::frame::Style( pBox->GetRight(),  nScaleX ) );
1038                 rArray.SetCellStyleTop(    nFirstCol, nFirstRow, svx::frame::Style( pBox->GetTop(),    nScaleY ) );
1039                 rArray.SetCellStyleBottom( nFirstCol, nFirstRow, svx::frame::Style( pBox->GetBottom(), nScaleY ) );
1040             }
1041 
1042             if( pTLBR )
1043                 rArray.SetCellStyleTLBR( nFirstCol, nFirstRow, svx::frame::Style( pTLBR->GetLine(), nScaleY ) );
1044             if( rInfo.mpBLTRLine )
1045                 rArray.SetCellStyleBLTR( nFirstCol, nFirstRow, svx::frame::Style( pBLTR->GetLine(), nScaleY ) );
1046         }
1047     }
1048 
1049     /*  Mirror the entire frame array.
1050         1st param = Mirror the vertical double line styles as well.
1051         2nd param = Do not swap diagonal lines.
1052      */
1053     if( bLayoutRTL )
1054         rArray.MirrorSelfX( true, false );
1055 }
1056 
1057 // ============================================================================
1058 
ScTableInfo()1059 ScTableInfo::ScTableInfo() :
1060     mpRowInfo( new RowInfo[ ROWINFO_MAX ] ),
1061     mbPageMode( false )
1062 {
1063     for( sal_uInt16 nIdx = 0; nIdx < ROWINFO_MAX; ++nIdx )
1064         mpRowInfo[ nIdx ].pCellInfo = 0;
1065 }
1066 
~ScTableInfo()1067 ScTableInfo::~ScTableInfo()
1068 {
1069     for( sal_uInt16 nIdx = 0; nIdx < ROWINFO_MAX; ++nIdx )
1070         delete [] mpRowInfo[ nIdx ].pCellInfo;
1071     delete [] mpRowInfo;
1072 }
1073 
1074 // ============================================================================
1075 
1076