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