xref: /trunk/main/sc/source/ui/view/printfun.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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