1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <svl/itemset.hxx>
22 #include <vcl/graph.hxx>
23 #include <scitems.hxx>
24 #include <svl/eitem.hxx>
25 #include <svl/intitem.hxx>
26 #include <svx/pageitem.hxx>
27 #include <editeng/sizeitem.hxx>
28 #include <editeng/lrspitem.hxx>
29 #include <editeng/ulspitem.hxx>
30 #include <editeng/brushitem.hxx>
31 #include <comphelper/configuration.hxx>
32 #include <document.hxx>
33 #include <stlsheet.hxx>
35 #include <xistream.hxx>
36 #include <xihelper.hxx>
37 #include <xiescher.hxx>
39 // Page settings ==============================================================
41 XclImpPageSettings::XclImpPageSettings( const XclImpRoot
& rRoot
) :
47 void XclImpPageSettings::Initialize()
53 void XclImpPageSettings::ReadSetup( XclImpStream
& rStrm
)
55 OSL_ENSURE_BIFF( GetBiff() >= EXC_BIFF4
);
56 if( GetBiff() < EXC_BIFF4
)
61 maData
.mnPaperSize
= rStrm
.ReaduInt16();
62 maData
.mnScaling
= rStrm
.ReaduInt16();
63 maData
.mnStartPage
= rStrm
.ReaduInt16();
64 maData
.mnFitToWidth
= rStrm
.ReaduInt16();
65 maData
.mnFitToHeight
= rStrm
.ReaduInt16();
66 nFlags
= rStrm
.ReaduInt16();
68 mbValidPaper
= maData
.mbValid
= !::get_flag( nFlags
, EXC_SETUP_INVALID
);
69 maData
.mbPrintInRows
= ::get_flag( nFlags
, EXC_SETUP_INROWS
);
70 maData
.mbPortrait
= ::get_flag( nFlags
, EXC_SETUP_PORTRAIT
);
71 maData
.mbBlackWhite
= ::get_flag( nFlags
, EXC_SETUP_BLACKWHITE
);
72 maData
.mbManualStart
= true;
74 // new in BIFF5 - BIFF8
75 if( GetBiff() >= EXC_BIFF5
)
77 maData
.mnHorPrintRes
= rStrm
.ReaduInt16();
78 maData
.mnVerPrintRes
= rStrm
.ReaduInt16();
79 maData
.mfHeaderMargin
= rStrm
.ReadDouble();
80 maData
.mfFooterMargin
= rStrm
.ReadDouble();
81 maData
.mnCopies
= rStrm
.ReaduInt16();
83 maData
.mbDraftQuality
= ::get_flag( nFlags
, EXC_SETUP_DRAFT
);
84 maData
.mbPrintNotes
= ::get_flag( nFlags
, EXC_SETUP_PRINTNOTES
);
85 maData
.mbManualStart
= ::get_flag( nFlags
, EXC_SETUP_STARTPAGE
);
89 void XclImpPageSettings::ReadMargin( XclImpStream
& rStrm
)
91 switch( rStrm
.GetRecId() )
93 case EXC_ID_LEFTMARGIN
: maData
.mfLeftMargin
= rStrm
.ReadDouble(); break;
94 case EXC_ID_RIGHTMARGIN
: maData
.mfRightMargin
= rStrm
.ReadDouble(); break;
95 case EXC_ID_TOPMARGIN
: maData
.mfTopMargin
= rStrm
.ReadDouble(); break;
96 case EXC_ID_BOTTOMMARGIN
: maData
.mfBottomMargin
= rStrm
.ReadDouble(); break;
97 default: OSL_FAIL( "XclImpPageSettings::ReadMargin - unknown record" );
101 void XclImpPageSettings::ReadCenter( XclImpStream
& rStrm
)
103 OSL_ENSURE_BIFF( GetBiff() >= EXC_BIFF3
); // read it anyway
104 bool bCenter
= (rStrm
.ReaduInt16() != 0);
105 switch( rStrm
.GetRecId() )
107 case EXC_ID_HCENTER
: maData
.mbHorCenter
= bCenter
; break;
108 case EXC_ID_VCENTER
: maData
.mbVerCenter
= bCenter
; break;
109 default: OSL_FAIL( "XclImpPageSettings::ReadCenter - unknown record" );
113 void XclImpPageSettings::ReadHeaderFooter( XclImpStream
& rStrm
)
116 if( rStrm
.GetRecLeft() )
117 aString
= (GetBiff() <= EXC_BIFF5
) ? rStrm
.ReadByteString( false ) : rStrm
.ReadUniString();
119 switch( rStrm
.GetRecId() )
121 case EXC_ID_HEADER
: maData
.maHeader
= aString
; break;
122 case EXC_ID_FOOTER
: maData
.maFooter
= aString
; break;
123 case EXC_ID_HEADER_EVEN
: maData
.maHeaderEven
= aString
; break;
124 case EXC_ID_FOOTER_EVEN
: maData
.maFooterEven
= aString
; break;
125 default: OSL_FAIL( "XclImpPageSettings::ReadHeaderFooter - unknown record" );
128 if (comphelper::IsFuzzing())
130 if (maData
.maHeader
.getLength() > 10)
131 maData
.maHeader
= maData
.maHeader
.copy(0, 10);
132 if (maData
.maFooter
.getLength() > 10)
133 maData
.maFooter
= maData
.maFooter
.copy(0, 10);
134 if (maData
.maHeaderEven
.getLength() > 10)
135 maData
.maHeaderEven
= maData
.maHeaderEven
.copy(0, 10);
136 if (maData
.maFooterEven
.getLength() > 10)
137 maData
.maFooterEven
= maData
.maFooterEven
.copy(0, 10);
141 void XclImpPageSettings::ReadPageBreaks( XclImpStream
& rStrm
)
143 ScfUInt16Vec
* pVec
= nullptr;
144 switch( rStrm
.GetRecId() )
146 case EXC_ID_HORPAGEBREAKS
: pVec
= &maData
.maHorPageBreaks
; break;
147 case EXC_ID_VERPAGEBREAKS
: pVec
= &maData
.maVerPageBreaks
; break;
148 default: OSL_FAIL( "XclImpPageSettings::ReadPageBreaks - unknown record" );
154 bool bIgnore
= GetBiff() == EXC_BIFF8
; // ignore start/end columns or rows in BIFF8
156 sal_uInt16 nCount
= rStrm
.ReaduInt16();
158 pVec
->reserve( nCount
);
162 sal_uInt16 nBreak
= rStrm
.ReaduInt16();
164 pVec
->push_back( nBreak
);
171 void XclImpPageSettings::ReadPrintHeaders( XclImpStream
& rStrm
)
173 maData
.mbPrintHeadings
= (rStrm
.ReaduInt16() != 0);
176 void XclImpPageSettings::ReadPrintGridLines( XclImpStream
& rStrm
)
178 maData
.mbPrintGrid
= (rStrm
.ReaduInt16() != 0);
181 void XclImpPageSettings::ReadImgData( XclImpStream
& rStrm
)
183 Graphic aGraphic
= XclImpDrawing::ReadImgData( GetRoot(), rStrm
);
184 if( aGraphic
.GetType() != GraphicType::NONE
)
185 maData
.mxBrushItem
.reset( new SvxBrushItem( aGraphic
, GPOS_TILED
, ATTR_BACKGROUND
) );
188 void XclImpPageSettings::SetPaperSize( sal_uInt16 nXclPaperSize
, bool bPortrait
)
190 maData
.mnPaperSize
= nXclPaperSize
;
191 maData
.mbPortrait
= bPortrait
;
197 void lclPutMarginItem( SfxItemSet
& rItemSet
, sal_uInt16 nRecId
, double fMarginInch
)
199 sal_uInt16 nMarginTwips
= XclTools::GetTwipsFromInch( fMarginInch
);
202 case EXC_ID_TOPMARGIN
:
203 case EXC_ID_BOTTOMMARGIN
:
205 SvxULSpaceItem
aItem( rItemSet
.Get( ATTR_ULSPACE
) );
206 if( nRecId
== EXC_ID_TOPMARGIN
)
207 aItem
.SetUpperValue( nMarginTwips
);
209 aItem
.SetLowerValue( nMarginTwips
);
210 rItemSet
.Put( aItem
);
213 case EXC_ID_LEFTMARGIN
:
214 case EXC_ID_RIGHTMARGIN
:
216 SvxLRSpaceItem
aItem( rItemSet
.Get( ATTR_LRSPACE
) );
217 if (nRecId
== EXC_ID_LEFTMARGIN
)
218 aItem
.SetLeft(SvxIndentValue::twips(nMarginTwips
));
220 aItem
.SetRight(SvxIndentValue::twips(nMarginTwips
));
221 rItemSet
.Put( aItem
);
225 OSL_FAIL( "XclImpPageSettings::SetMarginItem - unknown record id" );
231 void XclImpPageSettings::Finalize()
233 ScDocument
& rDoc
= GetDoc();
234 SCTAB nScTab
= GetCurrScTab();
236 // *** create page style sheet ***
240 if( GetDoc().GetName( nScTab
, aTableName
) )
241 aStyleName
= "PageStyle_" + aTableName
;
243 aStyleName
= "PageStyle_" + OUString::number(static_cast<sal_Int32
>(nScTab
+1));
245 ScStyleSheet
& rStyleSheet
= ScfTools::MakePageStyleSheet(
246 GetStyleSheetPool(), aStyleName
, false);
248 SfxItemSet
& rItemSet
= rStyleSheet
.GetItemSet();
250 // *** page settings ***
252 ScfTools::PutItem( rItemSet
, SfxBoolItem( ATTR_PAGE_TOPDOWN
, !maData
.mbPrintInRows
), true );
253 ScfTools::PutItem( rItemSet
, SfxBoolItem( ATTR_PAGE_HORCENTER
, maData
.mbHorCenter
), true );
254 ScfTools::PutItem( rItemSet
, SfxBoolItem( ATTR_PAGE_VERCENTER
, maData
.mbVerCenter
), true );
255 ScfTools::PutItem( rItemSet
, SfxBoolItem( ATTR_PAGE_HEADERS
, maData
.mbPrintHeadings
), true );
256 ScfTools::PutItem( rItemSet
, SfxBoolItem( ATTR_PAGE_GRID
, maData
.mbPrintGrid
), true );
257 ScfTools::PutItem( rItemSet
, SfxBoolItem( ATTR_PAGE_NOTES
, maData
.mbPrintNotes
), true );
259 sal_uInt16 nStartPage
= maData
.mbManualStart
? maData
.mnStartPage
: 0;
260 ScfTools::PutItem( rItemSet
, SfxUInt16Item( ATTR_PAGE_FIRSTPAGENO
, nStartPage
), true );
262 if( maData
.mxBrushItem
)
263 rItemSet
.Put( *maData
.mxBrushItem
);
267 SvxPageItem
aPageItem( rItemSet
.Get( ATTR_PAGE
) );
268 aPageItem
.SetLandscape( !maData
.mbPortrait
);
269 rItemSet
.Put( aPageItem
);
270 ScfTools::PutItem( rItemSet
, SvxSizeItem( ATTR_PAGE_SIZE
, maData
.GetScPaperSize() ), true );
273 if( maData
.mbFitToPages
)
274 rItemSet
.Put( ScPageScaleToItem( maData
.mnFitToWidth
, maData
.mnFitToHeight
) );
275 else if( maData
.mbValid
)
276 rItemSet
.Put( SfxUInt16Item( ATTR_PAGE_SCALE
, maData
.mnScaling
) );
278 // *** margin preparations ***
280 double fLeftMargin
= maData
.mfLeftMargin
;
281 double fRightMargin
= maData
.mfRightMargin
;
282 double fTopMargin
= maData
.mfTopMargin
;
283 double fBottomMargin
= maData
.mfBottomMargin
;
284 // distances between header/footer and page area
285 double fHeaderHeight
= 0.0;
286 double fHeaderDist
= 0.0;
287 double fFooterHeight
= 0.0;
288 double fFooterDist
= 0.0;
289 // in Calc, "header/footer left/right margin" is X distance between header/footer and page margin
290 double fHdrLeftMargin
= maData
.mfHdrLeftMargin
- maData
.mfLeftMargin
;
291 double fHdrRightMargin
= maData
.mfHdrRightMargin
- maData
.mfRightMargin
;
292 double fFtrLeftMargin
= maData
.mfFtrLeftMargin
- maData
.mfLeftMargin
;
293 double fFtrRightMargin
= maData
.mfFtrRightMargin
- maData
.mfRightMargin
;
295 // *** header and footer ***
297 XclImpHFConverter
aHFConv( GetRoot() );
300 bool bHasHeader
= !maData
.maHeader
.isEmpty();
301 SvxSetItem
aHdrSetItem( rItemSet
.Get( ATTR_PAGE_HEADERSET
) );
302 SfxItemSet
& rHdrItemSet
= aHdrSetItem
.GetItemSet();
303 rHdrItemSet
.Put( SfxBoolItem( ATTR_PAGE_ON
, bHasHeader
) );
306 aHFConv
.ParseString( maData
.maHeader
);
307 aHFConv
.FillToItemSet( rItemSet
, ATTR_PAGE_HEADERLEFT
);
308 aHFConv
.FillToItemSet( rItemSet
, ATTR_PAGE_HEADERRIGHT
);
309 aHFConv
.FillToItemSet( rItemSet
, ATTR_PAGE_HEADERFIRST
);
310 // #i23296# In Calc, "top margin" is distance to header
311 fTopMargin
= maData
.mfHeaderMargin
;
312 // Calc uses distance between header and sheet data area
313 fHeaderHeight
= XclTools::GetInchFromTwips( aHFConv
.GetTotalHeight() );
314 fHeaderDist
= maData
.mfTopMargin
- maData
.mfHeaderMargin
- fHeaderHeight
;
316 if( fHeaderDist
< 0.0 )
318 /* #i23296# Header overlays sheet data:
319 -> set fixed header height to get correct sheet data position. */
320 ScfTools::PutItem( rHdrItemSet
, SfxBoolItem( ATTR_PAGE_DYNAMIC
, false ), true );
321 // shrink header height
322 tools::Long nHdrHeight
= XclTools::GetTwipsFromInch( fHeaderHeight
+ fHeaderDist
);
323 ScfTools::PutItem( rHdrItemSet
, SvxSizeItem( ATTR_PAGE_SIZE
, Size( 0, nHdrHeight
) ), true );
324 lclPutMarginItem( rHdrItemSet
, EXC_ID_BOTTOMMARGIN
, 0.0 );
328 // use dynamic header height
329 ScfTools::PutItem( rHdrItemSet
, SfxBoolItem( ATTR_PAGE_DYNAMIC
, true ), true );
330 lclPutMarginItem( rHdrItemSet
, EXC_ID_BOTTOMMARGIN
, fHeaderDist
);
332 lclPutMarginItem( rHdrItemSet
, EXC_ID_LEFTMARGIN
, fHdrLeftMargin
);
333 lclPutMarginItem( rHdrItemSet
, EXC_ID_RIGHTMARGIN
, fHdrRightMargin
);
334 rItemSet
.Put( aHdrSetItem
);
337 bool bHasFooter
= !maData
.maFooter
.isEmpty();
338 SvxSetItem
aFtrSetItem( rItemSet
.Get( ATTR_PAGE_FOOTERSET
) );
339 SfxItemSet
& rFtrItemSet
= aFtrSetItem
.GetItemSet();
340 rFtrItemSet
.Put( SfxBoolItem( ATTR_PAGE_ON
, bHasFooter
) );
343 aHFConv
.ParseString( maData
.maFooter
);
344 aHFConv
.FillToItemSet( rItemSet
, ATTR_PAGE_FOOTERLEFT
);
345 aHFConv
.FillToItemSet( rItemSet
, ATTR_PAGE_FOOTERRIGHT
);
346 aHFConv
.FillToItemSet( rItemSet
, ATTR_PAGE_FOOTERFIRST
);
347 // #i23296# In Calc, "bottom margin" is distance to footer
348 fBottomMargin
= maData
.mfFooterMargin
;
349 // Calc uses distance between footer and sheet data area
350 fFooterHeight
= XclTools::GetInchFromTwips( aHFConv
.GetTotalHeight() );
351 fFooterDist
= maData
.mfBottomMargin
- maData
.mfFooterMargin
- fFooterHeight
;
353 if( fFooterDist
< 0.0 )
355 /* #i23296# Footer overlays sheet data:
356 -> set fixed footer height to get correct sheet data end position. */
357 ScfTools::PutItem( rFtrItemSet
, SfxBoolItem( ATTR_PAGE_DYNAMIC
, false ), true );
358 // shrink footer height
359 tools::Long nFtrHeight
= XclTools::GetTwipsFromInch( fFooterHeight
+ fFooterDist
);
360 ScfTools::PutItem( rFtrItemSet
, SvxSizeItem( ATTR_PAGE_SIZE
, Size( 0, nFtrHeight
) ), true );
361 lclPutMarginItem( rFtrItemSet
, EXC_ID_TOPMARGIN
, 0.0 );
365 // use dynamic footer height
366 ScfTools::PutItem( rFtrItemSet
, SfxBoolItem( ATTR_PAGE_DYNAMIC
, true ), true );
367 lclPutMarginItem( rFtrItemSet
, EXC_ID_TOPMARGIN
, fFooterDist
);
369 lclPutMarginItem( rFtrItemSet
, EXC_ID_LEFTMARGIN
, fFtrLeftMargin
);
370 lclPutMarginItem( rFtrItemSet
, EXC_ID_RIGHTMARGIN
, fFtrRightMargin
);
371 rItemSet
.Put( aFtrSetItem
);
373 // *** set final margins ***
375 lclPutMarginItem( rItemSet
, EXC_ID_LEFTMARGIN
, fLeftMargin
);
376 lclPutMarginItem( rItemSet
, EXC_ID_RIGHTMARGIN
, fRightMargin
);
377 lclPutMarginItem( rItemSet
, EXC_ID_TOPMARGIN
, fTopMargin
);
378 lclPutMarginItem( rItemSet
, EXC_ID_BOTTOMMARGIN
, fBottomMargin
);
380 // *** put style sheet into document ***
382 rDoc
.SetPageStyle( nScTab
, rStyleSheet
.GetName() );
384 // *** page breaks ***
386 for( const auto& rHorPageBreak
: maData
.maHorPageBreaks
)
388 SCROW nScRow
= static_cast< SCROW
>( rHorPageBreak
);
389 if( nScRow
<= rDoc
.MaxRow() )
390 rDoc
.SetRowBreak(nScRow
, nScTab
, false, true);
393 for( const auto& rVerPageBreak
: maData
.maVerPageBreaks
)
395 SCCOL nScCol
= static_cast< SCCOL
>( rVerPageBreak
);
396 if( nScCol
<= rDoc
.MaxCol() )
397 rDoc
.SetColBreak(nScCol
, nScTab
, false, true);
401 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */