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