LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/sc/source/filter/oox - pagesettings.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 302 488 61.9 %
Date: 2013-07-09 Functions: 39 52 75.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10