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

Generated by: LCOV version 1.11