xref: /aoo41x/main/sc/source/ui/view/printfun.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 // INCLUDE ---------------------------------------------------------------
32 
33 #include "scitems.hxx"
34 #include <editeng/eeitem.hxx>
35 
36 #include "printfun.hxx"
37 
38 #include <svx/svxids.hrc>
39 #include <editeng/adjitem.hxx>
40 #include <editeng/boxitem.hxx>
41 #include <editeng/brshitem.hxx>
42 #include <svtools/colorcfg.hxx>
43 #include <editeng/editstat.hxx>		// EE_CNTRL_RTFSTYLESHEETS
44 #include <svx/fmview.hxx>
45 #include <editeng/frmdiritem.hxx>
46 #include <editeng/lrspitem.hxx>
47 #include <editeng/paperinf.hxx>
48 #include <editeng/pbinitem.hxx>
49 #include <editeng/shaditem.hxx>
50 #include <editeng/sizeitem.hxx>
51 #include <svx/svdpagv.hxx>
52 #include <editeng/ulspitem.hxx>
53 #include <sfx2/app.hxx>
54 #include <sfx2/printer.hxx>
55 #include <tools/multisel.hxx>
56 #include <sfx2/docfile.hxx>
57 #include <tools/urlobj.hxx>
58 #include <svx/xoutbmp.hxx>
59 
60 #include "editutil.hxx"
61 #include "docsh.hxx"
62 #include "output.hxx"
63 #include "viewdata.hxx"
64 #include "viewopti.hxx"
65 #include "stlpool.hxx"
66 #include "pagepar.hxx"
67 #include "attrib.hxx"
68 #include "patattr.hxx"
69 #include "docpool.hxx"
70 #include "dociter.hxx"
71 #include "cell.hxx"
72 #include "drawutil.hxx"
73 #include "globstr.hrc"
74 #include "scresid.hxx"
75 #include "sc.hrc"
76 #include "pagedata.hxx"
77 #include "printopt.hxx"
78 #include "prevloc.hxx"
79 #include "scmod.hxx"
80 #include "drwlayer.hxx"
81 #include "fillinfo.hxx"
82 #include "postit.hxx"
83 
84 #include <vcl/lineinfo.hxx>
85 #include <tools/pstm.hxx>
86 
87 #include <boost/scoped_ptr.hpp>
88 
89 #define ZOOM_MIN	10
90 
91 #define GET_BOOL(set,which)   ((const SfxBoolItem&)(set)->Get((which))).GetValue()
92 #define GET_USHORT(set,which) ((const SfxUInt16Item&)(set)->Get((which))).GetValue()
93 #define GET_SHOW(set,which)   ( VOBJ_MODE_SHOW == ScVObjMode( ((const ScViewObjectModeItem&)(set)->Get((which))).GetValue()) )
94 
95 //------------------------------------------------------------------------
96 
97 ScPageRowEntry::ScPageRowEntry(const ScPageRowEntry& r)
98 {
99 	nStartRow = r.nStartRow;
100 	nEndRow	  = r.nEndRow;
101 	nPagesX   = r.nPagesX;
102 	if (r.pHidden && nPagesX)
103 	{
104 		pHidden = new sal_Bool[nPagesX];
105 		memcpy( pHidden, r.pHidden, nPagesX * sizeof(sal_Bool) );
106 	}
107 	else
108 		pHidden = NULL;
109 }
110 
111 const ScPageRowEntry& ScPageRowEntry::operator=(const ScPageRowEntry& r)
112 {
113 	delete[] pHidden;
114 
115 	nStartRow = r.nStartRow;
116 	nEndRow	  = r.nEndRow;
117 	nPagesX   = r.nPagesX;
118 	if (r.pHidden && nPagesX)
119 	{
120 		pHidden = new sal_Bool[nPagesX];
121 		memcpy( pHidden, r.pHidden, nPagesX * sizeof(sal_Bool) );
122 	}
123 	else
124 		pHidden = NULL;
125 
126 	return *this;
127 }
128 
129 void ScPageRowEntry::SetPagesX(size_t nNew)
130 {
131 	if (pHidden)
132 	{
133 		DBG_ERROR("SetPagesX nicht nach SetHidden");
134 		delete[] pHidden;
135 		pHidden = NULL;
136 	}
137 	nPagesX = nNew;
138 }
139 
140 void ScPageRowEntry::SetHidden(size_t nX)
141 {
142 	if ( nX < nPagesX )
143 	{
144 		if ( nX+1 == nPagesX )	// letzte Seite?
145 			--nPagesX;
146 		else
147 		{
148 			if (!pHidden)
149 			{
150 				pHidden = new sal_Bool[nPagesX];
151 				memset( pHidden, sal_False, nPagesX * sizeof(sal_Bool) );
152 			}
153 			pHidden[nX] = sal_True;
154 		}
155 	}
156 }
157 
158 sal_Bool ScPageRowEntry::IsHidden(size_t nX) const
159 {
160 	return nX>=nPagesX || ( pHidden && pHidden[nX] );		//! inline?
161 }
162 
163 size_t ScPageRowEntry::CountVisible() const
164 {
165 	if ( pHidden )
166 	{
167 		size_t nVis = 0;
168 		for (size_t i=0; i<nPagesX; i++)
169 			if (!pHidden[i])
170 				++nVis;
171 		return nVis;
172 	}
173 	else
174 		return nPagesX;
175 }
176 
177 //------------------------------------------------------------------------
178 
179 long lcl_LineTotal(const SvxBorderLine* pLine)
180 {
181 	return pLine ? ( pLine->GetOutWidth() + pLine->GetInWidth() + pLine->GetDistance() ) : 0;
182 }
183 
184 void ScPrintFunc::Construct( const ScPrintOptions* pOptions )
185 {
186     pDocShell->UpdatePendingRowHeights( nPrintTab );
187 	pDoc = pDocShell->GetDocument();
188 
189 	SfxPrinter* pDocPrinter = pDoc->GetPrinter();	// auch fuer Preview den Drucker nehmen
190 	if (pDocPrinter)
191 		aOldPrinterMode = pDocPrinter->GetMapMode();
192 
193 	//	einheitlicher MapMode ueber alle Aufrufe (z.B. Repaint !!!),
194 	//	weil die EditEngine sonst unterschiedliche Texthoehen liefert
195 	pDev->SetMapMode(MAP_PIXEL);
196 
197 	pPageEndX = NULL;
198 	pPageEndY = NULL;
199 	pPageRows = NULL;
200 	pBorderItem = NULL;
201 	pBackgroundItem = NULL;
202 	pShadowItem = NULL;
203 
204 	pEditEngine = NULL;
205 	pEditDefaults = NULL;
206 
207 	ScStyleSheetPool* pStylePool	= pDoc->GetStyleSheetPool();
208 	SfxStyleSheetBase* pStyleSheet  = pStylePool->Find(
209 											pDoc->GetPageStyle( nPrintTab ),
210 											SFX_STYLE_FAMILY_PAGE );
211 	if (pStyleSheet)
212 		pParamSet = &pStyleSheet->GetItemSet();
213 	else
214 	{
215 		DBG_ERROR("Seitenvorlage nicht gefunden" );
216 		pParamSet = NULL;
217 	}
218 
219 	if (!bState)
220 		nZoom = 100;
221 	nManualZoom = 100;
222 	bClearWin = sal_False;
223 	bUseStyleColor = sal_False;
224 	bIsRender = sal_False;
225 
226 	InitParam(pOptions);
227 
228 	pPageData = NULL;		// wird nur zur Initialisierung gebraucht
229 }
230 
231 ScPrintFunc::ScPrintFunc( ScDocShell* pShell, SfxPrinter* pNewPrinter, SCTAB nTab,
232 							long nPage, long nDocP, const ScRange* pArea,
233 							const ScPrintOptions* pOptions,
234 							ScPageBreakData* pData )
235 	:	pDocShell			( pShell ),
236 		pPrinter			( pNewPrinter ),
237 		pDrawView			( NULL ),
238 		nPrintTab			( nTab ),
239 		nPageStart			( nPage ),
240 		nDocPages			( nDocP ),
241 		pUserArea			( pArea ),
242 		bState				( sal_False ),
243 		bSourceRangeValid	( sal_False ),
244 		bPrintCurrentTable	( sal_False ),
245 		bMultiArea			( sal_False ),
246 		nTabPages			( 0 ),
247 		nTotalPages			( 0 ),
248 		pPageData			( pData )
249 {
250 	pDev = pPrinter;
251 	aSrcOffset = pPrinter->PixelToLogic( pPrinter->GetPageOffsetPixel(), MAP_100TH_MM );
252 	Construct( pOptions );
253 }
254 
255 ScPrintFunc::ScPrintFunc( OutputDevice* pOutDev, ScDocShell* pShell, SCTAB nTab,
256 							long nPage, long nDocP, const ScRange* pArea,
257 							const ScPrintOptions* pOptions )
258 	:	pDocShell			( pShell ),
259 		pPrinter			( NULL ),
260 		pDrawView			( NULL ),
261 		nPrintTab			( nTab ),
262 		nPageStart			( nPage ),
263 		nDocPages			( nDocP ),
264 		pUserArea			( pArea ),
265 		bState				( sal_False ),
266 		bSourceRangeValid	( sal_False ),
267 		bPrintCurrentTable	( sal_False ),
268 		bMultiArea			( sal_False ),
269 		nTabPages			( 0 ),
270 		nTotalPages			( 0 ),
271 		pPageData			( NULL )
272 {
273 	pDev = pOutDev;
274 	Construct( pOptions );
275 }
276 
277 ScPrintFunc::ScPrintFunc( OutputDevice* pOutDev, ScDocShell* pShell,
278 							 const ScPrintState& rState, const ScPrintOptions* pOptions )
279 	:	pDocShell			( pShell ),
280 		pPrinter			( NULL ),
281 		pDrawView			( NULL ),
282 		pUserArea			( NULL ),
283 		bSourceRangeValid	( sal_False ),
284 		bPrintCurrentTable	( sal_False ),
285 		bMultiArea			( sal_False ),
286 		pPageData			( NULL )
287 {
288 	pDev = pOutDev;
289 
290 	nPrintTab	= rState.nPrintTab;
291 	nStartCol	= rState.nStartCol;
292 	nStartRow	= rState.nStartRow;
293 	nEndCol		= rState.nEndCol;
294 	nEndRow		= rState.nEndRow;
295 	nZoom		= rState.nZoom;
296 	nPagesX		= rState.nPagesX;
297 	nPagesY		= rState.nPagesY;
298 	nTabPages	= rState.nTabPages;
299 	nTotalPages	= rState.nTotalPages;
300 	nPageStart	= rState.nPageStart;
301 	nDocPages	= rState.nDocPages;
302 	bState		= sal_True;
303 
304 	Construct( pOptions );
305 }
306 
307 void ScPrintFunc::GetPrintState( ScPrintState& rState )
308 {
309 	rState.nPrintTab	= nPrintTab;
310 	rState.nStartCol	= nStartCol;
311 	rState.nStartRow	= nStartRow;
312 	rState.nEndCol		= nEndCol;
313 	rState.nEndRow		= nEndRow;
314 	rState.nZoom		= nZoom;
315 	rState.nPagesX		= nPagesX;
316 	rState.nPagesY		= nPagesY;
317 	rState.nTabPages	= nTabPages;
318 	rState.nTotalPages	= nTotalPages;
319 	rState.nPageStart	= nPageStart;
320 	rState.nDocPages	= nDocPages;
321 }
322 
323 sal_Bool ScPrintFunc::GetLastSourceRange( ScRange& rRange ) const
324 {
325 	rRange = aLastSourceRange;
326 	return bSourceRangeValid;
327 }
328 
329 void ScPrintFunc::FillPageData()
330 {
331 	if (pPageData)
332 	{
333         sal_uInt16 nCount = sal::static_int_cast<sal_uInt16>( pPageData->GetCount() );
334 		ScPrintRangeData& rData = pPageData->GetData(nCount);		// hochzaehlen
335 
336 		rData.SetPrintRange( ScRange( nStartCol, nStartRow, nPrintTab,
337 										nEndCol, nEndRow, nPrintTab ) );
338 		rData.SetPagesX( nPagesX, pPageEndX );
339 		rData.SetPagesY( nTotalY, pPageEndY );
340 
341 		//	Einstellungen
342 		rData.SetTopDown( aTableParam.bTopDown );
343 		rData.SetAutomatic( !aAreaParam.bPrintArea );
344 	}
345 }
346 
347 ScPrintFunc::~ScPrintFunc()
348 {
349 	ScAddress* pTripel = (ScAddress*) aNotePosList.First();
350 	while (pTripel)
351 	{
352 		delete pTripel;
353 		pTripel = (ScAddress*) aNotePosList.Next();
354 	}
355 	aNotePosList.Clear();
356 
357 	delete[] pPageEndX;
358 	delete[] pPageEndY;
359 	delete[] pPageRows;
360 	delete pEditDefaults;
361 	delete pEditEngine;
362 
363 	//	Druckereinstellungen werden jetzt von aussen wiederhergestellt
364 
365 	//	#64294# Fuer DrawingLayer/Charts muss der MapMode am Drucker (RefDevice) immer stimmen
366 	SfxPrinter* pDocPrinter = pDoc->GetPrinter();	// auch fuer Preview den Drucker nehmen
367 	if (pDocPrinter)
368 		pDocPrinter->SetMapMode(aOldPrinterMode);
369 }
370 
371 void ScPrintFunc::SetDrawView( FmFormView* pNew )
372 {
373 	pDrawView = pNew;
374 }
375 
376 void lcl_HidePrint( ScTableInfo& rTabInfo, SCCOL nX1, SCCOL nX2 )
377 {
378     for (SCSIZE nArrY=1; nArrY+1<rTabInfo.mnArrCount; nArrY++)
379 	{
380         RowInfo* pThisRowInfo = &rTabInfo.mpRowInfo[nArrY];
381 		for (SCCOL nX=nX1; nX<=nX2; nX++)
382 		{
383 			const CellInfo& rCellInfo = pThisRowInfo->pCellInfo[nX+1];
384 			if (!rCellInfo.bEmptyCellText)
385 				if (((const ScProtectionAttr&)rCellInfo.pPatternAttr->
386 							GetItem(ATTR_PROTECTION, rCellInfo.pConditionSet)).GetHidePrint())
387 				{
388 					pThisRowInfo->pCellInfo[nX+1].pCell			 = NULL;
389 					pThisRowInfo->pCellInfo[nX+1].bEmptyCellText = sal_True;
390 				}
391 		}
392 	}
393 }
394 
395 //
396 //			Ausgabe auf Device (static)
397 //
398 //		wird benutzt fuer:
399 //		-	Clipboard/Bitmap
400 //		-	Ole-Object (DocShell::Draw)
401 //		-	Vorschau bei Vorlagen
402 
403 void ScPrintFunc::DrawToDev( ScDocument* pDoc, OutputDevice* pDev, double /* nPrintFactor */,
404 							const Rectangle& rBound, ScViewData* pViewData, sal_Bool bMetaFile )
405 {
406 	//!	nPrintFactor auswerten !!!
407 
408 	SCTAB nTab = 0;
409 	if (pViewData)
410 		nTab = pViewData->GetTabNo();
411 
412 	sal_Bool bDoGrid, bNullVal, bFormula;
413 	ScStyleSheetPool* pStylePool = pDoc->GetStyleSheetPool();
414 	SfxStyleSheetBase* pStyleSheet = pStylePool->Find( pDoc->GetPageStyle( nTab ), SFX_STYLE_FAMILY_PAGE );
415 	if (pStyleSheet)
416 	{
417 		SfxItemSet& rSet = pStyleSheet->GetItemSet();
418 		bDoGrid  = ((const SfxBoolItem&)rSet.Get(ATTR_PAGE_GRID)).GetValue();
419 		bNullVal = ((const SfxBoolItem&)rSet.Get(ATTR_PAGE_NULLVALS)).GetValue();
420 		bFormula = ((const SfxBoolItem&)rSet.Get(ATTR_PAGE_FORMULAS)).GetValue();
421 	}
422 	else
423 	{
424 		const ScViewOptions& rOpt = pDoc->GetViewOptions();
425 		bDoGrid  = rOpt.GetOption(VOPT_GRID);
426 		bNullVal = rOpt.GetOption(VOPT_NULLVALS);
427 		bFormula = rOpt.GetOption(VOPT_FORMULAS);
428 	}
429 
430 	MapMode aMode = pDev->GetMapMode();
431 
432 	Rectangle aRect = rBound;
433 
434 	if (aRect.Right() < aRect.Left() || aRect.Bottom() < aRect.Top())
435 		aRect = Rectangle( Point(), pDev->GetOutputSize() );
436 
437 	SCCOL nX1 = 0;
438 	SCROW nY1 = 0;
439 	SCCOL nX2 = OLE_STD_CELLS_X - 1;
440 	SCROW nY2 = OLE_STD_CELLS_Y - 1;
441 	if (bMetaFile)
442 	{
443 		ScRange aRange = pDoc->GetRange( nTab, rBound );
444 		nX1 = aRange.aStart.Col();
445 		nY1 = aRange.aStart.Row();
446 		nX2 = aRange.aEnd.Col();
447 		nY2 = aRange.aEnd.Row();
448 	}
449 	else if (pViewData)
450 	{
451 		ScSplitPos eWhich = pViewData->GetActivePart();
452 		ScHSplitPos eHWhich = WhichH(eWhich);
453 		ScVSplitPos eVWhich = WhichV(eWhich);
454 		nX1 = pViewData->GetPosX(eHWhich);
455 		nY1 = pViewData->GetPosY(eVWhich);
456 		nX2 = nX1 + pViewData->VisibleCellsX(eHWhich);
457 		if (nX2>nX1) --nX2;
458 		nY2 = nY1 + pViewData->VisibleCellsY(eVWhich);
459 		if (nY2>nY1) --nY2;
460 	}
461 
462 	if (nX1 > MAXCOL) nX1 = MAXCOL;
463 	if (nX2 > MAXCOL) nX2 = MAXCOL;
464 	if (nY1 > MAXROW) nY1 = MAXROW;
465 	if (nY2 > MAXROW) nY2 = MAXROW;
466 
467 	long nDevSizeX = aRect.Right()-aRect.Left()+1;
468 	long nDevSizeY = aRect.Bottom()-aRect.Top()+1;
469 
470 	Rectangle aLines;
471 	ScRange aRange( nX1,nY1,nTab, nX2,nY2,nTab );
472 //    sal_Bool bAddLines = pDoc->HasLines( aRange, aLines );
473 
474 	long nTwipsSizeX = 0;
475 	for (SCCOL i=nX1; i<=nX2; i++)
476 		nTwipsSizeX += pDoc->GetColWidth( i, nTab );
477 	long nTwipsSizeY = (long) pDoc->GetRowHeight( nY1, nY2, nTab );
478 
479 	//	wenn keine Linien, dann trotzdem Platz fuer den Aussenrahmen (20 Twips = 1pt)
480 	//	(HasLines initalisiert aLines auf 0,0,0,0)
481 	nTwipsSizeX += aLines.Left() + Max( aLines.Right(), 20L );
482 	nTwipsSizeY += aLines.Top() +  Max( aLines.Bottom(), 20L );
483 
484 	double nScaleX = (double) nDevSizeX / nTwipsSizeX;
485 	double nScaleY = (double) nDevSizeY / nTwipsSizeY;
486 
487 							//!		Flag bei FillInfo uebergeben !!!!!
488     ScRange aERange;
489 	sal_Bool bEmbed = pDoc->IsEmbedded();
490 	if (bEmbed)
491 	{
492 		pDoc->GetEmbedded(aERange);
493 		pDoc->ResetEmbedded();
494 	}
495 
496 	//	Daten zusammenstellen
497 
498     ScTableInfo aTabInfo;
499     pDoc->FillInfo( aTabInfo, nX1, nY1, nX2, nY2, nTab,
500 										nScaleX, nScaleY, sal_False, bFormula );
501     lcl_HidePrint( aTabInfo, nX1, nX2 );
502 
503 	if (bEmbed)
504 		pDoc->SetEmbedded(aERange);
505 
506 /*	if (!bMetaFile)
507 		pDev->SetMapMode(MAP_PIXEL);
508 */
509 	long nScrX = aRect.Left();
510 	long nScrY = aRect.Top();
511 
512 	//	Wenn keine Linien, trotzdem Platz fuer Gitterlinien lassen
513 	//	(werden sonst abgeschnitten)
514 	long nAddX = (long)( aLines.Left() * nScaleX );
515 	nScrX += ( nAddX ? nAddX : 1 );
516 	long nAddY = (long)( aLines.Top() * nScaleY );
517 	nScrY += ( nAddY ? nAddY : 1 );
518 
519     ScOutputData aOutputData( pDev, OUTTYPE_PRINTER, aTabInfo, pDoc, nTab,
520 								nScrX, nScrY, nX1, nY1, nX2, nY2, nScaleX, nScaleY );
521 	aOutputData.SetMetaFileMode(bMetaFile);
522 	aOutputData.SetShowNullValues(bNullVal);
523 	aOutputData.SetShowFormulas(bFormula);
524 
525 	// #114135#
526 	ScDrawLayer* pModel = pDoc->GetDrawLayer();
527 	FmFormView* pDrawView = NULL;
528 
529 	if( pModel )
530 	{
531 		pDrawView = new FmFormView( pModel, pDev );
532 		pDrawView->ShowSdrPage(pDrawView->GetModel()->GetPage(nTab));
533 		pDrawView->SetPrintPreview( sal_True );
534 		aOutputData.SetDrawView( pDrawView );
535 	}
536 
537 	//!	SetUseStyleColor ??
538 
539 	if ( bMetaFile && pDev->GetOutDevType() == OUTDEV_VIRDEV )
540 		aOutputData.SetSnapPixel();
541 
542 	Point aLogStart = pDev->PixelToLogic( Point(nScrX,nScrY), MAP_100TH_MM );
543 	long nLogStX = aLogStart.X();
544 	long nLogStY = aLogStart.Y();
545 
546 	//!		nZoom fuer GetFont in OutputData ???
547 
548 	if (!bMetaFile && pViewData)
549 		pDev->SetMapMode(pViewData->GetLogicMode(pViewData->GetActivePart()));
550 
551 	// #i72502#
552 	const Point aMMOffset(aOutputData.PrePrintDrawingLayer(nLogStX, nLogStY));
553 	aOutputData.PrintDrawingLayer(SC_LAYER_BACK, aMMOffset);
554 
555 	if (!bMetaFile && pViewData)
556 		pDev->SetMapMode(aMode);
557 
558 	aOutputData.DrawBackground();
559 
560 #ifdef OS2
561 	if (bMetaFile && !bDoGrid)
562 	{
563 					// unter OS2 fuer Metafiles gesamte Flaeche benutzen,
564 					// weil sonst die Groesse nicht erkannt wird
565 		pDev->SetLineColor();
566 		pDev->SetFillColor();
567 		pDev->DrawRect( Rectangle( nScrX,nScrY,
568 						nScrX+aOutputData.GetScrW(), nScrY+aOutputData.GetScrH() ) );
569 	}
570 #endif
571 
572 	aOutputData.DrawShadow();
573 	aOutputData.DrawFrame();
574 	aOutputData.DrawStrings();
575 
576 	if (!bMetaFile && pViewData)
577 		pDev->SetMapMode(pViewData->GetLogicMode(pViewData->GetActivePart()));
578 
579 	aOutputData.DrawEdit(!bMetaFile);
580 
581 	if (bDoGrid)
582 	{
583 		if (!bMetaFile && pViewData)
584 			pDev->SetMapMode(aMode);
585 
586 		aOutputData.DrawGrid( sal_True, sal_False );	// keine Seitenumbrueche
587 
588 		pDev->SetLineColor( COL_BLACK );
589 
590 		Size aOne = pDev->PixelToLogic( Size(1,1) );
591 		if (bMetaFile)
592 			aOne = Size(1,1);	// compatible with DrawGrid
593 		long nRight = nScrX + aOutputData.GetScrW() - aOne.Width();
594 		long nBottom = nScrY + aOutputData.GetScrH() - aOne.Height();
595 
596 		sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
597 
598 		// extra line at the left edge for left-to-right, right for right-to-left
599 		if ( bLayoutRTL )
600 			pDev->DrawLine( Point(nRight,nScrY), Point(nRight,nBottom) );
601 		else
602 			pDev->DrawLine( Point(nScrX,nScrY), Point(nScrX,nBottom) );
603 		// extra line at the top in both cases
604 		pDev->DrawLine( Point(nScrX,nScrY), Point(nRight,nScrY) );
605 	}
606 
607 	// #i72502#
608 	aOutputData.PrintDrawingLayer(SC_LAYER_FRONT, aMMOffset);
609 	aOutputData.PrintDrawingLayer(SC_LAYER_INTERN, aMMOffset);
610 	aOutputData.PostPrintDrawingLayer(aMMOffset); // #i74768#
611 
612 	// #114135#
613 	delete pDrawView;
614 }
615 
616 //
617 //			Drucken
618 //
619 
620 void lcl_FillHFParam( ScPrintHFParam& rParam, const SfxItemSet* pHFSet )
621 {
622 	//	nDistance muss vorher unterschiedlich initalisiert sein
623 
624 	if ( pHFSet == NULL )
625 	{
626 		rParam.bEnable	= sal_False;
627 		rParam.pBorder	= NULL;
628 		rParam.pBack	= NULL;
629 		rParam.pShadow	= NULL;
630 	}
631 	else
632 	{
633 		rParam.bEnable	= ((const SfxBoolItem&) pHFSet->Get(ATTR_PAGE_ON)).GetValue();
634 		rParam.bDynamic	= ((const SfxBoolItem&) pHFSet->Get(ATTR_PAGE_DYNAMIC)).GetValue();
635 		rParam.bShared	= ((const SfxBoolItem&) pHFSet->Get(ATTR_PAGE_SHARED)).GetValue();
636 		rParam.nHeight	= ((const SvxSizeItem&) pHFSet->Get(ATTR_PAGE_SIZE)).GetSize().Height();
637 		const SvxLRSpaceItem* pHFLR = &(const SvxLRSpaceItem&) pHFSet->Get(ATTR_LRSPACE);
638 		long nTmp;
639 		nTmp = pHFLR->GetLeft();
640 		rParam.nLeft = nTmp < 0 ? 0 : sal_uInt16(nTmp);
641 		nTmp = pHFLR->GetRight();
642 		rParam.nRight = nTmp < 0 ? 0 : sal_uInt16(nTmp);
643 		rParam.pBorder	= (const SvxBoxItem*)   &pHFSet->Get(ATTR_BORDER);
644 		rParam.pBack	= (const SvxBrushItem*) &pHFSet->Get(ATTR_BACKGROUND);
645 		rParam.pShadow	= (const SvxShadowItem*)&pHFSet->Get(ATTR_SHADOW);;
646 
647 //	jetzt doch wieder schon im Dialog:
648 //		rParam.nHeight += rParam.nDistance;				// nicht mehr im Dialog ???
649 
650 		if (rParam.pBorder)
651 			rParam.nHeight += lcl_LineTotal( rParam.pBorder->GetTop() ) +
652 							  lcl_LineTotal( rParam.pBorder->GetBottom() );
653 
654 		rParam.nManHeight = rParam.nHeight;
655 	}
656 
657 	if (!rParam.bEnable)
658 		rParam.nHeight = 0;
659 }
660 
661 //	bNew = TRUE:	benutzten Bereich aus dem Dokument suchen
662 //	bNew = FALSE:	nur ganze Zeilen/Spalten begrenzen
663 
664 sal_Bool ScPrintFunc::AdjustPrintArea( sal_Bool bNew )
665 {
666 	SCCOL nOldEndCol = nEndCol;	// nur wichtig bei !bNew
667 	SCROW nOldEndRow = nEndRow;
668 	sal_Bool bChangeCol = sal_True;			// bei bNew werden beide angepasst
669 	sal_Bool bChangeRow = sal_True;
670 
671 	sal_Bool bNotes = aTableParam.bNotes;
672 	if ( bNew )
673 	{
674 		nStartCol = 0;
675 		nStartRow = 0;
676 		if (!pDoc->GetPrintArea( nPrintTab, nEndCol, nEndRow, bNotes ))
677 			return sal_False;	// nix
678 	}
679 	else
680 	{
681 		sal_Bool bFound = sal_True;
682 		bChangeCol = ( nStartCol == 0 && nEndCol == MAXCOL );
683 		bChangeRow = ( nStartRow == 0 && nEndRow == MAXROW );
684         sal_Bool bForcedChangeRow = sal_False;
685 
686         // #i53558# Crop entire column of old row limit to real print area with
687         // some fuzzyness.
688         if (!bChangeRow && nStartRow == 0)
689         {
690             SCROW nPAEndRow;
691             bFound = pDoc->GetPrintAreaVer( nPrintTab, nStartCol, nEndCol, nPAEndRow, bNotes );
692             // Say we don't want to print more than ~1000 empty rows, which are
693             // about 14 pages intentionally left blank..
694             const SCROW nFuzzy = 23*42;
695             if (nPAEndRow + nFuzzy < nEndRow)
696             {
697                 bForcedChangeRow = sal_True;
698                 nEndRow = nPAEndRow;
699             }
700             else
701                 bFound = sal_True;  // user seems to _want_ to print some empty rows
702         }
703         // TODO: in case we extend the number of columns we may have to do the
704         // same for horizontal cropping.
705 
706 		if ( bChangeCol && bChangeRow )
707 			bFound = pDoc->GetPrintArea( nPrintTab, nEndCol, nEndRow, bNotes );
708 		else if ( bChangeCol )
709 			bFound = pDoc->GetPrintAreaHor( nPrintTab, nStartRow, nEndRow, nEndCol, bNotes );
710 		else if ( bChangeRow )
711 			bFound = pDoc->GetPrintAreaVer( nPrintTab, nStartCol, nEndCol, nEndRow, bNotes );
712 
713 		if (!bFound)
714 			return sal_False;	// leer
715 
716         if (bForcedChangeRow)
717             bChangeRow = sal_True;
718 	}
719 
720 	pDoc->ExtendMerge( nStartCol,nStartRow, nEndCol,nEndRow, nPrintTab,
721 						sal_False, sal_True );		// kein Refresh, incl. Attrs
722 
723 	if ( bChangeCol )
724 	{
725 		OutputDevice* pRefDev = pDoc->GetPrinter();		// auch fuer Preview den Drucker nehmen
726 		pRefDev->SetMapMode( MAP_PIXEL );				// wichtig fuer GetNeededSize
727 
728 		pDoc->ExtendPrintArea( pRefDev,
729 							nPrintTab, nStartCol, nStartRow, nEndCol, nEndRow );
730 		//	nEndCol wird veraendert
731 	}
732 
733 	if ( nEndCol < MAXCOL && pDoc->HasAttrib(
734 					nEndCol,nStartRow,nPrintTab, nEndCol,nEndRow,nPrintTab, HASATTR_SHADOW_RIGHT ) )
735 		++nEndCol;
736 	if ( nEndRow < MAXROW && pDoc->HasAttrib(
737 					nStartCol,nEndRow,nPrintTab, nEndCol,nEndRow,nPrintTab, HASATTR_SHADOW_DOWN ) )
738 		++nEndRow;
739 
740 	if (!bChangeCol) nEndCol = nOldEndCol;
741 	if (!bChangeRow) nEndRow = nOldEndRow;
742 
743 	return sal_True;
744 }
745 
746 long ScPrintFunc::TextHeight( const EditTextObject* pObject )
747 {
748 	if (!pObject)
749 		return 0;
750 
751 //	pEditEngine->SetPageNo( nTotalPages );
752 	pEditEngine->SetTextNewDefaults( *pObject, *pEditDefaults, sal_False );
753 
754 	return (long) pEditEngine->GetTextHeight();
755 }
756 
757 //	nZoom muss gesetzt sein !!!
758 //	und der entsprechende Twip-MapMode eingestellt
759 
760 void ScPrintFunc::UpdateHFHeight( ScPrintHFParam& rParam )
761 {
762 	DBG_ASSERT( aPageSize.Width(), "UpdateHFHeight ohne aPageSize");
763 
764 	if (rParam.bEnable && rParam.bDynamic)
765 	{
766 		//	nHeight aus Inhalten berechnen
767 
768 		MakeEditEngine();
769 		long nPaperWidth = ( aPageSize.Width() - nLeftMargin - nRightMargin -
770 								rParam.nLeft - rParam.nRight ) * 100 / nZoom;
771 		if (rParam.pBorder)
772 			nPaperWidth -= ( rParam.pBorder->GetDistance(BOX_LINE_LEFT) +
773 							 rParam.pBorder->GetDistance(BOX_LINE_RIGHT) +
774 							 lcl_LineTotal(rParam.pBorder->GetLeft()) +
775 							 lcl_LineTotal(rParam.pBorder->GetRight()) ) * 100 / nZoom;
776 
777 		if (rParam.pShadow && rParam.pShadow->GetLocation() != SVX_SHADOW_NONE)
778 			nPaperWidth -= ( rParam.pShadow->CalcShadowSpace(SHADOW_LEFT) +
779 							 rParam.pShadow->CalcShadowSpace(SHADOW_RIGHT) ) * 100L / nZoom;
780 
781 		pEditEngine->SetPaperSize( Size( nPaperWidth, 10000 ) );
782 
783 		long nMaxHeight = 0;
784 		if ( rParam.pLeft )
785 		{
786 			nMaxHeight = Max( nMaxHeight, TextHeight( rParam.pLeft->GetLeftArea() ) );
787 			nMaxHeight = Max( nMaxHeight, TextHeight( rParam.pLeft->GetCenterArea() ) );
788 			nMaxHeight = Max( nMaxHeight, TextHeight( rParam.pLeft->GetRightArea() ) );
789 		}
790 		if ( rParam.pRight )
791 		{
792 			nMaxHeight = Max( nMaxHeight, TextHeight( rParam.pRight->GetLeftArea() ) );
793 			nMaxHeight = Max( nMaxHeight, TextHeight( rParam.pRight->GetCenterArea() ) );
794 			nMaxHeight = Max( nMaxHeight, TextHeight( rParam.pRight->GetRightArea() ) );
795 		}
796 
797 		rParam.nHeight = nMaxHeight + rParam.nDistance;
798 		if (rParam.pBorder)
799 			rParam.nHeight += rParam.pBorder->GetDistance(BOX_LINE_TOP) +
800 							  rParam.pBorder->GetDistance(BOX_LINE_BOTTOM) +
801 							  lcl_LineTotal( rParam.pBorder->GetTop() ) +
802 							  lcl_LineTotal( rParam.pBorder->GetBottom() );
803 		if (rParam.pShadow && rParam.pShadow->GetLocation() != SVX_SHADOW_NONE)
804 			rParam.nHeight += rParam.pShadow->CalcShadowSpace(SHADOW_TOP) +
805 							  rParam.pShadow->CalcShadowSpace(SHADOW_BOTTOM);
806 
807 		if (rParam.nHeight < rParam.nManHeight)
808 			rParam.nHeight = rParam.nManHeight;			// eingestelltes Minimum
809 	}
810 }
811 
812 void ScPrintFunc::InitParam( const ScPrintOptions* pOptions )
813 {
814 	if (!pParamSet)
815 		return;
816 
817 								// TabPage "Seite"
818 	const SvxLRSpaceItem* pLRItem = (const SvxLRSpaceItem*) &pParamSet->Get( ATTR_LRSPACE );
819 	long nTmp;
820 	nTmp = pLRItem->GetLeft();
821 	nLeftMargin = nTmp < 0 ? 0 : sal_uInt16(nTmp);
822 	nTmp = pLRItem->GetRight();
823 	nRightMargin = nTmp < 0 ? 0 : sal_uInt16(nTmp);
824 	const SvxULSpaceItem* pULItem = (const SvxULSpaceItem*) &pParamSet->Get( ATTR_ULSPACE );
825 	nTopMargin    = pULItem->GetUpper();
826 	nBottomMargin = pULItem->GetLower();
827 
828 	const SvxPageItem* pPageItem = (const SvxPageItem*) &pParamSet->Get( ATTR_PAGE );
829 	nPageUsage			= pPageItem->GetPageUsage();
830 	bLandscape			= pPageItem->IsLandscape();
831 	aFieldData.eNumType	= pPageItem->GetNumType();
832 
833 	bCenterHor = ((const SfxBoolItem&) pParamSet->Get(ATTR_PAGE_HORCENTER)).GetValue();
834 	bCenterVer = ((const SfxBoolItem&) pParamSet->Get(ATTR_PAGE_VERCENTER)).GetValue();
835 
836 	aPageSize = ((const SvxSizeItem&) pParamSet->Get(ATTR_PAGE_SIZE)).GetSize();
837 	if ( !aPageSize.Width() || !aPageSize.Height() )
838 	{
839 		DBG_ERROR("PageSize Null ?!?!?");
840 		aPageSize = SvxPaperInfo::GetPaperSize( PAPER_A4 );
841 	}
842 
843 	pBorderItem		= (const SvxBoxItem*)    &pParamSet->Get(ATTR_BORDER);
844 	pBackgroundItem	= (const SvxBrushItem*)	 &pParamSet->Get(ATTR_BACKGROUND);
845 	pShadowItem		= (const SvxShadowItem*) &pParamSet->Get(ATTR_SHADOW);
846 
847 								// TabPage "Kopfzeile"
848 
849 	aHdr.pLeft		= (const ScPageHFItem*)	&pParamSet->Get(ATTR_PAGE_HEADERLEFT);		// Inhalt
850 	aHdr.pRight		= (const ScPageHFItem*)	&pParamSet->Get(ATTR_PAGE_HEADERRIGHT);
851 
852 	const SvxSetItem* pHeaderSetItem;
853 	const SfxItemSet* pHeaderSet = NULL;
854 	if ( pParamSet->GetItemState( ATTR_PAGE_HEADERSET, sal_False,
855 							(const SfxPoolItem**)&pHeaderSetItem ) == SFX_ITEM_SET )
856 	{
857 		pHeaderSet = &pHeaderSetItem->GetItemSet();
858 														// Kopfzeile hat unteren Abstand
859 		aHdr.nDistance	= ((const SvxULSpaceItem&) pHeaderSet->Get(ATTR_ULSPACE)).GetLower();
860 	}
861 	lcl_FillHFParam( aHdr, pHeaderSet );
862 
863 								// TabPage "Fusszeile"
864 
865 	aFtr.pLeft		= (const ScPageHFItem*)	&pParamSet->Get(ATTR_PAGE_FOOTERLEFT);		// Inhalt
866 	aFtr.pRight		= (const ScPageHFItem*)	&pParamSet->Get(ATTR_PAGE_FOOTERRIGHT);
867 
868 	const SvxSetItem* pFooterSetItem;
869 	const SfxItemSet* pFooterSet = NULL;
870 	if ( pParamSet->GetItemState( ATTR_PAGE_FOOTERSET, sal_False,
871 							(const SfxPoolItem**)&pFooterSetItem ) == SFX_ITEM_SET )
872 	{
873 		pFooterSet = &pFooterSetItem->GetItemSet();
874 														// Fusszeile hat oberen Abstand
875 		aFtr.nDistance	= ((const SvxULSpaceItem&) pFooterSet->Get(ATTR_ULSPACE)).GetUpper();
876 	}
877 	lcl_FillHFParam( aFtr, pFooterSet );
878 
879 	//------------------------------------------------------
880 	// Table-/Area-Params aus einzelnen Items zusammenbauen:
881 	//------------------------------------------------------
882 	// TabPage "Tabelle"
883 
884     const SfxUInt16Item*     pScaleItem          = NULL;
885     const ScPageScaleToItem* pScaleToItem        = NULL;
886     const SfxUInt16Item*     pScaleToPagesItem   = NULL;
887     SfxItemState             eState;
888 
889 	eState = pParamSet->GetItemState( ATTR_PAGE_SCALE, sal_False,
890 									  (const SfxPoolItem**)&pScaleItem );
891 	if ( SFX_ITEM_DEFAULT == eState )
892 		pScaleItem = (const SfxUInt16Item*)
893                     &pParamSet->GetPool()->GetDefaultItem( ATTR_PAGE_SCALE );
894 
895     eState = pParamSet->GetItemState( ATTR_PAGE_SCALETO, sal_False,
896                                       (const SfxPoolItem**)&pScaleToItem );
897     if ( SFX_ITEM_DEFAULT == eState )
898         pScaleToItem = (const ScPageScaleToItem*)
899                     &pParamSet->GetPool()->GetDefaultItem( ATTR_PAGE_SCALETO );
900 
901 	eState = pParamSet->GetItemState( ATTR_PAGE_SCALETOPAGES, sal_False,
902 									  (const SfxPoolItem**)&pScaleToPagesItem );
903 	if ( SFX_ITEM_DEFAULT == eState )
904 		pScaleToPagesItem = (const SfxUInt16Item*)
905                     &pParamSet->GetPool()->GetDefaultItem( ATTR_PAGE_SCALETOPAGES );
906 
907     DBG_ASSERT( pScaleItem && pScaleToItem && pScaleToPagesItem, "Missing ScaleItem! :-/" );
908 
909     aTableParam.bCellContent    = sal_True;
910 	aTableParam.bNotes			= GET_BOOL(pParamSet,ATTR_PAGE_NOTES);
911 	aTableParam.bGrid			= GET_BOOL(pParamSet,ATTR_PAGE_GRID);
912 	aTableParam.bHeaders		= GET_BOOL(pParamSet,ATTR_PAGE_HEADERS);
913 	aTableParam.bFormulas		= GET_BOOL(pParamSet,ATTR_PAGE_FORMULAS);
914 	aTableParam.bNullVals		= GET_BOOL(pParamSet,ATTR_PAGE_NULLVALS);
915 	aTableParam.bCharts			= GET_SHOW(pParamSet,ATTR_PAGE_CHARTS);
916 	aTableParam.bObjects		= GET_SHOW(pParamSet,ATTR_PAGE_OBJECTS);
917 	aTableParam.bDrawings		= GET_SHOW(pParamSet,ATTR_PAGE_DRAWINGS);
918 	aTableParam.bTopDown		= GET_BOOL(pParamSet,ATTR_PAGE_TOPDOWN);
919 	aTableParam.bLeftRight		= !aTableParam.bLeftRight;
920 	aTableParam.nFirstPageNo	= GET_USHORT(pParamSet,ATTR_PAGE_FIRSTPAGENO);
921 	if (!aTableParam.nFirstPageNo)
922 		aTableParam.nFirstPageNo = (sal_uInt16) nPageStart;		// von vorheriger Tabelle
923 
924     if ( pScaleItem && pScaleToItem && pScaleToPagesItem )
925 	{
926 		sal_uInt16	nScaleAll     = pScaleItem->GetValue();
927 		sal_uInt16	nScaleToPages = pScaleToPagesItem->GetValue();
928 
929 		aTableParam.bScaleNone		= (nScaleAll     == 100);
930 		aTableParam.bScaleAll		= (nScaleAll      > 0  );
931         aTableParam.bScaleTo        = pScaleToItem->IsValid();
932 		aTableParam.bScalePageNum	= (nScaleToPages  > 0  );
933 		aTableParam.nScaleAll		= nScaleAll;
934         aTableParam.nScaleWidth     = pScaleToItem->GetWidth();
935         aTableParam.nScaleHeight    = pScaleToItem->GetHeight();
936 		aTableParam.nScalePageNum	= nScaleToPages;
937 	}
938 	else
939 	{
940 		aTableParam.bScaleNone		= sal_True;
941 		aTableParam.bScaleAll		= sal_False;
942         aTableParam.bScaleTo        = sal_False;
943 		aTableParam.bScalePageNum	= sal_False;
944 		aTableParam.nScaleAll		= 0;
945         aTableParam.nScaleWidth     = 0;
946         aTableParam.nScaleHeight    = 0;
947 		aTableParam.nScalePageNum	= 0;
948 	}
949 
950 	//	skip empty pages only if options with that flag are passed
951 	aTableParam.bSkipEmpty = pOptions && pOptions->GetSkipEmpty();
952 	if ( pPageData )
953 		aTableParam.bSkipEmpty = sal_False;
954 	// Wenn pPageData gesetzt ist, interessieren fuer die Umbruch-Vorschau
955 	// nur die Umbrueche, leere Seiten werden nicht speziell behandelt
956 
957 	//------------------------------------------------------
958 	// TabPage "Bereiche":
959 	//------------------------------------------------------
960 
961 	//!	alle PrintAreas der Tabelle durchgehen !!!
962 	const ScRange*	pPrintArea = pDoc->GetPrintRange( nPrintTab, 0 );
963 	const ScRange*	pRepeatCol = pDoc->GetRepeatColRange( nPrintTab );
964 	const ScRange*	pRepeatRow = pDoc->GetRepeatRowRange( nPrintTab );
965 
966 	//	ATTR_PAGE_PRINTTABLES wird ignoriert
967 
968 	if ( pUserArea )				// UserArea (Selektion) hat Vorrang
969 	{
970 		bPrintCurrentTable    =
971 		aAreaParam.bPrintArea = sal_True;					// Selektion
972 		aAreaParam.aPrintArea = *pUserArea;
973 
974 		//	Die Tabellen-Abfrage ist schon in DocShell::Print, hier immer
975 		aAreaParam.aPrintArea.aStart.SetTab(nPrintTab);
976 		aAreaParam.aPrintArea.aEnd.SetTab(nPrintTab);
977 
978 //		lcl_LimitRange( aAreaParam.aPrintArea, nPrintTab );			// ganze Zeilen/Spalten...
979 	}
980 	else if ( pDoc->HasPrintRange() )
981 	{
982 		if ( pPrintArea )								// mindestens eine gesetzt ?
983 		{
984 			bPrintCurrentTable    =
985 			aAreaParam.bPrintArea = sal_True;
986 			aAreaParam.aPrintArea = *pPrintArea;
987 
988 			bMultiArea = ( pDoc->GetPrintRangeCount(nPrintTab) > 1 );
989 		}
990 		else
991 		{
992             // do not print hidden sheets with "Print entire sheet" flag
993             bPrintCurrentTable = pDoc->IsPrintEntireSheet( nPrintTab ) && pDoc->IsVisible( nPrintTab );
994             aAreaParam.bPrintArea = !bPrintCurrentTable;    // otherwise the table is always counted
995 		}
996 	}
997 	else
998 	{
999 		//	#74834# don't print hidden tables if there's no print range defined there
1000 		if ( pDoc->IsVisible( nPrintTab ) )
1001 		{
1002 			aAreaParam.bPrintArea = sal_False;
1003 			bPrintCurrentTable = sal_True;
1004 		}
1005 		else
1006 		{
1007 			aAreaParam.bPrintArea = sal_True;	// otherwise the table is always counted
1008 			bPrintCurrentTable = sal_False;
1009 		}
1010 	}
1011 
1012 	if ( pRepeatCol )
1013 	{
1014 		aAreaParam.bRepeatCol = sal_True;
1015 		aAreaParam.aRepeatCol = *pRepeatCol;
1016 		nRepeatStartCol	= pRepeatCol->aStart.Col();
1017 		nRepeatEndCol	= pRepeatCol->aEnd  .Col();
1018 	}
1019 	else
1020 	{
1021 		aAreaParam.bRepeatCol = sal_False;
1022 		nRepeatStartCol = nRepeatEndCol = SCCOL_REPEAT_NONE;
1023 	}
1024 
1025 	if ( pRepeatRow )
1026 	{
1027 		aAreaParam.bRepeatRow = sal_True;
1028 		aAreaParam.aRepeatRow = *pRepeatRow;
1029 		nRepeatStartRow	= pRepeatRow->aStart.Row();
1030 		nRepeatEndRow	= pRepeatRow->aEnd  .Row();
1031 	}
1032 	else
1033 	{
1034 		aAreaParam.bRepeatRow = sal_False;
1035 		nRepeatStartRow = nRepeatEndRow = SCROW_REPEAT_NONE;
1036 	}
1037 
1038 			//
1039 			//	Seiten aufteilen
1040 			//
1041 
1042 	if (!bState)
1043 	{
1044 		nTabPages = CountPages();									// berechnet auch Zoom
1045 		nTotalPages = nTabPages;
1046 		nTotalPages += CountNotePages();
1047 	}
1048 	else
1049 	{
1050 		CalcPages();			// nur Umbrueche suchen
1051 		CountNotePages();		// Notizen zaehlen, auch wenn Seitenzahl schon bekannt
1052 	}
1053 
1054 	if (nDocPages)
1055 		aFieldData.nTotalPages = nDocPages;
1056 	else
1057 		aFieldData.nTotalPages = nTotalPages;
1058 
1059 	SetDateTime( Date(), Time() );
1060 
1061 	aFieldData.aTitle		= pDocShell->GetTitle();
1062 	const INetURLObject& rURLObj = pDocShell->GetMedium()->GetURLObject();
1063 	aFieldData.aLongDocName	= rURLObj.GetMainURL( INetURLObject::DECODE_UNAMBIGUOUS );
1064 	if ( aFieldData.aLongDocName.Len() )
1065 		aFieldData.aShortDocName = rURLObj.GetName( INetURLObject::DECODE_UNAMBIGUOUS );
1066 	else
1067 		aFieldData.aShortDocName = aFieldData.aLongDocName = aFieldData.aTitle;
1068 
1069 	//	Druckereinstellungen (Orientation, Paper) jetzt erst bei DoPrint
1070 }
1071 
1072 Size ScPrintFunc::GetDataSize() const
1073 {
1074 	Size aSize = aPageSize;
1075 	aSize.Width()  -= nLeftMargin + nRightMargin;
1076 	aSize.Height() -= nTopMargin + nBottomMargin;
1077 	aSize.Height() -= aHdr.nHeight + aFtr.nHeight;
1078 	return aSize;
1079 }
1080 
1081 void ScPrintFunc::GetScaleData( Size& rPhysSize, long& rDocHdr, long& rDocFtr )
1082 {
1083 	rPhysSize = aPageSize;
1084 	rPhysSize.Width()  -= nLeftMargin + nRightMargin;
1085 	rPhysSize.Height() -= nTopMargin + nBottomMargin;
1086 
1087 	rDocHdr = aHdr.nHeight;
1088 	rDocFtr = aFtr.nHeight;
1089 }
1090 
1091 void ScPrintFunc::SetDateTime( const Date& rDate, const Time& rTime )
1092 {
1093 	aFieldData.aDate = rDate;
1094 	aFieldData.aTime = rTime;
1095 }
1096 
1097 void lcl_DrawGraphic( const Graphic &rGraphic, OutputDevice *pOut,
1098                       const Rectangle &rGrf, const Rectangle &rOut )
1099 {
1100     const FASTBOOL bNotInside = !rOut.IsInside( rGrf );
1101     if ( bNotInside )
1102     {
1103         pOut->Push();
1104         pOut->IntersectClipRegion( rOut );
1105     }
1106 
1107     ((Graphic&)rGraphic).Draw( pOut, rGrf.TopLeft(), rGrf.GetSize() );
1108 
1109     if ( bNotInside )
1110         pOut->Pop();
1111 }
1112 
1113 void lcl_DrawGraphic( const SvxBrushItem &rBrush, OutputDevice *pOut, OutputDevice* pRefDev,
1114 						const Rectangle &rOrg, const Rectangle &rOut )
1115 {
1116 	Size aGrfSize(0,0);
1117 	const Graphic *pGraphic = rBrush.GetGraphic();
1118 	SvxGraphicPosition ePos;
1119 	if ( pGraphic && pGraphic->IsSupportedGraphic() )
1120 	{
1121 		const MapMode aMapMM( MAP_100TH_MM );
1122 		if ( pGraphic->GetPrefMapMode().GetMapUnit() == MAP_PIXEL )
1123 			aGrfSize = pRefDev->PixelToLogic( pGraphic->GetPrefSize(), aMapMM );
1124 		else
1125 			aGrfSize = OutputDevice::LogicToLogic( pGraphic->GetPrefSize(),
1126 									pGraphic->GetPrefMapMode(), aMapMM );
1127 		ePos = rBrush.GetGraphicPos();
1128 	}
1129 	else
1130 		ePos = GPOS_NONE;
1131 
1132 	Point aPos;
1133 	Size aDrawSize = aGrfSize;
1134 
1135 	FASTBOOL bDraw = sal_True;
1136 //	FASTBOOL bRetouche = sal_True;
1137 	switch ( ePos )
1138 	{
1139 		case GPOS_LT: aPos = rOrg.TopLeft();
1140 					  break;
1141 		case GPOS_MT: aPos.Y() = rOrg.Top();
1142 					  aPos.X() = rOrg.Left() + rOrg.GetSize().Width()/2 - aGrfSize.Width()/2;
1143 					  break;
1144 		case GPOS_RT: aPos.Y() = rOrg.Top();
1145 					  aPos.X() = rOrg.Right() - aGrfSize.Width();
1146 					  break;
1147 
1148 		case GPOS_LM: aPos.Y() = rOrg.Top() + rOrg.GetSize().Height()/2 - aGrfSize.Height()/2;
1149 					  aPos.X() = rOrg.Left();
1150 					  break;
1151 		case GPOS_MM: aPos.Y() = rOrg.Top() + rOrg.GetSize().Height()/2 - aGrfSize.Height()/2;
1152 					  aPos.X() = rOrg.Left() + rOrg.GetSize().Width()/2 - aGrfSize.Width()/2;
1153 					  break;
1154 		case GPOS_RM: aPos.Y() = rOrg.Top() + rOrg.GetSize().Height()/2 - aGrfSize.Height()/2;
1155 					  aPos.X() = rOrg.Right() - aGrfSize.Width();
1156 					  break;
1157 
1158 		case GPOS_LB: aPos.Y() = rOrg.Bottom() - aGrfSize.Height();
1159 					  aPos.X() = rOrg.Left();
1160 					  break;
1161 		case GPOS_MB: aPos.Y() = rOrg.Bottom() - aGrfSize.Height();
1162 					  aPos.X() = rOrg.Left() + rOrg.GetSize().Width()/2 - aGrfSize.Width()/2;
1163 					  break;
1164 		case GPOS_RB: aPos.Y() = rOrg.Bottom() - aGrfSize.Height();
1165 					  aPos.X() = rOrg.Right() - aGrfSize.Width();
1166 					  break;
1167 
1168 		case GPOS_AREA:
1169 					  aPos = rOrg.TopLeft();
1170 					  aDrawSize = rOrg.GetSize();
1171 //					  bRetouche = sal_False;
1172 					  break;
1173 		case GPOS_TILED:
1174 					{
1175 						//	#104004# use GraphicObject::DrawTiled instead of an own loop
1176 						//	(pixel rounding is handled correctly, and a very small bitmap
1177 						//	is duplicated into a bigger one for better performance)
1178 
1179 						GraphicObject aObject( *pGraphic );
1180 
1181                         if( pOut->GetPDFWriter() &&
1182                             (aObject.GetType() == GRAPHIC_BITMAP || aObject.GetType() == GRAPHIC_DEFAULT) )
1183                         {
1184                             // #104004# For PDF export, every draw
1185                             // operation for bitmaps takes a noticeable
1186                             // amount of place (~50 characters). Thus,
1187                             // optimize between tile bitmap size and
1188                             // number of drawing operations here.
1189                             //
1190                             //                  A_out
1191                             // n_chars = k1 *  ---------- + k2 * A_bitmap
1192                             //                  A_bitmap
1193                             //
1194                             // minimum n_chars is obtained for (derive for
1195                             // A_bitmap, set to 0, take positive
1196                             // solution):
1197                             //                   k1
1198                             // A_bitmap = Sqrt( ---- A_out )
1199                             //                   k2
1200                             //
1201                             // where k1 is the number of chars per draw
1202                             // operation, and k2 is the number of chars
1203                             // per bitmap pixel. This is approximately 50
1204                             // and 7 for current PDF writer, respectively.
1205                             //
1206                             const double	k1( 50 );
1207                             const double	k2( 7 );
1208                             const Size 		aSize( rOrg.GetSize() );
1209                             const double 	Abitmap( k1/k2 * aSize.Width()*aSize.Height() );
1210 
1211                             aObject.DrawTiled( pOut, rOrg, aGrfSize, Size(0,0),
1212                                                NULL, GRFMGR_DRAW_STANDARD,
1213                                                ::std::max( 128, static_cast<int>( sqrt(sqrt( Abitmap)) + .5 ) ) );
1214                         }
1215                         else
1216                         {
1217                             aObject.DrawTiled( pOut, rOrg, aGrfSize, Size(0,0) );
1218                         }
1219 
1220 						bDraw = sal_False;
1221 //						bRetouche = sal_False;
1222 					}
1223 					break;
1224 
1225 		case GPOS_NONE:
1226 					  bDraw = sal_False;
1227 					  break;
1228 
1229 		default: DBG_ASSERT( !pOut, "new Graphic position?" );
1230 	}
1231 	Rectangle aGrf( aPos,aDrawSize );
1232 	if ( bDraw && aGrf.IsOver( rOut ) )
1233 	{
1234 		lcl_DrawGraphic( *pGraphic, pOut, aGrf, rOut );
1235 	}
1236 }
1237 
1238 //	Rahmen wird nach innen gezeichnet
1239 
1240 void ScPrintFunc::DrawBorder( long nScrX, long nScrY, long nScrW, long nScrH,
1241 								const SvxBoxItem* pBorderData, const SvxBrushItem* pBackground,
1242 								const SvxShadowItem* pShadow )
1243 {
1244 	//!		direkte Ausgabe aus SvxBoxItem !!!
1245 
1246 	if (pBorderData)
1247 		if ( !pBorderData->GetTop() && !pBorderData->GetBottom() && !pBorderData->GetLeft() &&
1248 										!pBorderData->GetRight() )
1249 			pBorderData = NULL;
1250 
1251 	if (!pBorderData && !pBackground && !pShadow)
1252 		return;										// nichts zu tun
1253 
1254 	long nLeft   = 0;
1255 	long nRight  = 0;
1256 	long nTop    = 0;
1257 	long nBottom = 0;
1258 
1259 	//	aFrameRect - aussen um die Umrandung, ohne Schatten
1260 	if ( pShadow && pShadow->GetLocation() != SVX_SHADOW_NONE )
1261 	{
1262 		nLeft	+= (long) ( pShadow->CalcShadowSpace(SHADOW_LEFT)	* nScaleX );
1263 		nRight	+= (long) ( pShadow->CalcShadowSpace(SHADOW_RIGHT)	* nScaleX );
1264 		nTop	+= (long) ( pShadow->CalcShadowSpace(SHADOW_TOP)	* nScaleY );
1265 		nBottom	+= (long) ( pShadow->CalcShadowSpace(SHADOW_BOTTOM)	* nScaleY );
1266 	}
1267 	Rectangle aFrameRect( Point(nScrX+nLeft, nScrY+nTop),
1268 						  Size(nScrW-nLeft-nRight, nScrH-nTop-nBottom) );
1269 
1270 	//	Mitte der Umrandung, um Linien ueber OutputData zu zeichnen:
1271 	if (pBorderData)
1272 	{
1273 		nLeft   += (long) ( lcl_LineTotal(pBorderData->GetLeft())   * nScaleX / 2 );
1274 		nRight  += (long) ( lcl_LineTotal(pBorderData->GetRight())  * nScaleX / 2 );
1275 		nTop    += (long) ( lcl_LineTotal(pBorderData->GetTop())    * nScaleY / 2 );
1276 		nBottom += (long) ( lcl_LineTotal(pBorderData->GetBottom()) * nScaleY / 2 );
1277 	}
1278 	long nEffHeight = nScrH - nTop - nBottom;
1279 	long nEffWidth = nScrW - nLeft - nRight;
1280 	if (nEffHeight<=0 || nEffWidth<=0)
1281 		return;											// leer
1282 
1283 	//	#105733# SvtAccessibilityOptions::GetIsForBorders is no longer used (always assumed sal_True)
1284 	sal_Bool bCellContrast = bUseStyleColor &&
1285 			Application::GetSettings().GetStyleSettings().GetHighContrastMode();
1286 
1287 	if ( pBackground && !bCellContrast )
1288 	{
1289 //		Rectangle aBackRect( Point(nScrX+nLeft, nScrY+nTop), Size(nEffWidth,nEffHeight) );
1290 		if (pBackground->GetGraphicPos() != GPOS_NONE)
1291 		{
1292 			OutputDevice* pRefDev;
1293 			if ( bIsRender )
1294 				pRefDev = pDev;					// don't use printer for PDF
1295 			else
1296 				pRefDev = pDoc->GetPrinter();	// use printer also for preview
1297 
1298 			lcl_DrawGraphic( *pBackground, pDev, pRefDev, aFrameRect, aFrameRect );
1299 		}
1300 		else
1301 		{
1302 			pDev->SetFillColor(pBackground->GetColor());
1303 			pDev->SetLineColor();
1304 			pDev->DrawRect(aFrameRect);
1305 		}
1306 	}
1307 
1308 	if ( pShadow && pShadow->GetLocation() != SVX_SHADOW_NONE )
1309 	{
1310 		if ( bCellContrast )
1311             pDev->SetFillColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
1312 		else
1313 			pDev->SetFillColor(pShadow->GetColor());
1314 		pDev->SetLineColor();
1315 		long nShadowX = (long) ( pShadow->GetWidth() * nScaleX );
1316 		long nShadowY = (long) ( pShadow->GetWidth() * nScaleY );
1317 		switch (pShadow->GetLocation())
1318 		{
1319 			case SVX_SHADOW_TOPLEFT:
1320 				pDev->DrawRect( Rectangle(
1321 						aFrameRect.Left()-nShadowX, aFrameRect.Top()-nShadowY,
1322 						aFrameRect.Right()-nShadowX, aFrameRect.Top() ) );
1323 				pDev->DrawRect( Rectangle(
1324 						aFrameRect.Left()-nShadowX, aFrameRect.Top()-nShadowY,
1325 						aFrameRect.Left(), aFrameRect.Bottom()-nShadowY ) );
1326 				break;
1327 			case SVX_SHADOW_TOPRIGHT:
1328 				pDev->DrawRect( Rectangle(
1329 						aFrameRect.Left()+nShadowX, aFrameRect.Top()-nShadowY,
1330 						aFrameRect.Right()+nShadowX, aFrameRect.Top() ) );
1331 				pDev->DrawRect( Rectangle(
1332 						aFrameRect.Right(), aFrameRect.Top()-nShadowY,
1333 						aFrameRect.Right()+nShadowX, aFrameRect.Bottom()-nShadowY ) );
1334 				break;
1335 			case SVX_SHADOW_BOTTOMLEFT:
1336 				pDev->DrawRect( Rectangle(
1337 						aFrameRect.Left()-nShadowX, aFrameRect.Bottom(),
1338 						aFrameRect.Right()-nShadowX, aFrameRect.Bottom()+nShadowY ) );
1339 				pDev->DrawRect( Rectangle(
1340 						aFrameRect.Left()-nShadowX, aFrameRect.Top()+nShadowY,
1341 						aFrameRect.Left(), aFrameRect.Bottom()+nShadowY ) );
1342 				break;
1343 			case SVX_SHADOW_BOTTOMRIGHT:
1344 				pDev->DrawRect( Rectangle(
1345 						aFrameRect.Left()+nShadowX, aFrameRect.Bottom(),
1346 						aFrameRect.Right()+nShadowX, aFrameRect.Bottom()+nShadowY ) );
1347 				pDev->DrawRect( Rectangle(
1348 						aFrameRect.Right(), aFrameRect.Top()+nShadowY,
1349 						aFrameRect.Right()+nShadowX, aFrameRect.Bottom()+nShadowY ) );
1350 				break;
1351             default:
1352             {
1353                 // added to avoid warnings
1354             }
1355 		}
1356 	}
1357 
1358 	if (pBorderData)
1359 	{
1360 		ScDocument* pBorderDoc = new ScDocument( SCDOCMODE_UNDO );
1361 		pBorderDoc->InitUndo( pDoc, 0,0, sal_True,sal_True );
1362 		if (pBorderData)
1363 			pBorderDoc->ApplyAttr( 0,0,0, *pBorderData );
1364 
1365         ScTableInfo aTabInfo;
1366         pBorderDoc->FillInfo( aTabInfo, 0,0, 0,0, 0,
1367 											nScaleX, nScaleY, sal_False, sal_False );
1368         DBG_ASSERT(aTabInfo.mnArrCount,"nArrCount == 0");
1369 
1370         aTabInfo.mpRowInfo[1].nHeight = (sal_uInt16) nEffHeight;
1371         aTabInfo.mpRowInfo[0].pCellInfo[1].nWidth =
1372             aTabInfo.mpRowInfo[1].pCellInfo[1].nWidth = (sal_uInt16) nEffWidth;
1373 
1374         ScOutputData aOutputData( pDev, OUTTYPE_PRINTER, aTabInfo, pBorderDoc, 0,
1375 									nScrX+nLeft, nScrY+nTop, 0,0, 0,0, nScaleX, nScaleY );
1376 		aOutputData.SetUseStyleColor( bUseStyleColor );
1377 
1378 //		pDev->SetMapMode(aTwipMode);
1379 
1380 		if (pBorderData)
1381 			aOutputData.DrawFrame();
1382 
1383 		delete pBorderDoc;
1384 	}
1385 }
1386 
1387 void ScPrintFunc::PrintColHdr( SCCOL nX1, SCCOL nX2, long nScrX, long nScrY )
1388 {
1389 	sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nPrintTab );
1390 	long nLayoutSign = bLayoutRTL ? -1 : 1;
1391 
1392 	Size aOnePixel = pDev->PixelToLogic(Size(1,1));
1393 	long nOneX = aOnePixel.Width();
1394 	long nOneY = aOnePixel.Height();
1395 	SCCOL nCol;
1396 
1397 	long nHeight = (long) (PRINT_HEADER_HEIGHT * nScaleY);
1398 	long nEndY = nScrY + nHeight - nOneY;
1399 
1400 	long nPosX = nScrX;
1401 	if ( bLayoutRTL )
1402 	{
1403 		for (nCol=nX1; nCol<=nX2; nCol++)
1404 			nPosX += (long)( pDoc->GetColWidth( nCol, nPrintTab ) * nScaleX );
1405 	}
1406 	else
1407 		nPosX -= nOneX;
1408 	long nPosY = nScrY - nOneY;
1409 	String aText;
1410 
1411 	for (nCol=nX1; nCol<=nX2; nCol++)
1412 	{
1413 		sal_uInt16 nDocW = pDoc->GetColWidth( nCol, nPrintTab );
1414 		if (nDocW)
1415 		{
1416 			long nWidth = (long) (nDocW * nScaleX);
1417 			long nEndX = nPosX + nWidth * nLayoutSign;
1418 
1419 			pDev->DrawRect( Rectangle( nPosX,nPosY,nEndX,nEndY ) );
1420 
1421             aText = ::ScColToAlpha( nCol);
1422 			long nTextWidth = pDev->GetTextWidth(aText);
1423 			long nTextHeight = pDev->GetTextHeight();
1424 			long nAddX = ( nWidth  - nTextWidth  ) / 2;
1425 			long nAddY = ( nHeight - nTextHeight ) / 2;
1426 			long nTextPosX = nPosX+nAddX;
1427 			if ( bLayoutRTL )
1428 				nTextPosX -= nWidth;
1429 			pDev->DrawText( Point( nTextPosX,nPosY+nAddY ), aText );
1430 
1431 			nPosX = nEndX;
1432 		}
1433 	}
1434 }
1435 
1436 void ScPrintFunc::PrintRowHdr( SCROW nY1, SCROW nY2, long nScrX, long nScrY )
1437 {
1438 	Size aOnePixel = pDev->PixelToLogic(Size(1,1));
1439 	long nOneX = aOnePixel.Width();
1440 	long nOneY = aOnePixel.Height();
1441 
1442 	sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nPrintTab );
1443 
1444 	long nWidth = (long) (PRINT_HEADER_WIDTH * nScaleX);
1445 	long nEndX = nScrX + nWidth;
1446 	long nPosX = nScrX;
1447 	if ( !bLayoutRTL )
1448 	{
1449 		nEndX -= nOneX;
1450 		nPosX -= nOneX;
1451 	}
1452 	long nPosY = nScrY - nOneY;
1453 	String aText;
1454 
1455 	for (SCROW nRow=nY1; nRow<=nY2; nRow++)
1456 	{
1457 		sal_uInt16 nDocH = pDoc->GetRowHeight( nRow, nPrintTab );
1458 		if (nDocH)
1459 		{
1460 			long nHeight = (long) (nDocH * nScaleY);
1461 			long nEndY = nPosY + nHeight;
1462 
1463 			pDev->DrawRect( Rectangle( nPosX,nPosY,nEndX,nEndY ) );
1464 
1465 			aText = String::CreateFromInt32( nRow+1 );
1466 			long nTextWidth = pDev->GetTextWidth(aText);
1467 			long nTextHeight = pDev->GetTextHeight();
1468 			long nAddX = ( nWidth  - nTextWidth  ) / 2;
1469 			long nAddY = ( nHeight - nTextHeight ) / 2;
1470 			pDev->DrawText( Point( nPosX+nAddX,nPosY+nAddY ), aText );
1471 
1472 			nPosY = nEndY;
1473 		}
1474 	}
1475 }
1476 
1477 void ScPrintFunc::LocateColHdr( SCCOL nX1, SCCOL nX2, long nScrX, long nScrY,
1478 								sal_Bool bRepCol, ScPreviewLocationData& rLocationData )
1479 {
1480 	Size aOnePixel = pDev->PixelToLogic(Size(1,1));
1481 	long nOneX = aOnePixel.Width();
1482 	long nOneY = aOnePixel.Height();
1483 
1484 	long nHeight = (long) (PRINT_HEADER_HEIGHT * nScaleY);
1485 	long nEndY = nScrY + nHeight - nOneY;
1486 
1487 	long nPosX = nScrX - nOneX;
1488 	for (SCCOL nCol=nX1; nCol<=nX2; nCol++)
1489 	{
1490 		sal_uInt16 nDocW = pDoc->GetColWidth( nCol, nPrintTab );
1491 		if (nDocW)
1492 			nPosX += (long) (nDocW * nScaleX);
1493 	}
1494 	Rectangle aCellRect( nScrX, nScrY, nPosX, nEndY );
1495 	rLocationData.AddColHeaders( aCellRect, nX1, nX2, bRepCol );
1496 }
1497 
1498 void ScPrintFunc::LocateRowHdr( SCROW nY1, SCROW nY2, long nScrX, long nScrY,
1499 								sal_Bool bRepRow, ScPreviewLocationData& rLocationData )
1500 {
1501 	Size aOnePixel = pDev->PixelToLogic(Size(1,1));
1502 	long nOneX = aOnePixel.Width();
1503 	long nOneY = aOnePixel.Height();
1504 
1505 	sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nPrintTab );
1506 
1507 	long nWidth = (long) (PRINT_HEADER_WIDTH * nScaleX);
1508 	long nEndX = nScrX + nWidth;
1509 	if ( !bLayoutRTL )
1510 		nEndX -= nOneX;
1511 
1512 	long nPosY = nScrY - nOneY;
1513     nPosY += pDoc->GetScaledRowHeight( nY1, nY2, nPrintTab, nScaleY);
1514 	Rectangle aCellRect( nScrX, nScrY, nEndX, nPosY );
1515 	rLocationData.AddRowHeaders( aCellRect, nY1, nY2, bRepRow );
1516 }
1517 
1518 void ScPrintFunc::LocateArea( SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2,
1519 								long nScrX, long nScrY, sal_Bool bRepCol, sal_Bool bRepRow,
1520 								ScPreviewLocationData& rLocationData )
1521 {
1522 	//	get MapMode for drawing objects (same MapMode as in ScOutputData::PrintDrawingLayer)
1523 
1524 	Point aLogPos = OutputDevice::LogicToLogic(Point(nScrX,nScrY), aOffsetMode, aLogicMode);
1525 	long nLogStX = aLogPos.X();
1526 	long nLogStY = aLogPos.Y();
1527 
1528 	SCCOL nCol;
1529 	Point aTwipOffset;
1530 	for (nCol=0; nCol<nX1; nCol++)
1531 		aTwipOffset.X() -= pDoc->GetColWidth( nCol, nPrintTab );
1532     aTwipOffset.Y() -= pDoc->GetRowHeight( 0, nY1-1, nPrintTab );
1533 
1534 	Point aMMOffset( aTwipOffset );
1535 	aMMOffset.X() = (long)(aMMOffset.X() * HMM_PER_TWIPS);
1536 	aMMOffset.Y() = (long)(aMMOffset.Y() * HMM_PER_TWIPS);
1537 	aMMOffset += Point( nLogStX, nLogStY );
1538 	MapMode aDrawMapMode( MAP_100TH_MM, aMMOffset, aLogicMode.GetScaleX(), aLogicMode.GetScaleY() );
1539 
1540 	//	get pixel rectangle
1541 
1542 	Size aOnePixel = pDev->PixelToLogic(Size(1,1));
1543 	long nOneX = aOnePixel.Width();
1544 	long nOneY = aOnePixel.Height();
1545 
1546 	long nPosX = nScrX - nOneX;
1547 	for (nCol=nX1; nCol<=nX2; nCol++)
1548 	{
1549 		sal_uInt16 nDocW = pDoc->GetColWidth( nCol, nPrintTab );
1550 		if (nDocW)
1551 			nPosX += (long) (nDocW * nScaleX);
1552 	}
1553 
1554 	long nPosY = nScrY - nOneY;
1555     nPosY += pDoc->GetScaledRowHeight( nY1, nY2, nPrintTab, nScaleY);
1556 	Rectangle aCellRect( nScrX, nScrY, nPosX, nPosY );
1557 	rLocationData.AddCellRange( aCellRect, ScRange( nX1,nY1,nPrintTab, nX2,nY2,nPrintTab ),
1558 								bRepCol, bRepRow, aDrawMapMode );
1559 }
1560 
1561 void ScPrintFunc::PrintArea( SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2,
1562 								long nScrX, long nScrY,
1563 								sal_Bool bShLeft, sal_Bool bShTop, sal_Bool bShRight, sal_Bool bShBottom )
1564 {
1565     // #i47547# nothing to do if the end of the print area is before the end of
1566     // the repeat columns/rows (don't use negative size for ScOutputData)
1567     if ( nX2 < nX1 || nY2 < nY1 )
1568         return;
1569 
1570 							//!		Flag bei FillInfo uebergeben !!!!!
1571     ScRange aERange;
1572 	sal_Bool bEmbed = pDoc->IsEmbedded();
1573 	if (bEmbed)
1574 	{
1575 		pDoc->GetEmbedded(aERange);
1576 		pDoc->ResetEmbedded();
1577 	}
1578 
1579 	Point aPos = OutputDevice::LogicToLogic(Point(nScrX,nScrY), aOffsetMode, aLogicMode);
1580 	long nLogStX = aPos.X();
1581 	long nLogStY = aPos.Y();
1582 
1583 					//	Daten zusammenstellen
1584 
1585     ScTableInfo aTabInfo;
1586     pDoc->FillInfo( aTabInfo, nX1, nY1, nX2, nY2, nPrintTab,
1587 										nScaleX, nScaleY, sal_True, aTableParam.bFormulas );
1588     lcl_HidePrint( aTabInfo, nX1, nX2 );
1589 
1590 	if (bEmbed)
1591 		pDoc->SetEmbedded(aERange);
1592 
1593     ScOutputData aOutputData( pDev, OUTTYPE_PRINTER, aTabInfo, pDoc, nPrintTab,
1594 								nScrX, nScrY, nX1, nY1, nX2, nY2, nScaleX, nScaleY );
1595 
1596 	// #114135#
1597 	aOutputData.SetDrawView( pDrawView );
1598 
1599 	// test if all paint parts are hidden, then a paint is not necessary at all
1600 	const Point aMMOffset(aOutputData.PrePrintDrawingLayer(nLogStX, nLogStY));
1601     const bool bHideAllDrawingLayer( pDrawView && pDrawView->getHideOle() && pDrawView->getHideChart()
1602             && pDrawView->getHideDraw() && pDrawView->getHideFormControl() );
1603 
1604     if(!bHideAllDrawingLayer)
1605 	{
1606 		pDev->SetMapMode(aLogicMode);
1607 		//	hier kein Clipping setzen (Mapmode wird verschoben)
1608 
1609 		// #i72502#
1610 		aOutputData.PrintDrawingLayer(SC_LAYER_BACK, aMMOffset);
1611 	}
1612 
1613 	pDev->SetMapMode(aOffsetMode);
1614 
1615 	aOutputData.SetShowFormulas( aTableParam.bFormulas );
1616 	aOutputData.SetShowNullValues( aTableParam.bNullVals );
1617 	aOutputData.SetUseStyleColor( bUseStyleColor );
1618 
1619 	Color aGridColor( COL_BLACK );
1620 	if ( bUseStyleColor )
1621         aGridColor.SetColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
1622 	aOutputData.SetGridColor( aGridColor );
1623 
1624 	if ( !pPrinter )
1625 	{
1626 		OutputDevice* pRefDev = pDoc->GetPrinter();		// auch fuer Preview den Drucker nehmen
1627 		Fraction aPrintFrac( nZoom, 100 );				// ohne nManualZoom
1628 		//	MapMode, wie er beim Drucken herauskommen wuerde:
1629 		pRefDev->SetMapMode( MapMode( MAP_100TH_MM, Point(), aPrintFrac, aPrintFrac ) );
1630 
1631 		//	when rendering (PDF), don't use printer as ref device, but printer's MapMode
1632 		//	has to be set anyway, as charts still use it (#106409#)
1633 		if ( !bIsRender )
1634 			aOutputData.SetRefDevice( pRefDev );
1635 	}
1636 
1637 //	aOutputData.SetMetaFileMode(sal_True);
1638     if( aTableParam.bCellContent )
1639 	    aOutputData.DrawBackground();
1640 
1641 	pDev->SetClipRegion( Rectangle( aPos, Size( aOutputData.GetScrW(), aOutputData.GetScrH() ) ) );
1642 	pDev->SetClipRegion();
1643 
1644 //	aOutputData.SetMetaFileMode(sal_False);
1645     if( aTableParam.bCellContent )
1646     {
1647 	    aOutputData.DrawExtraShadow( bShLeft, bShTop, bShRight, bShBottom );
1648 	    aOutputData.DrawFrame();
1649 	    aOutputData.DrawStrings();
1650 
1651     //	pDev->SetMapMode(aLogicMode);
1652 	    aOutputData.DrawEdit(sal_False);
1653     }
1654 
1655 //	pDev->SetMapMode(aOffsetMode);
1656 	if (aTableParam.bGrid)
1657 		aOutputData.DrawGrid( sal_True, sal_False );	// keine Seitenumbrueche
1658 
1659 /*!!!!!!!!!!!		Notizen in Tabelle markieren ??????????????????????????
1660 
1661 	if (aTableParam.bNotes)
1662 	{
1663 		pDev->SetMapMode(aOffsetMode);
1664 		aOutputData.PrintNoteMarks(aNotePosList);
1665 		pDev->SetMapMode(aLogicMode);
1666 	}
1667 */
1668 
1669     aOutputData.AddPDFNotes();      // has no effect if not rendering PDF with notes enabled
1670 
1671 //	pDev->SetMapMode(aDrawMode);
1672 
1673 	// test if all paint parts are hidden, then a paint is not necessary at all
1674 	if(!bHideAllDrawingLayer)
1675 	{
1676 		// #i72502#
1677 		aOutputData.PrintDrawingLayer(SC_LAYER_FRONT, aMMOffset);
1678 	}
1679 
1680 	// #i72502#
1681 	aOutputData.PrintDrawingLayer(SC_LAYER_INTERN, aMMOffset);
1682 	aOutputData.PostPrintDrawingLayer(aMMOffset); // #i74768#
1683 }
1684 
1685 sal_Bool ScPrintFunc::IsMirror( long nPageNo )			// Raender spiegeln ?
1686 {
1687 	SvxPageUsage eUsage = (SvxPageUsage) ( nPageUsage & 0x000f );
1688 	return ( eUsage == SVX_PAGE_MIRROR && (nPageNo & 1) );
1689 }
1690 
1691 sal_Bool ScPrintFunc::IsLeft( long nPageNo )			// linke Fussnoten ?
1692 {
1693 	SvxPageUsage eUsage = (SvxPageUsage) ( nPageUsage & 0x000f );
1694 	sal_Bool bLeft;
1695 	if (eUsage == SVX_PAGE_LEFT)
1696 		bLeft = sal_True;
1697 	else if (eUsage == SVX_PAGE_RIGHT)
1698 		bLeft = sal_False;
1699 	else
1700 		bLeft = (nPageNo & 1) != 0;
1701 	return bLeft;
1702 }
1703 
1704 void ScPrintFunc::MakeTableString()
1705 {
1706 	pDoc->GetName( nPrintTab, aFieldData.aTabName );
1707 }
1708 
1709 void ScPrintFunc::MakeEditEngine()
1710 {
1711 	if (!pEditEngine)
1712 	{
1713 		//	can't use document's edit engine pool here,
1714 		//	because pool must have twips as default metric
1715 		pEditEngine = new ScHeaderEditEngine( EditEngine::CreatePool(), sal_True );
1716 
1717 		pEditEngine->EnableUndo(sal_False);
1718 		pEditEngine->SetRefDevice( pDev );
1719 		pEditEngine->SetWordDelimiters(
1720 				ScEditUtil::ModifyDelimiters( pEditEngine->GetWordDelimiters() ) );
1721 		pEditEngine->SetControlWord( pEditEngine->GetControlWord() & ~EE_CNTRL_RTFSTYLESHEETS );
1722         pDoc->ApplyAsianEditSettings( *pEditEngine );
1723 		pEditEngine->EnableAutoColor( bUseStyleColor );
1724 
1725 		//	Default-Set fuer Ausrichtung
1726 		pEditDefaults = new SfxItemSet( pEditEngine->GetEmptyItemSet() );
1727 
1728 		const ScPatternAttr& rPattern = (const ScPatternAttr&)pDoc->GetPool()->GetDefaultItem(ATTR_PATTERN);
1729 		rPattern.FillEditItemSet( pEditDefaults );
1730 		//	FillEditItemSet adjusts font height to 1/100th mm,
1731 		//	but for header/footer twips is needed, as in the PatternAttr:
1732 		pEditDefaults->Put( rPattern.GetItem(ATTR_FONT_HEIGHT), EE_CHAR_FONTHEIGHT );
1733 		pEditDefaults->Put( rPattern.GetItem(ATTR_CJK_FONT_HEIGHT), EE_CHAR_FONTHEIGHT_CJK );
1734 		pEditDefaults->Put( rPattern.GetItem(ATTR_CTL_FONT_HEIGHT), EE_CHAR_FONTHEIGHT_CTL );
1735 		//	#69193# dont use font color, because background color is not used
1736 		//!	there's no way to set the background for note pages
1737 		pEditDefaults->ClearItem( EE_CHAR_COLOR );
1738 		if (ScGlobal::IsSystemRTL())
1739 			pEditDefaults->Put( SvxFrameDirectionItem( FRMDIR_HORI_RIGHT_TOP, EE_PARA_WRITINGDIR ) );
1740 	}
1741 
1742 	pEditEngine->SetData( aFieldData );		// Seitennummer etc. setzen
1743 }
1744 
1745 //	nStartY = logic
1746 void ScPrintFunc::PrintHF( long nPageNo, sal_Bool bHeader, long nStartY,
1747 							sal_Bool bDoPrint, ScPreviewLocationData* pLocationData )
1748 {
1749 	const ScPrintHFParam& rParam = bHeader ? aHdr : aFtr;
1750 
1751 	pDev->SetMapMode( aTwipMode );			// Kopf-/Fusszeilen in Twips
1752 
1753 	sal_Bool bLeft = IsLeft(nPageNo) && !rParam.bShared;
1754 	const ScPageHFItem* pHFItem = bLeft ? rParam.pLeft : rParam.pRight;
1755 
1756 	long nLineStartX = aPageRect.Left()  + rParam.nLeft;
1757 	long nLineEndX	 = aPageRect.Right() - rParam.nRight;
1758 	long nLineWidth  = nLineEndX - nLineStartX + 1;
1759 
1760 	//	Edit-Engine
1761 
1762 	Point aStart( nLineStartX, nStartY );
1763 	Size aPaperSize( nLineWidth, rParam.nHeight-rParam.nDistance );
1764 	if ( rParam.pBorder )
1765 	{
1766 		long nLeft = lcl_LineTotal( rParam.pBorder->GetLeft() ) + rParam.pBorder->GetDistance(BOX_LINE_LEFT);
1767 		long nTop = lcl_LineTotal( rParam.pBorder->GetTop() ) + rParam.pBorder->GetDistance(BOX_LINE_TOP);
1768 		aStart.X() += nLeft;
1769 		aStart.Y() += nTop;
1770 		aPaperSize.Width() -= nLeft + lcl_LineTotal( rParam.pBorder->GetRight() ) + rParam.pBorder->GetDistance(BOX_LINE_RIGHT);
1771 		aPaperSize.Height() -= nTop + lcl_LineTotal( rParam.pBorder->GetBottom() ) + rParam.pBorder->GetDistance(BOX_LINE_BOTTOM);
1772 	}
1773 
1774 	if ( rParam.pShadow && rParam.pShadow->GetLocation() != SVX_SHADOW_NONE )
1775 	{
1776 		long nLeft	= rParam.pShadow->CalcShadowSpace(SHADOW_LEFT);
1777 		long nTop	= rParam.pShadow->CalcShadowSpace(SHADOW_TOP);
1778 		aStart.X() += nLeft;
1779 		aStart.Y() += nTop;
1780 		aPaperSize.Width() -= nLeft + rParam.pShadow->CalcShadowSpace(SHADOW_RIGHT);
1781 		aPaperSize.Height() -= nTop + rParam.pShadow->CalcShadowSpace(SHADOW_BOTTOM);
1782 	}
1783 
1784 	aFieldData.nPageNo = nPageNo+aTableParam.nFirstPageNo;
1785 	MakeEditEngine();
1786 
1787 	pEditEngine->SetPaperSize(aPaperSize);
1788 	const EditTextObject* pObject;
1789 
1790 	//	Rahmen / Hintergrund
1791 
1792 	Point aBorderStart( nLineStartX, nStartY );
1793 	Size aBorderSize( nLineWidth, rParam.nHeight-rParam.nDistance );
1794 	if ( rParam.bDynamic )
1795 	{
1796 		//	hier nochmal anpassen, wegen geraden/ungeraden Kopf/Fusszeilen
1797 		//	und evtl. anderen Umbruechen durch Variablen (Seitennummer etc.)
1798 
1799 		long nMaxHeight = 0;
1800 		nMaxHeight = Max( nMaxHeight, TextHeight( pHFItem->GetLeftArea() ) );
1801 		nMaxHeight = Max( nMaxHeight, TextHeight( pHFItem->GetCenterArea() ) );
1802 		nMaxHeight = Max( nMaxHeight, TextHeight( pHFItem->GetRightArea() ) );
1803 		if (rParam.pBorder)
1804 			nMaxHeight += lcl_LineTotal( rParam.pBorder->GetTop() ) +
1805 						  lcl_LineTotal( rParam.pBorder->GetBottom() ) +
1806 									rParam.pBorder->GetDistance(BOX_LINE_TOP) +
1807 									rParam.pBorder->GetDistance(BOX_LINE_BOTTOM);
1808 		if (rParam.pShadow && rParam.pShadow->GetLocation() != SVX_SHADOW_NONE)
1809 			nMaxHeight += rParam.pShadow->CalcShadowSpace(SHADOW_TOP) +
1810 						  rParam.pShadow->CalcShadowSpace(SHADOW_BOTTOM);
1811 
1812 		if (nMaxHeight < rParam.nManHeight-rParam.nDistance)
1813 			nMaxHeight = rParam.nManHeight-rParam.nDistance;		// eingestelltes Minimum
1814 
1815 		aBorderSize.Height() = nMaxHeight;
1816 	}
1817 
1818 	if ( bDoPrint )
1819 	{
1820 		double nOldScaleX = nScaleX;
1821 		double nOldScaleY = nScaleY;
1822 		nScaleX = nScaleY = 1.0;			// direkt in Twips ausgeben
1823 		DrawBorder( aBorderStart.X(), aBorderStart.Y(), aBorderSize.Width(), aBorderSize.Height(),
1824 						rParam.pBorder, rParam.pBack, rParam.pShadow );
1825 		nScaleX = nOldScaleX;
1826 		nScaleY = nOldScaleY;
1827 
1828 		//	Clipping fuer Text
1829 
1830 		pDev->SetClipRegion( Rectangle( aStart, aPaperSize ) );
1831 
1832 		//	links
1833 
1834 		pObject = pHFItem->GetLeftArea();
1835 		if (pObject)
1836 		{
1837 			pEditDefaults->Put( SvxAdjustItem( SVX_ADJUST_LEFT, EE_PARA_JUST ) );
1838 			pEditEngine->SetTextNewDefaults( *pObject, *pEditDefaults, sal_False );
1839 			Point aDraw = aStart;
1840 			long nDif = aPaperSize.Height() - (long) pEditEngine->GetTextHeight();
1841 			if (nDif > 0)
1842 				aDraw.Y() += nDif / 2;
1843 			pEditEngine->Draw( pDev, aDraw, 0 );
1844 		}
1845 
1846 		//	Mitte
1847 
1848 		pObject = pHFItem->GetCenterArea();
1849 		if (pObject)
1850 		{
1851 			pEditDefaults->Put( SvxAdjustItem( SVX_ADJUST_CENTER, EE_PARA_JUST ) );
1852 			pEditEngine->SetTextNewDefaults( *pObject, *pEditDefaults, sal_False );
1853 			Point aDraw = aStart;
1854 			long nDif = aPaperSize.Height() - (long) pEditEngine->GetTextHeight();
1855 			if (nDif > 0)
1856 				aDraw.Y() += nDif / 2;
1857 			pEditEngine->Draw( pDev, aDraw, 0 );
1858 		}
1859 
1860 		//	rechts
1861 
1862 		pObject = pHFItem->GetRightArea();
1863 		if (pObject)
1864 		{
1865 			pEditDefaults->Put( SvxAdjustItem( SVX_ADJUST_RIGHT, EE_PARA_JUST ) );
1866 			pEditEngine->SetTextNewDefaults( *pObject, *pEditDefaults, sal_False );
1867 			Point aDraw = aStart;
1868 			long nDif = aPaperSize.Height() - (long) pEditEngine->GetTextHeight();
1869 			if (nDif > 0)
1870 				aDraw.Y() += nDif / 2;
1871 			pEditEngine->Draw( pDev, aDraw, 0 );
1872 		}
1873 
1874 		pDev->SetClipRegion();
1875 	}
1876 
1877 	if ( pLocationData )
1878 	{
1879 		Rectangle aHeaderRect( aBorderStart, aBorderSize );
1880 		pLocationData->AddHeaderFooter( aHeaderRect, bHeader, bLeft );
1881 	}
1882 }
1883 
1884 long ScPrintFunc::DoNotes( long nNoteStart, sal_Bool bDoPrint, ScPreviewLocationData* pLocationData )
1885 {
1886 	if (bDoPrint)
1887 		pDev->SetMapMode(aTwipMode);
1888 
1889 	MakeEditEngine();
1890 	pEditDefaults->Put( SvxAdjustItem( SVX_ADJUST_LEFT, EE_PARA_JUST ) );
1891 	pEditEngine->SetDefaults( *pEditDefaults );
1892 
1893 	Font aMarkFont;
1894 	ScAutoFontColorMode eColorMode = bUseStyleColor ? SC_AUTOCOL_DISPLAY : SC_AUTOCOL_PRINT;
1895 	((const ScPatternAttr&)pDoc->GetPool()->GetDefaultItem(ATTR_PATTERN)).GetFont( aMarkFont, eColorMode );
1896 //?	aMarkFont.SetWeight( WEIGHT_BOLD );
1897 	pDev->SetFont( aMarkFont );
1898 	long nMarkLen = pDev->GetTextWidth(
1899 			String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("GW99999:")));
1900 	// ohne Space, weil's eh selten so weit kommt
1901 
1902 	Size aDataSize = aPageRect.GetSize();
1903 	if ( nMarkLen > aDataSize.Width() / 2 )		// alles viel zu klein?
1904 		nMarkLen = aDataSize.Width() / 2;		// Seite bruederlich aufteilen
1905 	aDataSize.Width() -= nMarkLen;
1906 
1907 	pEditEngine->SetPaperSize( aDataSize );
1908 	long nPosX = aPageRect.Left() + nMarkLen;
1909 	long nPosY = aPageRect.Top();
1910 
1911 	long nCount = 0;
1912 	sal_Bool bOk;
1913 	do
1914 	{
1915 		bOk = sal_False;
1916 		ScAddress* pPos = (ScAddress*) aNotePosList.GetObject( nNoteStart+nCount );
1917 		if (pPos)
1918 		{
1919 			ScBaseCell* pCell = pDoc->GetCell( *pPos);
1920             if( const ScPostIt* pNote = pCell->GetNote() )
1921 			{
1922 				if(const EditTextObject *pEditText = pNote->GetEditTextObject())
1923 				    pEditEngine->SetText(*pEditText);
1924 				long nTextHeight = pEditEngine->GetTextHeight();
1925 				if ( nPosY + nTextHeight < aPageRect.Bottom() )
1926 				{
1927 					if (bDoPrint)
1928 					{
1929 						pEditEngine->Draw( pDev, Point( nPosX, nPosY ), 0 );
1930 
1931 						String aMarkStr;
1932 						pPos->Format( aMarkStr, SCA_VALID, pDoc, pDoc->GetAddressConvention() );
1933 						aMarkStr += ':';
1934 
1935 						//	Zellposition auch per EditEngine, damit die Position stimmt
1936 						pEditEngine->SetText(aMarkStr);
1937 						pEditEngine->Draw( pDev, Point( aPageRect.Left(), nPosY ), 0 );
1938 					}
1939 
1940 					if ( pLocationData )
1941 					{
1942 						Rectangle aTextRect( Point( nPosX, nPosY ), Size( aDataSize.Width(), nTextHeight ) );
1943 						pLocationData->AddNoteText( aTextRect, *pPos );
1944 						Rectangle aMarkRect( Point( aPageRect.Left(), nPosY ), Size( nMarkLen, nTextHeight ) );
1945 						pLocationData->AddNoteMark( aMarkRect, *pPos );
1946 					}
1947 
1948 					nPosY += nTextHeight;
1949 					nPosY += 200;					// Abstand
1950 					++nCount;
1951 					bOk = sal_True;
1952 				}
1953 			}
1954 		}
1955 	}
1956 	while (bOk);
1957 
1958 	return nCount;
1959 }
1960 
1961 long ScPrintFunc::PrintNotes( long nPageNo, long nNoteStart, sal_Bool bDoPrint, ScPreviewLocationData* pLocationData )
1962 {
1963 	if ( nNoteStart >= (long) aNotePosList.Count() || !aTableParam.bNotes )
1964 		return 0;
1965 
1966 	if ( bDoPrint && bClearWin )
1967 	{
1968 		//!	mit PrintPage zusammenfassen !!!
1969 
1970 		Color aBackgroundColor( COL_WHITE );
1971 		if ( bUseStyleColor )
1972             aBackgroundColor.SetColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::DOCCOLOR).nColor );
1973 
1974 		pDev->SetMapMode(aOffsetMode);
1975 		pDev->SetLineColor();
1976 		pDev->SetFillColor(aBackgroundColor);
1977 		pDev->DrawRect(Rectangle(Point(),
1978 				Size((long)(aPageSize.Width() * nScaleX * 100 / nZoom),
1979 					 (long)(aPageSize.Height() * nScaleY * 100 / nZoom))));
1980 	}
1981 
1982 
1983 	//		aPageRect auf linke / rechte Seiten anpassen
1984 
1985 	Rectangle aTempRect = Rectangle( Point(), aPageSize );
1986 	if (IsMirror(nPageNo))
1987 	{
1988 		aPageRect.Left()  = ( aTempRect.Left()  + nRightMargin ) * 100 / nZoom;
1989 		aPageRect.Right() = ( aTempRect.Right() - nLeftMargin  ) * 100 / nZoom;
1990 	}
1991 	else
1992 	{
1993 		aPageRect.Left()  = ( aTempRect.Left()  + nLeftMargin  ) * 100 / nZoom;
1994 		aPageRect.Right() = ( aTempRect.Right() - nRightMargin ) * 100 / nZoom;
1995 	}
1996 
1997 	if ( pPrinter && bDoPrint )
1998     {
1999         DBG_ERROR( "StartPage does not exist anymore" );
2000 		// pPrinter->StartPage();
2001     }
2002 
2003 	if ( bDoPrint || pLocationData )
2004 	{
2005 		//	Kopf- und Fusszeilen
2006 
2007 		if (aHdr.bEnable)
2008 		{
2009 			long nHeaderY = aPageRect.Top()-aHdr.nHeight;
2010 			PrintHF( nPageNo, sal_True, nHeaderY, bDoPrint, pLocationData );
2011 		}
2012 		if (aFtr.bEnable)
2013 		{
2014 			long nFooterY = aPageRect.Bottom()+aFtr.nDistance;
2015 			PrintHF( nPageNo, sal_False, nFooterY, bDoPrint, pLocationData );
2016 		}
2017 	}
2018 
2019 	long nCount = DoNotes( nNoteStart, bDoPrint, pLocationData );
2020 
2021 	if ( pPrinter && bDoPrint )
2022     {
2023         DBG_ERROR( "EndPage does not exist anymore" );
2024 		// pPrinter->EndPage();
2025     }
2026 
2027 	return nCount;
2028 }
2029 
2030 void ScPrintFunc::PrintPage( long nPageNo, SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2,
2031 								sal_Bool bDoPrint, ScPreviewLocationData* pLocationData )
2032 {
2033 	sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nPrintTab );
2034 	long nLayoutSign = bLayoutRTL ? -1 : 1;
2035 
2036 	//	nPageNo is the page number within all sheets of one "start page" setting
2037 
2038 	if ( bClearWin && bDoPrint )
2039 	{
2040 		//	muss genau zum Zeichnen des Rahmens in preview.cxx passen !!!
2041 
2042 		Color aBackgroundColor( COL_WHITE );
2043 		if ( bUseStyleColor )
2044             aBackgroundColor.SetColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::DOCCOLOR).nColor );
2045 
2046 		pDev->SetMapMode(aOffsetMode);
2047 		pDev->SetLineColor();
2048 		pDev->SetFillColor(aBackgroundColor);
2049 		pDev->DrawRect(Rectangle(Point(),
2050 				Size((long)(aPageSize.Width() * nScaleX * 100 / nZoom),
2051 					 (long)(aPageSize.Height() * nScaleY * 100 / nZoom))));
2052 	}
2053 
2054 
2055 	//		aPageRect auf linke / rechte Seiten anpassen
2056 
2057 	Rectangle aTempRect = Rectangle( Point(), aPageSize );
2058 	if (IsMirror(nPageNo))
2059 	{
2060 		aPageRect.Left()  = ( aTempRect.Left()  + nRightMargin ) * 100 / nZoom;
2061 		aPageRect.Right() = ( aTempRect.Right() - nLeftMargin  ) * 100 / nZoom;
2062 	}
2063 	else
2064 	{
2065 		aPageRect.Left()  = ( aTempRect.Left()  + nLeftMargin  ) * 100 / nZoom;
2066 		aPageRect.Right() = ( aTempRect.Right() - nRightMargin ) * 100 / nZoom;
2067 	}
2068 
2069 	if ( aAreaParam.bRepeatCol )
2070 		if ( nX1 > nRepeatStartCol && nX1 <= nRepeatEndCol )
2071 			nX1 = nRepeatEndCol + 1;
2072 	sal_Bool bDoRepCol = (aAreaParam.bRepeatCol && nX1 > nRepeatEndCol);
2073 	if ( aAreaParam.bRepeatRow )
2074 		if ( nY1 > nRepeatStartRow && nY1 <= nRepeatEndRow )
2075 			nY1 = nRepeatEndRow + 1;
2076 	sal_Bool bDoRepRow = (aAreaParam.bRepeatRow && nY1 > nRepeatEndRow);
2077 
2078     // use new object hide flags in SdrPaintView
2079     if(pDrawView)
2080     {
2081         pDrawView->setHideOle(!aTableParam.bObjects);
2082         pDrawView->setHideChart(!aTableParam.bCharts);
2083         pDrawView->setHideDraw(!aTableParam.bDrawings);
2084         pDrawView->setHideFormControl(!aTableParam.bDrawings);
2085     }
2086 
2087 	if ( pPrinter && bDoPrint )
2088     {
2089         DBG_ERROR( "StartPage does not exist anymore" );
2090 		// pPrinter->StartPage();
2091     }
2092 
2093 	//	Kopf- und Fusszeilen (ohne Zentrierung)
2094 
2095 	if (aHdr.bEnable)
2096 	{
2097 		long nHeaderY = aPageRect.Top()-aHdr.nHeight;
2098 		PrintHF( nPageNo, sal_True, nHeaderY, bDoPrint, pLocationData );
2099 	}
2100 	if (aFtr.bEnable)
2101 	{
2102 		long nFooterY = aPageRect.Bottom()+aFtr.nDistance;
2103 		PrintHF( nPageNo, sal_False, nFooterY, bDoPrint, pLocationData );
2104 	}
2105 
2106 	//	Position ( Raender / zentrieren )
2107 
2108 	long nLeftSpace = aPageRect.Left();		// Document-Twips
2109 	long nTopSpace  = aPageRect.Top();
2110 	if ( bCenterHor || bLayoutRTL )
2111 	{
2112 		long nDataWidth = 0;
2113         SCCOL i;
2114 		for (i=nX1; i<=nX2; i++)
2115 			nDataWidth += pDoc->GetColWidth( i,nPrintTab );
2116 		if (bDoRepCol)
2117 			for (i=nRepeatStartCol; i<=nRepeatEndCol; i++)
2118 				nDataWidth += pDoc->GetColWidth( i,nPrintTab );
2119 		if (aTableParam.bHeaders)
2120 			nDataWidth += (long) PRINT_HEADER_WIDTH;
2121 		if (pBorderItem)
2122 			nDataWidth += pBorderItem->GetDistance(BOX_LINE_LEFT) +
2123 						   pBorderItem->GetDistance(BOX_LINE_RIGHT);		//! Line width?
2124 		if (pShadowItem && pShadowItem->GetLocation() != SVX_SHADOW_NONE)
2125 			nDataWidth += pShadowItem->CalcShadowSpace(SHADOW_LEFT) +
2126 						   pShadowItem->CalcShadowSpace(SHADOW_RIGHT);
2127 		if ( bCenterHor )
2128 		{
2129 			nLeftSpace += ( aPageRect.GetWidth() - nDataWidth ) / 2;		// LTR or RTL
2130 			if (pBorderItem)
2131 				nLeftSpace -= lcl_LineTotal(pBorderItem->GetLeft());
2132 		}
2133 		else if ( bLayoutRTL )
2134 			nLeftSpace += aPageRect.GetWidth() - nDataWidth;				// align to the right edge of the page
2135 	}
2136 	if ( bCenterVer )
2137 	{
2138         long nDataHeight = pDoc->GetRowHeight( nY1, nY2, nPrintTab);
2139 		if (bDoRepRow)
2140             nDataHeight += pDoc->GetRowHeight( nRepeatStartRow,
2141                     nRepeatEndRow, nPrintTab);
2142 		if (aTableParam.bHeaders)
2143 			nDataHeight += (long) PRINT_HEADER_HEIGHT;
2144 		if (pBorderItem)
2145 			nDataHeight += pBorderItem->GetDistance(BOX_LINE_TOP) +
2146 						   pBorderItem->GetDistance(BOX_LINE_BOTTOM);		//! Line width?
2147 		if (pShadowItem && pShadowItem->GetLocation() != SVX_SHADOW_NONE)
2148 			nDataHeight += pShadowItem->CalcShadowSpace(SHADOW_TOP) +
2149 						   pShadowItem->CalcShadowSpace(SHADOW_BOTTOM);
2150 		nTopSpace += ( aPageRect.GetHeight() - nDataHeight ) / 2;
2151 		if (pBorderItem)
2152 			nTopSpace -= lcl_LineTotal(pBorderItem->GetTop());
2153 	}
2154 
2155 	//	calculate sizes of the elements for partitioning
2156 	//	(header, repeat, data)
2157 
2158 	long nHeaderWidth   = 0;
2159 	long nHeaderHeight  = 0;
2160 	long nRepeatWidth   = 0;
2161 	long nRepeatHeight  = 0;
2162 	long nContentWidth  = 0;		// scaled - not the same as nDataWidth above
2163 	long nContentHeight = 0;
2164 	if (aTableParam.bHeaders)
2165 	{
2166 		nHeaderWidth  = (long) (PRINT_HEADER_WIDTH * nScaleX);
2167 		nHeaderHeight = (long) (PRINT_HEADER_HEIGHT * nScaleY);
2168 	}
2169 	if (bDoRepCol)
2170 		for (SCCOL i=nRepeatStartCol; i<=nRepeatEndCol; i++)
2171 			nRepeatWidth += (long) (pDoc->GetColWidth(i,nPrintTab) * nScaleX);
2172 	if (bDoRepRow)
2173         nRepeatHeight += pDoc->GetScaledRowHeight( nRepeatStartRow,
2174                 nRepeatEndRow, nPrintTab, nScaleY);
2175 	for (SCCOL i=nX1; i<=nX2; i++)
2176 		nContentWidth += (long) (pDoc->GetColWidth(i,nPrintTab) * nScaleX);
2177     nContentHeight += pDoc->GetScaledRowHeight( nY1, nY2, nPrintTab,
2178             nScaleY);
2179 
2180 	//	partition the page
2181 
2182 	long nStartX = ((long) ( nLeftSpace * nScaleX ));
2183 	long nStartY = ((long) ( nTopSpace  * nScaleY ));
2184 //		nStartX -= aOffset.X();			// schon im MapMode
2185 //		nStartY -= aOffset.Y();
2186 
2187 	long nInnerStartX = nStartX;
2188 	long nInnerStartY = nStartY;
2189 	if (pBorderItem)
2190 	{
2191 		nInnerStartX += (long) ( ( lcl_LineTotal(pBorderItem->GetLeft()) +
2192 									pBorderItem->GetDistance(BOX_LINE_LEFT) ) * nScaleX );
2193 		nInnerStartY += (long) ( ( lcl_LineTotal(pBorderItem->GetTop()) +
2194 									pBorderItem->GetDistance(BOX_LINE_TOP) ) * nScaleY );
2195 	}
2196 	if (pShadowItem && pShadowItem->GetLocation() != SVX_SHADOW_NONE)
2197 	{
2198 		nInnerStartX += (long) ( pShadowItem->CalcShadowSpace(SHADOW_LEFT) * nScaleX );
2199 		nInnerStartY += (long) ( pShadowItem->CalcShadowSpace(SHADOW_TOP) * nScaleY );
2200 	}
2201 
2202 	if ( bLayoutRTL )
2203 	{
2204 		//	arrange elements starting from the right edge
2205 		nInnerStartX += nHeaderWidth + nRepeatWidth + nContentWidth;
2206 
2207 		//	make rounding easier so the elements are really next to each other in preview
2208 		Size aOffsetOnePixel = pDev->PixelToLogic( Size(1,1), aOffsetMode );
2209 		long nOffsetOneX = aOffsetOnePixel.Width();
2210 		nInnerStartX += nOffsetOneX / 2;
2211 	}
2212 
2213 	long nFrameStartX = nInnerStartX;
2214 	long nFrameStartY = nInnerStartY;
2215 
2216 	long nRepStartX = nInnerStartX + nHeaderWidth * nLayoutSign;	// widths/heights are 0 if not used
2217 	long nRepStartY = nInnerStartY + nHeaderHeight;
2218 	long nDataX = nRepStartX + nRepeatWidth * nLayoutSign;
2219 	long nDataY = nRepStartY + nRepeatHeight;
2220 	long nEndX = nDataX + nContentWidth * nLayoutSign;
2221 	long nEndY = nDataY + nContentHeight;
2222 	long nFrameEndX = nEndX;
2223 	long nFrameEndY = nEndY;
2224 
2225 	if ( bLayoutRTL )
2226 	{
2227 		//	each element's start position is its left edge
2228 		//!	subtract one pixel less?
2229 		nInnerStartX -= nHeaderWidth;		// used for header
2230 		nRepStartX   -= nRepeatWidth;
2231 		nDataX       -= nContentWidth;
2232 
2233 		//	continue right of the main elements again
2234 		nEndX += nHeaderWidth + nRepeatWidth + nContentWidth;
2235 	}
2236 
2237 	//	Seiten-Rahmen / Hintergrund
2238 
2239 	//!	nEndX/Y anpassen
2240 
2241 	long nBorderEndX = nEndX;
2242 	long nBorderEndY = nEndY;
2243 	if (pBorderItem)
2244 	{
2245 		nBorderEndX += (long) ( ( lcl_LineTotal(pBorderItem->GetRight()) +
2246 									pBorderItem->GetDistance(BOX_LINE_RIGHT) ) * nScaleX );
2247 		nBorderEndY += (long) ( ( lcl_LineTotal(pBorderItem->GetBottom()) +
2248 									pBorderItem->GetDistance(BOX_LINE_BOTTOM) ) * nScaleY );
2249 	}
2250 	if (pShadowItem && pShadowItem->GetLocation() != SVX_SHADOW_NONE)
2251 	{
2252 		nBorderEndX += (long) ( pShadowItem->CalcShadowSpace(SHADOW_RIGHT) * nScaleX );
2253 		nBorderEndY += (long) ( pShadowItem->CalcShadowSpace(SHADOW_BOTTOM) * nScaleY );
2254 	}
2255 
2256 	if ( bDoPrint )
2257 	{
2258 		pDev->SetMapMode( aOffsetMode );
2259 		DrawBorder( nStartX, nStartY, nBorderEndX-nStartX, nBorderEndY-nStartY,
2260 						pBorderItem, pBackgroundItem, pShadowItem );
2261 
2262 		pDev->SetMapMode( aTwipMode );
2263 	}
2264 
2265 	pDev->SetMapMode( aOffsetMode );
2266 
2267 	//	Wiederholungszeilen/Spalten ausgeben
2268 
2269 	if (bDoRepCol && bDoRepRow)
2270 	{
2271 		if ( bDoPrint )
2272 			PrintArea( nRepeatStartCol,nRepeatStartRow, nRepeatEndCol,nRepeatEndRow,
2273 							nRepStartX,nRepStartY, sal_True,sal_True,sal_False,sal_False );
2274 		if ( pLocationData )
2275 			LocateArea( nRepeatStartCol,nRepeatStartRow, nRepeatEndCol,nRepeatEndRow,
2276 							nRepStartX,nRepStartY, sal_True,sal_True, *pLocationData );
2277 	}
2278 	if (bDoRepCol)
2279 	{
2280 		if ( bDoPrint )
2281 			PrintArea( nRepeatStartCol,nY1, nRepeatEndCol,nY2, nRepStartX,nDataY,
2282 						sal_True,!bDoRepRow,sal_False,sal_True );
2283 		if ( pLocationData )
2284 			LocateArea( nRepeatStartCol,nY1, nRepeatEndCol,nY2, nRepStartX,nDataY, sal_True,sal_False, *pLocationData );
2285 	}
2286 	if (bDoRepRow)
2287 	{
2288 		if ( bDoPrint )
2289 			PrintArea( nX1,nRepeatStartRow, nX2,nRepeatEndRow, nDataX,nRepStartY,
2290 						!bDoRepCol,sal_True,sal_True,sal_False );
2291 		if ( pLocationData )
2292 			LocateArea( nX1,nRepeatStartRow, nX2,nRepeatEndRow, nDataX,nRepStartY, sal_False,sal_True, *pLocationData );
2293 	}
2294 
2295 	//	Daten ausgeben
2296 
2297 	if ( bDoPrint )
2298 		PrintArea( nX1,nY1, nX2,nY2, nDataX,nDataY, !bDoRepCol,!bDoRepRow,sal_True,sal_True );
2299 	if ( pLocationData )
2300 		LocateArea( nX1,nY1, nX2,nY2, nDataX,nDataY, sal_False,sal_False, *pLocationData );
2301 
2302 	//	Spalten-/Zeilenkoepfe ausgeben
2303 	//	nach den Daten (ueber evtl. weitergezeichneten Schatten)
2304 
2305 	Color aGridColor( COL_BLACK );
2306 	if ( bUseStyleColor )
2307         aGridColor.SetColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
2308 
2309 	if (aTableParam.bHeaders)
2310 	{
2311 		if ( bDoPrint )
2312 		{
2313 			pDev->SetLineColor( aGridColor );
2314 			pDev->SetFillColor();
2315 			pDev->SetMapMode(aOffsetMode);
2316 		}
2317 
2318 		ScPatternAttr aPattern( pDoc->GetPool() );
2319 		Font aFont;
2320 		ScAutoFontColorMode eColorMode = bUseStyleColor ? SC_AUTOCOL_DISPLAY : SC_AUTOCOL_PRINT;
2321 		aPattern.GetFont( aFont, eColorMode, pDev );
2322 		pDev->SetFont( aFont );
2323 
2324 		if (bDoRepCol)
2325 		{
2326 			if ( bDoPrint )
2327 				PrintColHdr( nRepeatStartCol,nRepeatEndCol, nRepStartX,nInnerStartY );
2328 			if ( pLocationData )
2329 				LocateColHdr( nRepeatStartCol,nRepeatEndCol, nRepStartX,nInnerStartY, sal_True, *pLocationData );
2330 		}
2331 		if ( bDoPrint )
2332 			PrintColHdr( nX1,nX2, nDataX,nInnerStartY );
2333 		if ( pLocationData )
2334 			LocateColHdr( nX1,nX2, nDataX,nInnerStartY, sal_False, *pLocationData );
2335 		if (bDoRepRow)
2336 		{
2337 			if ( bDoPrint )
2338 				PrintRowHdr( nRepeatStartRow,nRepeatEndRow, nInnerStartX,nRepStartY );
2339 			if ( pLocationData )
2340 				LocateRowHdr( nRepeatStartRow,nRepeatEndRow, nInnerStartX,nRepStartY, sal_True, *pLocationData );
2341 		}
2342 		if ( bDoPrint )
2343 			PrintRowHdr( nY1,nY2, nInnerStartX,nDataY );
2344 		if ( pLocationData )
2345 			LocateRowHdr( nY1,nY2, nInnerStartX,nDataY, sal_False, *pLocationData );
2346 	}
2347 
2348 	//	einfacher Rahmen
2349 
2350 	if ( bDoPrint && ( aTableParam.bGrid || aTableParam.bHeaders ) )
2351 	{
2352 		Size aOnePixel = pDev->PixelToLogic(Size(1,1));
2353 		long nOneX = aOnePixel.Width();
2354 		long nOneY = aOnePixel.Height();
2355 
2356 		long nLeftX   = nFrameStartX;
2357 		long nTopY    = nFrameStartY - nOneY;
2358 		long nRightX  = nFrameEndX;
2359 		long nBottomY = nFrameEndY - nOneY;
2360 		if ( !bLayoutRTL )
2361 		{
2362 			nLeftX   -= nOneX;
2363 			nRightX  -= nOneX;
2364 		}
2365 		pDev->SetMapMode(aOffsetMode);
2366 		pDev->SetLineColor( aGridColor );
2367 		pDev->SetFillColor();
2368 		pDev->DrawRect( Rectangle( nLeftX, nTopY, nRightX, nBottomY ) );
2369 		//	nEndX/Y ohne Rahmen-Anpassung
2370 	}
2371 
2372 	if ( pPrinter && bDoPrint )
2373     {
2374         DBG_ERROR( "EndPage does not exist anymore" );
2375 		// pPrinter->EndPage();
2376     }
2377 
2378 	aLastSourceRange = ScRange( nX1, nY1, nPrintTab, nX2, nY2, nPrintTab );
2379 	bSourceRangeValid = sal_True;
2380 }
2381 
2382 void ScPrintFunc::SetOffset( const Point& rOfs )
2383 {
2384 	aSrcOffset = rOfs;
2385 }
2386 
2387 void ScPrintFunc::SetManualZoom( sal_uInt16 nNewZoom )
2388 {
2389 	nManualZoom = nNewZoom;
2390 }
2391 
2392 void ScPrintFunc::SetClearFlag( sal_Bool bFlag )
2393 {
2394 	bClearWin = bFlag;
2395 }
2396 
2397 void ScPrintFunc::SetUseStyleColor( sal_Bool bFlag )
2398 {
2399 	bUseStyleColor = bFlag;
2400 	if (pEditEngine)
2401 		pEditEngine->EnableAutoColor( bUseStyleColor );
2402 }
2403 
2404 void ScPrintFunc::SetRenderFlag( sal_Bool bFlag )
2405 {
2406 	bIsRender = bFlag;		// set when using XRenderable (PDF)
2407 }
2408 
2409 void ScPrintFunc::SetExclusivelyDrawOleAndDrawObjects()
2410 {
2411     aTableParam.bCellContent = false;
2412     aTableParam.bNotes = false;
2413     aTableParam.bGrid = false;
2414     aTableParam.bHeaders = false;
2415     aTableParam.bFormulas = false;
2416     aTableParam.bNullVals = false;
2417 }
2418 
2419 //
2420 //	UpdatePages wird nur von aussen gerufen, um die Umbrueche fuer die Anzeige
2421 //	richtig zu setzen - immer ohne UserArea
2422 //
2423 
2424 sal_Bool ScPrintFunc::UpdatePages()
2425 {
2426 	if (!pParamSet)
2427 		return sal_False;
2428 
2429 	//	Zoom
2430 
2431 	nZoom = 100;
2432     if (aTableParam.bScalePageNum || aTableParam.bScaleTo)
2433 		nZoom = ZOOM_MIN;						// stimmt fuer Umbrueche
2434 	else if (aTableParam.bScaleAll)
2435 	{
2436 		nZoom = aTableParam.nScaleAll;
2437 		if ( nZoom <= ZOOM_MIN )
2438 			nZoom = ZOOM_MIN;
2439 	}
2440 
2441 	String aName = pDoc->GetPageStyle( nPrintTab );
2442 	SCTAB nTabCount = pDoc->GetTableCount();
2443 	for (SCTAB nTab=0; nTab<nTabCount; nTab++)
2444 		if ( nTab==nPrintTab || pDoc->GetPageStyle(nTab)==aName )
2445 		{
2446 			//	Wiederholungszeilen / Spalten
2447 			pDoc->SetRepeatArea( nTab, nRepeatStartCol,nRepeatEndCol, nRepeatStartRow,nRepeatEndRow );
2448 
2449 			//	Umbrueche setzen
2450 			ResetBreaks(nTab);
2451 			pDocShell->PostPaint(0,0,nTab, MAXCOL,MAXROW,nTab, PAINT_GRID);
2452 		}
2453 
2454 	return sal_True;
2455 }
2456 
2457 long ScPrintFunc::CountPages()							// setzt auch nPagesX, nPagesY
2458 {
2459 	sal_Bool bAreaOk = sal_False;
2460 
2461 	if (pDoc->HasTable( nPrintTab ))
2462 	{
2463 		if (aAreaParam.bPrintArea)							// Druckbereich angegeben?
2464 		{
2465 			if ( bPrintCurrentTable )
2466 			{
2467 				ScRange& rRange = aAreaParam.aPrintArea;
2468 
2469 				//	hier kein Vergleich der Tabellen mehr, die Area gilt immer fuer diese Tabelle
2470 				//	wenn hier verglichen werden soll, muss die Tabelle der Druckbereiche beim
2471 				//	Einfuegen von Tabellen etc. angepasst werden !
2472 
2473 				nStartCol = rRange.aStart.Col();
2474 				nStartRow = rRange.aStart.Row();
2475 				nEndCol   = rRange.aEnd  .Col();
2476 				nEndRow   = rRange.aEnd  .Row();
2477 				bAreaOk   = AdjustPrintArea(sal_False);			// begrenzen
2478 			}
2479 			else
2480 				bAreaOk = sal_False;
2481 		}
2482 		else												// aus Dokument suchen
2483 			bAreaOk = AdjustPrintArea(sal_True);
2484 	}
2485 
2486 	if (bAreaOk)
2487 	{
2488 		long nPages = 0;
2489 		size_t nY;
2490 		if (bMultiArea)
2491 		{
2492 			sal_uInt16 nRCount = pDoc->GetPrintRangeCount( nPrintTab );
2493 			for (sal_uInt16 i=0; i<nRCount; i++)
2494 			{
2495 				CalcZoom(i);
2496 				if ( aTableParam.bSkipEmpty )
2497 					for (nY=0; nY<nPagesY; nY++)
2498 						nPages += pPageRows[nY].CountVisible();
2499 				else
2500 					nPages += ((long) nPagesX) * nPagesY;
2501 				if ( pPageData )
2502 					FillPageData();
2503 			}
2504 		}
2505 		else
2506 		{
2507 			CalcZoom(RANGENO_NORANGE);						// Zoom berechnen
2508 			if ( aTableParam.bSkipEmpty )
2509 				for (nY=0; nY<nPagesY; nY++)
2510 					nPages += pPageRows[nY].CountVisible();
2511 			else
2512 				nPages += ((long) nPagesX) * nPagesY;
2513 			if ( pPageData )
2514 				FillPageData();
2515 		}
2516 		return nPages;
2517 	}
2518 	else
2519 	{
2520 //		nZoom = 100;						// nZoom auf letztem Wert stehenlassen !!!
2521 		nPagesX = nPagesY = nTotalY = 0;
2522 		return 0;
2523 	}
2524 }
2525 
2526 long ScPrintFunc::CountNotePages()
2527 {
2528 	if ( !aTableParam.bNotes || !bPrintCurrentTable )
2529 		return 0;
2530 
2531 	long nCount=0;
2532 	SCCOL nCol;
2533 	SCROW nRow;
2534 
2535 	sal_Bool bError = sal_False;
2536 	if (!aAreaParam.bPrintArea)
2537 		bError = !AdjustPrintArea(sal_True);			// komplett aus Dok suchen
2538 
2539 	sal_uInt16 nRepeats = 1;							// wie oft durchgehen ?
2540 	if (bMultiArea)
2541 		nRepeats = pDoc->GetPrintRangeCount(nPrintTab);
2542 	if (bError)
2543 		nRepeats = 0;
2544 
2545 	for (sal_uInt16 nStep=0; nStep<nRepeats; nStep++)
2546 	{
2547 		sal_Bool bDoThis = sal_True;
2548 		if (bMultiArea)				// alle Areas durchgehen
2549 		{
2550 			const ScRange* pThisRange = pDoc->GetPrintRange( nPrintTab, nStep );
2551 			if ( pThisRange )
2552 			{
2553 				nStartCol = pThisRange->aStart.Col();
2554 				nStartRow = pThisRange->aStart.Row();
2555 				nEndCol   = pThisRange->aEnd  .Col();
2556 				nEndRow   = pThisRange->aEnd  .Row();
2557 				bDoThis = AdjustPrintArea(sal_False);
2558 			}
2559 		}
2560 
2561 		if (bDoThis)
2562 		{
2563 			ScHorizontalCellIterator aIter( pDoc, nPrintTab, nStartCol,nStartRow, nEndCol,nEndRow );
2564 			ScBaseCell* pCell = aIter.GetNext( nCol, nRow );
2565 			while (pCell)
2566 			{
2567                 if (pCell->HasNote())
2568 				{
2569 					aNotePosList.Insert( new ScAddress( nCol,nRow,nPrintTab ), LIST_APPEND );
2570 					++nCount;
2571 				}
2572 
2573 				pCell = aIter.GetNext( nCol, nRow );
2574 			}
2575 		}
2576 	}
2577 
2578 	long nPages = 0;
2579 	long nNoteNr = 0;
2580 	long nNoteAdd;
2581 	do
2582 	{
2583 		nNoteAdd = PrintNotes( nPages, nNoteNr, sal_False, NULL );
2584 		if (nNoteAdd)
2585 		{
2586 			nNoteNr += nNoteAdd;
2587 			++nPages;
2588 		}
2589 	}
2590 	while (nNoteAdd);
2591 
2592 	return nPages;
2593 }
2594 
2595 void ScPrintFunc::InitModes()				// aus nZoom etc. die MapModes setzen
2596 {
2597 	aOffset = Point( aSrcOffset.X()*100/nZoom, aSrcOffset.Y()*100/nZoom );
2598 
2599 	long nEffZoom = nZoom * (long) nManualZoom;
2600 
2601 //	nScaleX = nScaleY = 1.0;			// Ausgabe in Twips
2602 	nScaleX = nScaleY = HMM_PER_TWIPS;	// Ausgabe in 1/100 mm
2603 
2604 	Fraction aZoomFract( nEffZoom,10000 );
2605 	Fraction aHorFract = aZoomFract;
2606 
2607 	if ( !pPrinter && !bIsRender )							// adjust scale for preview
2608 	{
2609 		double nFact = pDocShell->GetOutputFactor();
2610 		aHorFract = Fraction( (long)( nEffZoom / nFact ), 10000 );
2611 	}
2612 
2613 	aLogicMode = MapMode( MAP_100TH_MM, Point(), aHorFract, aZoomFract );
2614 
2615 	Point aLogicOfs( -aOffset.X(), -aOffset.Y() );
2616 	aOffsetMode = MapMode( MAP_100TH_MM, aLogicOfs, aHorFract, aZoomFract );
2617 
2618 	Point aTwipsOfs( (long) ( -aOffset.X() / nScaleX + 0.5 ), (long) ( -aOffset.Y() / nScaleY + 0.5 ) );
2619 	aTwipMode = MapMode( MAP_TWIP, aTwipsOfs, aHorFract, aZoomFract );
2620 }
2621 
2622 //--------------------------------------------------------------------
2623 
2624 void ScPrintFunc::ApplyPrintSettings()
2625 {
2626 	if ( pPrinter )
2627 	{
2628 		//
2629 		//	Printer zum Drucken umstellen
2630 		//
2631 
2632 		Size aEnumSize = aPageSize;
2633 
2634 
2635         pPrinter->SetOrientation( bLandscape ? ORIENTATION_LANDSCAPE : ORIENTATION_PORTRAIT );
2636         if ( bLandscape )
2637         {
2638                 // landscape is always interpreted as a rotation by 90 degrees !
2639                 // this leads to non WYSIWIG but at least it prints!
2640                 // #i21775#
2641                 long nTemp = aEnumSize.Width();
2642                 aEnumSize.Width() = aEnumSize.Height();
2643                 aEnumSize.Height() = nTemp;
2644         }
2645         Paper ePaper = SvxPaperInfo::GetSvxPaper( aEnumSize, MAP_TWIP, sal_True );
2646 		sal_uInt16 nPaperBin = ((const SvxPaperBinItem&)pParamSet->Get(ATTR_PAGE_PAPERBIN)).GetValue();
2647 
2648         pPrinter->SetPaper( ePaper );
2649         if ( PAPER_USER == ePaper )
2650         {
2651 		    MapMode aPrinterMode = pPrinter->GetMapMode();
2652 		    MapMode aLocalMode( MAP_TWIP );
2653 		    pPrinter->SetMapMode( aLocalMode );
2654 		    pPrinter->SetPaperSizeUser( aEnumSize );
2655 		    pPrinter->SetMapMode( aPrinterMode );
2656         }
2657 
2658 		pPrinter->SetPaperBin( nPaperBin );
2659 	}
2660 }
2661 
2662 //--------------------------------------------------------------------
2663 //	rPageRanges   = Range fuer alle Tabellen
2664 //	nStartPage	  = in rPageRanges beginnen bei nStartPage
2665 //	nDisplayStart = lfd. Nummer fuer Anzeige der Seitennummer
2666 
2667 long ScPrintFunc::DoPrint( const MultiSelection& rPageRanges,
2668 								long nStartPage, long nDisplayStart, sal_Bool bDoPrint,
2669                                 ScPreviewLocationData* pLocationData )
2670 {
2671 	DBG_ASSERT(pDev,"Device == NULL");
2672 	if (!pParamSet)
2673 		return 0;
2674 
2675 	if ( pPrinter && bDoPrint )
2676 		ApplyPrintSettings();
2677 
2678 	//--------------------------------------------------------------------
2679 
2680 	InitModes();
2681 	if ( pLocationData )
2682 	{
2683 		pLocationData->SetCellMapMode( aOffsetMode );
2684 		pLocationData->SetPrintTab( nPrintTab );
2685 	}
2686 
2687 	MakeTableString();
2688 
2689 	//--------------------------------------------------------------------
2690 
2691 	long nPageNo = 0;
2692 	long nPrinted = 0;
2693 	long nEndPage = rPageRanges.GetTotalRange().Max();
2694 
2695 	sal_uInt16 nRepeats = 1;					// wie oft durchgehen ?
2696 	if (bMultiArea)
2697 		nRepeats = pDoc->GetPrintRangeCount(nPrintTab);
2698 	for (sal_uInt16 nStep=0; nStep<nRepeats; nStep++)
2699 	{
2700 		if (bMultiArea)						// Bereich neu belegen ?
2701 		{
2702 			CalcZoom(nStep);				// setzt auch nStartCol etc. neu
2703 			InitModes();
2704 		}
2705 
2706 		SCCOL nX1;
2707 		SCROW nY1;
2708 		SCCOL nX2;
2709 		SCROW nY2;
2710 		size_t nCountX;
2711 		size_t nCountY;
2712 
2713 		if (aTableParam.bTopDown)							// von oben nach unten
2714 		{
2715 			nX1 = nStartCol;
2716 			for (nCountX=0; nCountX<nPagesX; nCountX++)
2717 			{
2718 				nX2 = pPageEndX[nCountX];
2719 				for (nCountY=0; nCountY<nPagesY; nCountY++)
2720 				{
2721 					nY1 = pPageRows[nCountY].GetStartRow();
2722 					nY2 = pPageRows[nCountY].GetEndRow();
2723 					if ( !aTableParam.bSkipEmpty || !pPageRows[nCountY].IsHidden(nCountX) )
2724 					{
2725 						if ( rPageRanges.IsSelected( nPageNo+nStartPage+1 ) )
2726 						{
2727 							PrintPage( nPageNo+nDisplayStart, nX1, nY1, nX2, nY2,
2728 										bDoPrint, pLocationData );
2729 							++nPrinted;
2730 						}
2731 						++nPageNo;
2732 					}
2733 				}
2734 				nX1 = nX2 + 1;
2735 			}
2736 		}
2737 		else												// von links nach rechts
2738 		{
2739 			for (nCountY=0; nCountY<nPagesY; nCountY++)
2740 			{
2741 				nY1 = pPageRows[nCountY].GetStartRow();
2742 				nY2 = pPageRows[nCountY].GetEndRow();
2743 				nX1 = nStartCol;
2744 				for (nCountX=0; nCountX<nPagesX; nCountX++)
2745 				{
2746 					nX2 = pPageEndX[nCountX];
2747 					if ( !aTableParam.bSkipEmpty || !pPageRows[nCountY].IsHidden(nCountX) )
2748 					{
2749 						if ( rPageRanges.IsSelected( nPageNo+nStartPage+1 ) )
2750 						{
2751 							PrintPage( nPageNo+nDisplayStart, nX1, nY1, nX2, nY2,
2752 										bDoPrint, pLocationData );
2753 							++nPrinted;
2754 						}
2755 						++nPageNo;
2756 					}
2757 					nX1 = nX2 + 1;
2758 				}
2759 			}
2760 		}
2761 	}
2762 
2763 	aFieldData.aTabName = ScGlobal::GetRscString( STR_NOTES );
2764 
2765 	long nNoteNr = 0;
2766 	long nNoteAdd;
2767 	do
2768 	{
2769 		if ( nPageNo+nStartPage <= nEndPage )
2770 		{
2771 			sal_Bool bPageSelected = rPageRanges.IsSelected( nPageNo+nStartPage+1 );
2772 			nNoteAdd = PrintNotes( nPageNo+nStartPage, nNoteNr, bDoPrint && bPageSelected,
2773 									( bPageSelected ? pLocationData : NULL ) );
2774 			if ( nNoteAdd )
2775 			{
2776 				nNoteNr += nNoteAdd;
2777 				if (bPageSelected)
2778 				{
2779 					++nPrinted;
2780 					bSourceRangeValid = sal_False;		// last page was no cell range
2781 				}
2782 				++nPageNo;
2783 			}
2784 		}
2785 		else
2786 			nNoteAdd = 0;
2787 	}
2788 	while (nNoteAdd);
2789 
2790 	if ( bMultiArea )
2791 		ResetBreaks(nPrintTab);							// Breaks fuer Anzeige richtig
2792 
2793 	return nPrinted;
2794 }
2795 
2796 void ScPrintFunc::CalcZoom( sal_uInt16 nRangeNo )						// Zoom berechnen
2797 {
2798 	sal_uInt16 nRCount = pDoc->GetPrintRangeCount( nPrintTab );
2799 	const ScRange* pThisRange = NULL;
2800 	if ( nRangeNo != RANGENO_NORANGE || nRangeNo < nRCount )
2801 		pThisRange = pDoc->GetPrintRange( nPrintTab, nRangeNo );
2802 	if ( pThisRange )
2803 	{
2804 		nStartCol = pThisRange->aStart.Col();
2805 		nStartRow = pThisRange->aStart.Row();
2806 		nEndCol   = pThisRange->aEnd  .Col();
2807 		nEndRow   = pThisRange->aEnd  .Row();
2808 	}
2809 
2810 	if (!AdjustPrintArea(sal_False))						// leer
2811 	{
2812 		nZoom = 100;
2813 		nPagesX = nPagesY = nTotalY = 0;
2814 		return;
2815 	}
2816 
2817 	pDoc->SetRepeatArea( nPrintTab, nRepeatStartCol,nRepeatEndCol, nRepeatStartRow,nRepeatEndRow );
2818 
2819 	if (aTableParam.bScalePageNum)
2820 	{
2821 		nZoom = 100;
2822 		sal_uInt16 nPagesToFit = aTableParam.nScalePageNum;
2823 
2824         sal_uInt16 nLastFitZoom = 0, nLastNonFitZoom = 0;
2825         while (true)
2826         {
2827             if (nZoom <= ZOOM_MIN)
2828                 break;
2829 
2830             CalcPages();
2831             bool bFitsPage = (nPagesX * nPagesY <= nPagesToFit);
2832 
2833             if (bFitsPage)
2834             {
2835                 if (nZoom == 100)
2836                     // If it fits at 100 %, it's good enough for me.
2837                     break;
2838 
2839                 nLastFitZoom = nZoom;
2840                 nZoom = (nLastNonFitZoom + nZoom) / 2;
2841 
2842                 if (nLastFitZoom == nZoom)
2843                     // It converged.  Use this zoom level.
2844                     break;
2845             }
2846             else
2847             {
2848                 if (nZoom - nLastFitZoom <= 1)
2849                 {
2850                     nZoom = nLastFitZoom;
2851                     CalcPages();
2852                     break;
2853                 }
2854 
2855                 nLastNonFitZoom = nZoom;
2856                 nZoom = (nLastFitZoom + nZoom) / 2;
2857             }
2858         }
2859 	}
2860     else if (aTableParam.bScaleTo)
2861     {
2862         nZoom = 100;
2863         sal_uInt16 nW = aTableParam.nScaleWidth;
2864         sal_uInt16 nH = aTableParam.nScaleHeight;
2865 
2866         sal_uInt16 nLastFitZoom = 0, nLastNonFitZoom = 0;
2867         while (true)
2868         {
2869             if (nZoom <= ZOOM_MIN)
2870                 break;
2871 
2872             CalcPages();
2873             bool bFitsPage = ((!nW || (nPagesX <= nW)) && (!nH || (nPagesY <= nH)));
2874 
2875             if (bFitsPage)
2876             {
2877                 if (nZoom == 100)
2878                     // If it fits at 100 %, it's good enough for me.
2879                     break;
2880 
2881                 nLastFitZoom = nZoom;
2882                 nZoom = (nLastNonFitZoom + nZoom) / 2;
2883 
2884                 if (nLastFitZoom == nZoom)
2885                     // It converged.  Use this zoom level.
2886                     break;
2887             }
2888             else
2889             {
2890                 if (nZoom - nLastFitZoom <= 1)
2891                 {
2892                     nZoom = nLastFitZoom;
2893                     CalcPages();
2894                     break;
2895                 }
2896 
2897                 nLastNonFitZoom = nZoom;
2898                 nZoom = (nLastFitZoom + nZoom) / 2;
2899             }
2900         }
2901     }
2902 	else if (aTableParam.bScaleAll)
2903 	{
2904 		nZoom = aTableParam.nScaleAll;
2905 		if ( nZoom <= ZOOM_MIN )
2906 			nZoom = ZOOM_MIN;
2907 		CalcPages();
2908 	}
2909 	else
2910 	{
2911 		DBG_ASSERT( aTableParam.bScaleNone, "kein Scale-Flag gesetzt" );
2912 		nZoom = 100;
2913 		CalcPages();
2914 	}
2915 }
2916 
2917 Size ScPrintFunc::GetDocPageSize()
2918 {
2919 						// Hoehe Kopf-/Fusszeile anpassen
2920 
2921 	InitModes();							// aTwipMode aus nZoom initialisieren
2922 	pDev->SetMapMode( aTwipMode );			// Kopf-/Fusszeilen in Twips
2923 	UpdateHFHeight( aHdr );
2924 	UpdateHFHeight( aFtr );
2925 
2926 						// Seitengroesse in Document-Twips
2927 						// 	Berechnung Left / Right auch in PrintPage
2928 
2929 	aPageRect = Rectangle( Point(), aPageSize );
2930 	aPageRect.Left()   = ( aPageRect.Left()   + nLeftMargin					 ) * 100 / nZoom;
2931 	aPageRect.Right()  = ( aPageRect.Right()  - nRightMargin				 ) * 100 / nZoom;
2932 	aPageRect.Top()    = ( aPageRect.Top()    + nTopMargin    ) * 100 / nZoom + aHdr.nHeight;
2933 	aPageRect.Bottom() = ( aPageRect.Bottom() - nBottomMargin ) * 100 / nZoom - aFtr.nHeight;
2934 
2935 	Size aDocPageSize = aPageRect.GetSize();
2936 	if (aTableParam.bHeaders)
2937 	{
2938 		aDocPageSize.Width()  -= (long) PRINT_HEADER_WIDTH;
2939 		aDocPageSize.Height() -= (long) PRINT_HEADER_HEIGHT;
2940 	}
2941 	if (pBorderItem)
2942 	{
2943 		aDocPageSize.Width()  -= lcl_LineTotal(pBorderItem->GetLeft()) +
2944 								 lcl_LineTotal(pBorderItem->GetRight()) +
2945 								 pBorderItem->GetDistance(BOX_LINE_LEFT) +
2946 								 pBorderItem->GetDistance(BOX_LINE_RIGHT);
2947 		aDocPageSize.Height() -= lcl_LineTotal(pBorderItem->GetTop()) +
2948 								 lcl_LineTotal(pBorderItem->GetBottom()) +
2949 								 pBorderItem->GetDistance(BOX_LINE_TOP) +
2950 								 pBorderItem->GetDistance(BOX_LINE_BOTTOM);
2951 	}
2952 	if (pShadowItem && pShadowItem->GetLocation() != SVX_SHADOW_NONE)
2953 	{
2954 		aDocPageSize.Width()  -= pShadowItem->CalcShadowSpace(SHADOW_LEFT) +
2955 								 pShadowItem->CalcShadowSpace(SHADOW_RIGHT);
2956 		aDocPageSize.Height() -= pShadowItem->CalcShadowSpace(SHADOW_TOP) +
2957 								 pShadowItem->CalcShadowSpace(SHADOW_BOTTOM);
2958 	}
2959 	return aDocPageSize;
2960 }
2961 
2962 void ScPrintFunc::ResetBreaks( SCTAB nTab )			// Breaks fuer Anzeige richtig setzen
2963 {
2964 	pDoc->SetPageSize( nTab, GetDocPageSize() );
2965 	pDoc->UpdatePageBreaks( nTab, NULL );
2966 }
2967 
2968 void lcl_SetHidden( ScDocument* pDoc, SCTAB nPrintTab, ScPageRowEntry& rPageRowEntry,
2969 					SCCOL nStartCol, const SCCOL* pPageEndX )
2970 {
2971 	size_t nPagesX   = rPageRowEntry.GetPagesX();
2972 	SCROW nStartRow = rPageRowEntry.GetStartRow();
2973 	SCROW nEndRow   = rPageRowEntry.GetEndRow();
2974 
2975 	sal_Bool bLeftIsEmpty = sal_False;
2976 	ScRange aTempRange;
2977 	Rectangle aTempRect = pDoc->GetMMRect( 0,0, 0,0, 0 );
2978 
2979 	for (size_t i=0; i<nPagesX; i++)
2980 	{
2981 		SCCOL nEndCol = pPageEndX[i];
2982 		if ( pDoc->IsPrintEmpty( nPrintTab, nStartCol, nStartRow, nEndCol, nEndRow,
2983 									bLeftIsEmpty, &aTempRange, &aTempRect ) )
2984 		{
2985 			rPageRowEntry.SetHidden(i);
2986 			bLeftIsEmpty = sal_True;
2987 		}
2988 		else
2989 			bLeftIsEmpty = sal_False;
2990 
2991 		nStartCol = nEndCol+1;
2992 	}
2993 }
2994 
2995 void ScPrintFunc::CalcPages()               // berechnet aPageRect und Seiten aus nZoom
2996 {
2997     if (!pPageEndX) pPageEndX = new SCCOL[MAXCOL+1];
2998     if (!pPageEndY) pPageEndY = new SCROW[MAXROW+1];
2999     if (!pPageRows) pPageRows = new ScPageRowEntry[MAXROW+1];   //! vorher zaehlen !!!!
3000 
3001     pDoc->SetPageSize( nPrintTab, GetDocPageSize() );
3002     if (aAreaParam.bPrintArea)
3003     {
3004         ScRange aRange( nStartCol, nStartRow, nPrintTab, nEndCol, nEndRow, nPrintTab );
3005         pDoc->UpdatePageBreaks( nPrintTab, &aRange );
3006     }
3007     else
3008         pDoc->UpdatePageBreaks( nPrintTab, NULL );      // sonst wird das Ende markiert
3009 
3010     //
3011     //  Seiteneinteilung nach Umbruechen in Col/RowFlags
3012     //  Von mehreren Umbruechen in einem ausgeblendeten Bereich zaehlt nur einer.
3013     //
3014 
3015     nPagesX = 0;
3016     nPagesY = 0;
3017     nTotalY = 0;
3018 
3019     bool bVisCol = false;
3020     SCCOL nLastCol = -1;
3021     for (SCCOL i=nStartCol; i<=nEndCol; i++)
3022     {
3023         bool bHidden = pDoc->ColHidden(i, nPrintTab, nLastCol);
3024         bool bPageBreak = (pDoc->HasColBreak(i, nPrintTab) & BREAK_PAGE);
3025         if ( i>nStartCol && bVisCol && bPageBreak )
3026         {
3027             pPageEndX[nPagesX] = i-1;
3028             ++nPagesX;
3029             bVisCol = false;
3030         }
3031         if (!bHidden)
3032             bVisCol = true;
3033     }
3034     if (bVisCol)    // auch am Ende keine leeren Seiten
3035     {
3036         pPageEndX[nPagesX] = nEndCol;
3037         ++nPagesX;
3038     }
3039 
3040     bool bVisRow = false;
3041     SCROW nPageStartRow = nStartRow;
3042     SCROW nLastVisibleRow = -1;
3043 
3044     ::boost::scoped_ptr<ScRowBreakIterator> pRowBreakIter(pDoc->GetRowBreakIterator(nPrintTab));
3045     SCROW nNextPageBreak = pRowBreakIter->first();
3046     while (nNextPageBreak != ScRowBreakIterator::NOT_FOUND && nNextPageBreak < nStartRow)
3047         // Skip until the page break position is at the start row or greater.
3048         nNextPageBreak = pRowBreakIter->next();
3049 
3050     for (SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow)
3051     {
3052         bool bPageBreak = (nNextPageBreak == nRow);
3053         if (bPageBreak)
3054             nNextPageBreak = pRowBreakIter->next();
3055 
3056         if (nRow > nStartRow && bVisRow && bPageBreak )
3057         {
3058             pPageEndY[nTotalY] = nRow-1;
3059             ++nTotalY;
3060 
3061             if ( !aTableParam.bSkipEmpty ||
3062                     !pDoc->IsPrintEmpty( nPrintTab, nStartCol, nPageStartRow, nEndCol, nRow-1 ) )
3063             {
3064                 pPageRows[nPagesY].SetStartRow( nPageStartRow );
3065                 pPageRows[nPagesY].SetEndRow( nRow-1 );
3066                 pPageRows[nPagesY].SetPagesX( nPagesX );
3067                 if (aTableParam.bSkipEmpty)
3068                     lcl_SetHidden( pDoc, nPrintTab, pPageRows[nPagesY], nStartCol, pPageEndX );
3069                 ++nPagesY;
3070             }
3071 
3072             nPageStartRow = nRow;
3073             bVisRow = false;
3074         }
3075 
3076         if (nRow <= nLastVisibleRow)
3077         {
3078             // This row is still visible.  Don't bother calling RowHidden() to
3079             // find out, for speed optimization.
3080             bVisRow = true;
3081             continue;
3082         }
3083 
3084         SCROW nLastRow = -1;
3085         if (!pDoc->RowHidden(nRow, nPrintTab, NULL, &nLastRow))
3086         {
3087             bVisRow = true;
3088             nLastVisibleRow = nLastRow;
3089         }
3090         else
3091             // skip all hidden rows.
3092             nRow = nLastRow;
3093     }
3094 
3095     if (bVisRow)
3096     {
3097         pPageEndY[nTotalY] = nEndRow;
3098         ++nTotalY;
3099 
3100         if ( !aTableParam.bSkipEmpty ||
3101                 !pDoc->IsPrintEmpty( nPrintTab, nStartCol, nPageStartRow, nEndCol, nEndRow ) )
3102         {
3103             pPageRows[nPagesY].SetStartRow( nPageStartRow );
3104             pPageRows[nPagesY].SetEndRow( nEndRow );
3105             pPageRows[nPagesY].SetPagesX( nPagesX );
3106             if (aTableParam.bSkipEmpty)
3107                 lcl_SetHidden( pDoc, nPrintTab, pPageRows[nPagesY], nStartCol, pPageEndX );
3108             ++nPagesY;
3109         }
3110     }
3111 }
3112 
3113 //------------------------------------------------------------------------
3114 //	class ScJobSetup
3115 //------------------------------------------------------------------------
3116 
3117 ScJobSetup::ScJobSetup( SfxPrinter* pPrinter )
3118 {
3119 	eOrientation = pPrinter->GetOrientation();
3120 	nPaperBin	 = pPrinter->GetPaperBin();
3121 	ePaper		 = pPrinter->GetPaper();
3122 
3123 	if ( PAPER_USER == ePaper )
3124 	{
3125 		aUserSize = pPrinter->GetPaperSize();
3126 		aUserMapMode = pPrinter->GetMapMode();
3127 	}
3128 };
3129 
3130 
3131 
3132 
3133 
3134