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