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

Generated by: LCOV version 1.10