LCOV - code coverage report
Current view: top level - sc/source/filter/excel - xestyle.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 1207 1579 76.4 %
Date: 2015-06-13 12:38:46 Functions: 176 197 89.3 %
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 "xestyle.hxx"
      21             : 
      22             : #include <iostream>
      23             : #include <algorithm>
      24             : #include <iterator>
      25             : #include <set>
      26             : #include <com/sun/star/i18n/ScriptType.hpp>
      27             : #include <vcl/font.hxx>
      28             : #include <svl/zformat.hxx>
      29             : #include <svl/itempool.hxx>
      30             : #include <svl/languageoptions.hxx>
      31             : #include <sfx2/printer.hxx>
      32             : #include "scitems.hxx"
      33             : #include <svx/algitem.hxx>
      34             : #include <editeng/boxitem.hxx>
      35             : #include <editeng/lineitem.hxx>
      36             : #include <svx/rotmodit.hxx>
      37             : #include <editeng/colritem.hxx>
      38             : #include <editeng/brushitem.hxx>
      39             : #include <editeng/frmdiritem.hxx>
      40             : #include <editeng/fontitem.hxx>
      41             : #include <editeng/eeitem.hxx>
      42             : #include <editeng/escapementitem.hxx>
      43             : #include <editeng/justifyitem.hxx>
      44             : #include "document.hxx"
      45             : #include "stlpool.hxx"
      46             : #include "stlsheet.hxx"
      47             : #include "patattr.hxx"
      48             : #include "attrib.hxx"
      49             : #include "globstr.hrc"
      50             : #include "xestring.hxx"
      51             : #include "conditio.hxx"
      52             : 
      53             : #include <oox/token/tokens.hxx>
      54             : #include <boost/ptr_container/ptr_vector.hpp>
      55             : 
      56             : using namespace ::com::sun::star;
      57             : using namespace oox;
      58             : 
      59             : // PALETTE record - color information =========================================
      60             : 
      61             : namespace {
      62             : 
      63         483 : sal_uInt32 lclGetWeighting( XclExpColorType eType )
      64             : {
      65         483 :     switch( eType )
      66             :     {
      67         124 :         case EXC_COLOR_CHARTLINE:   return 1;
      68             :         case EXC_COLOR_CELLBORDER:
      69         177 :         case EXC_COLOR_CHARTAREA:   return 2;
      70             :         case EXC_COLOR_CELLTEXT:
      71             :         case EXC_COLOR_CHARTTEXT:
      72         173 :         case EXC_COLOR_CTRLTEXT:    return 10;
      73             :         case EXC_COLOR_TABBG:
      74           9 :         case EXC_COLOR_CELLAREA:    return 20;
      75           0 :         case EXC_COLOR_GRID:        return 50;
      76             :         default:    OSL_FAIL( "lclGetWeighting - unknown color type" );
      77             :     }
      78           0 :     return 1;
      79             : }
      80             : 
      81       23357 : sal_Int32 lclGetColorDistance( const Color& rColor1, const Color& rColor2 )
      82             : {
      83       23357 :     sal_Int32 nDist = rColor1.GetRed() - rColor2.GetRed();
      84       23357 :     nDist *= nDist * 77;
      85       23357 :     sal_Int32 nDummy = rColor1.GetGreen() - rColor2.GetGreen();
      86       23357 :     nDist += nDummy * nDummy * 151;
      87       23357 :     nDummy = rColor1.GetBlue() - rColor2.GetBlue();
      88       23357 :     nDist += nDummy * nDummy * 28;
      89       23357 :     return nDist;
      90             : }
      91             : 
      92           0 : sal_uInt8 lclGetMergedColorComp( sal_uInt8 nComp1, sal_uInt32 nWeight1, sal_uInt8 nComp2, sal_uInt32 nWeight2 )
      93             : {
      94           0 :     sal_uInt8 nComp1Dist = ::std::min< sal_uInt8 >( nComp1, 0xFF - nComp1 );
      95           0 :     sal_uInt8 nComp2Dist = ::std::min< sal_uInt8 >( nComp2, 0xFF - nComp2 );
      96           0 :     if( nComp1Dist != nComp2Dist )
      97             :     {
      98             :         /*  #i36945# One of the passed RGB components is nearer at the limits (0x00 or 0xFF).
      99             :             Increase its weighting to prevent fading of the colors during reduction. */
     100           0 :         const sal_uInt8& rnCompNearer = (nComp1Dist < nComp2Dist) ? nComp1 : nComp2;
     101           0 :         sal_uInt32& rnWeight = (nComp1Dist < nComp2Dist) ? nWeight1 : nWeight2;
     102           0 :         rnWeight *= ((rnCompNearer - 0x80L) * (rnCompNearer - 0x7FL) / 0x1000L + 1);
     103             :     }
     104           0 :     sal_uInt32 nWSum = nWeight1 + nWeight2;
     105           0 :     return static_cast< sal_uInt8 >( (nComp1 * nWeight1 + nComp2 * nWeight2 + nWSum / 2) / nWSum );
     106             : }
     107             : 
     108           0 : void lclSetMixedColor( Color& rDest, const Color& rSrc1, const Color& rSrc2 )
     109             : {
     110           0 :     rDest.SetRed( static_cast< sal_uInt8 >( (static_cast< sal_uInt16 >( rSrc1.GetRed() ) + rSrc2.GetRed()) / 2 ) );
     111           0 :     rDest.SetGreen( static_cast< sal_uInt8 >( (static_cast< sal_uInt16 >( rSrc1.GetGreen() ) + rSrc2.GetGreen()) / 2 ) );
     112           0 :     rDest.SetBlue( static_cast< sal_uInt8 >( (static_cast< sal_uInt16 >( rSrc1.GetBlue() ) + rSrc2.GetBlue()) / 2 ) );
     113           0 : }
     114             : 
     115             : } // namespace
     116             : 
     117             : // additional classes for color reduction -------------------------------------
     118             : 
     119             : namespace {
     120             : 
     121             : /** Represents an entry in a color list.
     122             : 
     123             :     The color stores a weighting value, which increases the more the color is
     124             :     used in the document. Heavy-weighted colors will change less than others on
     125             :     color reduction.
     126             :  */
     127             : class XclListColor
     128             : {
     129         356 :     DECL_FIXEDMEMPOOL_NEWDEL( XclListColor )
     130             : 
     131             : private:
     132             :     Color               maColor;        /// The color value of this palette entry.
     133             :     sal_uInt32          mnColorId;      /// Unique color ID for color reduction.
     134             :     sal_uInt32          mnWeight;       /// Weighting for color reduction.
     135             :     bool                mbBaseColor;    /// true = Handle as base color, (don't remove/merge).
     136             : 
     137             : public:
     138             :     explicit            XclListColor( const Color& rColor, sal_uInt32 nColorId );
     139             : 
     140             :     /** Returns the RGB color value of the color. */
     141        2168 :     inline const Color& GetColor() const { return maColor; }
     142             :     /** Returns the unique ID of the color. */
     143         661 :     inline sal_uInt32   GetColorId() const { return mnColorId; }
     144             :     /** Returns the current weighting of the color. */
     145           0 :     inline sal_uInt32   GetWeighting() const { return mnWeight; }
     146             :     /** Returns true, if this color is a base color, i.e. it will not be removed or merged. */
     147           0 :     inline bool         IsBaseColor() const { return mbBaseColor; }
     148             : 
     149             :     /** Adds the passed weighting to this color. */
     150         483 :     inline void         AddWeighting( sal_uInt32 nWeight ) { mnWeight += nWeight; }
     151             :     /** Merges this color with rColor, regarding weighting settings. */
     152             :     void                Merge( const XclListColor& rColor );
     153             : };
     154             : 
     155          10 : IMPL_FIXEDMEMPOOL_NEWDEL( XclListColor )
     156             : 
     157         178 : XclListColor::XclListColor( const Color& rColor, sal_uInt32 nColorId ) :
     158             :     maColor( rColor ),
     159             :     mnColorId( nColorId ),
     160         178 :     mnWeight( 0 )
     161             : {
     162             :     mbBaseColor =
     163         372 :         ((rColor.GetRed()   == 0x00) || (rColor.GetRed()   == 0xFF)) &&
     164         464 :         ((rColor.GetGreen() == 0x00) || (rColor.GetGreen() == 0xFF)) &&
     165         265 :         ((rColor.GetBlue()  == 0x00) || (rColor.GetBlue()  == 0xFF));
     166         178 : }
     167             : 
     168           0 : void XclListColor::Merge( const XclListColor& rColor )
     169             : {
     170           0 :     sal_uInt32 nWeight2 = rColor.GetWeighting();
     171             :     // do not change RGB value of base colors
     172           0 :     if( !mbBaseColor )
     173             :     {
     174           0 :         maColor.SetRed(   lclGetMergedColorComp( maColor.GetRed(),   mnWeight, rColor.maColor.GetRed(),   nWeight2 ) );
     175           0 :         maColor.SetGreen( lclGetMergedColorComp( maColor.GetGreen(), mnWeight, rColor.maColor.GetGreen(), nWeight2 ) );
     176           0 :         maColor.SetBlue(  lclGetMergedColorComp( maColor.GetBlue(),  mnWeight, rColor.maColor.GetBlue(),  nWeight2 ) );
     177             :     }
     178           0 :     AddWeighting( nWeight2 );
     179           0 : }
     180             : 
     181             : /** Data for each inserted original color, represented by a color ID. */
     182         178 : struct XclColorIdData
     183             : {
     184             :     Color               maColor;        /// The original inserted color.
     185             :     sal_uInt32          mnIndex;        /// Maps current color ID to color list or export color vector.
     186             :     /** Sets the contents of this struct. */
     187         178 :     inline void         Set( const Color& rColor, sal_uInt32 nIndex ) { maColor = rColor; mnIndex = nIndex; }
     188             : };
     189             : 
     190             : /** A color that will be written to the Excel file. */
     191             : struct XclPaletteColor
     192             : {
     193             :     Color               maColor;        /// Resulting color to export.
     194             :     bool                mbUsed;         /// true = Entry is used in the document.
     195             : 
     196        4032 :     inline explicit     XclPaletteColor( const Color& rColor ) : maColor( rColor ), mbUsed( false ) {}
     197         178 :     inline void         SetColor( const Color& rColor ) { maColor = rColor; mbUsed = true; }
     198             : };
     199             : 
     200             : /** Maps a color list index to a palette index.
     201             :     @descr  Used to remap the color ID data vector from list indexes to palette indexes. */
     202             : struct XclRemap
     203             : {
     204             :     sal_uInt32          mnPalIndex;     /// Index to palette.
     205             :     bool                mbProcessed;    /// true = List color already processed.
     206             : 
     207         178 :     inline explicit     XclRemap() : mnPalIndex( 0 ), mbProcessed( false ) {}
     208         178 :     inline void         SetIndex( sal_uInt32 nPalIndex )
     209         178 :                             { mnPalIndex = nPalIndex; mbProcessed = true; }
     210             : };
     211             : 
     212             : /** Stores the nearest palette color index of a list color. */
     213             : struct XclNearest
     214             : {
     215             :     sal_uInt32          mnPalIndex;     /// Index to nearest palette color.
     216             :     sal_Int32           mnDist;         /// Distance to palette color.
     217             : 
     218         178 :     inline explicit     XclNearest() : mnPalIndex( 0 ), mnDist( 0 ) {}
     219             : };
     220             : 
     221             : typedef ::std::vector< XclRemap >   XclRemapVec;
     222             : typedef ::std::vector< XclNearest > XclNearestVec;
     223             : 
     224             : } // namespace
     225             : 
     226          72 : class XclExpPaletteImpl
     227             : {
     228             : public:
     229             :     explicit            XclExpPaletteImpl( const XclDefaultPalette& rDefPal );
     230             : 
     231             :     /** Inserts the color into the list and updates weighting.
     232             :         @param nAutoDefault  The Excel palette index for automatic color.
     233             :         @return  A unique ID for this color. */
     234             :     sal_uInt32          InsertColor( const Color& rColor, XclExpColorType eType, sal_uInt16 nAutoDefault = 0 );
     235             :     /** Returns the color ID representing a fixed Excel palette index (i.e. for auto colors). */
     236             :     static sal_uInt32   GetColorIdFromIndex( sal_uInt16 nIndex );
     237             : 
     238             :     /** Reduces the color list to the maximum count of the current BIFF version. */
     239             :     void                Finalize();
     240             : 
     241             :     /** Returns the Excel palette index of the color with passed color ID. */
     242             :     sal_uInt16          GetColorIndex( sal_uInt32 nColorId ) const;
     243             : 
     244             :     /** Returns a foreground and background color for the two passed color IDs.
     245             :         @descr  If rnXclPattern contains a solid pattern, this function tries to find
     246             :         the two best fitting colors and a mix pattern (25%, 50% or 75%) for nForeColorId.
     247             :         This will result in a better approximation to the passed foreground color. */
     248             :     void                GetMixedColors(
     249             :                             sal_uInt16& rnXclForeIx, sal_uInt16& rnXclBackIx, sal_uInt8& rnXclPattern,
     250             :                             sal_uInt32 nForeColorId, sal_uInt32 nBackColorId ) const;
     251             : 
     252             :     /** Returns the RGB color data for a (non-zero-based) Excel palette entry.
     253             :         @return  The color from current or default palette or COL_AUTO, if nothing else found. */
     254             :     ColorData           GetColorData( sal_uInt16 nXclIndex ) const;
     255             : 
     256             :     /** Returns true, if all colors of the palette are equal to default palette colors. */
     257             :     bool                IsDefaultPalette() const;
     258             :     /** Writes the color list (contents of the palette record) to the passed stream. */
     259             :     void                WriteBody( XclExpStream& rStrm );
     260             :     void                SaveXml( XclExpXmlStream& rStrm );
     261             : 
     262             : private:
     263             :     /** Returns the Excel index of a 0-based color index. */
     264        7211 :     static inline sal_uInt16 GetXclIndex( sal_uInt32 nIndex )
     265        7211 :                             { return static_cast< sal_uInt16 >( nIndex + EXC_COLOR_USEROFFSET ); }
     266             : 
     267             :     /** Returns the original inserted color represented by the color ID nColorId. */
     268             :     const Color&        GetOriginalColor( sal_uInt32 nColorId ) const;
     269             : 
     270             :     /** Searches for rColor, returns the ordered insertion index for rColor in rnIndex. */
     271             :     XclListColor*       SearchListEntry( const Color& rColor, sal_uInt32& rnIndex );
     272             :     /** Creates and inserts a new color list entry at the specified list position. */
     273             :     XclListColor*       CreateListEntry( const Color& rColor, sal_uInt32 nIndex );
     274             : 
     275             :     /** Raw and fast reduction of the palette. */
     276             :     void                RawReducePalette( sal_uInt32 nPass );
     277             :     /** Reduction of one color using advanced color merging based on color weighting. */
     278             :     void                ReduceLeastUsedColor();
     279             : 
     280             :     /** Finds the least used color and returns its current list index. */
     281             :     sal_uInt32          GetLeastUsedListColor() const;
     282             :     /** Returns the list index of the color nearest to rColor.
     283             :         @param nIgnore  List index of a color which will be ignored.
     284             :         @return  The list index of the found color. */
     285             :     sal_uInt32          GetNearestListColor( const Color& rColor, sal_uInt32 nIgnore ) const;
     286             :     /** Returns the list index of the color nearest to the color with list index nIndex. */
     287             :     sal_uInt32          GetNearestListColor( sal_uInt32 nIndex ) const;
     288             : 
     289             :     /** Returns in rnIndex the palette index of the color nearest to rColor.
     290             :         @param bDefaultOnly  true = Searches for default colors only (colors never replaced).
     291             :         @return  The distance from passed color to found color. */
     292             :     sal_Int32           GetNearestPaletteColor(
     293             :                             sal_uInt32& rnIndex,
     294             :                             const Color& rColor, bool bDefaultOnly ) const;
     295             :     /** Returns in rnFirst and rnSecond the palette indexes of the two colors nearest to rColor.
     296             :         @return  The minimum distance from passed color to found colors. */
     297             :     sal_Int32           GetNearPaletteColors(
     298             :                             sal_uInt32& rnFirst, sal_uInt32& rnSecond,
     299             :                             const Color& rColor ) const;
     300             : 
     301             : private:
     302             :     typedef boost::ptr_vector< XclListColor >     XclListColorList;
     303             :     typedef boost::shared_ptr< XclListColorList > XclListColorListRef;
     304             :     typedef ::std::vector< XclColorIdData >       XclColorIdDataVec;
     305             :     typedef ::std::vector< XclPaletteColor >      XclPaletteColorVec;
     306             : 
     307             :     const XclDefaultPalette& mrDefPal;      /// The default palette for the current BIFF version.
     308             :     XclListColorListRef mxColorList;        /// Working color list.
     309             :     XclColorIdDataVec   maColorIdDataVec;   /// Data of all CIDs.
     310             :     XclPaletteColorVec  maPalette;          /// Contains resulting colors to export.
     311             :     sal_uInt32          mnLastIdx;          /// Last insertion index for search opt.
     312             : };
     313             : 
     314             : const sal_uInt32 EXC_PAL_INDEXBASE          = 0xFFFF0000;
     315             : const sal_uInt32 EXC_PAL_MAXRAWSIZE         = 1024;
     316             : 
     317          72 : XclExpPaletteImpl::XclExpPaletteImpl( const XclDefaultPalette& rDefPal ) :
     318             :     mrDefPal( rDefPal ),
     319          72 :     mxColorList( new XclListColorList ),
     320         144 :     mnLastIdx( 0 )
     321             : {
     322             :     // initialize maPalette with default colors
     323          72 :     sal_uInt16 nCount = static_cast< sal_uInt16 >( mrDefPal.GetColorCount() );
     324          72 :     maPalette.reserve( nCount );
     325        4104 :     for( sal_uInt16 nIdx = 0; nIdx < nCount; ++nIdx )
     326        4032 :         maPalette.push_back( XclPaletteColor( mrDefPal.GetDefColor( GetXclIndex( nIdx ) ) ) );
     327             : 
     328          72 :     InsertColor( Color( COL_BLACK ), EXC_COLOR_CELLTEXT );
     329          72 : }
     330             : 
     331         607 : sal_uInt32 XclExpPaletteImpl::InsertColor( const Color& rColor, XclExpColorType eType, sal_uInt16 nAutoDefault )
     332             : {
     333         607 :     if( rColor.GetColor() == COL_AUTO )
     334         124 :         return GetColorIdFromIndex( nAutoDefault );
     335             : 
     336         483 :     sal_uInt32 nFoundIdx = 0;
     337         483 :     XclListColor* pEntry = SearchListEntry( rColor, nFoundIdx );
     338         483 :     if( !pEntry || (pEntry->GetColor() != rColor) )
     339         178 :         pEntry = CreateListEntry( rColor, nFoundIdx );
     340         483 :     pEntry->AddWeighting( lclGetWeighting( eType ) );
     341             : 
     342         483 :     return pEntry->GetColorId();
     343             : }
     344             : 
     345        7746 : sal_uInt32 XclExpPaletteImpl::GetColorIdFromIndex( sal_uInt16 nIndex )
     346             : {
     347        7746 :     return EXC_PAL_INDEXBASE | nIndex;
     348             : }
     349             : 
     350          72 : void XclExpPaletteImpl::Finalize()
     351             : {
     352             : // --- build initial color ID data vector (maColorIdDataVec) ---
     353             : 
     354          72 :     sal_uInt32 nCount = mxColorList->size();
     355          72 :     maColorIdDataVec.resize( nCount );
     356         250 :     for( sal_uInt32 nIdx = 0; nIdx < nCount; ++nIdx )
     357             :     {
     358         178 :         const XclListColor& listColor = mxColorList->at( nIdx );
     359         178 :         maColorIdDataVec[ listColor.GetColorId() ].Set( listColor.GetColor(), nIdx );
     360             :     }
     361             : 
     362             : // --- loop as long as current color count does not fit into palette of current BIFF ---
     363             : 
     364             :     // phase 1: raw reduction (performance reasons, #i36945#)
     365          72 :     sal_uInt32 nPass = 0;
     366         144 :     while( mxColorList->size() > EXC_PAL_MAXRAWSIZE )
     367           0 :         RawReducePalette( nPass++ );
     368             : 
     369             :     // phase 2: precise reduction using advanced color merging based on color weighting
     370         144 :     while( mxColorList->size() > mrDefPal.GetColorCount() )
     371           0 :         ReduceLeastUsedColor();
     372             : 
     373             : // --- use default palette and replace colors with nearest used colors ---
     374             : 
     375          72 :     nCount = mxColorList->size();
     376          72 :     XclRemapVec aRemapVec( nCount );
     377         144 :     XclNearestVec aNearestVec( nCount );
     378             : 
     379             :     // in each run: search the best fitting color and replace a default color with it
     380         250 :     for( sal_uInt32 nRun = 0; nRun < nCount; ++nRun )
     381             :     {
     382             :         sal_uInt32 nIndex;
     383             :         // find nearest unused default color for each unprocessed list color
     384         852 :         for( nIndex = 0; nIndex < nCount; ++nIndex )
     385         674 :             aNearestVec[ nIndex ].mnDist = aRemapVec[ nIndex ].mbProcessed ? SAL_MAX_INT32 :
     386         674 :                 GetNearestPaletteColor( aNearestVec[ nIndex ].mnPalIndex, mxColorList->at( nIndex ).GetColor(), true );
     387             :         // find the list color which is nearest to a default color
     388         178 :         sal_uInt32 nFound = 0;
     389         674 :         for( nIndex = 1; nIndex < nCount; ++nIndex )
     390         496 :             if( aNearestVec[ nIndex ].mnDist < aNearestVec[ nFound ].mnDist )
     391         156 :                 nFound = nIndex;
     392             :         // replace default color with list color
     393         178 :         sal_uInt32 nNearest = aNearestVec[ nFound ].mnPalIndex;
     394             :         OSL_ENSURE( nNearest < maPalette.size(), "XclExpPaletteImpl::Finalize - algorithm error" );
     395         178 :         maPalette[ nNearest ].SetColor( mxColorList->at( nFound ).GetColor() );
     396         178 :         aRemapVec[ nFound ].SetIndex( nNearest );
     397             :     }
     398             : 
     399             :     // remap color ID data map (maColorIdDataVec) from list indexes to palette indexes
     400         250 :     for( XclColorIdDataVec::iterator aIt = maColorIdDataVec.begin(), aEnd = maColorIdDataVec.end(); aIt != aEnd; ++aIt )
     401         250 :         aIt->mnIndex = aRemapVec[ aIt->mnIndex ].mnPalIndex;
     402          72 : }
     403             : 
     404       11936 : sal_uInt16 XclExpPaletteImpl::GetColorIndex( sal_uInt32 nColorId ) const
     405             : {
     406       11936 :     sal_uInt16 nRet = 0;
     407       11936 :     if( nColorId >= EXC_PAL_INDEXBASE )
     408       11776 :         nRet = static_cast< sal_uInt16 >( nColorId & ~EXC_PAL_INDEXBASE );
     409         160 :     else if( nColorId < maColorIdDataVec.size() )
     410         160 :         nRet = GetXclIndex( maColorIdDataVec[ nColorId ].mnIndex );
     411       11936 :     return nRet;
     412             : }
     413             : 
     414        1670 : void XclExpPaletteImpl::GetMixedColors(
     415             :         sal_uInt16& rnXclForeIx, sal_uInt16& rnXclBackIx, sal_uInt8& rnXclPattern,
     416             :         sal_uInt32 nForeColorId, sal_uInt32 nBackColorId ) const
     417             : {
     418        1670 :     rnXclForeIx = GetColorIndex( nForeColorId );
     419        1670 :     rnXclBackIx = GetColorIndex( nBackColorId );
     420        1670 :     if( (rnXclPattern != EXC_PATT_SOLID) || (nForeColorId >= maColorIdDataVec.size()) )
     421        3340 :         return;
     422             : 
     423             :     // now we have solid pattern, and a defined foreground (background doesn't care for solid pattern)
     424             : 
     425             :     sal_uInt32 nIndex1, nIndex2;
     426           0 :     Color aForeColor( GetOriginalColor( nForeColorId ) );
     427           0 :     sal_Int32 nFirstDist = GetNearPaletteColors( nIndex1, nIndex2, aForeColor );
     428           0 :     if( (nIndex1 >= maPalette.size()) || (nIndex2 >= maPalette.size()) )
     429           0 :         return;
     430             : 
     431           0 :     Color aColorArr[ 5 ];
     432           0 :     aColorArr[ 0 ] = maPalette[ nIndex1 ].maColor;
     433           0 :     aColorArr[ 4 ] = maPalette[ nIndex2 ].maColor;
     434           0 :     lclSetMixedColor( aColorArr[ 2 ], aColorArr[ 0 ], aColorArr[ 4 ] );
     435           0 :     lclSetMixedColor( aColorArr[ 1 ], aColorArr[ 0 ], aColorArr[ 2 ] );
     436           0 :     lclSetMixedColor( aColorArr[ 3 ], aColorArr[ 2 ], aColorArr[ 4 ] );
     437             : 
     438           0 :     sal_Int32 nMinDist = nFirstDist;
     439           0 :     sal_uInt32 nMinIndex = 0;
     440           0 :     for( sal_uInt32 nCnt = 1; nCnt < 4; ++nCnt )
     441             :     {
     442           0 :         sal_Int32 nDist = lclGetColorDistance( aForeColor, aColorArr[ nCnt ] );
     443           0 :         if( nDist < nMinDist )
     444             :         {
     445           0 :             nMinDist = nDist;
     446           0 :             nMinIndex = nCnt;
     447             :         }
     448             :     }
     449           0 :     rnXclForeIx = GetXclIndex( nIndex1 );
     450           0 :     rnXclBackIx = GetXclIndex( nIndex2 );
     451           0 :     if( nMinDist < nFirstDist )
     452             :     {
     453           0 :         switch( nMinIndex )
     454             :         {
     455           0 :             case 1: rnXclPattern = EXC_PATT_75_PERC;    break;
     456           0 :             case 2: rnXclPattern = EXC_PATT_50_PERC;    break;
     457           0 :             case 3: rnXclPattern = EXC_PATT_25_PERC;    break;
     458             :         }
     459             :     }
     460             : }
     461             : 
     462         510 : ColorData XclExpPaletteImpl::GetColorData( sal_uInt16 nXclIndex ) const
     463             : {
     464         510 :     if( nXclIndex >= EXC_COLOR_USEROFFSET )
     465             :     {
     466         109 :         sal_uInt32 nIdx = nXclIndex - EXC_COLOR_USEROFFSET;
     467         109 :         if( nIdx < maPalette.size() )
     468         109 :             return maPalette[ nIdx ].maColor.GetColor();
     469             :     }
     470         401 :     return mrDefPal.GetDefColorData( nXclIndex );
     471             : }
     472             : 
     473          72 : bool XclExpPaletteImpl::IsDefaultPalette() const
     474             : {
     475          72 :     bool bDefault = true;
     476        3091 :     for( sal_uInt32 nIdx = 0, nSize = static_cast< sal_uInt32 >( maPalette.size() ); bDefault && (nIdx < nSize); ++nIdx )
     477        3019 :         bDefault = maPalette[ nIdx ].maColor == mrDefPal.GetDefColor( GetXclIndex( nIdx ) );
     478          72 :     return bDefault;
     479             : }
     480             : 
     481           1 : void XclExpPaletteImpl::WriteBody( XclExpStream& rStrm )
     482             : {
     483           1 :     rStrm << static_cast< sal_uInt16 >( maPalette.size() );
     484          57 :     for( XclPaletteColorVec::const_iterator aIt = maPalette.begin(), aEnd = maPalette.end(); aIt != aEnd; ++aIt )
     485          56 :         rStrm << aIt->maColor;
     486           1 : }
     487             : 
     488          27 : void XclExpPaletteImpl::SaveXml( XclExpXmlStream& rStrm )
     489             : {
     490          27 :     if( !maPalette.size() )
     491          27 :         return;
     492             : 
     493          27 :     sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream();
     494          27 :     rStyleSheet->startElement( XML_colors, FSEND );
     495          27 :     rStyleSheet->startElement( XML_indexedColors, FSEND );
     496        1539 :     for( XclPaletteColorVec::const_iterator aIt = maPalette.begin(), aEnd = maPalette.end(); aIt != aEnd; ++aIt )
     497             :         rStyleSheet->singleElement( XML_rgbColor,
     498        1512 :                 XML_rgb,    XclXmlUtils::ToOString( aIt->maColor ).getStr(),
     499        1512 :                 FSEND );
     500          27 :     rStyleSheet->endElement( XML_indexedColors );
     501          27 :     rStyleSheet->endElement( XML_colors );
     502             : }
     503             : 
     504           0 : const Color& XclExpPaletteImpl::GetOriginalColor( sal_uInt32 nColorId ) const
     505             : {
     506           0 :     if( nColorId < maColorIdDataVec.size() )
     507           0 :         return maColorIdDataVec[ nColorId ].maColor;
     508           0 :     return maPalette[ 0 ].maColor;
     509             : }
     510             : 
     511         483 : XclListColor* XclExpPaletteImpl::SearchListEntry( const Color& rColor, sal_uInt32& rnIndex )
     512             : {
     513         483 :     rnIndex = 0;
     514             : 
     515         483 :     if (mxColorList->empty())
     516          72 :         return NULL;
     517             : 
     518         411 :     XclListColor* pEntry = NULL;
     519             : 
     520             :     // search optimization for equal-colored objects occurring repeatedly
     521         411 :     if (mnLastIdx < mxColorList->size())
     522             :     {
     523         411 :         pEntry = &(*mxColorList)[mnLastIdx];
     524         411 :         if( pEntry->GetColor() == rColor )
     525             :         {
     526         239 :             rnIndex = mnLastIdx;
     527         239 :             return pEntry;
     528             :         }
     529             :     }
     530             : 
     531             :     // binary search for color
     532         172 :     sal_uInt32 nBegIdx = 0;
     533         172 :     sal_uInt32 nEndIdx = mxColorList->size();
     534         172 :     bool bFound = false;
     535         659 :     while( !bFound && (nBegIdx < nEndIdx) )
     536             :     {
     537         315 :         rnIndex = (nBegIdx + nEndIdx) / 2;
     538         315 :         pEntry = &(*mxColorList)[rnIndex];
     539         315 :         bFound = pEntry->GetColor() == rColor;
     540         315 :         if( !bFound )
     541             :         {
     542         249 :             if( pEntry->GetColor().GetColor() < rColor.GetColor() )
     543         150 :                 nBegIdx = rnIndex + 1;
     544             :             else
     545          99 :                 nEndIdx = rnIndex;
     546             :         }
     547             :     }
     548             : 
     549             :     // not found - use end of range as new insertion position
     550         172 :     if( !bFound )
     551         106 :         rnIndex = nEndIdx;
     552             : 
     553         172 :     mnLastIdx = rnIndex;
     554         172 :     return pEntry;
     555             : }
     556             : 
     557         178 : XclListColor* XclExpPaletteImpl::CreateListEntry( const Color& rColor, sal_uInt32 nIndex )
     558             : {
     559         178 :     XclListColor* pEntry = new XclListColor( rColor, mxColorList->size() );
     560         178 :     XclListColorList::iterator itr = mxColorList->begin();
     561         178 :     ::std::advance(itr, nIndex);
     562         178 :     mxColorList->insert(itr, pEntry);
     563         178 :     return pEntry;
     564             : }
     565             : 
     566           0 : void XclExpPaletteImpl::RawReducePalette( sal_uInt32 nPass )
     567             : {
     568             :     /*  Fast palette reduction - in each call of this function one RGB component
     569             :         of each color is reduced to a lower number of distinct values.
     570             :         Pass 0: Blue is reduced to 128 distinct values.
     571             :         Pass 1: Red is reduced to 128 distinct values.
     572             :         Pass 2: Green is reduced to 128 distinct values.
     573             :         Pass 3: Blue is reduced to 64 distinct values.
     574             :         Pass 4: Red is reduced to 64 distinct values.
     575             :         Pass 5: Green is reduced to 64 distinct values.
     576             :         And so on...
     577             :      */
     578             : 
     579           0 :     XclListColorListRef xOldList = mxColorList;
     580           0 :     mxColorList.reset( new XclListColorList );
     581             : 
     582             :     // maps old list indexes to new list indexes, used to update maColorIdDataVec
     583           0 :     ScfUInt32Vec aListIndexMap;
     584           0 :     aListIndexMap.reserve( xOldList->size() );
     585             : 
     586             :     // preparations
     587             :     sal_uInt8 nR, nG, nB;
     588           0 :     sal_uInt8& rnComp = ((nPass % 3 == 0) ? nB : ((nPass % 3 == 1) ? nR : nG));
     589           0 :     nPass /= 3;
     590             :     OSL_ENSURE( nPass < 7, "XclExpPaletteImpl::RawReducePalette - reduction not terminated" );
     591             : 
     592             :     static const sal_uInt8 spnFactor2[] = { 0x81, 0x82, 0x84, 0x88, 0x92, 0xAA, 0xFF };
     593           0 :     sal_uInt8 nFactor1 = static_cast< sal_uInt8 >( 0x02 << nPass );
     594           0 :     sal_uInt8 nFactor2 = spnFactor2[ nPass ];
     595           0 :     sal_uInt8 nFactor3 = static_cast< sal_uInt8 >( 0x40 >> nPass );
     596             : 
     597             :     // process each color in the old color list
     598           0 :     for( sal_uInt32 nIdx = 0, nCount = xOldList->size(); nIdx < nCount; ++nIdx )
     599             :     {
     600             :         // get the old list entry
     601           0 :         const XclListColor* pOldEntry = &(xOldList->at( nIdx ));
     602           0 :         nR = pOldEntry->GetColor().GetRed();
     603           0 :         nG = pOldEntry->GetColor().GetGreen();
     604           0 :         nB = pOldEntry->GetColor().GetBlue();
     605             : 
     606             :         /*  Calculate the new RGB component (rnComp points to one of nR, nG, nB).
     607             :             Using integer arithmetic with its rounding errors, the results of
     608             :             this calculation are always exactly in the range 0x00 to 0xFF
     609             :             (simply cutting the lower bits would darken the colors slightly). */
     610           0 :         sal_uInt32 nNewComp = rnComp;
     611           0 :         nNewComp /= nFactor1;
     612           0 :         nNewComp *= nFactor2;
     613           0 :         nNewComp /= nFactor3;
     614           0 :         rnComp = static_cast< sal_uInt8 >( nNewComp );
     615           0 :         Color aNewColor( nR, nG, nB );
     616             : 
     617             :         // find or insert the new color
     618           0 :         sal_uInt32 nFoundIdx = 0;
     619           0 :         XclListColor* pNewEntry = SearchListEntry( aNewColor, nFoundIdx );
     620           0 :         if( !pNewEntry || (pNewEntry->GetColor() != aNewColor) )
     621           0 :             pNewEntry = CreateListEntry( aNewColor, nFoundIdx );
     622           0 :         pNewEntry->AddWeighting( pOldEntry->GetWeighting() );
     623           0 :         aListIndexMap.push_back( nFoundIdx );
     624             :     }
     625             : 
     626             :     // update color ID data map (maps color IDs to color list indexes), replace old by new list indexes
     627           0 :     for( XclColorIdDataVec::iterator aIt = maColorIdDataVec.begin(), aEnd = maColorIdDataVec.end(); aIt != aEnd; ++aIt )
     628           0 :         aIt->mnIndex = aListIndexMap[ aIt->mnIndex ];
     629           0 : }
     630             : 
     631           0 : void XclExpPaletteImpl::ReduceLeastUsedColor()
     632             : {
     633             :     // find a list color to remove
     634           0 :     sal_uInt32 nRemove = GetLeastUsedListColor();
     635             :     // find its nearest neighbor
     636           0 :     sal_uInt32 nKeep = GetNearestListColor( nRemove );
     637             : 
     638             :     // merge both colors to one color, remove one color from list
     639           0 :     XclListColor* pKeepEntry = &mxColorList->at(nKeep);
     640           0 :     XclListColor* pRemoveEntry = &mxColorList->at(nRemove);
     641           0 :     if( pKeepEntry && pRemoveEntry )
     642             :     {
     643             :         // merge both colors (if pKeepEntry is a base color, it will not change)
     644           0 :         pKeepEntry->Merge( *pRemoveEntry );
     645             :         // remove the less used color, adjust nKeep index if kept color follows removed color
     646           0 :         XclListColorList::iterator itr = mxColorList->begin();
     647           0 :         ::std::advance(itr, nRemove);
     648           0 :         mxColorList->erase(itr);
     649           0 :         if( nKeep > nRemove ) --nKeep;
     650             : 
     651             :         // recalculate color ID data map (maps color IDs to color list indexes)
     652           0 :         for( XclColorIdDataVec::iterator aIt = maColorIdDataVec.begin(), aEnd = maColorIdDataVec.end(); aIt != aEnd; ++aIt )
     653             :         {
     654           0 :             if( aIt->mnIndex > nRemove )
     655           0 :                 --aIt->mnIndex;
     656           0 :             else if( aIt->mnIndex == nRemove )
     657           0 :                 aIt->mnIndex = nKeep;
     658             :         }
     659             :     }
     660           0 : }
     661             : 
     662           0 : sal_uInt32 XclExpPaletteImpl::GetLeastUsedListColor() const
     663             : {
     664           0 :     sal_uInt32 nFound = 0;
     665           0 :     sal_uInt32 nMinW = SAL_MAX_UINT32;
     666             : 
     667           0 :     for( sal_uInt32 nIdx = 0, nCount = mxColorList->size(); nIdx < nCount; ++nIdx )
     668             :     {
     669           0 :         XclListColor& pEntry = mxColorList->at( nIdx );
     670             :         // ignore the base colors
     671           0 :         if( !pEntry.IsBaseColor() && (pEntry.GetWeighting() < nMinW) )
     672             :         {
     673           0 :             nFound = nIdx;
     674           0 :             nMinW = pEntry.GetWeighting();
     675             :         }
     676             :     }
     677           0 :     return nFound;
     678             : }
     679             : 
     680           0 : sal_uInt32 XclExpPaletteImpl::GetNearestListColor( const Color& rColor, sal_uInt32 nIgnore ) const
     681             : {
     682           0 :     sal_uInt32 nFound = 0;
     683           0 :     sal_Int32 nMinD = SAL_MAX_INT32;
     684             : 
     685           0 :     for( sal_uInt32 nIdx = 0, nCount = mxColorList->size(); nIdx < nCount; ++nIdx )
     686             :     {
     687           0 :         if( nIdx != nIgnore )
     688             :         {
     689           0 :             if( XclListColor* pEntry = &mxColorList->at(nIdx) )
     690             :             {
     691           0 :                 sal_Int32 nDist = lclGetColorDistance( rColor, pEntry->GetColor() );
     692           0 :                 if( nDist < nMinD )
     693             :                 {
     694           0 :                     nFound = nIdx;
     695           0 :                     nMinD = nDist;
     696             :                 }
     697             :             }
     698             :         }
     699             :     }
     700           0 :     return nFound;
     701             : }
     702             : 
     703           0 : sal_uInt32 XclExpPaletteImpl::GetNearestListColor( sal_uInt32 nIndex ) const
     704             : {
     705           0 :     if (nIndex >= mxColorList->size())
     706           0 :         return 0;
     707           0 :     XclListColor* pEntry = &mxColorList->at(nIndex);
     708           0 :     return GetNearestListColor( pEntry->GetColor(), nIndex );
     709             : }
     710             : 
     711         426 : sal_Int32 XclExpPaletteImpl::GetNearestPaletteColor(
     712             :         sal_uInt32& rnIndex, const Color& rColor, bool bDefaultOnly ) const
     713             : {
     714         426 :     rnIndex = 0;
     715         426 :     sal_Int32 nDist = SAL_MAX_INT32;
     716             : 
     717       24282 :     for( XclPaletteColorVec::const_iterator aIt = maPalette.begin(), aEnd = maPalette.end();
     718             :             aIt != aEnd; ++aIt )
     719             :     {
     720       23856 :         if( !bDefaultOnly || !aIt->mbUsed )
     721             :         {
     722       23357 :             sal_Int32 nCurrDist = lclGetColorDistance( rColor, aIt->maColor );
     723       23357 :             if( nCurrDist < nDist )
     724             :             {
     725        2089 :                 rnIndex = aIt - maPalette.begin();
     726        2089 :                 nDist = nCurrDist;
     727             :             }
     728             :         }
     729             :     }
     730         426 :     return nDist;
     731             : }
     732             : 
     733           0 : sal_Int32 XclExpPaletteImpl::GetNearPaletteColors(
     734             :         sal_uInt32& rnFirst, sal_uInt32& rnSecond, const Color& rColor ) const
     735             : {
     736           0 :     rnFirst = rnSecond = 0;
     737           0 :     sal_Int32 nDist1 = SAL_MAX_INT32;
     738           0 :     sal_Int32 nDist2 = SAL_MAX_INT32;
     739             : 
     740           0 :     for( XclPaletteColorVec::const_iterator aIt = maPalette.begin(), aEnd = maPalette.end();
     741             :             aIt != aEnd; ++aIt )
     742             :     {
     743           0 :         sal_Int32 nCurrDist = lclGetColorDistance( rColor, aIt->maColor );
     744           0 :         if( nCurrDist < nDist1 )
     745             :         {
     746           0 :             rnSecond = rnFirst;
     747           0 :             nDist2 = nDist1;
     748           0 :             rnFirst = aIt - maPalette.begin();
     749           0 :             nDist1 = nCurrDist;
     750             :         }
     751           0 :         else if( nCurrDist < nDist2 )
     752             :         {
     753           0 :             rnSecond = aIt - maPalette.begin();
     754           0 :             nDist2 = nCurrDist;
     755             :         }
     756             :     }
     757           0 :     return nDist1;
     758             : }
     759             : 
     760          72 : XclExpPalette::XclExpPalette( const XclExpRoot& rRoot ) :
     761             :     XclDefaultPalette( rRoot ),
     762          72 :     XclExpRecord( EXC_ID_PALETTE )
     763             : {
     764          72 :     mxImpl.reset( new XclExpPaletteImpl( *this ) );
     765          72 :     SetRecSize( GetColorCount() * 4 + 2 );
     766          72 : }
     767             : 
     768         144 : XclExpPalette::~XclExpPalette()
     769             : {
     770         144 : }
     771             : 
     772         535 : sal_uInt32 XclExpPalette::InsertColor( const Color& rColor, XclExpColorType eType, sal_uInt16 nAutoDefault )
     773             : {
     774         535 :     return mxImpl->InsertColor( rColor, eType, nAutoDefault );
     775             : }
     776             : 
     777        7622 : sal_uInt32 XclExpPalette::GetColorIdFromIndex( sal_uInt16 nIndex )
     778             : {
     779        7622 :     return XclExpPaletteImpl::GetColorIdFromIndex( nIndex );
     780             : }
     781             : 
     782          72 : void XclExpPalette::Finalize()
     783             : {
     784          72 :     mxImpl->Finalize();
     785          72 : }
     786             : 
     787        8596 : sal_uInt16 XclExpPalette::GetColorIndex( sal_uInt32 nColorId ) const
     788             : {
     789        8596 :     return mxImpl->GetColorIndex( nColorId );
     790             : }
     791             : 
     792        1670 : void XclExpPalette::GetMixedColors(
     793             :         sal_uInt16& rnXclForeIx, sal_uInt16& rnXclBackIx, sal_uInt8& rnXclPattern,
     794             :         sal_uInt32 nForeColorId, sal_uInt32 nBackColorId ) const
     795             : {
     796        1670 :     return mxImpl->GetMixedColors( rnXclForeIx, rnXclBackIx, rnXclPattern, nForeColorId, nBackColorId );
     797             : }
     798             : 
     799         510 : ColorData XclExpPalette::GetColorData( sal_uInt16 nXclIndex ) const
     800             : {
     801         510 :     return mxImpl->GetColorData( nXclIndex );
     802             : }
     803             : 
     804          17 : void XclExpPalette::Save( XclExpStream& rStrm )
     805             : {
     806          17 :     if( !mxImpl->IsDefaultPalette() )
     807           1 :         XclExpRecord::Save( rStrm );
     808          17 : }
     809             : 
     810          55 : void XclExpPalette::SaveXml( XclExpXmlStream& rStrm )
     811             : {
     812          55 :     if( !mxImpl->IsDefaultPalette() )
     813          27 :         mxImpl->SaveXml( rStrm );
     814          55 : }
     815             : 
     816           1 : void XclExpPalette::WriteBody( XclExpStream& rStrm )
     817             : {
     818           1 :     mxImpl->WriteBody( rStrm );
     819           1 : }
     820             : 
     821             : // FONT record - font information =============================================
     822             : 
     823             : namespace {
     824             : 
     825             : typedef ::std::pair< sal_uInt16, sal_Int16 > WhichAndScript;
     826             : 
     827          34 : sal_Int16 lclCheckFontItems( const SfxItemSet& rItemSet,
     828             :         const WhichAndScript& rWAS1, const WhichAndScript& rWAS2, const WhichAndScript& rWAS3 )
     829             : {
     830          34 :     if( ScfTools::CheckItem( rItemSet, rWAS1.first, false ) ) return rWAS1.second;
     831          22 :     if( ScfTools::CheckItem( rItemSet, rWAS2.first, false ) ) return rWAS2.second;
     832          22 :     if( ScfTools::CheckItem( rItemSet, rWAS3.first, false ) ) return rWAS3.second;
     833          22 :     return 0;
     834             : };
     835             : 
     836             : } // namespace
     837             : 
     838          22 : sal_Int16 XclExpFontHelper::GetFirstUsedScript( const XclExpRoot& rRoot, const SfxItemSet& rItemSet )
     839             : {
     840             :     namespace ApiScriptType = ::com::sun::star::i18n::ScriptType;
     841             : 
     842             :     /*  #i17050# #i107170# We need to determine which font items are set in the
     843             :         item set, and which script type we should prefer according to the
     844             :         current language settings. */
     845             : 
     846             :     static const WhichAndScript WAS_LATIN( ATTR_FONT, ::com::sun::star::i18n::ScriptType::LATIN );
     847             :     static const WhichAndScript WAS_ASIAN( ATTR_CJK_FONT, ::com::sun::star::i18n::ScriptType::ASIAN );
     848             :     static const WhichAndScript WAS_CMPLX( ATTR_CTL_FONT, ::com::sun::star::i18n::ScriptType::COMPLEX );
     849             : 
     850             :     /*  do not let a font from a parent style override an explicit
     851             :         cell font. */
     852             : 
     853          22 :     sal_Int16 nDefScript = rRoot.GetDefApiScript();
     854          22 :     sal_Int16 nScript = 0;
     855          22 :     const SfxItemSet* pCurrSet = &rItemSet;
     856             : 
     857          78 :     while( (nScript == 0) && pCurrSet )
     858             :     {
     859          34 :         switch( nDefScript )
     860             :         {
     861             :             case ApiScriptType::LATIN:
     862          34 :                 nScript = lclCheckFontItems( *pCurrSet, WAS_LATIN, WAS_CMPLX, WAS_ASIAN );
     863          34 :             break;
     864             :             case ApiScriptType::ASIAN:
     865           0 :                 nScript = lclCheckFontItems( *pCurrSet, WAS_ASIAN, WAS_CMPLX, WAS_LATIN );
     866           0 :             break;
     867             :             case ApiScriptType::COMPLEX:
     868           0 :                 nScript = lclCheckFontItems( *pCurrSet, WAS_CMPLX, WAS_ASIAN, WAS_LATIN );
     869           0 :             break;
     870             :             default:
     871             :                 OSL_FAIL( "XclExpFontHelper::GetFirstUsedScript - unknown script type" );
     872           0 :                 nScript = ApiScriptType::LATIN;
     873             :         };
     874          34 :         pCurrSet = pCurrSet->GetParent();
     875             :     }
     876             : 
     877          22 :     if (nScript == 0)
     878          10 :         nScript = nDefScript;
     879             : 
     880          22 :     if (nScript == 0)
     881             :     {
     882             :         OSL_FAIL( "XclExpFontHelper::GetFirstUsedScript - unknown script type" );
     883           0 :         nScript = ApiScriptType::LATIN;
     884             :     }
     885             : 
     886          22 :     return nScript;
     887             : }
     888             : 
     889         737 : vcl::Font XclExpFontHelper::GetFontFromItemSet( const XclExpRoot& rRoot, const SfxItemSet& rItemSet, sal_Int16 nScript )
     890             : {
     891             :     // if WEAK is passed, guess script type from existing items in the item set
     892         737 :     if( nScript == css::i18n::ScriptType::WEAK )
     893          12 :         nScript = GetFirstUsedScript( rRoot, rItemSet );
     894             : 
     895             :     // convert to core script type constants
     896         737 :     SvtScriptType nScScript = SvtLanguageOptions::FromI18NToSvtScriptType(nScript);
     897             : 
     898             :     // fill the font object
     899         737 :     vcl::Font aFont;
     900         737 :     ScPatternAttr::GetFont( aFont, rItemSet, SC_AUTOCOL_RAW, 0, 0, 0, nScScript );
     901         737 :     return aFont;
     902             : }
     903             : 
     904          10 : ScDxfFont XclExpFontHelper::GetDxfFontFromItemSet(const XclExpRoot& rRoot, const SfxItemSet& rItemSet)
     905             : {
     906          10 :     sal_Int16 nScript = GetFirstUsedScript(rRoot, rItemSet);
     907             : 
     908             :     // convert to core script type constants
     909          10 :     SvtScriptType nScScript = SvtLanguageOptions::FromI18NToSvtScriptType(nScript);
     910          10 :     return ScPatternAttr::GetDxfFont(rItemSet, nScScript);
     911             : }
     912             : 
     913         268 : bool XclExpFontHelper::CheckItems( const XclExpRoot& rRoot, const SfxItemSet& rItemSet, sal_Int16 nScript, bool bDeep )
     914             : {
     915             :     static const sal_uInt16 pnCommonIds[] = {
     916             :         ATTR_FONT_UNDERLINE, ATTR_FONT_CROSSEDOUT, ATTR_FONT_CONTOUR,
     917             :         ATTR_FONT_SHADOWED, ATTR_FONT_COLOR, ATTR_FONT_LANGUAGE, 0 };
     918             :     static const sal_uInt16 pnLatinIds[] = {
     919             :         ATTR_FONT, ATTR_FONT_HEIGHT, ATTR_FONT_WEIGHT, ATTR_FONT_POSTURE, 0 };
     920             :     static const sal_uInt16 pnAsianIds[] = {
     921             :         ATTR_CJK_FONT, ATTR_CJK_FONT_HEIGHT, ATTR_CJK_FONT_WEIGHT, ATTR_CJK_FONT_POSTURE, 0 };
     922             :     static const sal_uInt16 pnComplexIds[] = {
     923             :         ATTR_CTL_FONT, ATTR_CTL_FONT_HEIGHT, ATTR_CTL_FONT_WEIGHT, ATTR_CTL_FONT_POSTURE, 0 };
     924             : 
     925         268 :     bool bUsed = ScfTools::CheckItems( rItemSet, pnCommonIds, bDeep );
     926         268 :     if( !bUsed )
     927             :     {
     928             :         namespace ApiScriptType = ::com::sun::star::i18n::ScriptType;
     929             :         // if WEAK is passed, guess script type from existing items in the item set
     930         200 :         if( nScript == ApiScriptType::WEAK )
     931           0 :             nScript = GetFirstUsedScript( rRoot, rItemSet );
     932             :         // check the correct items
     933         200 :         switch( nScript )
     934             :         {
     935         200 :             case ApiScriptType::LATIN:      bUsed = ScfTools::CheckItems( rItemSet, pnLatinIds, bDeep );    break;
     936           0 :             case ApiScriptType::ASIAN:      bUsed = ScfTools::CheckItems( rItemSet, pnAsianIds, bDeep );    break;
     937           0 :             case ApiScriptType::COMPLEX:    bUsed = ScfTools::CheckItems( rItemSet, pnComplexIds, bDeep );  break;
     938             :             default:    OSL_FAIL( "XclExpFontHelper::CheckItems - unknown script type" );
     939             :         }
     940             :     }
     941         268 :     return bUsed;
     942             : }
     943             : 
     944             : namespace {
     945             : 
     946         985 : sal_uInt32 lclCalcHash( const XclFontData& rFontData )
     947             : {
     948         985 :     sal_uInt32 nHash = rFontData.maName.getLength();
     949         985 :     nHash += rFontData.maColor.GetColor() * 2;
     950         985 :     nHash += rFontData.mnWeight * 3;
     951         985 :     nHash += rFontData.mnCharSet * 5;
     952         985 :     nHash += rFontData.mnFamily * 7;
     953         985 :     nHash += rFontData.mnHeight * 11;
     954         985 :     nHash += rFontData.mnUnderline * 13;
     955         985 :     nHash += rFontData.mnEscapem * 17;
     956         985 :     if( rFontData.mbItalic ) nHash += 19;
     957         985 :     if( rFontData.mbStrikeout ) nHash += 23;
     958         985 :     if( rFontData.mbOutline ) nHash += 29;
     959         985 :     if( rFontData.mbShadow ) nHash += 31;
     960         985 :     return nHash;
     961             : }
     962             : 
     963             : } // namespace
     964             : 
     965         225 : XclExpFont::XclExpFont( const XclExpRoot& rRoot,
     966             :         const XclFontData& rFontData, XclExpColorType eColorType ) :
     967             :     XclExpRecord( EXC_ID2_FONT, 14 ),
     968             :     XclExpRoot( rRoot ),
     969         225 :     maData( rFontData )
     970             : {
     971             :     // insert font color into palette
     972         225 :     mnColorId = rRoot.GetPalette().InsertColor( rFontData.maColor, eColorType, EXC_COLOR_FONTAUTO );
     973             :     // hash value for faster comparison
     974         225 :     mnHash = lclCalcHash( maData );
     975             :     // record size
     976         225 :     sal_Int32 nStrLen = maData.maName.getLength();
     977         225 :     SetRecSize( ((GetBiff() == EXC_BIFF8) ? (nStrLen * 2 + 1) : nStrLen) + 15 );
     978         225 : }
     979             : 
     980        2119 : bool XclExpFont::Equals( const XclFontData& rFontData, sal_uInt32 nHash ) const
     981             : {
     982        2119 :     return (mnHash == nHash) && (maData == rFontData);
     983             : }
     984             : 
     985         276 : void XclExpFont::SaveXml( XclExpXmlStream& rStrm )
     986             : {
     987         276 :     sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream();
     988         276 :     rStyleSheet->startElement( XML_font, FSEND );
     989         276 :     XclXmlUtils::WriteFontData( rStyleSheet, maData, XML_name );
     990             :     // OOXTODO: XML_scheme; //scheme/@val values: "major", "minor", "none"
     991         276 :     rStyleSheet->endElement( XML_font );
     992         276 : }
     993             : 
     994             : // private --------------------------------------------------------------------
     995             : 
     996          76 : void XclExpFont::WriteBody( XclExpStream& rStrm )
     997             : {
     998          76 :     sal_uInt16 nAttr = EXC_FONTATTR_NONE;
     999          76 :     ::set_flag( nAttr, EXC_FONTATTR_ITALIC, maData.mbItalic );
    1000          76 :     ::set_flag( nAttr, EXC_FONTATTR_STRIKEOUT, maData.mbStrikeout );
    1001          76 :     ::set_flag( nAttr, EXC_FONTATTR_OUTLINE, maData.mbOutline );
    1002          76 :     ::set_flag( nAttr, EXC_FONTATTR_SHADOW, maData.mbShadow );
    1003             : 
    1004             :     OSL_ENSURE( maData.maName.getLength() < 256, "XclExpFont::WriteBody - font name too long" );
    1005          76 :     XclExpString aFontName;
    1006          76 :     if( GetBiff() <= EXC_BIFF5 )
    1007           0 :         aFontName.AssignByte( maData.maName, GetTextEncoding(), EXC_STR_8BITLENGTH );
    1008             :     else
    1009          76 :         aFontName.Assign( maData.maName, EXC_STR_FORCEUNICODE | EXC_STR_8BITLENGTH );
    1010             : 
    1011          76 :     rStrm   << maData.mnHeight
    1012         152 :             << nAttr
    1013         152 :             << GetPalette().GetColorIndex( mnColorId )
    1014         152 :             << maData.mnWeight
    1015         152 :             << maData.mnEscapem
    1016         152 :             << maData.mnUnderline
    1017         152 :             << maData.mnFamily
    1018         152 :             << maData.mnCharSet
    1019          76 :             << sal_uInt8( 0 )
    1020          76 :             << aFontName;
    1021          76 : }
    1022             : 
    1023          10 : XclExpDxfFont::XclExpDxfFont(const XclExpRoot& rRoot,
    1024             :         const SfxItemSet& rItemSet):
    1025          10 :     XclExpRoot(rRoot)
    1026             : {
    1027          10 :     maDxfData = XclExpFontHelper::GetDxfFontFromItemSet(rRoot, rItemSet);
    1028          10 : }
    1029             : 
    1030             : namespace {
    1031             : 
    1032           0 : const char* getUnderlineOOXValue(FontUnderline eUnderline)
    1033             : {
    1034           0 :     switch (eUnderline)
    1035             :     {
    1036             :         case UNDERLINE_NONE:
    1037             :         case UNDERLINE_DONTKNOW:
    1038           0 :             return "none";
    1039             :         case UNDERLINE_DOUBLE:
    1040             :         case UNDERLINE_DOUBLEWAVE:
    1041           0 :             return "double";
    1042             :         default:
    1043           0 :             return "single";
    1044             :     }
    1045             : }
    1046             : 
    1047           0 : const char* getFontFamilyOOXValue(FontFamily eValue)
    1048             : {
    1049           0 :     switch (eValue)
    1050             :     {
    1051             :         case FAMILY_DONTKNOW:
    1052           0 :             return "0";
    1053             :         break;
    1054             :         case FAMILY_SWISS:
    1055             :         case FAMILY_SYSTEM:
    1056           0 :             return "2";
    1057             :         case FAMILY_ROMAN:
    1058           0 :             return "1";
    1059             :         case FAMILY_SCRIPT:
    1060           0 :             return "4";
    1061             :         case FAMILY_MODERN:
    1062           0 :             return "3";
    1063             :         case FAMILY_DECORATIVE:
    1064           0 :             return "5";
    1065             :         default:
    1066           0 :             return "0";
    1067             :     }
    1068             : }
    1069             : 
    1070             : }
    1071             : 
    1072          10 : void XclExpDxfFont::SaveXml(XclExpXmlStream& rStrm)
    1073             : {
    1074          10 :     if (maDxfData.isEmpty())
    1075          20 :         return;
    1076             : 
    1077           0 :     sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream();
    1078           0 :     rStyleSheet->startElement(XML_font, FSEND);
    1079             : 
    1080           0 :     if (maDxfData.pFontAttr)
    1081             :     {
    1082           0 :         OUString aFontName = (*maDxfData.pFontAttr)->GetFamilyName();
    1083             : 
    1084           0 :         aFontName = XclTools::GetXclFontName(aFontName);
    1085           0 :         if (!aFontName.isEmpty())
    1086             :         {
    1087             :             rStyleSheet->singleElement(XML_name,
    1088             :                     XML_val, XclXmlUtils::ToOString(aFontName).getStr(),
    1089           0 :                     FSEND);
    1090             :         }
    1091             : 
    1092           0 :         rtl_TextEncoding eTextEnc = (*maDxfData.pFontAttr)->GetCharSet();
    1093           0 :         sal_uInt8 nExcelCharSet = rtl_getBestWindowsCharsetFromTextEncoding(eTextEnc);
    1094           0 :         if (nExcelCharSet)
    1095             :         {
    1096             :             rStyleSheet->singleElement(XML_charset,
    1097             :                     XML_val, OString::number(nExcelCharSet).getStr(),
    1098           0 :                     FSEND);
    1099             :         }
    1100             : 
    1101           0 :         FontFamily eFamily = (*maDxfData.pFontAttr)->GetFamily();
    1102           0 :         const char* pVal = getFontFamilyOOXValue(eFamily);
    1103           0 :         if (pVal)
    1104             :         {
    1105             :             rStyleSheet->singleElement(XML_family,
    1106             :                     XML_val, pVal,
    1107           0 :                     FSEND);
    1108           0 :         }
    1109             :     }
    1110             : 
    1111           0 :     if (maDxfData.eWeight)
    1112             :     {
    1113             :         rStyleSheet->singleElement(XML_b,
    1114           0 :                 XML_val, XclXmlUtils::ToPsz10(maDxfData.eWeight.get() != WEIGHT_NORMAL),
    1115           0 :                 FSEND);
    1116             :     }
    1117             : 
    1118           0 :     if (maDxfData.eItalic)
    1119             :     {
    1120           0 :         bool bItalic = (maDxfData.eItalic.get() == ITALIC_OBLIQUE) || (maDxfData.eItalic.get() == ITALIC_NORMAL);
    1121             :         rStyleSheet->singleElement(XML_i,
    1122             :                 XML_val, XclXmlUtils::ToPsz10(bItalic),
    1123           0 :                 FSEND);
    1124             :     }
    1125             : 
    1126           0 :     if (maDxfData.eStrike)
    1127             :     {
    1128             :         bool bStrikeout =
    1129           0 :             (maDxfData.eStrike.get() == STRIKEOUT_SINGLE) || (maDxfData.eStrike.get() == STRIKEOUT_DOUBLE) ||
    1130           0 :             (maDxfData.eStrike.get() == STRIKEOUT_BOLD)   || (maDxfData.eStrike.get() == STRIKEOUT_SLASH)  ||
    1131           0 :             (maDxfData.eStrike.get() == STRIKEOUT_X);
    1132             : 
    1133             :         rStyleSheet->singleElement(XML_strike,
    1134             :                 XML_val, XclXmlUtils::ToPsz10(bStrikeout),
    1135           0 :                 FSEND);
    1136             :     }
    1137             : 
    1138           0 :     if (maDxfData.bOutline)
    1139             :     {
    1140             :         rStyleSheet->singleElement(XML_outline,
    1141           0 :                 XML_val, XclXmlUtils::ToPsz10(maDxfData.bOutline.get()),
    1142           0 :                 FSEND);
    1143             :     }
    1144             : 
    1145           0 :     if (maDxfData.bShadow)
    1146             :     {
    1147             :         rStyleSheet->singleElement(XML_shadow,
    1148           0 :                 XML_val, XclXmlUtils::ToPsz10(maDxfData.bShadow.get()),
    1149           0 :                 FSEND);
    1150             :     }
    1151             : 
    1152           0 :     if (maDxfData.aColor)
    1153             :     {
    1154             :         rStyleSheet->singleElement(XML_color,
    1155           0 :                 XML_rgb, XclXmlUtils::ToOString(maDxfData.aColor.get()).getStr(),
    1156           0 :                 FSEND);
    1157             :     }
    1158             : 
    1159           0 :     if (maDxfData.eUnder)
    1160             :     {
    1161           0 :         const char* pVal = getUnderlineOOXValue(maDxfData.eUnder.get());
    1162             :         rStyleSheet->singleElement(XML_u,
    1163             :                 XML_val, pVal,
    1164           0 :                 FSEND);
    1165             :     }
    1166             : 
    1167           0 :     rStyleSheet->endElement(XML_font);
    1168             : }
    1169             : 
    1170          17 : XclExpBlindFont::XclExpBlindFont( const XclExpRoot& rRoot ) :
    1171          17 :     XclExpFont( rRoot, XclFontData(), EXC_COLOR_CELLTEXT )
    1172             : {
    1173          17 : }
    1174             : 
    1175         102 : bool XclExpBlindFont::Equals( const XclFontData& /*rFontData*/, sal_uInt32 /*nHash*/ ) const
    1176             : {
    1177         102 :     return false;
    1178             : }
    1179             : 
    1180          17 : void XclExpBlindFont::Save( XclExpStream& /*rStrm*/ )
    1181             : {
    1182             :     // do nothing
    1183          17 : }
    1184             : 
    1185          72 : XclExpFontBuffer::XclExpFontBuffer( const XclExpRoot& rRoot ) :
    1186             :     XclExpRoot( rRoot ),
    1187          72 :     mnXclMaxSize( 0 )
    1188             : {
    1189          72 :     switch( GetBiff() )
    1190             :     {
    1191           0 :         case EXC_BIFF4: mnXclMaxSize = EXC_FONT_MAXCOUNT4;  break;
    1192           0 :         case EXC_BIFF5: mnXclMaxSize = EXC_FONT_MAXCOUNT5;  break;
    1193          72 :         case EXC_BIFF8: mnXclMaxSize = EXC_FONT_MAXCOUNT8;  break;
    1194             :         default:        DBG_ERROR_BIFF();
    1195             :     }
    1196          72 :     InitDefaultFonts();
    1197          72 : }
    1198             : 
    1199         250 : const XclExpFont* XclExpFontBuffer::GetFont( sal_uInt16 nXclFont ) const
    1200             : {
    1201         250 :     return maFontList.GetRecord( nXclFont ).get();
    1202             : }
    1203             : 
    1204         316 : const XclFontData& XclExpFontBuffer::GetAppFontData() const
    1205             : {
    1206         316 :     return maFontList.GetRecord( EXC_FONT_APP )->GetFontData(); // exists always
    1207             : }
    1208             : 
    1209         832 : sal_uInt16 XclExpFontBuffer::Insert(
    1210             :         const XclFontData& rFontData, XclExpColorType eColorType, bool bAppFont )
    1211             : {
    1212         832 :     if( bAppFont )
    1213             :     {
    1214          72 :         XclExpFontRef xFont( new XclExpFont( GetRoot(), rFontData, eColorType ) );
    1215          72 :         maFontList.ReplaceRecord( xFont, EXC_FONT_APP );
    1216             :         // set width of '0' character for column width export
    1217          72 :         SetCharWidth( xFont->GetFontData() );
    1218          72 :         return EXC_FONT_APP;
    1219             :     }
    1220             : 
    1221         760 :     size_t nPos = Find( rFontData );
    1222         760 :     if( nPos == EXC_FONTLIST_NOTFOUND )
    1223             :     {
    1224             :         // not found in buffer - create new font
    1225          64 :         size_t nSize = maFontList.GetSize();
    1226          64 :         if( nSize < mnXclMaxSize )
    1227             :         {
    1228             :             // possible to insert
    1229          64 :             maFontList.AppendNewRecord( new XclExpFont( GetRoot(), rFontData, eColorType ) );
    1230          64 :             nPos = nSize;       // old size is last position now
    1231             :         }
    1232             :         else
    1233             :         {
    1234             :             // buffer is full - ignore new font, use default font
    1235           0 :             nPos = EXC_FONT_APP;
    1236             :         }
    1237             :     }
    1238         760 :     return static_cast< sal_uInt16 >( nPos );
    1239             : }
    1240             : 
    1241         268 : sal_uInt16 XclExpFontBuffer::Insert(
    1242             :         const vcl::Font& rFont, XclExpColorType eColorType, bool bAppFont )
    1243             : {
    1244         268 :     return Insert( XclFontData( rFont ), eColorType, bAppFont );
    1245             : }
    1246             : 
    1247         469 : sal_uInt16 XclExpFontBuffer::Insert(
    1248             :         const SvxFont& rFont, XclExpColorType eColorType, bool bAppFont )
    1249             : {
    1250         469 :     return Insert( XclFontData( rFont ), eColorType, bAppFont );
    1251             : }
    1252             : 
    1253         268 : sal_uInt16 XclExpFontBuffer::Insert( const SfxItemSet& rItemSet,
    1254             :         sal_Int16 nScript, XclExpColorType eColorType, bool bAppFont )
    1255             : {
    1256             :     // #i17050# script type now provided by caller
    1257         268 :     vcl::Font aFont = XclExpFontHelper::GetFontFromItemSet( GetRoot(), rItemSet, nScript );
    1258         268 :     return Insert( aFont, eColorType, bAppFont );
    1259             : }
    1260             : 
    1261          17 : void XclExpFontBuffer::Save( XclExpStream& rStrm )
    1262             : {
    1263          17 :     maFontList.Save( rStrm );
    1264          17 : }
    1265             : 
    1266          55 : void XclExpFontBuffer::SaveXml( XclExpXmlStream& rStrm )
    1267             : {
    1268          55 :     if( maFontList.IsEmpty() )
    1269          55 :         return;
    1270             : 
    1271          55 :     sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream();
    1272             :     rStyleSheet->startElement( XML_fonts,
    1273             :             XML_count,  OString::number(  maFontList.GetSize() ).getStr(),
    1274          55 :             FSEND );
    1275             : 
    1276          55 :     maFontList.SaveXml( rStrm );
    1277             : 
    1278          55 :     rStyleSheet->endElement( XML_fonts );
    1279             : }
    1280             : 
    1281             : // private --------------------------------------------------------------------
    1282             : 
    1283          72 : void XclExpFontBuffer::InitDefaultFonts()
    1284             : {
    1285          72 :     XclFontData aFontData;
    1286          72 :     aFontData.maName = "Arial";
    1287          72 :     aFontData.SetScFamily( FAMILY_DONTKNOW );
    1288          72 :     aFontData.SetFontEncoding( ScfTools::GetSystemTextEncoding() );
    1289          72 :     aFontData.SetScHeight( 200 );   // 200 twips = 10 pt
    1290          72 :     aFontData.SetScWeight( WEIGHT_NORMAL );
    1291             : 
    1292          72 :     switch( GetBiff() )
    1293             :     {
    1294             :         case EXC_BIFF5:
    1295             :         {
    1296           0 :             maFontList.AppendNewRecord( new XclExpFont( GetRoot(), aFontData, EXC_COLOR_CELLTEXT ) );
    1297           0 :             aFontData.SetScWeight( WEIGHT_BOLD );
    1298           0 :             maFontList.AppendNewRecord( new XclExpFont( GetRoot(), aFontData, EXC_COLOR_CELLTEXT ) );
    1299           0 :             aFontData.SetScWeight( WEIGHT_NORMAL );
    1300           0 :             aFontData.SetScPosture( ITALIC_NORMAL );
    1301           0 :             maFontList.AppendNewRecord( new XclExpFont( GetRoot(), aFontData, EXC_COLOR_CELLTEXT ) );
    1302           0 :             aFontData.SetScWeight( WEIGHT_BOLD );
    1303           0 :             maFontList.AppendNewRecord( new XclExpFont( GetRoot(), aFontData, EXC_COLOR_CELLTEXT ) );
    1304             :             // the blind font with index 4
    1305           0 :             maFontList.AppendNewRecord( new XclExpBlindFont( GetRoot() ) );
    1306             :             // already add the first user defined font (Excel does it too)
    1307           0 :             aFontData.SetScWeight( WEIGHT_NORMAL );
    1308           0 :             aFontData.SetScPosture( ITALIC_NONE );
    1309           0 :             maFontList.AppendNewRecord( new XclExpFont( GetRoot(), aFontData, EXC_COLOR_CELLTEXT ) );
    1310             :         }
    1311           0 :         break;
    1312             :         case EXC_BIFF8:
    1313             :         {
    1314          72 :             XclExpFontRef xFont( new XclExpFont( GetRoot(), aFontData, EXC_COLOR_CELLTEXT ) );
    1315          72 :             maFontList.AppendRecord( xFont );
    1316          72 :             maFontList.AppendRecord( xFont );
    1317          72 :             maFontList.AppendRecord( xFont );
    1318          72 :             maFontList.AppendRecord( xFont );
    1319          72 :             if( GetOutput() == EXC_OUTPUT_BINARY )
    1320             :                 // the blind font with index 4
    1321          17 :                 maFontList.AppendNewRecord( new XclExpBlindFont( GetRoot() ) );
    1322             :         }
    1323          72 :         break;
    1324             :         default:
    1325             :             DBG_ERROR_BIFF();
    1326          72 :     }
    1327          72 : }
    1328             : 
    1329         760 : size_t XclExpFontBuffer::Find( const XclFontData& rFontData )
    1330             : {
    1331         760 :     sal_uInt32 nHash = lclCalcHash( rFontData );
    1332        2285 :     for( size_t nPos = 0, nSize = maFontList.GetSize(); nPos < nSize; ++nPos )
    1333        2221 :         if( maFontList.GetRecord( nPos )->Equals( rFontData, nHash ) )
    1334         696 :             return nPos;
    1335          64 :     return EXC_FONTLIST_NOTFOUND;
    1336             : }
    1337             : 
    1338             : // FORMAT record - number formats =============================================
    1339             : 
    1340             : /** Predicate for search algorithm. */
    1341             : struct XclExpNumFmtPred
    1342             : {
    1343             :     sal_uLong               mnScNumFmt;
    1344         348 :     inline explicit     XclExpNumFmtPred( sal_uLong nScNumFmt ) : mnScNumFmt( nScNumFmt ) {}
    1345         315 :     inline bool         operator()( const XclExpNumFmt& rFormat ) const
    1346         315 :                             { return rFormat.mnScNumFmt == mnScNumFmt; }
    1347             : };
    1348             : 
    1349          74 : void XclExpNumFmt::SaveXml( XclExpXmlStream& rStrm )
    1350             : {
    1351          74 :     sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream();
    1352             :     rStyleSheet->singleElement( XML_numFmt,
    1353             :             XML_numFmtId,   OString::number( mnXclNumFmt ).getStr(),
    1354             :             XML_formatCode, OUStringToOString(maNumFmtString, RTL_TEXTENCODING_UTF8).getStr(),
    1355          74 :             FSEND );
    1356          74 : }
    1357             : 
    1358          72 : XclExpNumFmtBuffer::XclExpNumFmtBuffer( const XclExpRoot& rRoot ) :
    1359             :     XclExpRoot( rRoot ),
    1360             :     /*  Compiler needs a hint, this doesn't work: new NfKeywordTable;
    1361             :         cannot convert from 'class String *' to 'class String (*)[54]'
    1362             :         The effective result here is class String (*)[54*1] */
    1363          72 :     mxFormatter( new SvNumberFormatter( comphelper::getProcessComponentContext(), LANGUAGE_ENGLISH_US ) ),
    1364          72 :     mpKeywordTable( new NfKeywordTable ),
    1365         216 :     mnStdFmt( GetFormatter().GetStandardFormat( ScGlobal::eLnge ) )
    1366             : {
    1367          72 :     switch( GetBiff() )
    1368             :     {
    1369           0 :         case EXC_BIFF5: mnXclOffset = EXC_FORMAT_OFFSET5;   break;
    1370          72 :         case EXC_BIFF8: mnXclOffset = EXC_FORMAT_OFFSET8;   break;
    1371           0 :         default:        mnXclOffset = 0; DBG_ERROR_BIFF();
    1372             :     }
    1373             : 
    1374          72 :     mxFormatter->FillKeywordTable( *mpKeywordTable, LANGUAGE_ENGLISH_US );
    1375             :     // remap codes unknown to Excel
    1376          72 :     (*mpKeywordTable)[ NF_KEY_NN ] = "DDD";
    1377          72 :     (*mpKeywordTable)[ NF_KEY_NNN ] = "DDDD";
    1378             :     // NNNN gets a separator appended in SvNumberformat::GetMappedFormatString()
    1379          72 :     (*mpKeywordTable)[ NF_KEY_NNNN ] = "DDDD";
    1380             :     // Export the Thai T NatNum modifier.
    1381          72 :     (*mpKeywordTable)[ NF_KEY_THAI_T ] = "T";
    1382          72 : }
    1383             : 
    1384         144 : XclExpNumFmtBuffer::~XclExpNumFmtBuffer()
    1385             : {
    1386         144 : }
    1387             : 
    1388         348 : sal_uInt16 XclExpNumFmtBuffer::Insert( sal_uLong nScNumFmt )
    1389             : {
    1390             :     XclExpNumFmtVec::const_iterator aIt =
    1391         348 :         ::std::find_if( maFormatMap.begin(), maFormatMap.end(), XclExpNumFmtPred( nScNumFmt ) );
    1392         348 :     if( aIt != maFormatMap.end() )
    1393         262 :         return aIt->mnXclNumFmt;
    1394             : 
    1395          86 :     size_t nSize = maFormatMap.size();
    1396          86 :     if( nSize < static_cast< size_t >( 0xFFFF - mnXclOffset ) )
    1397             :     {
    1398          86 :         sal_uInt16 nXclNumFmt = static_cast< sal_uInt16 >( nSize + mnXclOffset );
    1399          86 :         maFormatMap.push_back( XclExpNumFmt( nScNumFmt, nXclNumFmt, GetFormatCode( nScNumFmt ) ) );
    1400          86 :         return nXclNumFmt;
    1401             :     }
    1402             : 
    1403           0 :     return 0;
    1404             : }
    1405             : 
    1406          17 : void XclExpNumFmtBuffer::Save( XclExpStream& rStrm )
    1407             : {
    1408          39 :     for( XclExpNumFmtVec::const_iterator aIt = maFormatMap.begin(), aEnd = maFormatMap.end(); aIt != aEnd; ++aIt )
    1409          22 :         WriteFormatRecord( rStrm, *aIt );
    1410          17 : }
    1411             : 
    1412          55 : void XclExpNumFmtBuffer::SaveXml( XclExpXmlStream& rStrm )
    1413             : {
    1414          55 :     if( !maFormatMap.size() )
    1415          55 :         return;
    1416             : 
    1417          55 :     sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream();
    1418             :     rStyleSheet->startElement( XML_numFmts,
    1419             :             XML_count,  OString::number(  maFormatMap.size() ).getStr(),
    1420          55 :             FSEND );
    1421         119 :     for( XclExpNumFmtVec::iterator aIt = maFormatMap.begin(), aEnd = maFormatMap.end(); aIt != aEnd; ++aIt )
    1422             :     {
    1423          64 :         aIt->SaveXml( rStrm );
    1424             :     }
    1425          55 :     rStyleSheet->endElement( XML_numFmts );
    1426             : }
    1427             : 
    1428          22 : void XclExpNumFmtBuffer::WriteFormatRecord( XclExpStream& rStrm, sal_uInt16 nXclNumFmt, const OUString& rFormatStr )
    1429             : {
    1430          22 :     XclExpString aExpStr;
    1431          22 :     if( GetBiff() <= EXC_BIFF5 )
    1432           0 :         aExpStr.AssignByte( rFormatStr, GetTextEncoding(), EXC_STR_8BITLENGTH );
    1433             :     else
    1434          22 :         aExpStr.Assign( rFormatStr );
    1435             : 
    1436          22 :     rStrm.StartRecord( EXC_ID4_FORMAT, 2 + aExpStr.GetSize() );
    1437          22 :     rStrm << nXclNumFmt << aExpStr;
    1438          22 :     rStrm.EndRecord();
    1439          22 : }
    1440             : 
    1441          22 : void XclExpNumFmtBuffer::WriteFormatRecord( XclExpStream& rStrm, const XclExpNumFmt& rFormat )
    1442             : {
    1443          22 :     WriteFormatRecord( rStrm, rFormat.mnXclNumFmt, GetFormatCode( rFormat.mnScNumFmt ) );
    1444          22 : }
    1445             : 
    1446             : namespace {
    1447             : 
    1448         118 : OUString GetNumberFormatCode(XclRoot& rRoot, const sal_uInt16 nScNumFmt, SvNumberFormatter* xFormatter, NfKeywordTable* pKeywordTable)
    1449             : {
    1450         118 :     OUString aFormatStr;
    1451             : 
    1452         118 :     if( const SvNumberformat* pEntry = rRoot.GetFormatter().GetEntry( nScNumFmt ) )
    1453             :     {
    1454         118 :         if( pEntry->GetType() == css::util::NumberFormat::LOGICAL )
    1455             :         {
    1456             :             // build Boolean number format
    1457           0 :             Color* pColor = 0;
    1458           0 :             OUString aTemp;
    1459           0 :             const_cast< SvNumberformat* >( pEntry )->GetOutputString( 1.0, aTemp, &pColor );
    1460           0 :             aFormatStr += "\"" + aTemp + "\";\"" + aTemp + "\";\"";
    1461           0 :             const_cast< SvNumberformat* >( pEntry )->GetOutputString( 0.0, aTemp, &pColor );
    1462           0 :             aFormatStr += aTemp + "\"";
    1463             :         }
    1464             :         else
    1465             :         {
    1466         118 :             LanguageType eLang = pEntry->GetLanguage();
    1467         118 :             if( eLang != LANGUAGE_ENGLISH_US )
    1468             :             {
    1469             :                 sal_Int32 nCheckPos;
    1470         118 :                 short nType = css::util::NumberFormat::DEFINED;
    1471             :                 sal_uInt32 nKey;
    1472         118 :                 OUString aTemp( pEntry->GetFormatstring() );
    1473         118 :                 xFormatter->PutandConvertEntry( aTemp, nCheckPos, nType, nKey, eLang, LANGUAGE_ENGLISH_US );
    1474             :                 OSL_ENSURE( nCheckPos == 0, "XclExpNumFmtBuffer::WriteFormatRecord - format code not convertible" );
    1475         118 :                 pEntry = xFormatter->GetEntry( nKey );
    1476             :             }
    1477             : 
    1478         118 :             aFormatStr = pEntry->GetMappedFormatstring( *pKeywordTable, *xFormatter->GetLocaleData() );
    1479         118 :             if( aFormatStr == "Standard" )
    1480           0 :                 aFormatStr = "General";
    1481             :         }
    1482             :     }
    1483             :     else
    1484             :     {
    1485             :         OSL_FAIL( "XclExpNumFmtBuffer::WriteFormatRecord - format not found" );
    1486           0 :         aFormatStr = "General";
    1487             :     }
    1488             : 
    1489         118 :     return aFormatStr;
    1490             : }
    1491             : 
    1492             : }
    1493             : 
    1494         108 : OUString XclExpNumFmtBuffer::GetFormatCode( sal_uInt16 nScNumFmt )
    1495             : {
    1496         108 :     return GetNumberFormatCode( *this, nScNumFmt, mxFormatter.get(), mpKeywordTable.get() );
    1497             : }
    1498             : 
    1499             : // XF, STYLE record - Cell formatting =========================================
    1500             : 
    1501         312 : bool XclExpCellProt::FillFromItemSet( const SfxItemSet& rItemSet, bool bStyle )
    1502             : {
    1503         312 :     const ScProtectionAttr& rProtItem = GETITEM( rItemSet, ScProtectionAttr, ATTR_PROTECTION );
    1504         312 :     mbLocked = rProtItem.GetProtection();
    1505         312 :     mbHidden = rProtItem.GetHideFormula() || rProtItem.GetHideCell();
    1506         312 :     return ScfTools::CheckItem( rItemSet, ATTR_PROTECTION, bStyle );
    1507             : }
    1508             : 
    1509         402 : void XclExpCellProt::FillToXF3( sal_uInt16& rnProt ) const
    1510             : {
    1511         402 :     ::set_flag( rnProt, EXC_XF_LOCKED, mbLocked );
    1512         402 :     ::set_flag( rnProt, EXC_XF_HIDDEN, mbHidden );
    1513         402 : }
    1514             : 
    1515         181 : void XclExpCellProt::SaveXml( XclExpXmlStream& rStrm ) const
    1516             : {
    1517         181 :     rStrm.GetCurrentStream()->singleElement( XML_protection,
    1518             :             XML_locked,     XclXmlUtils::ToPsz( mbLocked ),
    1519             :             XML_hidden,     XclXmlUtils::ToPsz( mbHidden ),
    1520         362 :             FSEND );
    1521         181 : }
    1522             : 
    1523         312 : bool XclExpCellAlign::FillFromItemSet(
    1524             :         const SfxItemSet& rItemSet, bool bForceLineBreak, XclBiff eBiff, bool bStyle )
    1525             : {
    1526         312 :     bool bUsed = false;
    1527         312 :     SvxCellHorJustify eHorAlign = GETITEMVALUE( rItemSet, SvxHorJustifyItem, ATTR_HOR_JUSTIFY, SvxCellHorJustify );
    1528         312 :     SvxCellVerJustify eVerAlign = GETITEMVALUE( rItemSet, SvxVerJustifyItem, ATTR_VER_JUSTIFY, SvxCellVerJustify );
    1529             : 
    1530         312 :     switch( eBiff )
    1531             :     {
    1532             :         // ALL 'case's - run through!
    1533             : 
    1534             :         case EXC_BIFF8: // attributes new in BIFF8
    1535             :         {
    1536             :             // text indent
    1537         312 :             long nTmpIndent = GETITEMVALUE( rItemSet, SfxUInt16Item, ATTR_INDENT, sal_Int32 );
    1538         312 :             (nTmpIndent += 100) /= 200; // 1 Excel unit == 10 pt == 200 twips
    1539         312 :             mnIndent = limit_cast< sal_uInt8 >( nTmpIndent, 0, 15 );
    1540         312 :             bUsed |= ScfTools::CheckItem( rItemSet, ATTR_INDENT, bStyle );
    1541             : 
    1542             :             // shrink to fit
    1543         312 :             mbShrink = GETITEM( rItemSet, SfxBoolItem, ATTR_SHRINKTOFIT ).GetValue();
    1544         312 :             bUsed |= ScfTools::CheckItem( rItemSet, ATTR_SHRINKTOFIT, bStyle );
    1545             : 
    1546             :             // CTL text direction
    1547         312 :             SetScFrameDir( GETITEMVALUE( rItemSet, SvxFrameDirectionItem, ATTR_WRITINGDIR, SvxFrameDirection ) );
    1548         312 :             bUsed |= ScfTools::CheckItem( rItemSet, ATTR_WRITINGDIR, bStyle );
    1549             :         }
    1550             : 
    1551             :         case EXC_BIFF5: // attributes new in BIFF5
    1552             :         case EXC_BIFF4: // attributes new in BIFF4
    1553             :         {
    1554             :             // vertical alignment
    1555         312 :             SetScVerAlign( eVerAlign );
    1556         312 :             bUsed |= ScfTools::CheckItem( rItemSet, ATTR_VER_JUSTIFY, bStyle );
    1557             : 
    1558             :             // stacked/rotation
    1559         312 :             bool bStacked = GETITEM( rItemSet, SfxBoolItem, ATTR_STACKED ).GetValue();
    1560         312 :             bUsed |= ScfTools::CheckItem( rItemSet, ATTR_STACKED, bStyle );
    1561         312 :             if( bStacked )
    1562             :             {
    1563           0 :                 mnRotation = EXC_ROT_STACKED;
    1564             :             }
    1565             :             else
    1566             :             {
    1567             :                 // rotation
    1568         312 :                 sal_Int32 nScRot = GETITEMVALUE( rItemSet, SfxInt32Item, ATTR_ROTATE_VALUE, sal_Int32 );
    1569         312 :                 mnRotation = XclTools::GetXclRotation( nScRot );
    1570         312 :                 bUsed |= ScfTools::CheckItem( rItemSet, ATTR_ROTATE_VALUE, bStyle );
    1571             :             }
    1572         312 :             mnOrient = XclTools::GetXclOrientFromRot( mnRotation );
    1573             :         }
    1574             : 
    1575             :         case EXC_BIFF3: // attributes new in BIFF3
    1576             :         {
    1577             :             // text wrap
    1578         312 :             mbLineBreak = bForceLineBreak || GETITEMBOOL( rItemSet, ATTR_LINEBREAK );
    1579         312 :             bUsed |= bForceLineBreak || ScfTools::CheckItem( rItemSet, ATTR_LINEBREAK, bStyle );
    1580             :         }
    1581             : 
    1582             :         case EXC_BIFF2: // attributes new in BIFF2
    1583             :         {
    1584             :             // horizontal alignment
    1585         312 :             SetScHorAlign( eHorAlign );
    1586         312 :             bUsed |= ScfTools::CheckItem( rItemSet, ATTR_HOR_JUSTIFY, bStyle );
    1587             :         }
    1588             : 
    1589         312 :         break;
    1590             :         default:    DBG_ERROR_BIFF();
    1591             :     }
    1592             : 
    1593         312 :     if (eBiff == EXC_BIFF8)
    1594             :     {
    1595             :         // Adjust for distributed alignments.
    1596         312 :         if (eHorAlign == SVX_HOR_JUSTIFY_BLOCK)
    1597             :         {
    1598           0 :             SvxCellJustifyMethod eHorJustMethod = GETITEMVALUE(
    1599             :                 rItemSet, SvxJustifyMethodItem, ATTR_HOR_JUSTIFY_METHOD, SvxCellJustifyMethod);
    1600           0 :             if (eHorJustMethod == SVX_JUSTIFY_METHOD_DISTRIBUTE)
    1601           0 :                 mnHorAlign = EXC_XF_HOR_DISTRIB;
    1602             :         }
    1603             : 
    1604         312 :         if (eVerAlign == SVX_VER_JUSTIFY_BLOCK)
    1605             :         {
    1606           0 :             SvxCellJustifyMethod eVerJustMethod = GETITEMVALUE(
    1607             :                 rItemSet, SvxJustifyMethodItem, ATTR_VER_JUSTIFY_METHOD, SvxCellJustifyMethod);
    1608           0 :             if (eVerJustMethod == SVX_JUSTIFY_METHOD_DISTRIBUTE)
    1609           0 :                 mnVerAlign = EXC_XF_VER_DISTRIB;
    1610             :         }
    1611             :     }
    1612             : 
    1613         312 :     return bUsed;
    1614             : }
    1615             : 
    1616           0 : void XclExpCellAlign::FillToXF5( sal_uInt16& rnAlign ) const
    1617             : {
    1618           0 :     ::insert_value( rnAlign, mnHorAlign, 0, 3 );
    1619           0 :     ::set_flag( rnAlign, EXC_XF_LINEBREAK, mbLineBreak );
    1620           0 :     ::insert_value( rnAlign, mnVerAlign, 4, 3 );
    1621           0 :     ::insert_value( rnAlign, mnOrient, 8, 2 );
    1622           0 : }
    1623             : 
    1624         402 : void XclExpCellAlign::FillToXF8( sal_uInt16& rnAlign, sal_uInt16& rnMiscAttrib ) const
    1625             : {
    1626         402 :     ::insert_value( rnAlign, mnHorAlign, 0, 3 );
    1627         402 :     ::set_flag( rnAlign, EXC_XF_LINEBREAK, mbLineBreak );
    1628         402 :     ::insert_value( rnAlign, mnVerAlign, 4, 3 );
    1629         402 :     ::insert_value( rnAlign, mnRotation, 8, 8 );
    1630         402 :     ::insert_value( rnMiscAttrib, mnIndent, 0, 4 );
    1631         402 :     ::set_flag( rnMiscAttrib, EXC_XF8_SHRINK, mbShrink );
    1632         402 :     ::insert_value( rnMiscAttrib, mnTextDir, 6, 2 );
    1633         402 : }
    1634             : 
    1635         193 : static const char* ToHorizontalAlignment( sal_uInt8 nHorAlign )
    1636             : {
    1637         193 :     switch( nHorAlign )
    1638             :     {
    1639         175 :         case EXC_XF_HOR_GENERAL:    return "general";
    1640          15 :         case EXC_XF_HOR_LEFT:       return "left";
    1641           2 :         case EXC_XF_HOR_CENTER:     return "center";
    1642           1 :         case EXC_XF_HOR_RIGHT:      return "right";
    1643           0 :         case EXC_XF_HOR_FILL:       return "fill";
    1644           0 :         case EXC_XF_HOR_JUSTIFY:    return "justify";
    1645           0 :         case EXC_XF_HOR_CENTER_AS:  return "centerContinuous";
    1646           0 :         case EXC_XF_HOR_DISTRIB:    return "distributed";
    1647             :     }
    1648           0 :     return "*unknown*";
    1649             : }
    1650             : 
    1651         193 : static const char* ToVerticalAlignment( sal_uInt8 nVerAlign )
    1652             : {
    1653         193 :     switch( nVerAlign )
    1654             :     {
    1655           0 :         case EXC_XF_VER_TOP:        return "top";
    1656           3 :         case EXC_XF_VER_CENTER:     return "center";
    1657         190 :         case EXC_XF_VER_BOTTOM:     return "bottom";
    1658           0 :         case EXC_XF_VER_JUSTIFY:    return "justify";
    1659           0 :         case EXC_XF_VER_DISTRIB:    return "distributed";
    1660             :     }
    1661           0 :     return "*unknown*";
    1662             : }
    1663             : 
    1664         193 : void XclExpCellAlign::SaveXml( XclExpXmlStream& rStrm ) const
    1665             : {
    1666         193 :     rStrm.GetCurrentStream()->singleElement( XML_alignment,
    1667             :             XML_horizontal,         ToHorizontalAlignment( mnHorAlign ),
    1668             :             XML_vertical,           ToVerticalAlignment( mnVerAlign ),
    1669             :             XML_textRotation,       OString::number(  mnRotation ).getStr(),
    1670             :             XML_wrapText,           XclXmlUtils::ToPsz( mbLineBreak ),
    1671             :             XML_indent,             OString::number(  mnIndent ).getStr(),
    1672             :             // OOXTODO: XML_relativeIndent,     mnIndent?
    1673             :             // OOXTODO: XML_justifyLastLine,
    1674             :             XML_shrinkToFit,        XclXmlUtils::ToPsz( mbShrink ),
    1675             :             // OOXTODO: XML_readingOrder,
    1676         386 :             FSEND );
    1677         193 : }
    1678             : 
    1679             : namespace {
    1680             : 
    1681        1872 : void lclGetBorderLine(
    1682             :         sal_uInt8& rnXclLine, sal_uInt32& rnColorId,
    1683             :         const ::editeng::SvxBorderLine* pLine, XclExpPalette& rPalette, XclBiff eBiff )
    1684             : {
    1685        1872 :     rnXclLine = EXC_LINE_NONE;
    1686        1872 :     if( pLine )
    1687             :     {
    1688         138 :         sal_uInt16 nOuterWidth = pLine->GetOutWidth();
    1689         138 :         sal_uInt16 nDistance = pLine->GetDistance();
    1690         138 :         if( nDistance > 0 )
    1691           3 :             rnXclLine = EXC_LINE_DOUBLE;
    1692         135 :         else if( nOuterWidth >= EXC_BORDER_THICK )
    1693           3 :             rnXclLine = EXC_LINE_THICK;
    1694         132 :         else if( nOuterWidth >= EXC_BORDER_MEDIUM )
    1695             :         {
    1696          47 :             rnXclLine = EXC_LINE_MEDIUM;
    1697          47 :             switch (pLine->GetBorderLineStyle())
    1698             :             {
    1699             :                 case table::BorderLineStyle::DASHED:
    1700           3 :                     rnXclLine = EXC_LINE_MEDIUM_DASHED;
    1701           3 :                 break;
    1702             :                 case table::BorderLineStyle::DASH_DOT:
    1703           3 :                     rnXclLine = EXC_LINE_MEDIUM_DASHDOT;
    1704           3 :                     break;
    1705             :                 case table::BorderLineStyle::DASH_DOT_DOT:
    1706           3 :                     rnXclLine = EXC_LINE_MEDIUM_DASHDOTDOT;
    1707           3 :                     break;
    1708             :                 default:
    1709             :                     ;
    1710             :             }
    1711             :         }
    1712          85 :         else if( nOuterWidth >= EXC_BORDER_THIN )
    1713             :         {
    1714          83 :             rnXclLine = EXC_LINE_THIN;
    1715          83 :             switch (pLine->GetBorderLineStyle())
    1716             :             {
    1717             :                 case table::BorderLineStyle::DASHED:
    1718             :                 case table::BorderLineStyle::FINE_DASHED:
    1719           3 :                     rnXclLine = EXC_LINE_DASHED;
    1720           3 :                     break;
    1721             :                 case table::BorderLineStyle::DASH_DOT:
    1722           3 :                     rnXclLine = EXC_LINE_THIN_DASHDOT;
    1723           3 :                     break;
    1724             :                 case table::BorderLineStyle::DASH_DOT_DOT:
    1725           3 :                     rnXclLine = EXC_LINE_THIN_DASHDOTDOT;
    1726           3 :                     break;
    1727             :                 case table::BorderLineStyle::DOTTED:
    1728           3 :                     rnXclLine = EXC_LINE_DOTTED;
    1729           3 :                     break;
    1730             :                 default:
    1731          71 :                     break;
    1732             :             }
    1733             :         }
    1734           2 :         else if (nOuterWidth >= EXC_BORDER_HAIR)
    1735           2 :             rnXclLine = EXC_LINE_HAIR;
    1736             :         else
    1737           0 :             rnXclLine = EXC_LINE_NONE;
    1738             :     }
    1739        1872 :     if( (eBiff == EXC_BIFF2) && (rnXclLine != EXC_LINE_NONE) )
    1740           0 :         rnXclLine = EXC_LINE_THIN;
    1741             : 
    1742         138 :     rnColorId = (pLine && (rnXclLine != EXC_LINE_NONE)) ?
    1743         138 :         rPalette.InsertColor( pLine->GetColor(), EXC_COLOR_CELLBORDER ) :
    1744        2010 :         XclExpPalette::GetColorIdFromIndex( 0 );
    1745        1872 : }
    1746             : 
    1747             : } // namespace
    1748             : 
    1749         538 : XclExpCellBorder::XclExpCellBorder() :
    1750         538 :     mnLeftColorId(   XclExpPalette::GetColorIdFromIndex( mnLeftColor ) ),
    1751         538 :     mnRightColorId(  XclExpPalette::GetColorIdFromIndex( mnRightColor ) ),
    1752         538 :     mnTopColorId(    XclExpPalette::GetColorIdFromIndex( mnTopColor ) ),
    1753         538 :     mnBottomColorId( XclExpPalette::GetColorIdFromIndex( mnBottomColor ) ),
    1754        2690 :     mnDiagColorId(   XclExpPalette::GetColorIdFromIndex( mnDiagColor ) )
    1755             : {
    1756         538 : }
    1757             : 
    1758         312 : bool XclExpCellBorder::FillFromItemSet(
    1759             :         const SfxItemSet& rItemSet, XclExpPalette& rPalette, XclBiff eBiff, bool bStyle )
    1760             : {
    1761         312 :     bool bUsed = false;
    1762             : 
    1763         312 :     switch( eBiff )
    1764             :     {
    1765             :         // ALL 'case's - run through!
    1766             : 
    1767             :         case EXC_BIFF8: // attributes new in BIFF8
    1768             :         {
    1769         312 :             const SvxLineItem& rTLBRItem = GETITEM( rItemSet, SvxLineItem, ATTR_BORDER_TLBR );
    1770             :             sal_uInt8 nTLBRLine;
    1771             :             sal_uInt32 nTLBRColorId;
    1772         312 :             lclGetBorderLine( nTLBRLine, nTLBRColorId, rTLBRItem.GetLine(), rPalette, eBiff );
    1773         312 :             mbDiagTLtoBR = (nTLBRLine != EXC_LINE_NONE);
    1774             : 
    1775         312 :             const SvxLineItem& rBLTRItem = GETITEM( rItemSet, SvxLineItem, ATTR_BORDER_BLTR );
    1776             :             sal_uInt8 nBLTRLine;
    1777             :             sal_uInt32 nBLTRColorId;
    1778         312 :             lclGetBorderLine( nBLTRLine, nBLTRColorId, rBLTRItem.GetLine(), rPalette, eBiff );
    1779         312 :             mbDiagBLtoTR = (nBLTRLine != EXC_LINE_NONE);
    1780             : 
    1781         312 :             if( ::ScHasPriority( rTLBRItem.GetLine(), rBLTRItem.GetLine() ) )
    1782             :             {
    1783           0 :                 mnDiagLine = nTLBRLine;
    1784           0 :                 mnDiagColorId = nTLBRColorId;
    1785             :             }
    1786             :             else
    1787             :             {
    1788         312 :                 mnDiagLine = nBLTRLine;
    1789         312 :                 mnDiagColorId = nBLTRColorId;
    1790             :             }
    1791             : 
    1792         574 :             bUsed |= ScfTools::CheckItem( rItemSet, ATTR_BORDER_TLBR, bStyle ) ||
    1793         574 :                      ScfTools::CheckItem( rItemSet, ATTR_BORDER_BLTR, bStyle );
    1794             :         }
    1795             : 
    1796             :         case EXC_BIFF5:
    1797             :         case EXC_BIFF4:
    1798             :         case EXC_BIFF3:
    1799             :         case EXC_BIFF2:
    1800             :         {
    1801         312 :             const SvxBoxItem& rBoxItem = GETITEM( rItemSet, SvxBoxItem, ATTR_BORDER );
    1802         312 :             lclGetBorderLine( mnLeftLine,   mnLeftColorId,   rBoxItem.GetLeft(),   rPalette, eBiff );
    1803         312 :             lclGetBorderLine( mnRightLine,  mnRightColorId,  rBoxItem.GetRight(),  rPalette, eBiff );
    1804         312 :             lclGetBorderLine( mnTopLine,    mnTopColorId,    rBoxItem.GetTop(),    rPalette, eBiff );
    1805         312 :             lclGetBorderLine( mnBottomLine, mnBottomColorId, rBoxItem.GetBottom(), rPalette, eBiff );
    1806         312 :             bUsed |= ScfTools::CheckItem( rItemSet, ATTR_BORDER, bStyle );
    1807             :         }
    1808             : 
    1809         312 :         break;
    1810             :         default:    DBG_ERROR_BIFF();
    1811             :     }
    1812             : 
    1813         312 :     return bUsed;
    1814             : }
    1815             : 
    1816        1670 : void XclExpCellBorder::SetFinalColors( const XclExpPalette& rPalette )
    1817             : {
    1818        1670 :     mnLeftColor   = rPalette.GetColorIndex( mnLeftColorId );
    1819        1670 :     mnRightColor  = rPalette.GetColorIndex( mnRightColorId );
    1820        1670 :     mnTopColor    = rPalette.GetColorIndex( mnTopColorId );
    1821        1670 :     mnBottomColor = rPalette.GetColorIndex( mnBottomColorId );
    1822        1670 :     mnDiagColor   = rPalette.GetColorIndex( mnDiagColorId );
    1823        1670 : }
    1824             : 
    1825           0 : void XclExpCellBorder::FillToXF5( sal_uInt32& rnBorder, sal_uInt32& rnArea ) const
    1826             : {
    1827           0 :     ::insert_value( rnBorder, mnTopLine,      0, 3 );
    1828           0 :     ::insert_value( rnBorder, mnLeftLine,     3, 3 );
    1829           0 :     ::insert_value( rnArea,   mnBottomLine,  22, 3 );
    1830           0 :     ::insert_value( rnBorder, mnRightLine,    6, 3 );
    1831           0 :     ::insert_value( rnBorder, mnTopColor,     9, 7 );
    1832           0 :     ::insert_value( rnBorder, mnLeftColor,   16, 7 );
    1833           0 :     ::insert_value( rnArea,   mnBottomColor, 25, 7 );
    1834           0 :     ::insert_value( rnBorder, mnRightColor,  23, 7 );
    1835           0 : }
    1836             : 
    1837         402 : void XclExpCellBorder::FillToXF8( sal_uInt32& rnBorder1, sal_uInt32& rnBorder2 ) const
    1838             : {
    1839         402 :     ::insert_value( rnBorder1, mnLeftLine,     0, 4 );
    1840         402 :     ::insert_value( rnBorder1, mnRightLine,    4, 4 );
    1841         402 :     ::insert_value( rnBorder1, mnTopLine,      8, 4 );
    1842         402 :     ::insert_value( rnBorder1, mnBottomLine,  12, 4 );
    1843         402 :     ::insert_value( rnBorder1, mnLeftColor,   16, 7 );
    1844         402 :     ::insert_value( rnBorder1, mnRightColor,  23, 7 );
    1845         402 :     ::insert_value( rnBorder2, mnTopColor,     0, 7 );
    1846         402 :     ::insert_value( rnBorder2, mnBottomColor,  7, 7 );
    1847         402 :     ::insert_value( rnBorder2, mnDiagColor,   14, 7 );
    1848         402 :     ::insert_value( rnBorder2, mnDiagLine,    21, 4 );
    1849         402 :     ::set_flag( rnBorder1, EXC_XF_DIAGONAL_TL_TO_BR, mbDiagTLtoBR );
    1850         402 :     ::set_flag( rnBorder1, EXC_XF_DIAGONAL_BL_TO_TR, mbDiagBLtoTR );
    1851         402 : }
    1852             : 
    1853           0 : void XclExpCellBorder::FillToCF8( sal_uInt16& rnLine, sal_uInt32& rnColor ) const
    1854             : {
    1855           0 :     ::insert_value( rnLine,  mnLeftLine,     0, 4 );
    1856           0 :     ::insert_value( rnLine,  mnRightLine,    4, 4 );
    1857           0 :     ::insert_value( rnLine,  mnTopLine,      8, 4 );
    1858           0 :     ::insert_value( rnLine,  mnBottomLine,  12, 4 );
    1859           0 :     ::insert_value( rnColor, mnLeftColor,    0, 7 );
    1860           0 :     ::insert_value( rnColor, mnRightColor,   7, 7 );
    1861           0 :     ::insert_value( rnColor, mnTopColor,    16, 7 );
    1862           0 :     ::insert_value( rnColor, mnBottomColor, 23, 7 );
    1863           0 : }
    1864             : 
    1865         109 : static const char* ToLineStyle( sal_uInt8 nLineStyle )
    1866             : {
    1867         109 :     switch( nLineStyle )
    1868             :     {
    1869           0 :         case EXC_LINE_NONE:              return "none";
    1870          64 :         case EXC_LINE_THIN:              return "thin";
    1871          35 :         case EXC_LINE_MEDIUM:            return "medium";
    1872           1 :         case EXC_LINE_THICK:             return "thick";
    1873           1 :         case EXC_LINE_DOUBLE:            return "double";
    1874           1 :         case EXC_LINE_HAIR:              return "hair";
    1875           1 :         case EXC_LINE_DOTTED:            return "dotted";
    1876           1 :         case EXC_LINE_DASHED:            return "dashed";
    1877           1 :         case EXC_LINE_MEDIUM_DASHED:     return "mediumDashed";
    1878           1 :         case EXC_LINE_THIN_DASHDOT:      return "dashDot";
    1879           1 :         case EXC_LINE_THIN_DASHDOTDOT:   return "dashDotDot";
    1880           1 :         case EXC_LINE_MEDIUM_DASHDOT:    return "mediumDashDot";
    1881           1 :         case EXC_LINE_MEDIUM_DASHDOTDOT: return "mediumDashDotDot";
    1882             :     }
    1883           0 :     return "*unknown*";
    1884             : }
    1885             : 
    1886         510 : static void lcl_WriteBorder( XclExpXmlStream& rStrm, sal_Int32 nElement, sal_uInt8 nLineStyle, const Color& rColor )
    1887             : {
    1888         510 :     sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream();
    1889         510 :     if( nLineStyle == EXC_LINE_NONE )
    1890         401 :         rStyleSheet->singleElement( nElement, FSEND );
    1891         109 :     else if( rColor == Color( 0, 0, 0, 0 ) )
    1892             :         rStyleSheet->singleElement( nElement,
    1893             :                 XML_style,  ToLineStyle( nLineStyle ),
    1894         109 :                 FSEND );
    1895             :     else
    1896             :     {
    1897             :         rStyleSheet->startElement( nElement,
    1898             :                 XML_style,  ToLineStyle( nLineStyle ),
    1899           0 :                 FSEND );
    1900             :         rStyleSheet->singleElement( XML_color,
    1901             :                 XML_rgb,    XclXmlUtils::ToOString( rColor ).getStr(),
    1902           0 :                 FSEND );
    1903           0 :         rStyleSheet->endElement( nElement );
    1904             :     }
    1905         510 : }
    1906             : 
    1907         102 : void XclExpCellBorder::SaveXml( XclExpXmlStream& rStrm ) const
    1908             : {
    1909         102 :     sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream();
    1910             : 
    1911         102 :     XclExpPalette& rPalette = rStrm.GetRoot().GetPalette();
    1912             : 
    1913             :     rStyleSheet->startElement( XML_border,
    1914             :             XML_diagonalUp,     XclXmlUtils::ToPsz( mbDiagBLtoTR ),
    1915             :             XML_diagonalDown,   XclXmlUtils::ToPsz( mbDiagTLtoBR ),
    1916             :             // OOXTODO: XML_outline,
    1917         102 :             FSEND );
    1918         102 :     lcl_WriteBorder( rStrm, XML_left,       mnLeftLine,     rPalette.GetColor( mnLeftColor ) );
    1919         102 :     lcl_WriteBorder( rStrm, XML_right,      mnRightLine,    rPalette.GetColor( mnRightColor ) );
    1920         102 :     lcl_WriteBorder( rStrm, XML_top,        mnTopLine,      rPalette.GetColor( mnTopColor ) );
    1921         102 :     lcl_WriteBorder( rStrm, XML_bottom,     mnBottomLine,   rPalette.GetColor( mnBottomColor ) );
    1922         102 :     lcl_WriteBorder( rStrm, XML_diagonal,   mnDiagLine,     rPalette.GetColor( mnDiagColor ) );
    1923             :     // OOXTODO: XML_vertical, XML_horizontal
    1924         102 :     rStyleSheet->endElement( XML_border );
    1925         102 : }
    1926             : 
    1927         672 : XclExpCellArea::XclExpCellArea() :
    1928         672 :     mnForeColorId( XclExpPalette::GetColorIdFromIndex( mnForeColor ) ),
    1929        1344 :     mnBackColorId( XclExpPalette::GetColorIdFromIndex( mnBackColor ) )
    1930             : {
    1931         672 : }
    1932             : 
    1933         302 : bool XclExpCellArea::FillFromItemSet( const SfxItemSet& rItemSet, XclExpPalette& rPalette, bool bStyle )
    1934             : {
    1935         302 :     const SvxBrushItem& rBrushItem = GETITEM( rItemSet, SvxBrushItem, ATTR_BACKGROUND );
    1936         302 :     if( rBrushItem.GetColor().GetTransparency() )
    1937             :     {
    1938         302 :         mnPattern = EXC_PATT_NONE;
    1939         302 :         mnForeColorId = XclExpPalette::GetColorIdFromIndex( EXC_COLOR_WINDOWTEXT );
    1940         302 :         mnBackColorId = XclExpPalette::GetColorIdFromIndex( EXC_COLOR_WINDOWBACK );
    1941             :     }
    1942             :     else
    1943             :     {
    1944           0 :         mnPattern = EXC_PATT_SOLID;
    1945           0 :         mnForeColorId = rPalette.InsertColor( rBrushItem.GetColor(), EXC_COLOR_CELLAREA );
    1946           0 :         mnBackColorId = XclExpPalette::GetColorIdFromIndex( EXC_COLOR_WINDOWTEXT );
    1947             :     }
    1948         302 :     return ScfTools::CheckItem( rItemSet, ATTR_BACKGROUND, bStyle );
    1949             : }
    1950             : 
    1951        1670 : void XclExpCellArea::SetFinalColors( const XclExpPalette& rPalette )
    1952             : {
    1953        1670 :     rPalette.GetMixedColors( mnForeColor, mnBackColor, mnPattern, mnForeColorId, mnBackColorId );
    1954        1670 : }
    1955             : 
    1956           0 : void XclExpCellArea::FillToXF5( sal_uInt32& rnArea ) const
    1957             : {
    1958           0 :     ::insert_value( rnArea, mnPattern,   16, 6 );
    1959           0 :     ::insert_value( rnArea, mnForeColor,  0, 7 );
    1960           0 :     ::insert_value( rnArea, mnBackColor,  7, 7 );
    1961           0 : }
    1962             : 
    1963         402 : void XclExpCellArea::FillToXF8( sal_uInt32& rnBorder2, sal_uInt16& rnArea ) const
    1964             : {
    1965         402 :     ::insert_value( rnBorder2, mnPattern,   26, 6 );
    1966         402 :     ::insert_value( rnArea,    mnForeColor,  0, 7 );
    1967         402 :     ::insert_value( rnArea,    mnBackColor,  7, 7 );
    1968         402 : }
    1969             : 
    1970           0 : void XclExpCellArea::FillToCF8( sal_uInt16& rnPattern, sal_uInt16& rnColor ) const
    1971             : {
    1972           0 :     XclCellArea aTmp( *this );
    1973           0 :     if( !aTmp.IsTransparent() && (aTmp.mnBackColor == EXC_COLOR_WINDOWTEXT) )
    1974           0 :         aTmp.mnBackColor = 0;
    1975           0 :     if( aTmp.mnPattern == EXC_PATT_SOLID )
    1976           0 :         ::std::swap( aTmp.mnForeColor, aTmp.mnBackColor );
    1977           0 :     ::insert_value( rnColor,   aTmp.mnForeColor,  0, 7 );
    1978           0 :     ::insert_value( rnColor,   aTmp.mnBackColor,  7, 7 );
    1979           0 :     ::insert_value( rnPattern, aTmp.mnPattern,   10, 6 );
    1980           0 : }
    1981             : 
    1982         110 : static const char* ToPatternType( sal_uInt8 nPattern )
    1983             : {
    1984         110 :     switch( nPattern )
    1985             :     {
    1986          55 :         case EXC_PATT_NONE:         return "none";
    1987           0 :         case EXC_PATT_SOLID:        return "solid";
    1988           0 :         case EXC_PATT_50_PERC:      return "mediumGray";
    1989           0 :         case EXC_PATT_75_PERC:      return "darkGray";
    1990           0 :         case EXC_PATT_25_PERC:      return "lightGray";
    1991          55 :         case EXC_PATT_12_5_PERC:    return "gray125";
    1992           0 :         case EXC_PATT_6_25_PERC:    return "gray0625";
    1993             :     }
    1994           0 :     return "*unknown*";
    1995             : }
    1996             : 
    1997         110 : void XclExpCellArea::SaveXml( XclExpXmlStream& rStrm ) const
    1998             : {
    1999         110 :     sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream();
    2000             :     rStyleSheet->startElement( XML_fill,
    2001         110 :             FSEND );
    2002             : 
    2003             :     // OOXTODO: XML_gradientFill
    2004             : 
    2005         110 :     XclExpPalette& rPalette = rStrm.GetRoot().GetPalette();
    2006             : 
    2007         110 :     if( mnPattern == EXC_PATT_NONE || ( mnForeColor == 0 && mnBackColor == 0 ) )
    2008             :         rStyleSheet->singleElement( XML_patternFill,
    2009             :                 XML_patternType,    ToPatternType( mnPattern ),
    2010         110 :                 FSEND );
    2011             :     else
    2012             :     {
    2013             :         rStyleSheet->startElement( XML_patternFill,
    2014             :                 XML_patternType,    ToPatternType( mnPattern ),
    2015           0 :                 FSEND );
    2016             :         rStyleSheet->singleElement( XML_fgColor,
    2017           0 :                 XML_rgb,    XclXmlUtils::ToOString( rPalette.GetColor( mnForeColor ) ).getStr(),
    2018           0 :                 FSEND );
    2019             :         rStyleSheet->singleElement( XML_bgColor,
    2020           0 :                 XML_rgb,    XclXmlUtils::ToOString( rPalette.GetColor( mnBackColor ) ).getStr(),
    2021           0 :                 FSEND );
    2022           0 :         rStyleSheet->endElement( XML_patternFill );
    2023             :     }
    2024             : 
    2025         110 :     rStyleSheet->endElement( XML_fill );
    2026         110 : }
    2027             : 
    2028          10 : bool XclExpColor::FillFromItemSet( const SfxItemSet& rItemSet )
    2029             : {
    2030          10 :     if( !ScfTools::CheckItem( rItemSet, ATTR_BACKGROUND, true ) )
    2031          10 :         return false;
    2032             : 
    2033           0 :     const SvxBrushItem& rBrushItem = GETITEM( rItemSet, SvxBrushItem, ATTR_BACKGROUND );
    2034           0 :     maColor = rBrushItem.GetColor();
    2035             : 
    2036           0 :     return true;
    2037             : }
    2038             : 
    2039           0 : void XclExpColor::SaveXml( XclExpXmlStream& rStrm ) const
    2040             : {
    2041           0 :     sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream();
    2042             :     rStyleSheet->startElement( XML_fill,
    2043           0 :             FSEND );
    2044             :     rStyleSheet->startElement( XML_patternFill,
    2045           0 :             FSEND );
    2046             :     rStyleSheet->singleElement( XML_bgColor,
    2047             :             XML_rgb, XclXmlUtils::ToOString(maColor).getStr(),
    2048           0 :             FSEND );
    2049             : 
    2050           0 :     rStyleSheet->endElement( XML_patternFill );
    2051           0 :     rStyleSheet->endElement( XML_fill );
    2052           0 : }
    2053             : 
    2054      109824 : XclExpXFId::XclExpXFId() :
    2055      109824 :     mnXFId( XclExpXFBuffer::GetDefCellXFId() ),
    2056      109824 :     mnXFIndex( EXC_XF_DEFAULTCELL )
    2057             : {
    2058      109824 : }
    2059             : 
    2060        6108 : XclExpXFId::XclExpXFId( sal_uInt32 nXFId ) :
    2061             :     mnXFId( nXFId ),
    2062        6108 :     mnXFIndex( EXC_XF_DEFAULTCELL )
    2063             : {
    2064        6108 : }
    2065             : 
    2066      114360 : void XclExpXFId::ConvertXFIndex( const XclExpRoot& rRoot )
    2067             : {
    2068      114360 :     mnXFIndex = rRoot.GetXFBuffer().GetXFIndex( mnXFId );
    2069      114360 : }
    2070             : 
    2071         218 : XclExpXF::XclExpXF(
    2072             :         const XclExpRoot& rRoot, const ScPatternAttr& rPattern, sal_Int16 nScript,
    2073             :         sal_uLong nForceScNumFmt, sal_uInt16 nForceXclFont, bool bForceLineBreak ) :
    2074             :     XclXFBase( true ),
    2075         218 :     XclExpRoot( rRoot )
    2076             : {
    2077         218 :     mnParentXFId = GetXFBuffer().InsertStyle( rPattern.GetStyleSheet() );
    2078         218 :     Init( rPattern.GetItemSet(), nScript, nForceScNumFmt, nForceXclFont, bForceLineBreak, false );
    2079         218 : }
    2080             : 
    2081          84 : XclExpXF::XclExpXF( const XclExpRoot& rRoot, const SfxStyleSheetBase& rStyleSheet ) :
    2082             :     XclXFBase( false ),
    2083             :     XclExpRoot( rRoot ),
    2084          84 :     mnParentXFId( XclExpXFBuffer::GetXFIdFromIndex( EXC_XF_STYLEPARENT ) )
    2085             : {
    2086          84 :     bool bDefStyle = (rStyleSheet.GetName() == ScGlobal::GetRscString( STR_STYLENAME_STANDARD ));
    2087          84 :     sal_Int16 nScript = bDefStyle ? GetDefApiScript() : ::com::sun::star::i18n::ScriptType::WEAK;
    2088          84 :     Init( const_cast< SfxStyleSheetBase& >( rStyleSheet ).GetItemSet(), nScript,
    2089         168 :         NUMBERFORMAT_ENTRY_NOT_FOUND, EXC_FONT_NOTFOUND, false, bDefStyle );
    2090          84 : }
    2091             : 
    2092         216 : XclExpXF::XclExpXF( const XclExpRoot& rRoot, bool bCellXF ) :
    2093             :     XclXFBase( bCellXF ),
    2094             :     XclExpRoot( rRoot ),
    2095         216 :     mnParentXFId( XclExpXFBuffer::GetXFIdFromIndex( EXC_XF_STYLEPARENT ) )
    2096             : {
    2097         216 :     InitDefault();
    2098         216 : }
    2099             : 
    2100      413193 : bool XclExpXF::Equals( const ScPatternAttr& rPattern,
    2101             :         sal_uLong nForceScNumFmt, sal_uInt16 nForceXclFont, bool bForceLineBreak ) const
    2102             : {
    2103      474476 :     return IsCellXF() && (mpItemSet == &rPattern.GetItemSet()) &&
    2104       18597 :         (!bForceLineBreak || maAlignment.mbLineBreak) &&
    2105      432738 :         ((nForceScNumFmt == NUMBERFORMAT_ENTRY_NOT_FOUND) || (mnScNumFmt == nForceScNumFmt)) &&
    2106      413609 :         ((nForceXclFont == EXC_FONT_NOTFOUND) || (mnXclFont == nForceXclFont));
    2107             : }
    2108             : 
    2109        1210 : bool XclExpXF::Equals( const SfxStyleSheetBase& rStyleSheet ) const
    2110             : {
    2111        1210 :     return IsStyleXF() && (mpItemSet == &const_cast< SfxStyleSheetBase& >( rStyleSheet ).GetItemSet());
    2112             : }
    2113             : 
    2114        1670 : void XclExpXF::SetFinalColors()
    2115             : {
    2116        1670 :     maBorder.SetFinalColors( GetPalette() );
    2117        1670 :     maArea.SetFinalColors( GetPalette() );
    2118        1670 : }
    2119             : 
    2120        1076 : bool XclExpXF::Equals( const XclExpXF& rCmpXF ) const
    2121             : {
    2122        1605 :     return XclXFBase::Equals( rCmpXF ) &&
    2123        1584 :         (maProtection == rCmpXF.maProtection) && (maAlignment  == rCmpXF.maAlignment) &&
    2124         638 :         (maBorder     == rCmpXF.maBorder)     && (maArea       == rCmpXF.maArea)      &&
    2125        1194 :         (mnXclFont    == rCmpXF.mnXclFont)    && (mnXclNumFmt  == rCmpXF.mnXclNumFmt) &&
    2126        1106 :         (mnParentXFId == rCmpXF.mnParentXFId);
    2127             : }
    2128             : 
    2129         518 : void XclExpXF::InitDefault()
    2130             : {
    2131         518 :     SetRecHeader( EXC_ID5_XF, (GetBiff() == EXC_BIFF8) ? 20 : 16 );
    2132         518 :     mpItemSet = 0;
    2133         518 :     mnScNumFmt = NUMBERFORMAT_ENTRY_NOT_FOUND;
    2134         518 :     mnXclFont = mnXclNumFmt = 0;
    2135         518 :     SetXmlIds(0, 0);
    2136         518 : }
    2137             : 
    2138         302 : void XclExpXF::Init( const SfxItemSet& rItemSet, sal_Int16 nScript,
    2139             :         sal_uLong nForceScNumFmt, sal_uInt16 nForceXclFont, bool bForceLineBreak, bool bDefStyle )
    2140             : {
    2141         302 :     InitDefault();
    2142         302 :     mpItemSet = &rItemSet;
    2143             : 
    2144             :     // cell protection
    2145         302 :     mbProtUsed = maProtection.FillFromItemSet( rItemSet, IsStyleXF() );
    2146             : 
    2147             :     // font
    2148         302 :     if( nForceXclFont == EXC_FONT_NOTFOUND )
    2149             :     {
    2150         268 :         mnXclFont = GetFontBuffer().Insert( rItemSet, nScript, EXC_COLOR_CELLTEXT, bDefStyle );
    2151         268 :         mbFontUsed = XclExpFontHelper::CheckItems( GetRoot(), rItemSet, nScript, IsStyleXF() );
    2152             :     }
    2153             :     else
    2154             :     {
    2155          34 :         mnXclFont = nForceXclFont;
    2156          34 :         mbFontUsed = true;
    2157             :     }
    2158             : 
    2159             :     // number format
    2160             :     mnScNumFmt = (nForceScNumFmt == NUMBERFORMAT_ENTRY_NOT_FOUND) ?
    2161         302 :         GETITEMVALUE( rItemSet, SfxUInt32Item, ATTR_VALUE_FORMAT, sal_uLong ) : nForceScNumFmt;
    2162         302 :     mnXclNumFmt = GetNumFmtBuffer().Insert( mnScNumFmt );
    2163         302 :     mbFmtUsed = ScfTools::CheckItem( rItemSet, ATTR_VALUE_FORMAT, IsStyleXF() );
    2164             :     // alignment
    2165         302 :     mbAlignUsed = maAlignment.FillFromItemSet( rItemSet, bForceLineBreak, GetBiff(), IsStyleXF() );
    2166             : 
    2167             :     // cell border
    2168         302 :     mbBorderUsed = maBorder.FillFromItemSet( rItemSet, GetPalette(), GetBiff(), IsStyleXF() );
    2169             : 
    2170             :     // background area
    2171         302 :     mbAreaUsed = maArea.FillFromItemSet( rItemSet, GetPalette(), IsStyleXF() );
    2172             : 
    2173             :     // set all b***Used flags to true in "Default"/"Normal" style
    2174         302 :     if( bDefStyle )
    2175          72 :         SetAllUsedFlags( true );
    2176         302 : }
    2177             : 
    2178         402 : sal_uInt8 XclExpXF::GetUsedFlags() const
    2179             : {
    2180         402 :     sal_uInt8 nUsedFlags = 0;
    2181             :     /*  In cell XFs a set bit means a used attribute, in style XFs a cleared bit.
    2182             :         "mbCellXF == mb***Used" evaluates to correct value in cell and style XFs. */
    2183         402 :     ::set_flag( nUsedFlags, EXC_XF_DIFF_PROT,   mbCellXF == mbProtUsed );
    2184         402 :     ::set_flag( nUsedFlags, EXC_XF_DIFF_FONT,   mbCellXF == mbFontUsed );
    2185         402 :     ::set_flag( nUsedFlags, EXC_XF_DIFF_VALFMT, mbCellXF == mbFmtUsed );
    2186         402 :     ::set_flag( nUsedFlags, EXC_XF_DIFF_ALIGN,  mbCellXF == mbAlignUsed );
    2187         402 :     ::set_flag( nUsedFlags, EXC_XF_DIFF_BORDER, mbCellXF == mbBorderUsed );
    2188         402 :     ::set_flag( nUsedFlags, EXC_XF_DIFF_AREA,   mbCellXF == mbAreaUsed );
    2189         402 :     return nUsedFlags;
    2190             : }
    2191             : 
    2192           0 : void XclExpXF::WriteBody5( XclExpStream& rStrm )
    2193             : {
    2194           0 :     sal_uInt16 nTypeProt = 0, nAlign = 0;
    2195           0 :     sal_uInt32 nArea = 0, nBorder = 0;
    2196             : 
    2197           0 :     ::set_flag( nTypeProt, EXC_XF_STYLE, IsStyleXF() );
    2198           0 :     ::insert_value( nTypeProt, mnParent, 4, 12 );
    2199           0 :     ::insert_value( nAlign, GetUsedFlags(), 10, 6 );
    2200             : 
    2201           0 :     maProtection.FillToXF3( nTypeProt );
    2202           0 :     maAlignment.FillToXF5( nAlign );
    2203           0 :     maBorder.FillToXF5( nBorder, nArea );
    2204           0 :     maArea.FillToXF5( nArea );
    2205             : 
    2206           0 :     rStrm << mnXclFont << mnXclNumFmt << nTypeProt << nAlign << nArea << nBorder;
    2207           0 : }
    2208             : 
    2209         402 : void XclExpXF::WriteBody8( XclExpStream& rStrm )
    2210             : {
    2211         402 :     sal_uInt16 nTypeProt = 0, nAlign = 0, nMiscAttrib = 0, nArea = 0;
    2212         402 :     sal_uInt32 nBorder1 = 0, nBorder2 = 0;
    2213             : 
    2214         402 :     ::set_flag( nTypeProt, EXC_XF_STYLE, IsStyleXF() );
    2215         402 :     ::insert_value( nTypeProt, mnParent, 4, 12 );
    2216         402 :     ::insert_value( nMiscAttrib, GetUsedFlags(), 10, 6 );
    2217             : 
    2218         402 :     maProtection.FillToXF3( nTypeProt );
    2219         402 :     maAlignment.FillToXF8( nAlign, nMiscAttrib );
    2220         402 :     maBorder.FillToXF8( nBorder1, nBorder2 );
    2221         402 :     maArea.FillToXF8( nBorder2, nArea );
    2222             : 
    2223         402 :     rStrm << mnXclFont << mnXclNumFmt << nTypeProt << nAlign << nMiscAttrib << nBorder1 << nBorder2 << nArea;
    2224         402 : }
    2225             : 
    2226         402 : void XclExpXF::WriteBody( XclExpStream& rStrm )
    2227             : {
    2228         402 :     XclExpXFId aParentId( mnParentXFId );
    2229         402 :     aParentId.ConvertXFIndex( GetRoot() );
    2230         402 :     mnParent = aParentId.mnXFIndex;
    2231         402 :     switch( GetBiff() )
    2232             :     {
    2233           0 :         case EXC_BIFF5: WriteBody5( rStrm );    break;
    2234         402 :         case EXC_BIFF8: WriteBody8( rStrm );    break;
    2235             :         default:        DBG_ERROR_BIFF();
    2236             :     }
    2237         402 : }
    2238             : 
    2239        1756 : void XclExpXF::SetXmlIds( sal_uInt32 nBorderId, sal_uInt32 nFillId )
    2240             : {
    2241        1756 :     mnBorderId = nBorderId;
    2242        1756 :     mnFillId   = nFillId;
    2243        1756 : }
    2244             : 
    2245        1238 : void XclExpXF::SaveXml( XclExpXmlStream& rStrm )
    2246             : {
    2247        1238 :     sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream();
    2248             : 
    2249        1238 :     sal_Int32 nXfId = 0;
    2250        1238 :     const XclExpXF* pStyleXF = NULL;
    2251        1238 :     if( IsCellXF() )
    2252             :     {
    2253         126 :         sal_uInt16 nXFIndex = rStrm.GetRoot().GetXFBuffer().GetXFIndex( mnParentXFId );
    2254         126 :         nXfId = rStrm.GetRoot().GetXFBuffer().GetXmlStyleIndex( nXFIndex );
    2255         126 :         pStyleXF = rStrm.GetRoot().GetXFBuffer().GetXFById( mnParentXFId );
    2256             :     }
    2257             : 
    2258             :     rStyleSheet->startElement( XML_xf,
    2259             :             XML_numFmtId,           OString::number(  mnXclNumFmt ).getStr(),
    2260             :             XML_fontId,             OString::number(  mnXclFont ).getStr(),
    2261             :             XML_fillId,             OString::number(  mnFillId ).getStr(),
    2262             :             XML_borderId,           OString::number(  mnBorderId ).getStr(),
    2263        2728 :             XML_xfId,               IsStyleXF() ? NULL : OString::number( nXfId ).getStr(),
    2264             :             // OOXTODO: XML_quotePrefix,
    2265             :             // OOXTODO: XML_pivotButton,
    2266             :             // OOXTODO: XML_applyNumberFormat,  ;
    2267             :             XML_applyFont,          XclXmlUtils::ToPsz( mbFontUsed ),
    2268             :             // OOXTODO: XML_applyFill,
    2269             :             XML_applyBorder,        XclXmlUtils::ToPsz( mbBorderUsed ),
    2270             :             XML_applyAlignment,     XclXmlUtils::ToPsz( mbAlignUsed ),
    2271             :             XML_applyProtection,    XclXmlUtils::ToPsz( mbProtUsed ),
    2272        3714 :             FSEND );
    2273        1238 :     if( mbAlignUsed )
    2274          70 :         maAlignment.SaveXml( rStrm );
    2275        1168 :     else if ( pStyleXF )
    2276         123 :         pStyleXF->GetAlignmentData().SaveXml( rStrm );
    2277        1238 :     if( mbProtUsed )
    2278          55 :         maProtection.SaveXml( rStrm );
    2279        1183 :     else if ( pStyleXF )
    2280         126 :         pStyleXF->GetProtectionData().SaveXml( rStrm );
    2281             : 
    2282             :     // OOXTODO: XML_extLst
    2283        1238 :     rStyleSheet->endElement( XML_xf );
    2284        1238 : }
    2285             : 
    2286         216 : XclExpDefaultXF::XclExpDefaultXF( const XclExpRoot& rRoot, bool bCellXF ) :
    2287         216 :     XclExpXF( rRoot, bCellXF )
    2288             : {
    2289         216 : }
    2290             : 
    2291         288 : void XclExpDefaultXF::SetFont( sal_uInt16 nXclFont )
    2292             : {
    2293         288 :     mnXclFont = nXclFont;
    2294         288 :     mbFontUsed = true;
    2295         288 : }
    2296             : 
    2297         360 : void XclExpDefaultXF::SetNumFmt( sal_uInt16 nXclNumFmt )
    2298             : {
    2299         360 :     mnXclNumFmt = nXclNumFmt;
    2300         360 :     mbFmtUsed = true;
    2301         360 : }
    2302             : 
    2303          12 : XclExpStyle::XclExpStyle( sal_uInt32 nXFId, const OUString& rStyleName ) :
    2304             :     XclExpRecord( EXC_ID_STYLE, 4 ),
    2305             :     maName( rStyleName ),
    2306             :     maXFId( nXFId ),
    2307             :     mnStyleId( EXC_STYLE_USERDEF ),
    2308          12 :     mnLevel( EXC_STYLE_NOLEVEL )
    2309             : {
    2310             :     OSL_ENSURE( !maName.isEmpty(), "XclExpStyle::XclExpStyle - empty style name" );
    2311             : #if OSL_DEBUG_LEVEL > 0
    2312             :     sal_uInt8 nStyleId, nLevel; // do not use members for debug tests
    2313             :     OSL_ENSURE( !XclTools::GetBuiltInStyleId( nStyleId, nLevel, maName ),
    2314             :         "XclExpStyle::XclExpStyle - this is a built-in style" );
    2315             : #endif
    2316          12 : }
    2317             : 
    2318         432 : XclExpStyle::XclExpStyle( sal_uInt32 nXFId, sal_uInt8 nStyleId, sal_uInt8 nLevel ) :
    2319             :     XclExpRecord( EXC_ID_STYLE, 4 ),
    2320             :     maXFId( nXFId ),
    2321             :     mnStyleId( nStyleId ),
    2322         432 :     mnLevel( nLevel )
    2323             : {
    2324         432 : }
    2325             : 
    2326         102 : void XclExpStyle::WriteBody( XclExpStream& rStrm )
    2327             : {
    2328         102 :     maXFId.ConvertXFIndex( rStrm.GetRoot() );
    2329         102 :     ::set_flag( maXFId.mnXFIndex, EXC_STYLE_BUILTIN, IsBuiltIn() );
    2330         102 :     rStrm << maXFId.mnXFIndex;
    2331             : 
    2332         102 :     if( IsBuiltIn() )
    2333             :     {
    2334         102 :         rStrm << mnStyleId << mnLevel;
    2335             :     }
    2336             :     else
    2337             :     {
    2338           0 :         XclExpString aNameEx;
    2339           0 :         if( rStrm.GetRoot().GetBiff() == EXC_BIFF8 )
    2340           0 :             aNameEx.Assign( maName );
    2341             :         else
    2342           0 :             aNameEx.AssignByte( maName, rStrm.GetRoot().GetTextEncoding(), EXC_STR_8BITLENGTH );
    2343           0 :         rStrm << aNameEx;
    2344             :     }
    2345         102 : }
    2346             : 
    2347         330 : static const char* lcl_StyleNameFromId( sal_Int32 nStyleId )
    2348             : {
    2349         330 :     switch( nStyleId )
    2350             :     {
    2351          55 :         case 0:     return "Normal";
    2352          55 :         case 3:     return "Comma";
    2353          55 :         case 4:     return "Currency";
    2354          55 :         case 5:     return "Percent";
    2355          55 :         case 6:     return "Comma [0]";
    2356          55 :         case 7:     return "Currency [0]";
    2357             :     }
    2358           0 :     return "*unknown*";
    2359             : }
    2360             : 
    2361         342 : void XclExpStyle::SaveXml( XclExpXmlStream& rStrm )
    2362             : {
    2363         342 :     OString sName;
    2364         342 :     if( IsBuiltIn() )
    2365             :     {
    2366         330 :         sName = OString( lcl_StyleNameFromId( mnStyleId ) );
    2367             :     }
    2368             :     else
    2369          12 :         sName = XclXmlUtils::ToOString( maName );
    2370             :     // get the index in sortedlist associated with the mnXId
    2371         342 :     sal_Int32 nXFId = rStrm.GetRoot().GetXFBuffer().GetXFIndex( maXFId.mnXFId );
    2372             :     // get the style index associated with index into sortedlist
    2373         342 :     nXFId = rStrm.GetRoot().GetXFBuffer().GetXmlStyleIndex( nXFId );
    2374         342 :     rStrm.GetCurrentStream()->singleElement( XML_cellStyle,
    2375             :             XML_name,           sName.getStr(),
    2376             :             XML_xfId,           OString::number( nXFId ).getStr(),
    2377             : // builtinId of 54 or above is invalid according to OpenXML SDK validator.
    2378             : #define CELL_STYLE_MAX_BUILTIN_ID 54
    2379         684 :                                              XML_builtinId, OString::number( std::min( static_cast<sal_Int32>( CELL_STYLE_MAX_BUILTIN_ID - 1 ), static_cast <sal_Int32>( mnStyleId ) ) ).getStr(),
    2380             :             // OOXTODO: XML_iLevel,
    2381             :             // OOXTODO: XML_hidden,
    2382         342 :             XML_customBuiltin,  XclXmlUtils::ToPsz( ! IsBuiltIn() ),
    2383        1368 :             FSEND );
    2384             :     // OOXTODO: XML_extLst
    2385         342 : }
    2386             : 
    2387             : namespace {
    2388             : 
    2389             : const sal_uInt32 EXC_XFLIST_INDEXBASE   = 0xFFFE0000;
    2390             : /** Maximum count of XF records to store in the XF list (performance). */
    2391             : const sal_uInt32 EXC_XFLIST_HARDLIMIT   = 256 * 1024;
    2392             : 
    2393          22 : bool lclIsBuiltInStyle( const OUString& rStyleName )
    2394             : {
    2395             :     return
    2396          44 :         XclTools::IsBuiltInStyleName( rStyleName ) ||
    2397          44 :         XclTools::IsCondFormatStyleName( rStyleName );
    2398             : }
    2399             : 
    2400             : } // namespace
    2401             : 
    2402        1512 : XclExpXFBuffer::XclExpBuiltInInfo::XclExpBuiltInInfo() :
    2403             :     mnStyleId( EXC_STYLE_USERDEF ),
    2404             :     mnLevel( EXC_STYLE_NOLEVEL ),
    2405             :     mbPredefined( true ),
    2406        1512 :     mbHasStyleRec( false )
    2407             : {
    2408        1512 : }
    2409             : 
    2410             : /** Predicate for search algorithm. */
    2411             : struct XclExpBorderPred
    2412             : {
    2413             :     const XclExpCellBorder&
    2414             :                         mrBorder;
    2415        2878 :     inline explicit     XclExpBorderPred( const XclExpCellBorder& rBorder ) : mrBorder( rBorder ) {}
    2416             :     bool                operator()( const XclExpCellBorder& rBorder ) const;
    2417             : };
    2418             : 
    2419        3864 : bool XclExpBorderPred::operator()( const XclExpCellBorder& rBorder ) const
    2420             : {
    2421             :     return
    2422        7251 :         mrBorder.mnLeftColor     == rBorder.mnLeftColor &&
    2423        6610 :         mrBorder.mnRightColor    == rBorder.mnRightColor &&
    2424        6328 :         mrBorder.mnTopColor      == rBorder.mnTopColor &&
    2425        6142 :         mrBorder.mnBottomColor   == rBorder.mnBottomColor &&
    2426        6074 :         mrBorder.mnDiagColor     == rBorder.mnDiagColor &&
    2427        5995 :         mrBorder.mnLeftLine      == rBorder.mnLeftLine &&
    2428        5906 :         mrBorder.mnRightLine     == rBorder.mnRightLine &&
    2429        5690 :         mrBorder.mnTopLine       == rBorder.mnTopLine &&
    2430        5478 :         mrBorder.mnBottomLine    == rBorder.mnBottomLine &&
    2431        5472 :         mrBorder.mnDiagLine      == rBorder.mnDiagLine &&
    2432        5472 :         mrBorder.mbDiagTLtoBR    == rBorder.mbDiagTLtoBR &&
    2433        5472 :         mrBorder.mbDiagBLtoTR    == rBorder.mbDiagBLtoTR &&
    2434        5472 :         mrBorder.mnLeftColorId   == rBorder.mnLeftColorId &&
    2435        5472 :         mrBorder.mnRightColorId  == rBorder.mnRightColorId &&
    2436        5472 :         mrBorder.mnTopColorId    == rBorder.mnTopColorId &&
    2437        9336 :         mrBorder.mnBottomColorId == rBorder.mnBottomColorId &&
    2438        6600 :         mrBorder.mnDiagColorId   == rBorder.mnDiagColorId;
    2439             : }
    2440             : 
    2441             : struct XclExpFillPred
    2442             : {
    2443             :     const XclExpCellArea&
    2444             :                         mrFill;
    2445        2878 :     inline explicit     XclExpFillPred( const XclExpCellArea& rFill ) : mrFill( rFill ) {}
    2446             :     bool                operator()( const XclExpCellArea& rFill ) const;
    2447             : };
    2448             : 
    2449        2878 : bool XclExpFillPred::operator()( const XclExpCellArea& rFill ) const
    2450             : {
    2451             :     return
    2452        5756 :         mrFill.mnForeColor      == rFill.mnForeColor &&
    2453        5756 :         mrFill.mnBackColor      == rFill.mnBackColor &&
    2454        5756 :         mrFill.mnPattern        == rFill.mnPattern &&
    2455        8634 :         mrFill.mnForeColorId    == rFill.mnForeColorId &&
    2456        5756 :         mrFill.mnBackColorId    == rFill.mnBackColorId;
    2457             : }
    2458             : 
    2459          72 : XclExpXFBuffer::XclExpXFBuffer( const XclExpRoot& rRoot ) :
    2460          72 :     XclExpRoot( rRoot )
    2461             : {
    2462          72 : }
    2463             : 
    2464          72 : void XclExpXFBuffer::Initialize()
    2465             : {
    2466          72 :     InsertDefaultRecords();
    2467          72 :     InsertUserStyles();
    2468          72 : }
    2469             : 
    2470      111646 : sal_uInt32 XclExpXFBuffer::Insert( const ScPatternAttr* pPattern, sal_Int16 nScript )
    2471             : {
    2472      111646 :     return InsertCellXF( pPattern, nScript, NUMBERFORMAT_ENTRY_NOT_FOUND, EXC_FONT_NOTFOUND, false );
    2473             : }
    2474             : 
    2475         449 : sal_uInt32 XclExpXFBuffer::InsertWithFont( const ScPatternAttr* pPattern, sal_Int16 nScript,
    2476             :         sal_uInt16 nForceXclFont, bool bForceLineBreak )
    2477             : {
    2478         449 :     return InsertCellXF( pPattern, nScript, NUMBERFORMAT_ENTRY_NOT_FOUND, nForceXclFont, bForceLineBreak );
    2479             : }
    2480             : 
    2481        1111 : sal_uInt32 XclExpXFBuffer::InsertWithNumFmt( const ScPatternAttr* pPattern, sal_Int16 nScript, sal_uLong nForceScNumFmt, bool bForceLineBreak )
    2482             : {
    2483        1111 :     return InsertCellXF( pPattern, nScript, nForceScNumFmt, EXC_FONT_NOTFOUND, bForceLineBreak );
    2484             : }
    2485             : 
    2486         218 : sal_uInt32 XclExpXFBuffer::InsertStyle( const SfxStyleSheetBase* pStyleSheet )
    2487             : {
    2488         218 :     return pStyleSheet ? InsertStyleXF( *pStyleSheet ) : GetXFIdFromIndex( EXC_XF_DEFAULTSTYLE );
    2489             : }
    2490             : 
    2491      205276 : sal_uInt32 XclExpXFBuffer::GetXFIdFromIndex( sal_uInt16 nXFIndex )
    2492             : {
    2493      205276 :     return EXC_XFLIST_INDEXBASE | nXFIndex;
    2494             : }
    2495             : 
    2496      204976 : sal_uInt32 XclExpXFBuffer::GetDefCellXFId()
    2497             : {
    2498      204976 :     return GetXFIdFromIndex( EXC_XF_DEFAULTCELL );
    2499             : }
    2500             : 
    2501         575 : const XclExpXF* XclExpXFBuffer::GetXFById( sal_uInt32 nXFId ) const
    2502             : {
    2503         575 :     return maXFList.GetRecord( nXFId ).get();
    2504             : }
    2505             : 
    2506          72 : void XclExpXFBuffer::Finalize()
    2507             : {
    2508        1742 :     for( size_t nPos = 0, nSize = maXFList.GetSize(); nPos < nSize; ++nPos )
    2509        1670 :         maXFList.GetRecord( nPos )->SetFinalColors();
    2510             : 
    2511          72 :     sal_uInt32 nTotalCount = static_cast< sal_uInt32 >( maXFList.GetSize() );
    2512             :     sal_uInt32 nId;
    2513          72 :     maXFIndexVec.resize( nTotalCount, EXC_XF_DEFAULTCELL );
    2514          72 :     maStyleIndexes.resize( nTotalCount, EXC_XF_DEFAULTCELL );
    2515          72 :     maCellIndexes.resize( nTotalCount, EXC_XF_DEFAULTCELL );
    2516             : 
    2517          72 :     XclExpBuiltInMap::const_iterator aBuiltInEnd = maBuiltInMap.end();
    2518             :     /*  nMaxBuiltInXFId used to decide faster whether an XF record is
    2519             :         user-defined. If the current XF ID is greater than this value,
    2520             :         maBuiltInMap doesn't need to be searched. */
    2521          72 :     sal_uInt32 nMaxBuiltInXFId = maBuiltInMap.empty() ? 0 : maBuiltInMap.rbegin()->first;
    2522             : 
    2523             :     // *** map all built-in XF records (cell and style) *** -------------------
    2524             : 
    2525             :     // do not change XF order -> std::map<> iterates elements in ascending order
    2526        1584 :     for( XclExpBuiltInMap::const_iterator aIt = maBuiltInMap.begin(); aIt != aBuiltInEnd; ++aIt )
    2527        1512 :         AppendXFIndex( aIt->first );
    2528             : 
    2529             :     // *** insert all user-defined style XF records, without reduce *** -------
    2530             : 
    2531          72 :     sal_uInt32 nStyleXFCount = 0;       // counts up to EXC_XF_MAXSTYLECOUNT limit
    2532             : 
    2533        1742 :     for( nId = 0; nId < nTotalCount; ++nId )
    2534             :     {
    2535        1670 :         XclExpXFRef xXF = maXFList.GetRecord( nId );
    2536        1670 :         if( xXF->IsStyleXF() && ((nId > nMaxBuiltInXFId) || (maBuiltInMap.find( nId ) == aBuiltInEnd)) )
    2537             :         {
    2538          12 :             if( nStyleXFCount < EXC_XF_MAXSTYLECOUNT )
    2539             :             {
    2540             :                 // maximum count of styles not reached
    2541          12 :                 AppendXFIndex( nId );
    2542          12 :                 ++nStyleXFCount;
    2543             :             }
    2544             :             else
    2545             :             {
    2546             :                 /*  Maximum count of styles reached - do not append more
    2547             :                     pointers to XFs; use default style XF instead; do not break
    2548             :                     the loop to initialize all maXFIndexVec elements. */
    2549           0 :                 maXFIndexVec[ nId ] = EXC_XF_DEFAULTSTYLE;
    2550             :             }
    2551             :         }
    2552        1670 :     }
    2553             : 
    2554             :     // *** insert all cell XF records *** -------------------------------------
    2555             : 
    2556             :     // start position to search for equal inserted XF records
    2557          72 :     size_t nSearchStart = maSortedXFList.GetSize();
    2558             : 
    2559             :     // break the loop if XF limit reached - maXFIndexVec is already initialized with default index
    2560          72 :     XclExpXFRef xDefCellXF = maXFList.GetRecord( EXC_XF_DEFAULTCELL );
    2561        1742 :     for( nId = 0; (nId < nTotalCount) && (maSortedXFList.GetSize() < EXC_XF_MAXCOUNT); ++nId )
    2562             :     {
    2563        1670 :         XclExpXFRef xXF = maXFList.GetRecord( nId );
    2564        1670 :         if( xXF->IsCellXF() && ((nId > nMaxBuiltInXFId) || (maBuiltInMap.find( nId ) == aBuiltInEnd)) )
    2565             :         {
    2566             :             // try to find an XF record equal to *xXF, which is already inserted
    2567         146 :             sal_uInt16 nFoundIndex = EXC_XF_NOTFOUND;
    2568             : 
    2569             :             // first try if it is equal to the default cell XF
    2570         146 :             if( xDefCellXF->Equals( *xXF ) )
    2571             :             {
    2572          30 :                 nFoundIndex = EXC_XF_DEFAULTCELL;
    2573             :             }
    2574        1046 :             else for( size_t nSearchPos = nSearchStart, nSearchEnd = maSortedXFList.GetSize();
    2575         930 :                         (nSearchPos < nSearchEnd) && (nFoundIndex == EXC_XF_NOTFOUND); ++nSearchPos )
    2576             :             {
    2577         930 :                 if( maSortedXFList.GetRecord( nSearchPos )->Equals( *xXF ) )
    2578           0 :                     nFoundIndex = static_cast< sal_uInt16 >( nSearchPos );
    2579             :             }
    2580             : 
    2581         146 :             if( nFoundIndex != EXC_XF_NOTFOUND )
    2582             :                 // equal XF already in the list, use its resulting XF index
    2583          30 :                 maXFIndexVec[ nId ] = nFoundIndex;
    2584             :             else
    2585         116 :                 AppendXFIndex( nId );
    2586             :         }
    2587        1670 :     }
    2588             : 
    2589          72 :     sal_uInt16 nXmlStyleIndex   = 0;
    2590          72 :     sal_uInt16 nXmlCellIndex    = 0;
    2591             : 
    2592          72 :     size_t nXFCount = maSortedXFList.GetSize();
    2593        1712 :     for( size_t i = 0; i < nXFCount; ++i )
    2594             :     {
    2595        1640 :         XclExpXFList::RecordRefType xXF = maSortedXFList.GetRecord( i );
    2596        1640 :         if( xXF->IsStyleXF() )
    2597        1452 :             maStyleIndexes[ i ] = nXmlStyleIndex++;
    2598             :         else
    2599         188 :             maCellIndexes[ i ] = nXmlCellIndex++;
    2600        1712 :     }
    2601          72 : }
    2602             : 
    2603      115776 : sal_uInt16 XclExpXFBuffer::GetXFIndex( sal_uInt32 nXFId ) const
    2604             : {
    2605      115776 :     sal_uInt16 nXFIndex = EXC_XF_DEFAULTSTYLE;
    2606      115776 :     if( nXFId >= EXC_XFLIST_INDEXBASE )
    2607       95479 :         nXFIndex = static_cast< sal_uInt16 >( nXFId & ~EXC_XFLIST_INDEXBASE );
    2608       20297 :     else if( nXFId < maXFIndexVec.size() )
    2609       20297 :         nXFIndex = maXFIndexVec[ nXFId ];
    2610      115776 :     return nXFIndex;
    2611             : }
    2612             : 
    2613         468 : sal_Int32 XclExpXFBuffer::GetXmlStyleIndex( sal_uInt32 nXFIndex ) const
    2614             : {
    2615             :     OSL_ENSURE( nXFIndex < maStyleIndexes.size(), "XclExpXFBuffer::GetXmlStyleIndex - invalid index!" );
    2616         468 :     if( nXFIndex > maStyleIndexes.size() )
    2617           0 :         return 0;   // should be caught/debugged via above assert; return "valid" index.
    2618         468 :     return maStyleIndexes[ nXFIndex ];
    2619             : }
    2620             : 
    2621        2030 : sal_Int32 XclExpXFBuffer::GetXmlCellIndex( sal_uInt32 nXFIndex ) const
    2622             : {
    2623             :     OSL_ENSURE( nXFIndex < maCellIndexes.size(), "XclExpXFBuffer::GetXmlStyleIndex - invalid index!" );
    2624        2030 :     if( nXFIndex > maCellIndexes.size() )
    2625           0 :         return 0;   // should be caught/debugged via above assert; return "valid" index.
    2626        2030 :     return maCellIndexes[ nXFIndex ];
    2627             : }
    2628             : 
    2629          17 : void XclExpXFBuffer::Save( XclExpStream& rStrm )
    2630             : {
    2631             :     // save all XF records contained in the maSortedXFList vector (sorted by XF index)
    2632          17 :     maSortedXFList.Save( rStrm );
    2633             :     // save all STYLE records
    2634          17 :     maStyleList.Save( rStrm );
    2635          17 : }
    2636             : 
    2637          55 : static void lcl_GetCellCounts( const XclExpRecordList< XclExpXF >& rXFList, sal_Int32& rCells, sal_Int32& rStyles )
    2638             : {
    2639          55 :     rCells  = 0;
    2640          55 :     rStyles = 0;
    2641          55 :     size_t nXFCount = rXFList.GetSize();
    2642        1293 :     for( size_t i = 0; i < nXFCount; ++i )
    2643             :     {
    2644        1238 :         XclExpRecordList< XclExpXF >::RecordRefType xXF = rXFList.GetRecord( i );
    2645        1238 :         if( xXF->IsCellXF() )
    2646         126 :             ++rCells;
    2647        1112 :         else if( xXF->IsStyleXF() )
    2648        1112 :             ++rStyles;
    2649        1238 :     }
    2650          55 : }
    2651             : 
    2652          55 : void XclExpXFBuffer::SaveXml( XclExpXmlStream& rStrm )
    2653             : {
    2654          55 :     sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream();
    2655             : 
    2656             :     rStyleSheet->startElement( XML_fills,
    2657             :             XML_count,  OString::number(  maFills.size() ).getStr(),
    2658          55 :             FSEND );
    2659         165 :     for( XclExpFillList::iterator aIt = maFills.begin(), aEnd = maFills.end();
    2660             :             aIt != aEnd; ++aIt )
    2661             :     {
    2662         110 :         aIt->SaveXml( rStrm );
    2663             :     }
    2664          55 :     rStyleSheet->endElement( XML_fills );
    2665             : 
    2666             :     rStyleSheet->startElement( XML_borders,
    2667             :             XML_count,  OString::number(  maBorders.size() ).getStr(),
    2668          55 :             FSEND );
    2669         157 :     for( XclExpBorderList::iterator aIt = maBorders.begin(), aEnd = maBorders.end();
    2670             :             aIt != aEnd; ++aIt )
    2671             :     {
    2672         102 :         aIt->SaveXml( rStrm );
    2673             :     }
    2674          55 :     rStyleSheet->endElement( XML_borders );
    2675             : 
    2676             :     // save all XF records contained in the maSortedXFList vector (sorted by XF index)
    2677             :     sal_Int32 nCells, nStyles;
    2678          55 :     lcl_GetCellCounts( maSortedXFList, nCells, nStyles );
    2679             : 
    2680          55 :     if( nStyles > 0 )
    2681             :     {
    2682             :         rStyleSheet->startElement( XML_cellStyleXfs,
    2683             :                 XML_count,  OString::number( nStyles ).getStr(),
    2684          55 :                 FSEND );
    2685          55 :         size_t nXFCount = maSortedXFList.GetSize();
    2686        1293 :         for( size_t i = 0; i < nXFCount; ++i )
    2687             :         {
    2688        1238 :             XclExpXFList::RecordRefType xXF = maSortedXFList.GetRecord( i );
    2689        1238 :             if( ! xXF->IsStyleXF() )
    2690         126 :                 continue;
    2691        1112 :             SaveXFXml( rStrm, *xXF );
    2692        1112 :         }
    2693          55 :         rStyleSheet->endElement( XML_cellStyleXfs );
    2694             :     }
    2695             : 
    2696          55 :     if( nCells > 0 )
    2697             :     {
    2698             :         rStyleSheet->startElement( XML_cellXfs,
    2699             :                 XML_count,  OString::number( nCells ).getStr(),
    2700          55 :                 FSEND );
    2701          55 :         size_t nXFCount = maSortedXFList.GetSize();
    2702        1293 :         for( size_t i = 0; i < nXFCount; ++i )
    2703             :         {
    2704        1238 :             XclExpXFList::RecordRefType xXF = maSortedXFList.GetRecord( i );
    2705        1238 :             if( ! xXF->IsCellXF() )
    2706        1112 :                 continue;
    2707         126 :             SaveXFXml( rStrm, *xXF );
    2708         126 :         }
    2709          55 :         rStyleSheet->endElement( XML_cellXfs );
    2710             :     }
    2711             : 
    2712             :     // save all STYLE records
    2713             :     rStyleSheet->startElement( XML_cellStyles,
    2714             :             XML_count,  OString::number(  maStyleList.GetSize() ).getStr(),
    2715          55 :             FSEND );
    2716          55 :     maStyleList.SaveXml( rStrm );
    2717          55 :     rStyleSheet->endElement( XML_cellStyles );
    2718          55 : }
    2719             : 
    2720        1238 : void XclExpXFBuffer::SaveXFXml( XclExpXmlStream& rStrm, XclExpXF& rXF )
    2721             : {
    2722             :     XclExpBorderList::iterator aBorderPos =
    2723        1238 :         std::find_if( maBorders.begin(), maBorders.end(), XclExpBorderPred( rXF.GetBorderData() ) );
    2724             :     OSL_ENSURE( aBorderPos != maBorders.end(), "XclExpXFBuffer::SaveXml - Invalid @borderId!" );
    2725             :     XclExpFillList::iterator aFillPos =
    2726        1238 :         std::find_if( maFills.begin(), maFills.end(), XclExpFillPred( rXF.GetAreaData() ) );
    2727             :     OSL_ENSURE( aFillPos != maFills.end(), "XclExpXFBuffer::SaveXml - Invalid @fillId!" );
    2728             : 
    2729        1238 :     sal_Int32 nBorderId = 0, nFillId = 0;
    2730        1238 :     if( aBorderPos != maBorders.end() )
    2731        1238 :         nBorderId = std::distance( maBorders.begin(), aBorderPos );
    2732        1238 :     if( aFillPos != maFills.end() )
    2733        1238 :         nFillId = std::distance( maFills.begin(), aFillPos );
    2734             : 
    2735        1238 :     rXF.SetXmlIds( nBorderId, nFillId );
    2736        1238 :     rXF.SaveXml( rStrm );
    2737        1238 : }
    2738             : 
    2739       18742 : sal_uInt32 XclExpXFBuffer::FindXF( const ScPatternAttr& rPattern,
    2740             :         sal_uLong nForceScNumFmt, sal_uInt16 nForceXclFont, bool bForceLineBreak ) const
    2741             : {
    2742      413339 :     for( size_t nPos = 0, nSize = maXFList.GetSize(); nPos < nSize; ++nPos )
    2743      413193 :         if( maXFList.GetRecord( nPos )->Equals( rPattern, nForceScNumFmt, nForceXclFont, bForceLineBreak ) )
    2744       18596 :             return static_cast< sal_uInt32 >( nPos );
    2745         146 :     return EXC_XFID_NOTFOUND;
    2746             : }
    2747             : 
    2748          50 : sal_uInt32 XclExpXFBuffer::FindXF( const SfxStyleSheetBase& rStyleSheet ) const
    2749             : {
    2750        1222 :     for( size_t nPos = 0, nSize = maXFList.GetSize(); nPos < nSize; ++nPos )
    2751        1210 :         if( maXFList.GetRecord( nPos )->Equals( rStyleSheet ) )
    2752          38 :             return static_cast< sal_uInt32 >( nPos );
    2753          12 :     return EXC_XFID_NOTFOUND;
    2754             : }
    2755             : 
    2756         180 : sal_uInt32 XclExpXFBuffer::FindBuiltInXF( sal_uInt8 nStyleId, sal_uInt8 nLevel ) const
    2757             : {
    2758         180 :     for( XclExpBuiltInMap::const_iterator aIt = maBuiltInMap.begin(), aEnd = maBuiltInMap.end(); aIt != aEnd; ++aIt )
    2759         180 :         if( (aIt->second.mnStyleId == nStyleId) && (aIt->second.mnLevel == nLevel) )
    2760         180 :             return aIt->first;
    2761           0 :     return EXC_XFID_NOTFOUND;
    2762             : }
    2763             : 
    2764      113206 : sal_uInt32 XclExpXFBuffer::InsertCellXF( const ScPatternAttr* pPattern, sal_Int16 nScript,
    2765             :         sal_uLong nForceScNumFmt, sal_uInt16 nForceXclFont, bool bForceLineBreak )
    2766             : {
    2767      113206 :     const ScPatternAttr* pDefPattern = GetDoc().GetDefPattern();
    2768      113206 :     if( !pPattern )
    2769        1722 :         pPattern = pDefPattern;
    2770             : 
    2771             :     // special handling for default cell formatting
    2772      113206 :     if( (pPattern == pDefPattern) && !bForceLineBreak &&
    2773       94652 :         (nForceScNumFmt == NUMBERFORMAT_ENTRY_NOT_FOUND) &&
    2774             :         (nForceXclFont == EXC_FONT_NOTFOUND) )
    2775             :     {
    2776             :         // Is it the first try to insert the default cell format?
    2777       94464 :         bool& rbPredefined = maBuiltInMap[ EXC_XF_DEFAULTCELL ].mbPredefined;
    2778       94464 :         if( rbPredefined )
    2779             :         {
    2780             :             // replace default cell pattern
    2781          72 :             XclExpXFRef xNewXF( new XclExpXF( GetRoot(), *pPattern, nScript ) );
    2782          72 :             maXFList.ReplaceRecord( xNewXF, EXC_XF_DEFAULTCELL );
    2783          72 :             rbPredefined = false;
    2784             :         }
    2785       94464 :         return GetDefCellXFId();
    2786             :     }
    2787             : 
    2788       18742 :     sal_uInt32 nXFId = FindXF( *pPattern, nForceScNumFmt, nForceXclFont, bForceLineBreak );
    2789       18742 :     if( nXFId == EXC_XFID_NOTFOUND )
    2790             :     {
    2791             :         // not found - insert new cell XF
    2792         146 :         if( maXFList.GetSize() < EXC_XFLIST_HARDLIMIT )
    2793             :         {
    2794             :             maXFList.AppendNewRecord( new XclExpXF(
    2795         146 :                 GetRoot(), *pPattern, nScript, nForceScNumFmt, nForceXclFont, bForceLineBreak ) );
    2796             :             // do not set nXFId before the AppendNewRecord() call - it may insert 2 XFs (style+cell)
    2797         146 :             nXFId = static_cast< sal_uInt32 >( maXFList.GetSize() - 1 );
    2798             :         }
    2799             :         else
    2800             :         {
    2801             :             // list full - fall back to default cell XF
    2802           0 :             nXFId = GetDefCellXFId();
    2803             :         }
    2804             :     }
    2805       18742 :     return nXFId;
    2806             : }
    2807             : 
    2808         230 : sal_uInt32 XclExpXFBuffer::InsertStyleXF( const SfxStyleSheetBase& rStyleSheet )
    2809             : {
    2810             :     // *** try, if it is a built-in style - create new XF or replace existing predefined XF ***
    2811             : 
    2812             :     sal_uInt8 nStyleId, nLevel;
    2813         230 :     if( XclTools::GetBuiltInStyleId( nStyleId, nLevel, rStyleSheet.GetName() ) )
    2814             :     {
    2815             :         // try to find the built-in XF record (if already created in InsertDefaultRecords())
    2816         180 :         sal_uInt32 nXFId = FindBuiltInXF( nStyleId, nLevel );
    2817         180 :         if( nXFId == EXC_XFID_NOTFOUND )
    2818             :         {
    2819             :             // built-in style XF not yet created - do it now
    2820           0 :             XclExpXFRef xXF( new XclExpXF( GetRoot(), rStyleSheet ) );
    2821           0 :             nXFId = AppendBuiltInXFWithStyle( xXF, nStyleId, nLevel );
    2822             :             // this new XF record is not predefined
    2823           0 :             maBuiltInMap[ nXFId ].mbPredefined = false;
    2824             :         }
    2825             :         else
    2826             :         {
    2827             :             OSL_ENSURE( maXFList.HasRecord( nXFId ), "XclExpXFBuffer::InsertStyleXF - built-in XF not found" );
    2828             :             // XF record still predefined? -> Replace with real XF
    2829         180 :             bool& rbPredefined = maBuiltInMap[ nXFId ].mbPredefined;
    2830         180 :             if( rbPredefined )
    2831             :             {
    2832             :                 // replace predefined built-in style (ReplaceRecord() deletes old record)
    2833           0 :                 maXFList.ReplaceRecord( XclExpXFRef( new XclExpXF( GetRoot(), rStyleSheet ) ), nXFId );
    2834           0 :                 rbPredefined = false;
    2835             :             }
    2836             :         }
    2837             : 
    2838             :         // STYLE already inserted? (may be not, i.e. for RowLevel/ColLevel or Hyperlink styles)
    2839         180 :         bool& rbHasStyleRec = maBuiltInMap[ nXFId ].mbHasStyleRec;
    2840         180 :         if( !rbHasStyleRec )
    2841             :         {
    2842           0 :             maStyleList.AppendNewRecord( new XclExpStyle( nXFId, nStyleId, nLevel ) );
    2843           0 :             rbHasStyleRec = true;
    2844             :         }
    2845             : 
    2846         180 :         return nXFId;
    2847             :     }
    2848             : 
    2849             :     // *** try to find the XF record of a user-defined style ***
    2850             : 
    2851          50 :     sal_uInt32 nXFId = FindXF( rStyleSheet );
    2852          50 :     if( nXFId == EXC_XFID_NOTFOUND )
    2853             :     {
    2854             :         // not found - insert new style XF and STYLE
    2855          12 :         nXFId = static_cast< sal_uInt32 >( maXFList.GetSize() );
    2856          12 :         if( nXFId < EXC_XFLIST_HARDLIMIT )
    2857             :         {
    2858          12 :             maXFList.AppendNewRecord( new XclExpXF( GetRoot(), rStyleSheet ) );
    2859             :             // create the STYLE record
    2860          12 :             if( !rStyleSheet.GetName().isEmpty() )
    2861          12 :                 maStyleList.AppendNewRecord( new XclExpStyle( nXFId, rStyleSheet.GetName() ) );
    2862             :         }
    2863             :         else
    2864             :             // list full - fall back to default style XF
    2865           0 :             nXFId = GetXFIdFromIndex( EXC_XF_DEFAULTSTYLE );
    2866             :     }
    2867          50 :     return nXFId;
    2868             : }
    2869             : 
    2870          72 : void XclExpXFBuffer::InsertUserStyles()
    2871             : {
    2872          72 :     SfxStyleSheetIterator aStyleIter( GetDoc().GetStyleSheetPool(), SFX_STYLE_FAMILY_PARA );
    2873         454 :     for( SfxStyleSheetBase* pStyleSheet = aStyleIter.First(); pStyleSheet; pStyleSheet = aStyleIter.Next() )
    2874         382 :         if( pStyleSheet->IsUserDefined() && !lclIsBuiltInStyle( pStyleSheet->GetName() ) )
    2875          84 :             InsertStyleXF( *pStyleSheet );
    2876          72 : }
    2877             : 
    2878        1440 : sal_uInt32 XclExpXFBuffer::AppendBuiltInXF( XclExpXFRef xXF, sal_uInt8 nStyleId, sal_uInt8 nLevel )
    2879             : {
    2880        1440 :     sal_uInt32 nXFId = static_cast< sal_uInt32 >( maXFList.GetSize() );
    2881        1440 :     maXFList.AppendRecord( xXF );
    2882        1440 :     XclExpBuiltInInfo& rInfo = maBuiltInMap[ nXFId ];
    2883        1440 :     rInfo.mnStyleId = nStyleId;
    2884        1440 :     rInfo.mnLevel = nLevel;
    2885        1440 :     rInfo.mbPredefined = true;
    2886        1440 :     return nXFId;
    2887             : }
    2888             : 
    2889         432 : sal_uInt32 XclExpXFBuffer::AppendBuiltInXFWithStyle( XclExpXFRef xXF, sal_uInt8 nStyleId, sal_uInt8 nLevel )
    2890             : {
    2891         432 :     sal_uInt32 nXFId = AppendBuiltInXF( xXF, nStyleId, nLevel );
    2892         432 :     maStyleList.AppendNewRecord( new XclExpStyle( nXFId, nStyleId, nLevel ) );
    2893         432 :     maBuiltInMap[ nXFId ].mbHasStyleRec = true;  // mark existing STYLE record
    2894         432 :     return nXFId;
    2895             : }
    2896             : 
    2897          72 : static XclExpCellArea lcl_GetPatternFill_None()
    2898             : {
    2899          72 :     XclExpCellArea aFill;
    2900          72 :     aFill.mnPattern = EXC_PATT_NONE;
    2901          72 :     return aFill;
    2902             : }
    2903             : 
    2904          72 : static XclExpCellArea lcl_GetPatternFill_Gray125()
    2905             : {
    2906          72 :     XclExpCellArea aFill;
    2907          72 :     aFill.mnPattern     = EXC_PATT_12_5_PERC;
    2908          72 :     aFill.mnForeColor   = 0;
    2909          72 :     aFill.mnBackColor   = 0;
    2910          72 :     return aFill;
    2911             : }
    2912             : 
    2913          72 : void XclExpXFBuffer::InsertDefaultRecords()
    2914             : {
    2915          72 :     maFills.push_back( lcl_GetPatternFill_None() );
    2916          72 :     maFills.push_back( lcl_GetPatternFill_Gray125() );
    2917             : 
    2918             :     // index 0: default style
    2919          72 :     if( SfxStyleSheetBase* pDefStyleSheet = GetStyleSheetPool().Find( ScGlobal::GetRscString( STR_STYLENAME_STANDARD ), SFX_STYLE_FAMILY_PARA ) )
    2920             :     {
    2921          72 :         XclExpXFRef xDefStyle( new XclExpXF( GetRoot(), *pDefStyleSheet ) );
    2922          72 :         sal_uInt32 nXFId = AppendBuiltInXFWithStyle( xDefStyle, EXC_STYLE_NORMAL );
    2923             :         // mark this XF as not predefined, prevents overwriting
    2924          72 :         maBuiltInMap[ nXFId ].mbPredefined = false;
    2925             :     }
    2926             :     else
    2927             :     {
    2928             :         OSL_FAIL( "XclExpXFBuffer::InsertDefaultRecords - default style not found" );
    2929           0 :         XclExpXFRef xDefStyle( new XclExpDefaultXF( GetRoot(), false ) );
    2930           0 :         xDefStyle->SetAllUsedFlags( true );
    2931           0 :         AppendBuiltInXFWithStyle( xDefStyle, EXC_STYLE_NORMAL );
    2932             :     }
    2933             : 
    2934             :     // index 1-14: RowLevel and ColLevel styles (without STYLE records)
    2935          72 :     XclExpDefaultXF aLevelStyle( GetRoot(), false );
    2936             :     // RowLevel_1, ColLevel_1
    2937          72 :     aLevelStyle.SetFont( 1 );
    2938          72 :     AppendBuiltInXF( XclExpXFRef( new XclExpDefaultXF( aLevelStyle ) ), EXC_STYLE_ROWLEVEL, 0 );
    2939          72 :     AppendBuiltInXF( XclExpXFRef( new XclExpDefaultXF( aLevelStyle ) ), EXC_STYLE_COLLEVEL, 0 );
    2940             :     // RowLevel_2, ColLevel_2
    2941          72 :     aLevelStyle.SetFont( 2 );
    2942          72 :     AppendBuiltInXF( XclExpXFRef( new XclExpDefaultXF( aLevelStyle ) ), EXC_STYLE_ROWLEVEL, 1 );
    2943          72 :     AppendBuiltInXF( XclExpXFRef( new XclExpDefaultXF( aLevelStyle ) ), EXC_STYLE_COLLEVEL, 1 );
    2944             :     // RowLevel_3, ColLevel_3 ... RowLevel_7, ColLevel_7
    2945          72 :     aLevelStyle.SetFont( 0 );
    2946         432 :     for( sal_uInt8 nLevel = 2; nLevel < EXC_STYLE_LEVELCOUNT; ++nLevel )
    2947             :     {
    2948         360 :         AppendBuiltInXF( XclExpXFRef( new XclExpDefaultXF( aLevelStyle ) ), EXC_STYLE_ROWLEVEL, nLevel );
    2949         360 :         AppendBuiltInXF( XclExpXFRef( new XclExpDefaultXF( aLevelStyle ) ), EXC_STYLE_COLLEVEL, nLevel );
    2950             :     }
    2951             : 
    2952             :     // index 15: default hard cell format, placeholder to be able to add more built-in styles
    2953          72 :     maXFList.AppendNewRecord( new XclExpDefaultXF( GetRoot(), true ) );
    2954          72 :     maBuiltInMap[ EXC_XF_DEFAULTCELL ].mbPredefined = true;
    2955             : 
    2956             :     // index 16-20: other built-in styles
    2957         144 :     XclExpDefaultXF aFormatStyle( GetRoot(), false );
    2958          72 :     aFormatStyle.SetFont( 1 );
    2959          72 :     aFormatStyle.SetNumFmt( 43 );
    2960          72 :     AppendBuiltInXFWithStyle( XclExpXFRef( new XclExpDefaultXF( aFormatStyle ) ), EXC_STYLE_COMMA );
    2961          72 :     aFormatStyle.SetNumFmt( 41 );
    2962          72 :     AppendBuiltInXFWithStyle( XclExpXFRef( new XclExpDefaultXF( aFormatStyle ) ), EXC_STYLE_COMMA_0 );
    2963          72 :     aFormatStyle.SetNumFmt( 44 );
    2964          72 :     AppendBuiltInXFWithStyle( XclExpXFRef( new XclExpDefaultXF( aFormatStyle ) ), EXC_STYLE_CURRENCY );
    2965          72 :     aFormatStyle.SetNumFmt( 42 );
    2966          72 :     AppendBuiltInXFWithStyle( XclExpXFRef( new XclExpDefaultXF( aFormatStyle ) ), EXC_STYLE_CURRENCY_0 );
    2967          72 :     aFormatStyle.SetNumFmt( 9 );
    2968          72 :     AppendBuiltInXFWithStyle( XclExpXFRef( new XclExpDefaultXF( aFormatStyle ) ), EXC_STYLE_PERCENT );
    2969             : 
    2970             :     // other built-in style XF records (i.e. Hyperlink styles) are created on demand
    2971             : 
    2972             :     /*  Insert the real default hard cell format -> 0 is document default pattern.
    2973             :         Do it here (and not already above) to really have all built-in styles. */
    2974         144 :     Insert( 0, GetDefApiScript() );
    2975          72 : }
    2976             : 
    2977        1640 : void XclExpXFBuffer::AppendXFIndex( sal_uInt32 nXFId )
    2978             : {
    2979             :     OSL_ENSURE( nXFId < maXFIndexVec.size(), "XclExpXFBuffer::AppendXFIndex - XF ID out of range" );
    2980        1640 :     maXFIndexVec[ nXFId ] = static_cast< sal_uInt16 >( maSortedXFList.GetSize() );
    2981        1640 :     XclExpXFRef xXF = maXFList.GetRecord( nXFId );
    2982        1640 :     AddBorderAndFill( *xXF );
    2983        1640 :     maSortedXFList.AppendRecord( xXF );
    2984        1640 :     OSL_ENSURE( maXFList.HasRecord( nXFId ), "XclExpXFBuffer::AppendXFIndex - XF not found" );
    2985        1640 : }
    2986             : 
    2987        1640 : void XclExpXFBuffer::AddBorderAndFill( const XclExpXF& rXF )
    2988             : {
    2989        1640 :     if( std::none_of( maBorders.begin(), maBorders.end(), XclExpBorderPred( rXF.GetBorderData() ) ) )
    2990             :     {
    2991         142 :         maBorders.push_back( rXF.GetBorderData() );
    2992             :     }
    2993             : 
    2994        1640 :     if( std::none_of( maFills.begin(), maFills.end(), XclExpFillPred( rXF.GetAreaData() ) ) )
    2995             :     {
    2996           0 :         maFills.push_back( rXF.GetAreaData() );
    2997             :     }
    2998        1640 : }
    2999             : 
    3000          72 : XclExpDxfs::XclExpDxfs( const XclExpRoot& rRoot )
    3001             :     : XclExpRoot( rRoot ),
    3002          72 :     mxFormatter( new SvNumberFormatter( comphelper::getProcessComponentContext(), LANGUAGE_ENGLISH_US ) ),
    3003         144 :     mpKeywordTable( new NfKeywordTable )
    3004             : {
    3005          72 :     mxFormatter->FillKeywordTable( *mpKeywordTable, LANGUAGE_ENGLISH_US );
    3006             :     // remap codes unknown to Excel
    3007          72 :     (*mpKeywordTable)[ NF_KEY_NN ] = "DDD";
    3008          72 :     (*mpKeywordTable)[ NF_KEY_NNN ] = "DDDD";
    3009             :     // NNNN gets a separator appended in SvNumberformat::GetMappedFormatString()
    3010          72 :     (*mpKeywordTable)[ NF_KEY_NNNN ] = "DDDD";
    3011             :     // Export the Thai T NatNum modifier.
    3012          72 :     (*mpKeywordTable)[ NF_KEY_THAI_T ] = "T";
    3013             : 
    3014          72 :     SCTAB nTables = rRoot.GetDoc().GetTableCount();
    3015         201 :     for(SCTAB nTab = 0; nTab < nTables; ++nTab)
    3016             :     {
    3017         129 :         ScConditionalFormatList* pList = rRoot.GetDoc().GetCondFormList(nTab);
    3018         129 :         if (pList)
    3019             :         {
    3020         129 :             sal_Int32 nIndex = 0;
    3021         450 :             for (ScConditionalFormatList::const_iterator itr = pList->begin();
    3022         300 :                     itr != pList->end(); ++itr)
    3023             :             {
    3024          21 :                 size_t nEntryCount = itr->size();
    3025          42 :                 for (size_t nFormatEntry = 0; nFormatEntry < nEntryCount; ++nFormatEntry)
    3026             :                 {
    3027          21 :                     const ScFormatEntry* pFormatEntry = itr->GetEntry(nFormatEntry);
    3028          32 :                     if (!pFormatEntry || (pFormatEntry->GetType() != condformat::CONDITION &&
    3029          11 :                                 pFormatEntry->GetType() != condformat::DATE))
    3030          22 :                         continue;
    3031             : 
    3032          10 :                     OUString aStyleName;
    3033          10 :                     if(pFormatEntry->GetType() == condformat::CONDITION)
    3034             :                     {
    3035          10 :                         const ScCondFormatEntry* pEntry = static_cast<const ScCondFormatEntry*>(pFormatEntry);
    3036          10 :                         aStyleName= pEntry->GetStyle();
    3037             :                     }
    3038             :                     else
    3039             :                     {
    3040           0 :                         const ScCondDateFormatEntry* pEntry = static_cast<const ScCondDateFormatEntry*>(pFormatEntry);
    3041           0 :                         aStyleName = pEntry->GetStyleName();
    3042             :                     }
    3043             : 
    3044          10 :                     if (maStyleNameToDxfId.find(aStyleName) == maStyleNameToDxfId.end())
    3045             :                     {
    3046          10 :                         maStyleNameToDxfId.insert(std::pair<OUString, sal_Int32>(aStyleName, nIndex));
    3047             : 
    3048          10 :                         SfxStyleSheetBase* pStyle = rRoot.GetDoc().GetStyleSheetPool()->Find(aStyleName);
    3049          10 :                         if(!pStyle)
    3050           0 :                             continue;
    3051             : 
    3052          10 :                         SfxItemSet& rSet = pStyle->GetItemSet();
    3053             : 
    3054          10 :                         XclExpCellBorder* pBorder = new XclExpCellBorder;
    3055          10 :                         if (!pBorder->FillFromItemSet( rSet, GetPalette(), GetBiff()) )
    3056             :                         {
    3057          10 :                             delete pBorder;
    3058          10 :                             pBorder = NULL;
    3059             :                         }
    3060             : 
    3061          10 :                         XclExpCellAlign* pAlign = new XclExpCellAlign;
    3062          10 :                         if (!pAlign->FillFromItemSet( rSet, false, GetBiff()))
    3063             :                         {
    3064          10 :                             delete pAlign;
    3065          10 :                             pAlign = NULL;
    3066             :                         }
    3067             : 
    3068          10 :                         XclExpCellProt* pCellProt = new XclExpCellProt;
    3069          10 :                         if (!pCellProt->FillFromItemSet( rSet ))
    3070             :                         {
    3071          10 :                             delete pCellProt;
    3072          10 :                             pCellProt = NULL;
    3073             :                         }
    3074             : 
    3075          10 :                         XclExpColor* pColor = new XclExpColor();
    3076          10 :                         if(!pColor->FillFromItemSet( rSet ))
    3077             :                         {
    3078          10 :                             delete pColor;
    3079          10 :                             pColor = NULL;
    3080             :                         }
    3081             : 
    3082          10 :                         XclExpDxfFont* pFont = new XclExpDxfFont(rRoot, rSet);
    3083             : 
    3084          10 :                         XclExpNumFmt* pNumFormat = NULL;
    3085          10 :                         const SfxPoolItem *pPoolItem = NULL;
    3086          10 :                         if( rSet.GetItemState( ATTR_VALUE_FORMAT, true, &pPoolItem ) == SfxItemState::SET )
    3087             :                         {
    3088          10 :                             sal_uLong nScNumFmt = static_cast< const SfxUInt32Item* >(pPoolItem)->GetValue();
    3089          10 :                             sal_Int32 nXclNumFmt = GetRoot().GetNumFmtBuffer().Insert(nScNumFmt);
    3090          10 :                             pNumFormat = new XclExpNumFmt( nScNumFmt, nXclNumFmt, GetNumberFormatCode( *this, nScNumFmt, mxFormatter.get(), mpKeywordTable.get() ));
    3091             :                         }
    3092             : 
    3093          10 :                         maDxf.push_back(new XclExpDxf( rRoot, pAlign, pBorder, pFont, pNumFormat, pCellProt, pColor ));
    3094          10 :                         ++nIndex;
    3095             :                     }
    3096             : 
    3097          10 :                 }
    3098             :             }
    3099             :         }
    3100             :     }
    3101          72 : }
    3102             : 
    3103          10 : sal_Int32 XclExpDxfs::GetDxfId( const OUString& rStyleName )
    3104             : {
    3105          10 :     std::map<OUString, sal_Int32>::iterator itr = maStyleNameToDxfId.find(rStyleName);
    3106          10 :     if(itr!= maStyleNameToDxfId.end())
    3107          10 :         return itr->second;
    3108           0 :     return -1;
    3109             : }
    3110             : 
    3111          55 : void XclExpDxfs::SaveXml( XclExpXmlStream& rStrm )
    3112             : {
    3113          55 :     if(maDxf.empty())
    3114         109 :         return;
    3115             : 
    3116           1 :     sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream();
    3117             :     rStyleSheet->startElement( XML_dxfs,
    3118             :             XML_count, OString::number(maDxf.size()).getStr(),
    3119           1 :             FSEND );
    3120             : 
    3121          11 :     for ( DxfContainer::iterator itr = maDxf.begin(); itr != maDxf.end(); ++itr )
    3122             :     {
    3123          10 :         itr->SaveXml( rStrm );
    3124             :     }
    3125             : 
    3126           1 :     rStyleSheet->endElement( XML_dxfs );
    3127             : }
    3128             : 
    3129          10 : XclExpDxf::XclExpDxf( const XclExpRoot& rRoot, XclExpCellAlign* pAlign, XclExpCellBorder* pBorder,
    3130             :             XclExpDxfFont* pFont, XclExpNumFmt* pNumberFmt, XclExpCellProt* pProt, XclExpColor* pColor)
    3131             :     : XclExpRoot( rRoot ),
    3132             :     mpAlign(pAlign),
    3133             :     mpBorder(pBorder),
    3134             :     mpFont(pFont),
    3135             :     mpNumberFmt(pNumberFmt),
    3136             :     mpProt(pProt),
    3137          10 :     mpColor(pColor)
    3138             : {
    3139          10 : }
    3140             : 
    3141          20 : XclExpDxf::~XclExpDxf()
    3142             : {
    3143          20 : }
    3144             : 
    3145          10 : void XclExpDxf::SaveXml( XclExpXmlStream& rStrm )
    3146             : {
    3147          10 :     sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream();
    3148          10 :     rStyleSheet->startElement( XML_dxf, FSEND );
    3149             : 
    3150          10 :     if (mpFont)
    3151          10 :         mpFont->SaveXml(rStrm);
    3152          10 :     if (mpNumberFmt)
    3153          10 :         mpNumberFmt->SaveXml(rStrm);
    3154          10 :     if (mpColor)
    3155           0 :         mpColor->SaveXml(rStrm);
    3156          10 :     if (mpAlign)
    3157           0 :         mpAlign->SaveXml(rStrm);
    3158          10 :     if (mpBorder)
    3159           0 :         mpBorder->SaveXml(rStrm);
    3160          10 :     if (mpProt)
    3161           0 :         mpProt->SaveXml(rStrm);
    3162          10 :     rStyleSheet->endElement( XML_dxf );
    3163          10 : }
    3164             : 
    3165          55 : XclExpXmlStyleSheet::XclExpXmlStyleSheet( const XclExpRoot& rRoot )
    3166          55 :     : XclExpRoot( rRoot )
    3167             : {
    3168          55 : }
    3169             : 
    3170          55 : void XclExpXmlStyleSheet::SaveXml( XclExpXmlStream& rStrm )
    3171             : {
    3172             :     sax_fastparser::FSHelperPtr aStyleSheet = rStrm.CreateOutputStream(
    3173             :             OUString( "xl/styles.xml"),
    3174             :             OUString( "styles.xml" ),
    3175          55 :             rStrm.GetCurrentStream()->getOutputStream(),
    3176             :             "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml",
    3177          55 :             "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" );
    3178          55 :     rStrm.PushStream( aStyleSheet );
    3179             : 
    3180             :     aStyleSheet->startElement( XML_styleSheet,
    3181             :             XML_xmlns, "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
    3182          55 :             FSEND );
    3183             : 
    3184          55 :     CreateRecord( EXC_ID_FORMATLIST )->SaveXml( rStrm );
    3185          55 :     CreateRecord( EXC_ID_FONTLIST )->SaveXml( rStrm );
    3186          55 :     CreateRecord( EXC_ID_XFLIST )->SaveXml( rStrm );
    3187          55 :     CreateRecord( EXC_ID_DXFS )->SaveXml( rStrm );
    3188          55 :     CreateRecord( EXC_ID_PALETTE )->SaveXml( rStrm );
    3189             : 
    3190          55 :     aStyleSheet->endElement( XML_styleSheet );
    3191             : 
    3192          55 :     rStrm.PopStream();
    3193          85 : }
    3194             : 
    3195             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11