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 #include "oox/xls/pagesettings.hxx"
25
26 #include <algorithm>
27 #include <set>
28 #include <com/sun/star/awt/Size.hpp>
29 #include <com/sun/star/container/XNamed.hpp>
30 #include <com/sun/star/sheet/XHeaderFooterContent.hpp>
31 #include <com/sun/star/style/GraphicLocation.hpp>
32 #include <com/sun/star/text/FilenameDisplayFormat.hpp>
33 #include <com/sun/star/text/XText.hpp>
34 #include <com/sun/star/text/XTextContent.hpp>
35 #include <com/sun/star/text/XTextCursor.hpp>
36 #include <rtl/strbuf.hxx>
37 #include <rtl/ustrbuf.hxx>
38 #include "oox/core/xmlfilterbase.hxx"
39 #include "oox/helper/attributelist.hxx"
40 #include "oox/helper/graphichelper.hxx"
41 #include "oox/helper/propertymap.hxx"
42 #include "oox/helper/propertyset.hxx"
43 #include "oox/xls/biffinputstream.hxx"
44 #include "oox/xls/excelhandlers.hxx"
45 #include "oox/xls/stylesbuffer.hxx"
46 #include "oox/xls/unitconverter.hxx"
47
48 namespace oox {
49 namespace xls {
50
51 // ============================================================================
52
53 using namespace ::com::sun::star::awt;
54 using namespace ::com::sun::star::container;
55 using namespace ::com::sun::star::lang;
56 using namespace ::com::sun::star::sheet;
57 using namespace ::com::sun::star::style;
58 using namespace ::com::sun::star::text;
59 using namespace ::com::sun::star::uno;
60
61 using ::oox::core::Relations;
62 using ::rtl::OString;
63 using ::rtl::OStringBuffer;
64 using ::rtl::OUString;
65 using ::rtl::OUStringBuffer;
66
67 // ============================================================================
68
69 namespace {
70
71 const double OOX_MARGIN_DEFAULT_LR = 0.748; /// Left/right default margin in inches.
72 const double OOX_MARGIN_DEFAULT_TB = 0.984; /// Top/bottom default margin in inches.
73 const double OOX_MARGIN_DEFAULT_HF = 0.512; /// Header/footer default margin in inches.
74
75 const sal_uInt16 BIFF12_PRINTOPT_HORCENTER = 0x0001;
76 const sal_uInt16 BIFF12_PRINTOPT_VERCENTER = 0x0002;
77 const sal_uInt16 BIFF12_PRINTOPT_PRINTHEADING = 0x0004;
78 const sal_uInt16 BIFF12_PRINTOPT_PRINTGRID = 0x0008;
79
80 const sal_uInt16 BIFF12_HEADERFOOTER_DIFFEVEN = 0x0001;
81 const sal_uInt16 BIFF12_HEADERFOOTER_DIFFFIRST = 0x0002;
82 const sal_uInt16 BIFF12_HEADERFOOTER_SCALEDOC = 0x0004;
83 const sal_uInt16 BIFF12_HEADERFOOTER_ALIGNMARGIN = 0x0008;
84
85 const sal_uInt16 BIFF12_PAGESETUP_INROWS = 0x0001;
86 const sal_uInt16 BIFF12_PAGESETUP_LANDSCAPE = 0x0002;
87 const sal_uInt16 BIFF12_PAGESETUP_INVALID = 0x0004;
88 const sal_uInt16 BIFF12_PAGESETUP_BLACKWHITE = 0x0008;
89 const sal_uInt16 BIFF12_PAGESETUP_DRAFTQUALITY = 0x0010;
90 const sal_uInt16 BIFF12_PAGESETUP_PRINTNOTES = 0x0020;
91 const sal_uInt16 BIFF12_PAGESETUP_DEFAULTORIENT = 0x0040;
92 const sal_uInt16 BIFF12_PAGESETUP_USEFIRSTPAGE = 0x0080;
93 const sal_uInt16 BIFF12_PAGESETUP_NOTES_END = 0x0100; // different to BIFF flag
94
95 const sal_uInt16 BIFF12_CHARTPAGESETUP_LANDSCAPE = 0x0001;
96 const sal_uInt16 BIFF12_CHARTPAGESETUP_INVALID = 0x0002;
97 const sal_uInt16 BIFF12_CHARTPAGESETUP_BLACKWHITE = 0x0004;
98 const sal_uInt16 BIFF12_CHARTPAGESETUP_DEFAULTORIENT= 0x0008;
99 const sal_uInt16 BIFF12_CHARTPAGESETUP_USEFIRSTPAGE = 0x0010;
100 const sal_uInt16 BIFF12_CHARTPAGESETUP_DRAFTQUALITY = 0x0020;
101
102 const sal_uInt16 BIFF_PAGESETUP_INROWS = 0x0001;
103 const sal_uInt16 BIFF_PAGESETUP_PORTRAIT = 0x0002;
104 const sal_uInt16 BIFF_PAGESETUP_INVALID = 0x0004;
105 const sal_uInt16 BIFF_PAGESETUP_BLACKWHITE = 0x0008;
106 const sal_uInt16 BIFF_PAGESETUP_DRAFTQUALITY = 0x0010;
107 const sal_uInt16 BIFF_PAGESETUP_PRINTNOTES = 0x0020;
108 const sal_uInt16 BIFF_PAGESETUP_DEFAULTORIENT = 0x0040;
109 const sal_uInt16 BIFF_PAGESETUP_USEFIRSTPAGE = 0x0080;
110 const sal_uInt16 BIFF_PAGESETUP_NOTES_END = 0x0200;
111
112 } // namespace
113
114 // ============================================================================
115
PageSettingsModel()116 PageSettingsModel::PageSettingsModel() :
117 mfLeftMargin( OOX_MARGIN_DEFAULT_LR ),
118 mfRightMargin( OOX_MARGIN_DEFAULT_LR ),
119 mfTopMargin( OOX_MARGIN_DEFAULT_TB ),
120 mfBottomMargin( OOX_MARGIN_DEFAULT_TB ),
121 mfHeaderMargin( OOX_MARGIN_DEFAULT_HF ),
122 mfFooterMargin( OOX_MARGIN_DEFAULT_HF ),
123 mnPaperSize( 1 ),
124 mnCopies( 1 ),
125 mnScale( 100 ),
126 mnFirstPage( 1 ),
127 mnFitToWidth( 1 ),
128 mnFitToHeight( 1 ),
129 mnHorPrintRes( 600 ),
130 mnVerPrintRes( 600 ),
131 mnOrientation( XML_default ),
132 mnPageOrder( XML_downThenOver ),
133 mnCellComments( XML_none ),
134 mnPrintErrors( XML_displayed ),
135 mbUseEvenHF( false ),
136 mbUseFirstHF( false ),
137 mbValidSettings( true ),
138 mbUseFirstPage( false ),
139 mbBlackWhite( false ),
140 mbDraftQuality( false ),
141 mbFitToPages( false ),
142 mbHorCenter( false ),
143 mbVerCenter( false ),
144 mbPrintGrid( false ),
145 mbPrintHeadings( false )
146 {
147 }
148
setBiffPrintErrors(sal_uInt8 nPrintErrors)149 void PageSettingsModel::setBiffPrintErrors( sal_uInt8 nPrintErrors )
150 {
151 static const sal_Int32 spnErrorIds[] = { XML_displayed, XML_none, XML_dash, XML_NA };
152 mnPrintErrors = STATIC_ARRAY_SELECT( spnErrorIds, nPrintErrors, XML_none );
153 }
154
155 // ============================================================================
156
PageSettings(const WorksheetHelper & rHelper)157 PageSettings::PageSettings( const WorksheetHelper& rHelper ) :
158 WorksheetHelper( rHelper )
159 {
160 }
161
importPrintOptions(const AttributeList & rAttribs)162 void PageSettings::importPrintOptions( const AttributeList& rAttribs )
163 {
164 maModel.mbHorCenter = rAttribs.getBool( XML_horizontalCentered, false );
165 maModel.mbVerCenter = rAttribs.getBool( XML_verticalCentered, false );
166 maModel.mbPrintGrid = rAttribs.getBool( XML_gridLines, false );
167 maModel.mbPrintHeadings = rAttribs.getBool( XML_headings, false );
168 }
169
importPageMargins(const AttributeList & rAttribs)170 void PageSettings::importPageMargins( const AttributeList& rAttribs )
171 {
172 maModel.mfLeftMargin = rAttribs.getDouble( XML_left, OOX_MARGIN_DEFAULT_LR );
173 maModel.mfRightMargin = rAttribs.getDouble( XML_right, OOX_MARGIN_DEFAULT_LR );
174 maModel.mfTopMargin = rAttribs.getDouble( XML_top, OOX_MARGIN_DEFAULT_TB );
175 maModel.mfBottomMargin = rAttribs.getDouble( XML_bottom, OOX_MARGIN_DEFAULT_TB );
176 maModel.mfHeaderMargin = rAttribs.getDouble( XML_header, OOX_MARGIN_DEFAULT_HF );
177 maModel.mfFooterMargin = rAttribs.getDouble( XML_footer, OOX_MARGIN_DEFAULT_HF );
178 }
179
importPageSetup(const Relations & rRelations,const AttributeList & rAttribs)180 void PageSettings::importPageSetup( const Relations& rRelations, const AttributeList& rAttribs )
181 {
182 maModel.maBinSettPath = rRelations.getFragmentPathFromRelId( rAttribs.getString( R_TOKEN( id ), OUString() ) );
183 maModel.mnPaperSize = rAttribs.getInteger( XML_paperSize, 1 );
184 maModel.mnCopies = rAttribs.getInteger( XML_copies, 1 );
185 maModel.mnScale = rAttribs.getInteger( XML_scale, 100 );
186 maModel.mnFirstPage = rAttribs.getInteger( XML_firstPageNumber, 1 );
187 maModel.mnFitToWidth = rAttribs.getInteger( XML_fitToWidth, 1 );
188 maModel.mnFitToHeight = rAttribs.getInteger( XML_fitToHeight, 1 );
189 maModel.mnHorPrintRes = rAttribs.getInteger( XML_horizontalDpi, 600 );
190 maModel.mnVerPrintRes = rAttribs.getInteger( XML_verticalDpi, 600 );
191 maModel.mnOrientation = rAttribs.getToken( XML_orientation, XML_default );
192 maModel.mnPageOrder = rAttribs.getToken( XML_pageOrder, XML_downThenOver );
193 maModel.mnCellComments = rAttribs.getToken( XML_cellComments, XML_none );
194 maModel.mnPrintErrors = rAttribs.getToken( XML_errors, XML_displayed );
195 maModel.mbValidSettings = rAttribs.getBool( XML_usePrinterDefaults, true );
196 maModel.mbUseFirstPage = rAttribs.getBool( XML_useFirstPageNumber, false );
197 maModel.mbBlackWhite = rAttribs.getBool( XML_blackAndWhite, false );
198 maModel.mbDraftQuality = rAttribs.getBool( XML_draft, false );
199 }
200
importChartPageSetup(const Relations & rRelations,const AttributeList & rAttribs)201 void PageSettings::importChartPageSetup( const Relations& rRelations, const AttributeList& rAttribs )
202 {
203 maModel.maBinSettPath = rRelations.getFragmentPathFromRelId( rAttribs.getString( R_TOKEN( id ), OUString() ) );
204 maModel.mnPaperSize = rAttribs.getInteger( XML_paperSize, 1 );
205 maModel.mnCopies = rAttribs.getInteger( XML_copies, 1 );
206 maModel.mnFirstPage = rAttribs.getInteger( XML_firstPageNumber, 1 );
207 maModel.mnHorPrintRes = rAttribs.getInteger( XML_horizontalDpi, 600 );
208 maModel.mnVerPrintRes = rAttribs.getInteger( XML_verticalDpi, 600 );
209 maModel.mnOrientation = rAttribs.getToken( XML_orientation, XML_default );
210 maModel.mbValidSettings = rAttribs.getBool( XML_usePrinterDefaults, true );
211 maModel.mbUseFirstPage = rAttribs.getBool( XML_useFirstPageNumber, false );
212 maModel.mbBlackWhite = rAttribs.getBool( XML_blackAndWhite, false );
213 maModel.mbDraftQuality = rAttribs.getBool( XML_draft, false );
214 }
215
importHeaderFooter(const AttributeList & rAttribs)216 void PageSettings::importHeaderFooter( const AttributeList& rAttribs )
217 {
218 maModel.mbUseEvenHF = rAttribs.getBool( XML_differentOddEven, false );
219 maModel.mbUseFirstHF = rAttribs.getBool( XML_differentFirst, false );
220 }
221
importHeaderFooterCharacters(const OUString & rChars,sal_Int32 nElement)222 void PageSettings::importHeaderFooterCharacters( const OUString& rChars, sal_Int32 nElement )
223 {
224 switch( nElement )
225 {
226 case XLS_TOKEN( oddHeader ): maModel.maOddHeader += rChars; break;
227 case XLS_TOKEN( oddFooter ): maModel.maOddFooter += rChars; break;
228 case XLS_TOKEN( evenHeader ): maModel.maEvenHeader += rChars; break;
229 case XLS_TOKEN( evenFooter ): maModel.maEvenFooter += rChars; break;
230 case XLS_TOKEN( firstHeader ): maModel.maFirstHeader += rChars; break;
231 case XLS_TOKEN( firstFooter ): maModel.maFirstFooter += rChars; break;
232 }
233 }
234
importPicture(const Relations & rRelations,const AttributeList & rAttribs)235 void PageSettings::importPicture( const Relations& rRelations, const AttributeList& rAttribs )
236 {
237 importPictureData( rRelations, rAttribs.getString( R_TOKEN( id ), OUString() ) );
238 }
239
importPageMargins(SequenceInputStream & rStrm)240 void PageSettings::importPageMargins( SequenceInputStream& rStrm )
241 {
242 rStrm >> maModel.mfLeftMargin >> maModel.mfRightMargin
243 >> maModel.mfTopMargin >> maModel.mfBottomMargin
244 >> maModel.mfHeaderMargin >> maModel.mfFooterMargin;
245 }
246
importPrintOptions(SequenceInputStream & rStrm)247 void PageSettings::importPrintOptions( SequenceInputStream& rStrm )
248 {
249 sal_uInt16 nFlags;
250 rStrm >> nFlags;
251 maModel.mbHorCenter = getFlag( nFlags, BIFF12_PRINTOPT_HORCENTER );
252 maModel.mbVerCenter = getFlag( nFlags, BIFF12_PRINTOPT_VERCENTER );
253 maModel.mbPrintGrid = getFlag( nFlags, BIFF12_PRINTOPT_PRINTGRID );
254 maModel.mbPrintHeadings = getFlag( nFlags, BIFF12_PRINTOPT_PRINTHEADING );
255 }
256
importPageSetup(const Relations & rRelations,SequenceInputStream & rStrm)257 void PageSettings::importPageSetup( const Relations& rRelations, SequenceInputStream& rStrm )
258 {
259 OUString aRelId;
260 sal_uInt16 nFlags;
261 rStrm >> maModel.mnPaperSize >> maModel.mnScale
262 >> maModel.mnHorPrintRes >> maModel.mnVerPrintRes
263 >> maModel.mnCopies >> maModel.mnFirstPage
264 >> maModel.mnFitToWidth >> maModel.mnFitToHeight
265 >> nFlags >> aRelId;
266 maModel.setBiffPrintErrors( extractValue< sal_uInt8 >( nFlags, 9, 2 ) );
267 maModel.maBinSettPath = rRelations.getFragmentPathFromRelId( aRelId );
268 maModel.mnOrientation = getFlagValue( nFlags, BIFF12_PAGESETUP_DEFAULTORIENT, XML_default, getFlagValue( nFlags, BIFF12_PAGESETUP_LANDSCAPE, XML_landscape, XML_portrait ) );
269 maModel.mnPageOrder = getFlagValue( nFlags, BIFF12_PAGESETUP_INROWS, XML_overThenDown, XML_downThenOver );
270 maModel.mnCellComments = getFlagValue( nFlags, BIFF12_PAGESETUP_PRINTNOTES, getFlagValue( nFlags, BIFF12_PAGESETUP_NOTES_END, XML_atEnd, XML_asDisplayed ), XML_none );
271 maModel.mbValidSettings = !getFlag( nFlags, BIFF12_PAGESETUP_INVALID );
272 maModel.mbUseFirstPage = getFlag( nFlags, BIFF12_PAGESETUP_USEFIRSTPAGE );
273 maModel.mbBlackWhite = getFlag( nFlags, BIFF12_PAGESETUP_BLACKWHITE );
274 maModel.mbDraftQuality = getFlag( nFlags, BIFF12_PAGESETUP_DRAFTQUALITY );
275 }
276
importChartPageSetup(const Relations & rRelations,SequenceInputStream & rStrm)277 void PageSettings::importChartPageSetup( const Relations& rRelations, SequenceInputStream& rStrm )
278 {
279 OUString aRelId;
280 sal_uInt16 nFirstPage, nFlags;
281 rStrm >> maModel.mnPaperSize >> maModel.mnHorPrintRes >> maModel.mnVerPrintRes
282 >> maModel.mnCopies >> nFirstPage >> nFlags >> aRelId;
283 maModel.maBinSettPath = rRelations.getFragmentPathFromRelId( aRelId );
284 maModel.mnFirstPage = nFirstPage; // 16-bit in CHARTPAGESETUP
285 maModel.mnOrientation = getFlagValue( nFlags, BIFF12_CHARTPAGESETUP_DEFAULTORIENT, XML_default, getFlagValue( nFlags, BIFF12_CHARTPAGESETUP_LANDSCAPE, XML_landscape, XML_portrait ) );
286 maModel.mbValidSettings = !getFlag( nFlags, BIFF12_CHARTPAGESETUP_INVALID );
287 maModel.mbUseFirstPage = getFlag( nFlags, BIFF12_CHARTPAGESETUP_USEFIRSTPAGE );
288 maModel.mbBlackWhite = getFlag( nFlags, BIFF12_CHARTPAGESETUP_BLACKWHITE );
289 maModel.mbDraftQuality = getFlag( nFlags, BIFF12_CHARTPAGESETUP_DRAFTQUALITY );
290 }
291
importHeaderFooter(SequenceInputStream & rStrm)292 void PageSettings::importHeaderFooter( SequenceInputStream& rStrm )
293 {
294 sal_uInt16 nFlags;
295 rStrm >> nFlags
296 >> maModel.maOddHeader >> maModel.maOddFooter
297 >> maModel.maEvenHeader >> maModel.maEvenFooter
298 >> maModel.maFirstHeader >> maModel.maFirstFooter;
299 maModel.mbUseEvenHF = getFlag( nFlags, BIFF12_HEADERFOOTER_DIFFEVEN );
300 maModel.mbUseFirstHF = getFlag( nFlags, BIFF12_HEADERFOOTER_DIFFFIRST );
301 }
302
importPicture(const Relations & rRelations,SequenceInputStream & rStrm)303 void PageSettings::importPicture( const Relations& rRelations, SequenceInputStream& rStrm )
304 {
305 importPictureData( rRelations, BiffHelper::readString( rStrm ) );
306 }
307
importLeftMargin(BiffInputStream & rStrm)308 void PageSettings::importLeftMargin( BiffInputStream& rStrm )
309 {
310 rStrm >> maModel.mfLeftMargin;
311 }
312
importRightMargin(BiffInputStream & rStrm)313 void PageSettings::importRightMargin( BiffInputStream& rStrm )
314 {
315 rStrm >> maModel.mfRightMargin;
316 }
317
importTopMargin(BiffInputStream & rStrm)318 void PageSettings::importTopMargin( BiffInputStream& rStrm )
319 {
320 rStrm >> maModel.mfTopMargin;
321 }
322
importBottomMargin(BiffInputStream & rStrm)323 void PageSettings::importBottomMargin( BiffInputStream& rStrm )
324 {
325 rStrm >> maModel.mfBottomMargin;
326 }
327
importPageSetup(BiffInputStream & rStrm)328 void PageSettings::importPageSetup( BiffInputStream& rStrm )
329 {
330 sal_uInt16 nPaperSize, nScale, nFirstPage, nFitToWidth, nFitToHeight, nFlags;
331 rStrm >> nPaperSize >> nScale >> nFirstPage >> nFitToWidth >> nFitToHeight >> nFlags;
332
333 maModel.mnPaperSize = nPaperSize; // equal in BIFF and OOX
334 maModel.mnScale = nScale;
335 maModel.mnFirstPage = nFirstPage;
336 maModel.mnFitToWidth = nFitToWidth;
337 maModel.mnFitToHeight = nFitToHeight;
338 maModel.mnOrientation = getFlagValue( nFlags, BIFF_PAGESETUP_PORTRAIT, XML_portrait, XML_landscape );
339 maModel.mnPageOrder = getFlagValue( nFlags, BIFF_PAGESETUP_INROWS, XML_overThenDown, XML_downThenOver );
340 maModel.mbValidSettings = !getFlag( nFlags, BIFF_PAGESETUP_INVALID );
341 maModel.mbUseFirstPage = true;
342 maModel.mbBlackWhite = getFlag( nFlags, BIFF_PAGESETUP_BLACKWHITE );
343
344 if( getBiff() >= BIFF5 )
345 {
346 sal_uInt16 nHorPrintRes, nVerPrintRes, nCopies;
347 rStrm >> nHorPrintRes >> nVerPrintRes >> maModel.mfHeaderMargin >> maModel.mfFooterMargin >> nCopies;
348
349 maModel.mnCopies = nCopies;
350 maModel.mnOrientation = getFlagValue( nFlags, BIFF_PAGESETUP_DEFAULTORIENT, XML_default, maModel.mnOrientation );
351 maModel.mnHorPrintRes = nHorPrintRes;
352 maModel.mnVerPrintRes = nVerPrintRes;
353 maModel.mnCellComments = getFlagValue( nFlags, BIFF_PAGESETUP_PRINTNOTES, XML_asDisplayed, XML_none );
354 maModel.mbUseFirstPage = getFlag( nFlags, BIFF_PAGESETUP_USEFIRSTPAGE );
355 maModel.mbDraftQuality = getFlag( nFlags, BIFF_PAGESETUP_DRAFTQUALITY );
356
357 if( getBiff() == BIFF8 )
358 {
359 maModel.setBiffPrintErrors( extractValue< sal_uInt8 >( nFlags, 10, 2 ) );
360 maModel.mnCellComments = getFlagValue( nFlags, BIFF_PAGESETUP_PRINTNOTES, getFlagValue( nFlags, BIFF_PAGESETUP_NOTES_END, XML_atEnd, XML_asDisplayed ), XML_none );
361 }
362 }
363 }
364
importHorCenter(BiffInputStream & rStrm)365 void PageSettings::importHorCenter( BiffInputStream& rStrm )
366 {
367 maModel.mbHorCenter = rStrm.readuInt16() != 0;
368 }
369
importVerCenter(BiffInputStream & rStrm)370 void PageSettings::importVerCenter( BiffInputStream& rStrm )
371 {
372 maModel.mbVerCenter = rStrm.readuInt16() != 0;
373 }
374
importPrintHeaders(BiffInputStream & rStrm)375 void PageSettings::importPrintHeaders( BiffInputStream& rStrm )
376 {
377 maModel.mbPrintHeadings = rStrm.readuInt16() != 0;
378 }
379
importPrintGridLines(BiffInputStream & rStrm)380 void PageSettings::importPrintGridLines( BiffInputStream& rStrm )
381 {
382 maModel.mbPrintGrid = rStrm.readuInt16() != 0;
383 }
384
importHeader(BiffInputStream & rStrm)385 void PageSettings::importHeader( BiffInputStream& rStrm )
386 {
387 if( rStrm.getRemaining() > 0 )
388 maModel.maOddHeader = (getBiff() == BIFF8) ? rStrm.readUniString() : rStrm.readByteStringUC( false, getTextEncoding() );
389 else
390 maModel.maOddHeader = OUString();
391 }
392
importFooter(BiffInputStream & rStrm)393 void PageSettings::importFooter( BiffInputStream& rStrm )
394 {
395 if( rStrm.getRemaining() > 0 )
396 maModel.maOddFooter = (getBiff() == BIFF8) ? rStrm.readUniString() : rStrm.readByteStringUC( false, getTextEncoding() );
397 else
398 maModel.maOddFooter = OUString();
399 }
400
importPicture(BiffInputStream & rStrm)401 void PageSettings::importPicture( BiffInputStream& rStrm )
402 {
403 StreamDataSequence aPictureData;
404 BiffHelper::importImgData( aPictureData, rStrm, getBiff() );
405 maModel.maGraphicUrl = getBaseFilter().getGraphicHelper().importGraphicObject( aPictureData );
406 }
407
setFitToPagesMode(bool bFitToPages)408 void PageSettings::setFitToPagesMode( bool bFitToPages )
409 {
410 maModel.mbFitToPages = bFitToPages;
411 }
412
finalizeImport()413 void PageSettings::finalizeImport()
414 {
415 OUStringBuffer aStyleNameBuffer( CREATE_OUSTRING( "PageStyle_" ) );
416 Reference< XNamed > xSheetName( getSheet(), UNO_QUERY );
417 if( xSheetName.is() )
418 aStyleNameBuffer.append( xSheetName->getName() );
419 else
420 aStyleNameBuffer.append( static_cast< sal_Int32 >( getSheetIndex() + 1 ) );
421 OUString aStyleName = aStyleNameBuffer.makeStringAndClear();
422
423 Reference< XStyle > xStyle = createStyleObject( aStyleName, true );
424 PropertySet aStyleProps( xStyle );
425 getPageSettingsConverter().writePageSettingsProperties( aStyleProps, maModel, getSheetType() );
426
427 PropertySet aSheetProps( getSheet() );
428 aSheetProps.setProperty( PROP_PageStyle, aStyleName );
429 }
430
importPictureData(const Relations & rRelations,const OUString & rRelId)431 void PageSettings::importPictureData( const Relations& rRelations, const OUString& rRelId )
432 {
433 OUString aPicturePath = rRelations.getFragmentPathFromRelId( rRelId );
434 if( aPicturePath.getLength() > 0 )
435 maModel.maGraphicUrl = getBaseFilter().getGraphicHelper().importEmbeddedGraphicObject( aPicturePath );
436 }
437
438 // ============================================================================
439 // ============================================================================
440
441 enum HFPortionId
442 {
443 HF_LEFT,
444 HF_CENTER,
445 HF_RIGHT,
446 HF_COUNT
447 };
448
449 // ----------------------------------------------------------------------------
450
451 struct HFPortionInfo
452 {
453 Reference< XText > mxText; /// XText interface of this portion.
454 Reference< XTextCursor > mxStart; /// Start position of current text range for formatting.
455 Reference< XTextCursor > mxEnd; /// End position of current text range for formatting.
456 double mfTotalHeight; /// Sum of heights of previous lines in points.
457 double mfCurrHeight; /// Height of the current text line in points.
458
459 bool initialize( const Reference< XText >& rxText );
460 };
461
initialize(const Reference<XText> & rxText)462 bool HFPortionInfo::initialize( const Reference< XText >& rxText )
463 {
464 mfTotalHeight = mfCurrHeight = 0.0;
465 mxText = rxText;
466 if( mxText.is() )
467 {
468 mxStart = mxText->createTextCursor();
469 mxEnd = mxText->createTextCursor();
470 }
471 bool bRet = mxText.is() && mxStart.is() && mxEnd.is();
472 OSL_ENSURE( bRet, "HFPortionInfo::initialize - missing interfaces" );
473 return bRet;
474 }
475
476 // ============================================================================
477
478 class HeaderFooterParser : public WorkbookHelper
479 {
480 public:
481 explicit HeaderFooterParser( const WorkbookHelper& rHelper );
482
483 /** Parses the passed string and creates the header/footer contents.
484 @returns The total height of the converted header or footer in points. */
485 double parse(
486 const Reference< XHeaderFooterContent >& rxContext,
487 const OUString& rData );
488
489 private:
490 /** Returns the current edit engine text object. */
getPortion()491 inline HFPortionInfo& getPortion() { return maPortions[ meCurrPortion ]; }
492 /** Returns the start cursor of the current text range. */
getStartPos()493 inline const Reference< XTextCursor >& getStartPos() { return getPortion().mxStart; }
494 /** Returns the end cursor of the current text range. */
getEndPos()495 inline const Reference< XTextCursor >& getEndPos() { return getPortion().mxEnd; }
496
497 /** Returns the current line height of the specified portion. */
498 double getCurrHeight( HFPortionId ePortion ) const;
499 /** Returns the current line height. */
500 double getCurrHeight() const;
501
502 /** Updates the current line height of the specified portion, using the current font size. */
503 void updateCurrHeight( HFPortionId ePortion );
504 /** Updates the current line height, using the current font size. */
505 void updateCurrHeight();
506
507 /** Sets the font attributes at the current selection. */
508 void setAttributes();
509 /** Appends and clears internal string buffer. */
510 void appendText();
511 /** Appends a line break and adjusts internal text height data. */
512 void appendLineBreak();
513
514 /** Creates a text field from the passed service name. */
515 Reference< XTextContent > createField( const OUString& rServiceName ) const;
516 /** Appends the passed text field. */
517 void appendField( const Reference< XTextContent >& rxContent );
518
519 /** Sets the passed font name if it is valid. */
520 void convertFontName( const OUString& rStyle );
521 /** Converts a font style given as string. */
522 void convertFontStyle( const OUString& rStyle );
523 /** Converts a font color given as string. */
524 void convertFontColor( const OUString& rColor );
525
526 /** Finalizes current portion: sets font attributes and updates text height data. */
527 void finalizePortion();
528 /** Changes current header/footer portion. */
529 void setNewPortion( HFPortionId ePortion );
530
531 private:
532 typedef ::std::vector< HFPortionInfo > HFPortionInfoVec;
533 typedef ::std::set< OString > OStringSet;
534
535 const OUString maPageNumberService;
536 const OUString maPageCountService;
537 const OUString maSheetNameService;
538 const OUString maFileNameService;
539 const OUString maDateTimeService;
540 const OStringSet maBoldNames; /// All names for bold font style in lowercase UTF-8.
541 const OStringSet maItalicNames; /// All names for italic font style in lowercase UTF-8.
542 HFPortionInfoVec maPortions;
543 HFPortionId meCurrPortion; /// Identifier of current H/F portion.
544 OUStringBuffer maBuffer; /// Text data to append to current text range.
545 FontModel maFontModel; /// Font attributes of current text range.
546 };
547
548 // ----------------------------------------------------------------------------
549
550 namespace {
551
552 // different names for bold font style (lowercase)
553 static const sal_Char* const sppcBoldNames[] =
554 {
555 "bold",
556 "fett", // German 'bold'
557 "demibold",
558 "halbfett", // German 'demibold'
559 "black",
560 "heavy"
561 };
562
563 // different names for italic font style (lowercase)
564 static const sal_Char* const sppcItalicNames[] =
565 {
566 "italic",
567 "kursiv", // German 'italic'
568 "oblique",
569 "schr\303\204g", // German 'oblique' with uppercase A umlaut
570 "schr\303\244g" // German 'oblique' with lowercase A umlaut
571 };
572
573 } // namespace
574
575 // ----------------------------------------------------------------------------
576
HeaderFooterParser(const WorkbookHelper & rHelper)577 HeaderFooterParser::HeaderFooterParser( const WorkbookHelper& rHelper ) :
578 WorkbookHelper( rHelper ),
579 maPageNumberService( CREATE_OUSTRING( "com.sun.star.text.TextField.PageNumber" ) ),
580 maPageCountService( CREATE_OUSTRING( "com.sun.star.text.TextField.PageCount" ) ),
581 maSheetNameService( CREATE_OUSTRING( "com.sun.star.text.TextField.SheetName" ) ),
582 maFileNameService( CREATE_OUSTRING( "com.sun.star.text.TextField.FileName" ) ),
583 maDateTimeService( CREATE_OUSTRING( "com.sun.star.text.TextField.DateTime" ) ),
584 maBoldNames( sppcBoldNames, STATIC_ARRAY_END( sppcBoldNames ) ),
585 maItalicNames( sppcItalicNames, STATIC_ARRAY_END( sppcItalicNames ) ),
586 maPortions( static_cast< size_t >( HF_COUNT ) ),
587 meCurrPortion( HF_CENTER )
588 {
589 }
590
parse(const Reference<XHeaderFooterContent> & rxContext,const OUString & rData)591 double HeaderFooterParser::parse( const Reference< XHeaderFooterContent >& rxContext, const OUString& rData )
592 {
593 if( !rxContext.is() || (rData.getLength() == 0) ||
594 !maPortions[ HF_LEFT ].initialize( rxContext->getLeftText() ) ||
595 !maPortions[ HF_CENTER ].initialize( rxContext->getCenterText() ) ||
596 !maPortions[ HF_RIGHT ].initialize( rxContext->getRightText() ) )
597 return 0.0;
598
599 meCurrPortion = HF_CENTER;
600 maBuffer.setLength( 0 );
601 maFontModel = getStyles().getDefaultFontModel();
602 OUStringBuffer aFontName; // current font name
603 OUStringBuffer aFontStyle; // current font style
604 sal_Int32 nFontHeight = 0; // current font height
605
606 /** State of the parser. */
607 enum
608 {
609 STATE_TEXT, /// Literal text data.
610 STATE_TOKEN, /// Control token following a '&' character.
611 STATE_FONTNAME, /// Font name ('&' is followed by '"', reads until next '"' or ',').
612 STATE_FONTSTYLE, /// Font style name (font part after ',', reads until next '"').
613 STATE_FONTHEIGHT /// Font height ('&' is followed by num. digits, reads until non-digit).
614 }
615 eState = STATE_TEXT;
616
617 const sal_Unicode* pcChar = rData.getStr();
618 const sal_Unicode* pcEnd = pcChar + rData.getLength();
619 for( ; (pcChar != pcEnd) && (*pcChar != 0); ++pcChar )
620 {
621 sal_Unicode cChar = *pcChar;
622 switch( eState )
623 {
624 case STATE_TEXT:
625 {
626 switch( cChar )
627 {
628 case '&': // new token
629 appendText();
630 eState = STATE_TOKEN;
631 break;
632 case '\n': // line break
633 appendText();
634 appendLineBreak();
635 break;
636 default:
637 maBuffer.append( cChar );
638 }
639 }
640 break;
641
642 case STATE_TOKEN:
643 {
644 // default: back to text mode, may be changed in specific cases
645 eState = STATE_TEXT;
646 // ignore case of token codes
647 if( ('a' <= cChar) && (cChar <= 'z') )
648 (cChar -= 'a') += 'A';
649 switch( cChar )
650 {
651 case '&': maBuffer.append( cChar ); break; // the '&' character
652
653 case 'L': setNewPortion( HF_LEFT ); break; // left portion
654 case 'C': setNewPortion( HF_CENTER ); break; // center portion
655 case 'R': setNewPortion( HF_RIGHT ); break; // right portion
656
657 case 'P': // page number
658 appendField( createField( maPageNumberService ) );
659 break;
660 case 'N': // total page count
661 appendField( createField( maPageCountService ) );
662 break;
663 case 'A': // current sheet name
664 appendField( createField( maSheetNameService ) );
665 break;
666
667 case 'F': // file name
668 {
669 Reference< XTextContent > xContent = createField( maFileNameService );
670 PropertySet aPropSet( xContent );
671 aPropSet.setProperty( PROP_FileFormat, ::com::sun::star::text::FilenameDisplayFormat::NAME_AND_EXT );
672 appendField( xContent );
673 }
674 break;
675 case 'Z': // file path (without file name), OOXML, BIFF12, and BIFF8 only
676 if( (getFilterType() == FILTER_OOXML) || ((getFilterType() == FILTER_BIFF) && (getBiff() == BIFF8)) )
677 {
678 Reference< XTextContent > xContent = createField( maFileNameService );
679 PropertySet aPropSet( xContent );
680 // FilenameDisplayFormat::PATH not supported by Calc
681 aPropSet.setProperty( PROP_FileFormat, ::com::sun::star::text::FilenameDisplayFormat::FULL );
682 appendField( xContent );
683 /* path only is not supported -- if we find a '&Z&F'
684 combination for path/name, skip the '&F' part */
685 if( (pcChar + 2 < pcEnd) && (pcChar[ 1 ] == '&') && ((pcChar[ 2 ] == 'f') || (pcChar[ 2 ] == 'F')) )
686 pcChar += 2;
687 }
688 break;
689 case 'D': // date
690 {
691 Reference< XTextContent > xContent = createField( maDateTimeService );
692 PropertySet aPropSet( xContent );
693 aPropSet.setProperty( PROP_IsDate, true );
694 appendField( xContent );
695 }
696 break;
697 case 'T': // time
698 {
699 Reference< XTextContent > xContent = createField( maDateTimeService );
700 PropertySet aPropSet( xContent );
701 aPropSet.setProperty( PROP_IsDate, false );
702 appendField( xContent );
703 }
704 break;
705
706 case 'B': // bold
707 setAttributes();
708 maFontModel.mbBold = !maFontModel.mbBold;
709 break;
710 case 'I': // italic
711 setAttributes();
712 maFontModel.mbItalic = !maFontModel.mbItalic;
713 break;
714 case 'U': // underline
715 setAttributes();
716 maFontModel.mnUnderline = (maFontModel.mnUnderline == XML_single) ? XML_none : XML_single;
717 break;
718 case 'E': // double underline
719 setAttributes();
720 maFontModel.mnUnderline = (maFontModel.mnUnderline == XML_double) ? XML_none : XML_double;
721 break;
722 case 'S': // strikeout
723 setAttributes();
724 maFontModel.mbStrikeout = !maFontModel.mbStrikeout;
725 break;
726 case 'X': // superscript
727 setAttributes();
728 maFontModel.mnEscapement = (maFontModel.mnEscapement == XML_superscript) ? XML_baseline : XML_superscript;
729 break;
730 case 'Y': // subsrcipt
731 setAttributes();
732 maFontModel.mnEscapement = (maFontModel.mnEscapement == XML_subscript) ? XML_baseline : XML_subscript;
733 break;
734 case 'O': // outlined
735 setAttributes();
736 maFontModel.mbOutline = !maFontModel.mbOutline;
737 break;
738 case 'H': // shadow
739 setAttributes();
740 maFontModel.mbShadow = !maFontModel.mbShadow;
741 break;
742
743 case 'K': // text color (not in BIFF)
744 if( (getFilterType() == FILTER_OOXML) && (pcChar + 6 < pcEnd) )
745 {
746 setAttributes();
747 // eat the following 6 characters
748 convertFontColor( OUString( pcChar + 1, 6 ) );
749 pcChar += 6;
750 }
751 break;
752
753 case '\"': // font name
754 aFontName.setLength( 0 );
755 aFontStyle.setLength( 0 );
756 eState = STATE_FONTNAME;
757 break;
758 default:
759 if( ('0' <= cChar) && (cChar <= '9') ) // font size
760 {
761 nFontHeight = cChar - '0';
762 eState = STATE_FONTHEIGHT;
763 }
764 }
765 }
766 break;
767
768 case STATE_FONTNAME:
769 {
770 switch( cChar )
771 {
772 case '\"':
773 setAttributes();
774 convertFontName( aFontName.makeStringAndClear() );
775 eState = STATE_TEXT;
776 break;
777 case ',':
778 eState = STATE_FONTSTYLE;
779 break;
780 default:
781 aFontName.append( cChar );
782 }
783 }
784 break;
785
786 case STATE_FONTSTYLE:
787 {
788 switch( cChar )
789 {
790 case '\"':
791 setAttributes();
792 convertFontName( aFontName.makeStringAndClear() );
793 convertFontStyle( aFontStyle.makeStringAndClear() );
794 eState = STATE_TEXT;
795 break;
796 default:
797 aFontStyle.append( cChar );
798 }
799 }
800 break;
801
802 case STATE_FONTHEIGHT:
803 {
804 if( ('0' <= cChar) && (cChar <= '9') )
805 {
806 if( nFontHeight >= 0 )
807 {
808 nFontHeight *= 10;
809 nFontHeight += (cChar - '0');
810 if( nFontHeight > 1000 )
811 nFontHeight = -1;
812 }
813 }
814 else
815 {
816 if( nFontHeight > 0 )
817 {
818 setAttributes();
819 maFontModel.mfHeight = nFontHeight;
820 }
821 --pcChar;
822 eState = STATE_TEXT;
823 }
824 }
825 break;
826 }
827 }
828
829 // finalize
830 finalizePortion();
831 maPortions[ HF_LEFT ].mfTotalHeight += getCurrHeight( HF_LEFT );
832 maPortions[ HF_CENTER ].mfTotalHeight += getCurrHeight( HF_CENTER );
833 maPortions[ HF_RIGHT ].mfTotalHeight += getCurrHeight( HF_RIGHT );
834
835 return ::std::max( maPortions[ HF_LEFT ].mfTotalHeight,
836 ::std::max( maPortions[ HF_CENTER ].mfTotalHeight, maPortions[ HF_RIGHT ].mfTotalHeight ) );
837 }
838
839 // private --------------------------------------------------------------------
840
getCurrHeight(HFPortionId ePortion) const841 double HeaderFooterParser::getCurrHeight( HFPortionId ePortion ) const
842 {
843 double fMaxHt = maPortions[ ePortion ].mfCurrHeight;
844 return (fMaxHt == 0.0) ? maFontModel.mfHeight : fMaxHt;
845 }
846
getCurrHeight() const847 double HeaderFooterParser::getCurrHeight() const
848 {
849 return getCurrHeight( meCurrPortion );
850 }
851
updateCurrHeight(HFPortionId ePortion)852 void HeaderFooterParser::updateCurrHeight( HFPortionId ePortion )
853 {
854 double& rfMaxHt = maPortions[ ePortion ].mfCurrHeight;
855 rfMaxHt = ::std::max( rfMaxHt, maFontModel.mfHeight );
856 }
857
updateCurrHeight()858 void HeaderFooterParser::updateCurrHeight()
859 {
860 updateCurrHeight( meCurrPortion );
861 }
862
setAttributes()863 void HeaderFooterParser::setAttributes()
864 {
865 Reference< XTextRange > xRange( getStartPos(), UNO_QUERY );
866 getEndPos()->gotoRange( xRange, sal_False );
867 getEndPos()->gotoEnd( sal_True );
868 if( !getEndPos()->isCollapsed() )
869 {
870 Font aFont( *this, maFontModel );
871 aFont.finalizeImport();
872 PropertySet aPropSet( getEndPos() );
873 aFont.writeToPropertySet( aPropSet, FONT_PROPTYPE_TEXT );
874 getStartPos()->gotoEnd( sal_False );
875 getEndPos()->gotoEnd( sal_False );
876 }
877 }
878
appendText()879 void HeaderFooterParser::appendText()
880 {
881 if( maBuffer.getLength() > 0 )
882 {
883 getEndPos()->gotoEnd( sal_False );
884 getEndPos()->setString( maBuffer.makeStringAndClear() );
885 updateCurrHeight();
886 }
887 }
888
appendLineBreak()889 void HeaderFooterParser::appendLineBreak()
890 {
891 getEndPos()->gotoEnd( sal_False );
892 getEndPos()->setString( OUString( sal_Unicode( '\n' ) ) );
893 getPortion().mfTotalHeight += getCurrHeight();
894 getPortion().mfCurrHeight = 0;
895 }
896
createField(const OUString & rServiceName) const897 Reference< XTextContent > HeaderFooterParser::createField( const OUString& rServiceName ) const
898 {
899 Reference< XTextContent > xContent;
900 try
901 {
902 xContent.set( getBaseFilter().getModelFactory()->createInstance( rServiceName ), UNO_QUERY_THROW );
903 }
904 catch( Exception& )
905 {
906 OSL_ENSURE( false,
907 OStringBuffer( "HeaderFooterParser::createField - error while creating text field \"" ).
908 append( OUStringToOString( rServiceName, RTL_TEXTENCODING_ASCII_US ) ).
909 append( '"' ).getStr() );
910 }
911 return xContent;
912 }
913
appendField(const Reference<XTextContent> & rxContent)914 void HeaderFooterParser::appendField( const Reference< XTextContent >& rxContent )
915 {
916 getEndPos()->gotoEnd( sal_False );
917 try
918 {
919 Reference< XTextRange > xRange( getEndPos(), UNO_QUERY_THROW );
920 getPortion().mxText->insertTextContent( xRange, rxContent, sal_False );
921 updateCurrHeight();
922 }
923 catch( Exception& )
924 {
925 }
926 }
927
convertFontName(const OUString & rName)928 void HeaderFooterParser::convertFontName( const OUString& rName )
929 {
930 if( rName.getLength() > 0 )
931 {
932 // single dash is document default font
933 if( (rName.getLength() == 1) && (rName[ 0 ] == '-') )
934 maFontModel.maName = getStyles().getDefaultFontModel().maName;
935 else
936 maFontModel.maName = rName;
937 }
938 }
939
convertFontStyle(const OUString & rStyle)940 void HeaderFooterParser::convertFontStyle( const OUString& rStyle )
941 {
942 maFontModel.mbBold = maFontModel.mbItalic = false;
943 sal_Int32 nPos = 0;
944 sal_Int32 nLen = rStyle.getLength();
945 while( (0 <= nPos) && (nPos < nLen) )
946 {
947 OString aToken = OUStringToOString( rStyle.getToken( 0, ' ', nPos ), RTL_TEXTENCODING_UTF8 ).toAsciiLowerCase();
948 if( aToken.getLength() > 0 )
949 {
950 if( maBoldNames.count( aToken ) > 0 )
951 maFontModel.mbBold = true;
952 else if( maItalicNames.count( aToken ) > 0 )
953 maFontModel.mbItalic = true;
954 }
955 }
956 }
957
convertFontColor(const OUString & rColor)958 void HeaderFooterParser::convertFontColor( const OUString& rColor )
959 {
960 OSL_ENSURE( rColor.getLength() == 6, "HeaderFooterParser::convertFontColor - invalid font color code" );
961 if( (rColor[ 2 ] == '+') || (rColor[ 2 ] == '-') )
962 // theme color: TTSNNN (TT = decimal theme index, S = +/-, NNN = decimal tint/shade in percent)
963 maFontModel.maColor.setTheme(
964 rColor.copy( 0, 2 ).toInt32(),
965 static_cast< double >( rColor.copy( 2 ).toInt32() ) / 100.0 );
966 else
967 // RGB color: RRGGBB
968 maFontModel.maColor.setRgb( rColor.toInt32( 16 ) );
969 }
970
finalizePortion()971 void HeaderFooterParser::finalizePortion()
972 {
973 appendText();
974 setAttributes();
975 }
976
setNewPortion(HFPortionId ePortion)977 void HeaderFooterParser::setNewPortion( HFPortionId ePortion )
978 {
979 if( ePortion != meCurrPortion )
980 {
981 finalizePortion();
982 meCurrPortion = ePortion;
983 maFontModel = getStyles().getDefaultFontModel();
984 }
985 }
986
987 // ============================================================================
988
989 namespace {
990
991 /** Paper size in 1/100 millimeters. */
992 struct ApiPaperSize
993 {
994 sal_Int32 mnWidth;
995 sal_Int32 mnHeight;
996 };
997
998 #define IN2MM100( v ) static_cast< sal_Int32 >( (v) * 2540.0 + 0.5 )
999 #define MM2MM100( v ) static_cast< sal_Int32 >( (v) * 100.0 + 0.5 )
1000
1001 static const ApiPaperSize spPaperSizeTable[] =
1002 {
1003 { 0, 0 }, // 0 - (undefined)
1004 { IN2MM100( 8.5 ), IN2MM100( 11 ) }, // 1 - Letter paper
1005 { IN2MM100( 8.5 ), IN2MM100( 11 ) }, // 2 - Letter small paper
1006 { IN2MM100( 11 ), IN2MM100( 17 ) }, // 3 - Tabloid paper
1007 { IN2MM100( 17 ), IN2MM100( 11 ) }, // 4 - Ledger paper
1008 { IN2MM100( 8.5 ), IN2MM100( 14 ) }, // 5 - Legal paper
1009 { IN2MM100( 5.5 ), IN2MM100( 8.5 ) }, // 6 - Statement paper
1010 { IN2MM100( 7.25 ), IN2MM100( 10.5 ) }, // 7 - Executive paper
1011 { MM2MM100( 297 ), MM2MM100( 420 ) }, // 8 - A3 paper
1012 { MM2MM100( 210 ), MM2MM100( 297 ) }, // 9 - A4 paper
1013 { MM2MM100( 210 ), MM2MM100( 297 ) }, // 10 - A4 small paper
1014 { MM2MM100( 148 ), MM2MM100( 210 ) }, // 11 - A5 paper
1015 { MM2MM100( 250 ), MM2MM100( 353 ) }, // 12 - B4 paper
1016 { MM2MM100( 176 ), MM2MM100( 250 ) }, // 13 - B5 paper
1017 { IN2MM100( 8.5 ), IN2MM100( 13 ) }, // 14 - Folio paper
1018 { MM2MM100( 215 ), MM2MM100( 275 ) }, // 15 - Quarto paper
1019 { IN2MM100( 10 ), IN2MM100( 14 ) }, // 16 - Standard paper
1020 { IN2MM100( 11 ), IN2MM100( 17 ) }, // 17 - Standard paper
1021 { IN2MM100( 8.5 ), IN2MM100( 11 ) }, // 18 - Note paper
1022 { IN2MM100( 3.875 ), IN2MM100( 8.875 ) }, // 19 - #9 envelope
1023 { IN2MM100( 4.125 ), IN2MM100( 9.5 ) }, // 20 - #10 envelope
1024 { IN2MM100( 4.5 ), IN2MM100( 10.375 ) }, // 21 - #11 envelope
1025 { IN2MM100( 4.75 ), IN2MM100( 11 ) }, // 22 - #12 envelope
1026 { IN2MM100( 5 ), IN2MM100( 11.5 ) }, // 23 - #14 envelope
1027 { IN2MM100( 17 ), IN2MM100( 22 ) }, // 24 - C paper
1028 { IN2MM100( 22 ), IN2MM100( 34 ) }, // 25 - D paper
1029 { IN2MM100( 34 ), IN2MM100( 44 ) }, // 26 - E paper
1030 { MM2MM100( 110 ), MM2MM100( 220 ) }, // 27 - DL envelope
1031 { MM2MM100( 162 ), MM2MM100( 229 ) }, // 28 - C5 envelope
1032 { MM2MM100( 324 ), MM2MM100( 458 ) }, // 29 - C3 envelope
1033 { MM2MM100( 229 ), MM2MM100( 324 ) }, // 30 - C4 envelope
1034 { MM2MM100( 114 ), MM2MM100( 162 ) }, // 31 - C6 envelope
1035 { MM2MM100( 114 ), MM2MM100( 229 ) }, // 32 - C65 envelope
1036 { MM2MM100( 250 ), MM2MM100( 353 ) }, // 33 - B4 envelope
1037 { MM2MM100( 176 ), MM2MM100( 250 ) }, // 34 - B5 envelope
1038 { MM2MM100( 176 ), MM2MM100( 125 ) }, // 35 - B6 envelope
1039 { MM2MM100( 110 ), MM2MM100( 230 ) }, // 36 - Italy envelope
1040 { IN2MM100( 3.875 ), IN2MM100( 7.5 ) }, // 37 - Monarch envelope
1041 { IN2MM100( 3.625 ), IN2MM100( 6.5 ) }, // 38 - 6 3/4 envelope
1042 { IN2MM100( 14.875 ), IN2MM100( 11 ) }, // 39 - US standard fanfold
1043 { IN2MM100( 8.5 ), IN2MM100( 12 ) }, // 40 - German standard fanfold
1044 { IN2MM100( 8.5 ), IN2MM100( 13 ) }, // 41 - German legal fanfold
1045 { MM2MM100( 250 ), MM2MM100( 353 ) }, // 42 - ISO B4
1046 { MM2MM100( 200 ), MM2MM100( 148 ) }, // 43 - Japanese double postcard
1047 { IN2MM100( 9 ), IN2MM100( 11 ) }, // 44 - Standard paper
1048 { IN2MM100( 10 ), IN2MM100( 11 ) }, // 45 - Standard paper
1049 { IN2MM100( 15 ), IN2MM100( 11 ) }, // 46 - Standard paper
1050 { MM2MM100( 220 ), MM2MM100( 220 ) }, // 47 - Invite envelope
1051 { 0, 0 }, // 48 - (undefined)
1052 { 0, 0 }, // 49 - (undefined)
1053 { IN2MM100( 9.275 ), IN2MM100( 12 ) }, // 50 - Letter extra paper
1054 { IN2MM100( 9.275 ), IN2MM100( 15 ) }, // 51 - Legal extra paper
1055 { IN2MM100( 11.69 ), IN2MM100( 18 ) }, // 52 - Tabloid extra paper
1056 { MM2MM100( 236 ), MM2MM100( 322 ) }, // 53 - A4 extra paper
1057 { IN2MM100( 8.275 ), IN2MM100( 11 ) }, // 54 - Letter transverse paper
1058 { MM2MM100( 210 ), MM2MM100( 297 ) }, // 55 - A4 transverse paper
1059 { IN2MM100( 9.275 ), IN2MM100( 12 ) }, // 56 - Letter extra transverse paper
1060 { MM2MM100( 227 ), MM2MM100( 356 ) }, // 57 - SuperA/SuperA/A4 paper
1061 { MM2MM100( 305 ), MM2MM100( 487 ) }, // 58 - SuperB/SuperB/A3 paper
1062 { IN2MM100( 8.5 ), IN2MM100( 12.69 ) }, // 59 - Letter plus paper
1063 { MM2MM100( 210 ), MM2MM100( 330 ) }, // 60 - A4 plus paper
1064 { MM2MM100( 148 ), MM2MM100( 210 ) }, // 61 - A5 transverse paper
1065 { MM2MM100( 182 ), MM2MM100( 257 ) }, // 62 - JIS B5 transverse paper
1066 { MM2MM100( 322 ), MM2MM100( 445 ) }, // 63 - A3 extra paper
1067 { MM2MM100( 174 ), MM2MM100( 235 ) }, // 64 - A5 extra paper
1068 { MM2MM100( 201 ), MM2MM100( 276 ) }, // 65 - ISO B5 extra paper
1069 { MM2MM100( 420 ), MM2MM100( 594 ) }, // 66 - A2 paper
1070 { MM2MM100( 297 ), MM2MM100( 420 ) }, // 67 - A3 transverse paper
1071 { MM2MM100( 322 ), MM2MM100( 445 ) } // 68 - A3 extra transverse paper
1072 };
1073
1074 } // namespace
1075
1076 // ----------------------------------------------------------------------------
1077
HFHelperData(sal_Int32 nLeftPropId,sal_Int32 nRightPropId)1078 PageSettingsConverter::HFHelperData::HFHelperData( sal_Int32 nLeftPropId, sal_Int32 nRightPropId ) :
1079 mnLeftPropId( nLeftPropId ),
1080 mnRightPropId( nRightPropId ),
1081 mnHeight( 0 ),
1082 mnBodyDist( 0 ),
1083 mbHasContent( false ),
1084 mbShareOddEven( false ),
1085 mbDynamicHeight( false )
1086 {
1087 }
1088
1089 // ----------------------------------------------------------------------------
1090
PageSettingsConverter(const WorkbookHelper & rHelper)1091 PageSettingsConverter::PageSettingsConverter( const WorkbookHelper& rHelper ) :
1092 WorkbookHelper( rHelper ),
1093 mxHFParser( new HeaderFooterParser( rHelper ) ),
1094 maHeaderData( PROP_LeftPageHeaderContent, PROP_RightPageHeaderContent ),
1095 maFooterData( PROP_LeftPageFooterContent, PROP_RightPageFooterContent )
1096 {
1097 }
1098
~PageSettingsConverter()1099 PageSettingsConverter::~PageSettingsConverter()
1100 {
1101 }
1102
writePageSettingsProperties(PropertySet & rPropSet,const PageSettingsModel & rModel,WorksheetType eSheetType)1103 void PageSettingsConverter::writePageSettingsProperties(
1104 PropertySet& rPropSet, const PageSettingsModel& rModel, WorksheetType eSheetType )
1105 {
1106 // special handling for chart sheets
1107 bool bChartSheet = eSheetType == SHEETTYPE_CHARTSHEET;
1108
1109 // printout scaling
1110 if( bChartSheet )
1111 {
1112 // always fit chart sheet to 1 page
1113 rPropSet.setProperty< sal_Int16 >( PROP_ScaleToPages, 1 );
1114 }
1115 else if( rModel.mbFitToPages )
1116 {
1117 // fit to number of pages
1118 rPropSet.setProperty( PROP_ScaleToPagesX, getLimitedValue< sal_Int16, sal_Int32 >( rModel.mnFitToWidth, 0, 1000 ) );
1119 rPropSet.setProperty( PROP_ScaleToPagesY, getLimitedValue< sal_Int16, sal_Int32 >( rModel.mnFitToHeight, 0, 1000 ) );
1120 }
1121 else
1122 {
1123 // scale may be 0 which indicates uninitialized
1124 sal_Int16 nScale = (rModel.mbValidSettings && (rModel.mnScale > 0)) ? getLimitedValue< sal_Int16, sal_Int32 >( rModel.mnScale, 10, 400 ) : 100;
1125 rPropSet.setProperty( PROP_PageScale, nScale );
1126 }
1127
1128 // paper orientation
1129 bool bLandscape = rModel.mnOrientation == XML_landscape;
1130 // default orientation for current sheet type (chart sheets default to landscape)
1131 if( !rModel.mbValidSettings || (rModel.mnOrientation == XML_default) )
1132 bLandscape = bChartSheet;
1133
1134 // paper size
1135 if( rModel.mbValidSettings && (0 < rModel.mnPaperSize) && (rModel.mnPaperSize < static_cast< sal_Int32 >( STATIC_ARRAY_SIZE( spPaperSizeTable ) )) )
1136 {
1137 const ApiPaperSize& rPaperSize = spPaperSizeTable[ rModel.mnPaperSize ];
1138 Size aSize( rPaperSize.mnWidth, rPaperSize.mnHeight );
1139 if( bLandscape )
1140 ::std::swap( aSize.Width, aSize.Height );
1141 rPropSet.setProperty( PROP_Size, aSize );
1142 }
1143
1144 // header/footer
1145 convertHeaderFooterData( rPropSet, maHeaderData, rModel.maOddHeader, rModel.maEvenHeader, rModel.mbUseEvenHF, rModel.mfTopMargin, rModel.mfHeaderMargin );
1146 convertHeaderFooterData( rPropSet, maFooterData, rModel.maOddFooter, rModel.maEvenFooter, rModel.mbUseEvenHF, rModel.mfBottomMargin, rModel.mfFooterMargin );
1147
1148 // write all properties to property set
1149 const UnitConverter& rUnitConv = getUnitConverter();
1150 PropertyMap aPropMap;
1151 aPropMap[ PROP_IsLandscape ] <<= bLandscape;
1152 aPropMap[ PROP_FirstPageNumber ] <<= getLimitedValue< sal_Int16, sal_Int32 >( rModel.mbUseFirstPage ? rModel.mnFirstPage : 0, 0, 9999 );
1153 aPropMap[ PROP_PrintDownFirst ] <<= (rModel.mnPageOrder == XML_downThenOver);
1154 aPropMap[ PROP_PrintAnnotations ] <<= (rModel.mnCellComments == XML_asDisplayed);
1155 aPropMap[ PROP_CenterHorizontally ] <<= rModel.mbHorCenter;
1156 aPropMap[ PROP_CenterVertically ] <<= rModel.mbVerCenter;
1157 aPropMap[ PROP_PrintGrid ] <<= (!bChartSheet && rModel.mbPrintGrid); // no gridlines in chart sheets
1158 aPropMap[ PROP_PrintHeaders ] <<= (!bChartSheet && rModel.mbPrintHeadings); // no column/row headings in chart sheets
1159 aPropMap[ PROP_LeftMargin ] <<= rUnitConv.scaleToMm100( rModel.mfLeftMargin, UNIT_INCH );
1160 aPropMap[ PROP_RightMargin ] <<= rUnitConv.scaleToMm100( rModel.mfRightMargin, UNIT_INCH );
1161 // #i23296# In Calc, "TopMargin" property is distance to top of header if enabled
1162 aPropMap[ PROP_TopMargin ] <<= rUnitConv.scaleToMm100( maHeaderData.mbHasContent ? rModel.mfHeaderMargin : rModel.mfTopMargin, UNIT_INCH );
1163 // #i23296# In Calc, "BottomMargin" property is distance to bottom of footer if enabled
1164 aPropMap[ PROP_BottomMargin ] <<= rUnitConv.scaleToMm100( maFooterData.mbHasContent ? rModel.mfFooterMargin : rModel.mfBottomMargin, UNIT_INCH );
1165 aPropMap[ PROP_HeaderIsOn ] <<= maHeaderData.mbHasContent;
1166 aPropMap[ PROP_HeaderIsShared ] <<= maHeaderData.mbShareOddEven;
1167 aPropMap[ PROP_HeaderIsDynamicHeight ] <<= maHeaderData.mbDynamicHeight;
1168 aPropMap[ PROP_HeaderHeight ] <<= maHeaderData.mnHeight;
1169 aPropMap[ PROP_HeaderBodyDistance ] <<= maHeaderData.mnBodyDist;
1170 aPropMap[ PROP_FooterIsOn ] <<= maFooterData.mbHasContent;
1171 aPropMap[ PROP_FooterIsShared ] <<= maFooterData.mbShareOddEven;
1172 aPropMap[ PROP_FooterIsDynamicHeight ] <<= maFooterData.mbDynamicHeight;
1173 aPropMap[ PROP_FooterHeight ] <<= maFooterData.mnHeight;
1174 aPropMap[ PROP_FooterBodyDistance ] <<= maFooterData.mnBodyDist;
1175 // background image
1176 if( rModel.maGraphicUrl.getLength() > 0 )
1177 {
1178 aPropMap[ PROP_BackGraphicURL ] <<= rModel.maGraphicUrl;
1179 aPropMap[ PROP_BackGraphicLocation ] <<= ::com::sun::star::style::GraphicLocation_TILED;
1180 }
1181
1182 rPropSet.setProperties( aPropMap );
1183 }
1184
convertHeaderFooterData(PropertySet & rPropSet,HFHelperData & orHFData,const OUString rOddContent,const OUString rEvenContent,bool bUseEvenContent,double fPageMargin,double fContentMargin)1185 void PageSettingsConverter::convertHeaderFooterData(
1186 PropertySet& rPropSet, HFHelperData& orHFData,
1187 const OUString rOddContent, const OUString rEvenContent, bool bUseEvenContent,
1188 double fPageMargin, double fContentMargin )
1189 {
1190 bool bHasOddContent = rOddContent.getLength() > 0;
1191 bool bHasEvenContent = bUseEvenContent && (rEvenContent.getLength() > 0);
1192
1193 sal_Int32 nOddHeight = bHasOddContent ? writeHeaderFooter( rPropSet, orHFData.mnRightPropId, rOddContent ) : 0;
1194 sal_Int32 nEvenHeight = bHasEvenContent ? writeHeaderFooter( rPropSet, orHFData.mnLeftPropId, rEvenContent ) : 0;
1195
1196 orHFData.mnHeight = 750;
1197 orHFData.mnBodyDist = 250;
1198 orHFData.mbHasContent = bHasOddContent || bHasEvenContent;
1199 orHFData.mbShareOddEven = !bUseEvenContent;
1200 orHFData.mbDynamicHeight = true;
1201
1202 if( orHFData.mbHasContent )
1203 {
1204 // use maximum height of odd/even header/footer
1205 orHFData.mnHeight = ::std::max( nOddHeight, nEvenHeight );
1206 /* Calc contains distance between bottom of header and top of page
1207 body in "HeaderBodyDistance" property, and distance between bottom
1208 of page body and top of footer in "FooterBodyDistance" property */
1209 orHFData.mnBodyDist = getUnitConverter().scaleToMm100( fPageMargin - fContentMargin, UNIT_INCH ) - orHFData.mnHeight;
1210 /* #i23296# Distance less than 0 means, header or footer overlays page
1211 body. As this is not possible in Calc, set fixed header or footer
1212 height (crop header/footer) to get correct top position of page body. */
1213 orHFData.mbDynamicHeight = orHFData.mnBodyDist >= 0;
1214 /* "HeaderHeight" property is in fact distance from top of header to
1215 top of page body (including "HeaderBodyDistance").
1216 "FooterHeight" property is in fact distance from bottom of page
1217 body to bottom of footer (including "FooterBodyDistance"). */
1218 orHFData.mnHeight += orHFData.mnBodyDist;
1219 // negative body distance not allowed
1220 orHFData.mnBodyDist = ::std::max< sal_Int32 >( orHFData.mnBodyDist, 0 );
1221 }
1222 }
1223
writeHeaderFooter(PropertySet & rPropSet,sal_Int32 nPropId,const OUString & rContent)1224 sal_Int32 PageSettingsConverter::writeHeaderFooter(
1225 PropertySet& rPropSet, sal_Int32 nPropId, const OUString& rContent )
1226 {
1227 OSL_ENSURE( rContent.getLength() > 0, "PageSettingsConverter::writeHeaderFooter - empty h/f string found" );
1228 sal_Int32 nHeight = 0;
1229 if( rContent.getLength() > 0 )
1230 {
1231 Reference< XHeaderFooterContent > xHFContent( rPropSet.getAnyProperty( nPropId ), UNO_QUERY );
1232 if( xHFContent.is() )
1233 {
1234 double fTotalHeight = mxHFParser->parse( xHFContent, rContent );
1235 rPropSet.setProperty( nPropId, xHFContent );
1236 nHeight = getUnitConverter().scaleToMm100( fTotalHeight, UNIT_POINT );
1237 }
1238 }
1239 return nHeight;
1240 }
1241
1242 // ============================================================================
1243
1244 } // namespace xls
1245 } // namespace oox
1246