1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20 #include <xipage.hxx>
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 <unotools/configmgr.hxx>
32 #include <document.hxx>
33 #include <stlsheet.hxx>
34 #include <attrib.hxx>
35 #include <xistream.hxx>
36 #include <xihelper.hxx>
37 #include <xiescher.hxx>
38
39 // Page settings ==============================================================
40
XclImpPageSettings(const XclImpRoot & rRoot)41 XclImpPageSettings::XclImpPageSettings( const XclImpRoot& rRoot ) :
42 XclImpRoot( rRoot )
43 {
44 Initialize();
45 }
46
Initialize()47 void XclImpPageSettings::Initialize()
48 {
49 maData.SetDefaults();
50 mbValidPaper = false;
51 }
52
ReadSetup(XclImpStream & rStrm)53 void XclImpPageSettings::ReadSetup( XclImpStream& rStrm )
54 {
55 OSL_ENSURE_BIFF( GetBiff() >= EXC_BIFF4 );
56 if( GetBiff() < EXC_BIFF4 )
57 return;
58
59 // BIFF4 - BIFF8
60 sal_uInt16 nFlags;
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();
67
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;
73
74 // new in BIFF5 - BIFF8
75 if( GetBiff() >= EXC_BIFF5 )
76 {
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();
82
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 );
86 }
87 }
88
ReadMargin(XclImpStream & rStrm)89 void XclImpPageSettings::ReadMargin( XclImpStream& rStrm )
90 {
91 switch( rStrm.GetRecId() )
92 {
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" );
98 }
99 }
100
ReadCenter(XclImpStream & rStrm)101 void XclImpPageSettings::ReadCenter( XclImpStream& rStrm )
102 {
103 OSL_ENSURE_BIFF( GetBiff() >= EXC_BIFF3 ); // read it anyway
104 bool bCenter = (rStrm.ReaduInt16() != 0);
105 switch( rStrm.GetRecId() )
106 {
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" );
110 }
111 }
112
ReadHeaderFooter(XclImpStream & rStrm)113 void XclImpPageSettings::ReadHeaderFooter( XclImpStream& rStrm )
114 {
115 OUString aString;
116 if( rStrm.GetRecLeft() )
117 aString = (GetBiff() <= EXC_BIFF5) ? rStrm.ReadByteString( false ) : rStrm.ReadUniString();
118
119 switch( rStrm.GetRecId() )
120 {
121 case EXC_ID_HEADER: maData.maHeader = aString; break;
122 case EXC_ID_FOOTER: maData.maFooter = aString; break;
123 default: OSL_FAIL( "XclImpPageSettings::ReadHeaderFooter - unknown record" );
124 }
125
126 if (maData.maHeader.getLength() > 10 && utl::ConfigManager::IsFuzzing())
127 maData.maHeader = maData.maHeader.copy(0, 10);
128 }
129
ReadPageBreaks(XclImpStream & rStrm)130 void XclImpPageSettings::ReadPageBreaks( XclImpStream& rStrm )
131 {
132 ScfUInt16Vec* pVec = nullptr;
133 switch( rStrm.GetRecId() )
134 {
135 case EXC_ID_HORPAGEBREAKS: pVec = &maData.maHorPageBreaks; break;
136 case EXC_ID_VERPAGEBREAKS: pVec = &maData.maVerPageBreaks; break;
137 default: OSL_FAIL( "XclImpPageSettings::ReadPageBreaks - unknown record" );
138 }
139
140 if( pVec )
141 {
142 bool bIgnore = GetBiff() == EXC_BIFF8; // ignore start/end columns or rows in BIFF8
143
144 sal_uInt16 nCount, nBreak;
145 nCount = rStrm.ReaduInt16();
146 pVec->clear();
147 pVec->reserve( nCount );
148
149 while( nCount-- )
150 {
151 nBreak = rStrm.ReaduInt16();
152 if( nBreak )
153 pVec->push_back( nBreak );
154 if( bIgnore )
155 rStrm.Ignore( 4 );
156 }
157 }
158 }
159
ReadPrintHeaders(XclImpStream & rStrm)160 void XclImpPageSettings::ReadPrintHeaders( XclImpStream& rStrm )
161 {
162 maData.mbPrintHeadings = (rStrm.ReaduInt16() != 0);
163 }
164
ReadPrintGridLines(XclImpStream & rStrm)165 void XclImpPageSettings::ReadPrintGridLines( XclImpStream& rStrm )
166 {
167 maData.mbPrintGrid = (rStrm.ReaduInt16() != 0);
168 }
169
ReadImgData(XclImpStream & rStrm)170 void XclImpPageSettings::ReadImgData( XclImpStream& rStrm )
171 {
172 Graphic aGraphic = XclImpDrawing::ReadImgData( GetRoot(), rStrm );
173 if( aGraphic.GetType() != GraphicType::NONE )
174 maData.mxBrushItem.reset( new SvxBrushItem( aGraphic, GPOS_TILED, ATTR_BACKGROUND ) );
175 }
176
SetPaperSize(sal_uInt16 nXclPaperSize,bool bPortrait)177 void XclImpPageSettings::SetPaperSize( sal_uInt16 nXclPaperSize, bool bPortrait )
178 {
179 maData.mnPaperSize = nXclPaperSize;
180 maData.mbPortrait = bPortrait;
181 mbValidPaper = true;
182 }
183
184 namespace {
185
lclPutMarginItem(SfxItemSet & rItemSet,sal_uInt16 nRecId,double fMarginInch)186 void lclPutMarginItem( SfxItemSet& rItemSet, sal_uInt16 nRecId, double fMarginInch )
187 {
188 sal_uInt16 nMarginTwips = XclTools::GetTwipsFromInch( fMarginInch );
189 switch( nRecId )
190 {
191 case EXC_ID_TOPMARGIN:
192 case EXC_ID_BOTTOMMARGIN:
193 {
194 SvxULSpaceItem aItem( rItemSet.Get( ATTR_ULSPACE ) );
195 if( nRecId == EXC_ID_TOPMARGIN )
196 aItem.SetUpperValue( nMarginTwips );
197 else
198 aItem.SetLowerValue( nMarginTwips );
199 rItemSet.Put( aItem );
200 }
201 break;
202 case EXC_ID_LEFTMARGIN:
203 case EXC_ID_RIGHTMARGIN:
204 {
205 SvxLRSpaceItem aItem( rItemSet.Get( ATTR_LRSPACE ) );
206 if( nRecId == EXC_ID_LEFTMARGIN )
207 aItem.SetLeftValue( nMarginTwips );
208 else
209 aItem.SetRightValue( nMarginTwips );
210 rItemSet.Put( aItem );
211 }
212 break;
213 default:
214 OSL_FAIL( "XclImpPageSettings::SetMarginItem - unknown record id" );
215 }
216 }
217
218 } // namespace
219
Finalize()220 void XclImpPageSettings::Finalize()
221 {
222 ScDocument& rDoc = GetDoc();
223 SCTAB nScTab = GetCurrScTab();
224
225 // *** create page style sheet ***
226
227 OUString aStyleName;
228 OUString aTableName;
229 if( GetDoc().GetName( nScTab, aTableName ) )
230 aStyleName = "PageStyle_" + aTableName;
231 else
232 aStyleName = "PageStyle_" + OUString::number(static_cast<sal_Int32>(nScTab+1));
233
234 ScStyleSheet& rStyleSheet = ScfTools::MakePageStyleSheet(
235 GetStyleSheetPool(), aStyleName, false);
236
237 SfxItemSet& rItemSet = rStyleSheet.GetItemSet();
238
239 // *** page settings ***
240
241 ScfTools::PutItem( rItemSet, SfxBoolItem( ATTR_PAGE_TOPDOWN, !maData.mbPrintInRows ), true );
242 ScfTools::PutItem( rItemSet, SfxBoolItem( ATTR_PAGE_HORCENTER, maData.mbHorCenter ), true );
243 ScfTools::PutItem( rItemSet, SfxBoolItem( ATTR_PAGE_VERCENTER, maData.mbVerCenter ), true );
244 ScfTools::PutItem( rItemSet, SfxBoolItem( ATTR_PAGE_HEADERS, maData.mbPrintHeadings ), true );
245 ScfTools::PutItem( rItemSet, SfxBoolItem( ATTR_PAGE_GRID, maData.mbPrintGrid ), true );
246 ScfTools::PutItem( rItemSet, SfxBoolItem( ATTR_PAGE_NOTES, maData.mbPrintNotes ), true );
247
248 sal_uInt16 nStartPage = maData.mbManualStart ? maData.mnStartPage : 0;
249 ScfTools::PutItem( rItemSet, SfxUInt16Item( ATTR_PAGE_FIRSTPAGENO, nStartPage ), true );
250
251 if( maData.mxBrushItem.get() )
252 rItemSet.Put( *maData.mxBrushItem );
253
254 if( mbValidPaper )
255 {
256 SvxPageItem aPageItem( rItemSet.Get( ATTR_PAGE ) );
257 aPageItem.SetLandscape( !maData.mbPortrait );
258 rItemSet.Put( aPageItem );
259 ScfTools::PutItem( rItemSet, SvxSizeItem( ATTR_PAGE_SIZE, maData.GetScPaperSize() ), true );
260 }
261
262 if( maData.mbFitToPages )
263 rItemSet.Put( ScPageScaleToItem( maData.mnFitToWidth, maData.mnFitToHeight ) );
264 else if( maData.mbValid )
265 rItemSet.Put( SfxUInt16Item( ATTR_PAGE_SCALE, maData.mnScaling ) );
266
267 // *** margin preparations ***
268
269 double fLeftMargin = maData.mfLeftMargin;
270 double fRightMargin = maData.mfRightMargin;
271 double fTopMargin = maData.mfTopMargin;
272 double fBottomMargin = maData.mfBottomMargin;
273 // distances between header/footer and page area
274 double fHeaderHeight = 0.0;
275 double fHeaderDist = 0.0;
276 double fFooterHeight = 0.0;
277 double fFooterDist = 0.0;
278 // in Calc, "header/footer left/right margin" is X distance between header/footer and page margin
279 double fHdrLeftMargin = maData.mfHdrLeftMargin - maData.mfLeftMargin;
280 double fHdrRightMargin = maData.mfHdrRightMargin - maData.mfRightMargin;
281 double fFtrLeftMargin = maData.mfFtrLeftMargin - maData.mfLeftMargin;
282 double fFtrRightMargin = maData.mfFtrRightMargin - maData.mfRightMargin;
283
284 // *** header and footer ***
285
286 XclImpHFConverter aHFConv( GetRoot() );
287
288 // header
289 bool bHasHeader = !maData.maHeader.isEmpty();
290 SvxSetItem aHdrSetItem( rItemSet.Get( ATTR_PAGE_HEADERSET ) );
291 SfxItemSet& rHdrItemSet = aHdrSetItem.GetItemSet();
292 rHdrItemSet.Put( SfxBoolItem( ATTR_PAGE_ON, bHasHeader ) );
293 if( bHasHeader )
294 {
295 aHFConv.ParseString( maData.maHeader );
296 aHFConv.FillToItemSet( rItemSet, ATTR_PAGE_HEADERLEFT );
297 aHFConv.FillToItemSet( rItemSet, ATTR_PAGE_HEADERRIGHT );
298 // #i23296# In Calc, "top margin" is distance to header
299 fTopMargin = maData.mfHeaderMargin;
300 // Calc uses distance between header and sheet data area
301 fHeaderHeight = XclTools::GetInchFromTwips( aHFConv.GetTotalHeight() );
302 fHeaderDist = maData.mfTopMargin - maData.mfHeaderMargin - fHeaderHeight;
303 }
304 if( fHeaderDist < 0.0 )
305 {
306 /* #i23296# Header overlays sheet data:
307 -> set fixed header height to get correct sheet data position. */
308 ScfTools::PutItem( rHdrItemSet, SfxBoolItem( ATTR_PAGE_DYNAMIC, false ), true );
309 // shrink header height
310 long nHdrHeight = XclTools::GetTwipsFromInch( fHeaderHeight + fHeaderDist );
311 ScfTools::PutItem( rHdrItemSet, SvxSizeItem( ATTR_PAGE_SIZE, Size( 0, nHdrHeight ) ), true );
312 lclPutMarginItem( rHdrItemSet, EXC_ID_BOTTOMMARGIN, 0.0 );
313 }
314 else
315 {
316 // use dynamic header height
317 ScfTools::PutItem( rHdrItemSet, SfxBoolItem( ATTR_PAGE_DYNAMIC, true ), true );
318 lclPutMarginItem( rHdrItemSet, EXC_ID_BOTTOMMARGIN, fHeaderDist );
319 }
320 lclPutMarginItem( rHdrItemSet, EXC_ID_LEFTMARGIN, fHdrLeftMargin );
321 lclPutMarginItem( rHdrItemSet, EXC_ID_RIGHTMARGIN, fHdrRightMargin );
322 rItemSet.Put( aHdrSetItem );
323
324 // footer
325 bool bHasFooter = !maData.maFooter.isEmpty();
326 SvxSetItem aFtrSetItem( rItemSet.Get( ATTR_PAGE_FOOTERSET ) );
327 SfxItemSet& rFtrItemSet = aFtrSetItem.GetItemSet();
328 rFtrItemSet.Put( SfxBoolItem( ATTR_PAGE_ON, bHasFooter ) );
329 if( bHasFooter )
330 {
331 aHFConv.ParseString( maData.maFooter );
332 aHFConv.FillToItemSet( rItemSet, ATTR_PAGE_FOOTERLEFT );
333 aHFConv.FillToItemSet( rItemSet, ATTR_PAGE_FOOTERRIGHT );
334 // #i23296# In Calc, "bottom margin" is distance to footer
335 fBottomMargin = maData.mfFooterMargin;
336 // Calc uses distance between footer and sheet data area
337 fFooterHeight = XclTools::GetInchFromTwips( aHFConv.GetTotalHeight() );
338 fFooterDist = maData.mfBottomMargin - maData.mfFooterMargin - fFooterHeight;
339 }
340 if( fFooterDist < 0.0 )
341 {
342 /* #i23296# Footer overlays sheet data:
343 -> set fixed footer height to get correct sheet data end position. */
344 ScfTools::PutItem( rFtrItemSet, SfxBoolItem( ATTR_PAGE_DYNAMIC, false ), true );
345 // shrink footer height
346 long nFtrHeight = XclTools::GetTwipsFromInch( fFooterHeight + fFooterDist );
347 ScfTools::PutItem( rFtrItemSet, SvxSizeItem( ATTR_PAGE_SIZE, Size( 0, nFtrHeight ) ), true );
348 lclPutMarginItem( rFtrItemSet, EXC_ID_TOPMARGIN, 0.0 );
349 }
350 else
351 {
352 // use dynamic footer height
353 ScfTools::PutItem( rFtrItemSet, SfxBoolItem( ATTR_PAGE_DYNAMIC, true ), true );
354 lclPutMarginItem( rFtrItemSet, EXC_ID_TOPMARGIN, fFooterDist );
355 }
356 lclPutMarginItem( rFtrItemSet, EXC_ID_LEFTMARGIN, fFtrLeftMargin );
357 lclPutMarginItem( rFtrItemSet, EXC_ID_RIGHTMARGIN, fFtrRightMargin );
358 rItemSet.Put( aFtrSetItem );
359
360 // *** set final margins ***
361
362 lclPutMarginItem( rItemSet, EXC_ID_LEFTMARGIN, fLeftMargin );
363 lclPutMarginItem( rItemSet, EXC_ID_RIGHTMARGIN, fRightMargin );
364 lclPutMarginItem( rItemSet, EXC_ID_TOPMARGIN, fTopMargin );
365 lclPutMarginItem( rItemSet, EXC_ID_BOTTOMMARGIN, fBottomMargin );
366
367 // *** put style sheet into document ***
368
369 rDoc.SetPageStyle( nScTab, rStyleSheet.GetName() );
370
371 // *** page breaks ***
372
373 for( const auto& rHorPageBreak : maData.maHorPageBreaks )
374 {
375 SCROW nScRow = static_cast< SCROW >( rHorPageBreak );
376 if( nScRow <= rDoc.MaxRow() )
377 rDoc.SetRowBreak(nScRow, nScTab, false, true);
378 }
379
380 for( const auto& rVerPageBreak : maData.maVerPageBreaks )
381 {
382 SCCOL nScCol = static_cast< SCCOL >( rVerPageBreak );
383 if( nScCol <= rDoc.MaxCol() )
384 rDoc.SetColBreak(nScCol, nScTab, false, true);
385 }
386 }
387
388 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
389