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