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