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