LCOV - code coverage report
Current view: top level - sc/source/filter/oox - pagesettings.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 302 488 61.9 %
Date: 2014-04-11 Functions: 39 52 75.0 %
Legend: Lines: hit not hit

          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: */

Generated by: LCOV version 1.10