/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sc.hxx"
#include "xestyle.hxx"

#include <algorithm>
#include <iterator>
#include <set>
#include <com/sun/star/i18n/ScriptType.hpp>
#include <vcl/font.hxx>
#include <svl/zformat.hxx>
#include <svl/languageoptions.hxx>
#include <sfx2/printer.hxx>
#include "scitems.hxx"
#include <svx/algitem.hxx>
#include <editeng/boxitem.hxx>
#include <editeng/bolnitem.hxx>
#include <svx/rotmodit.hxx>
#include <editeng/colritem.hxx>
#include <editeng/brshitem.hxx>
#include <editeng/frmdiritem.hxx>
#include <editeng/eeitem.hxx>
#include <editeng/escpitem.hxx>
#include "document.hxx"
#include "stlpool.hxx"
#include "stlsheet.hxx"
#include "patattr.hxx"
#include "attrib.hxx"
#include "globstr.hrc"
#include "xestring.hxx"

using namespace ::oox;

using ::rtl::OString;
using ::rtl::OUString;

// PALETTE record - color information =========================================

namespace {

sal_uInt32 lclGetWeighting( XclExpColorType eType )
{
    switch( eType )
    {
        case EXC_COLOR_CHARTLINE:   return 1;
        case EXC_COLOR_CELLBORDER:
        case EXC_COLOR_CHARTAREA:   return 2;
        case EXC_COLOR_CELLTEXT:
        case EXC_COLOR_CHARTTEXT:
        case EXC_COLOR_CTRLTEXT:    return 10;
        case EXC_COLOR_TABBG:
        case EXC_COLOR_CELLAREA:    return 20;
        case EXC_COLOR_GRID:        return 50;
        default:    DBG_ERRORFILE( "lclGetWeighting - unknown color type" );
    }
    return 1;
}

sal_Int32 lclGetColorDistance( const Color& rColor1, const Color& rColor2 )
{
    sal_Int32 nDist = rColor1.GetRed() - rColor2.GetRed();
    nDist *= nDist * 77;
    sal_Int32 nDummy = rColor1.GetGreen() - rColor2.GetGreen();
    nDist += nDummy * nDummy * 151;
    nDummy = rColor1.GetBlue() - rColor2.GetBlue();
    nDist += nDummy * nDummy * 28;
    return nDist;
}

sal_uInt8 lclGetMergedColorComp( sal_uInt8 nComp1, sal_uInt32 nWeight1, sal_uInt8 nComp2, sal_uInt32 nWeight2 )
{
    sal_uInt8 nComp1Dist = ::std::min< sal_uInt8 >( nComp1, 0xFF - nComp1 );
    sal_uInt8 nComp2Dist = ::std::min< sal_uInt8 >( nComp2, 0xFF - nComp2 );
    if( nComp1Dist != nComp2Dist )
    {
        /*  #i36945# One of the passed RGB components is nearer at the limits (0x00 or 0xFF).
            Increase its weighting to prevent fading of the colors during reduction. */
        const sal_uInt8& rnCompNearer = (nComp1Dist < nComp2Dist) ? nComp1 : nComp2;
        sal_uInt32& rnWeight = (nComp1Dist < nComp2Dist) ? nWeight1 : nWeight2;
        rnWeight *= ((rnCompNearer - 0x80L) * (rnCompNearer - 0x7FL) / 0x1000L + 1);
    }
    sal_uInt32 nWSum = nWeight1 + nWeight2;
    return static_cast< sal_uInt8 >( (nComp1 * nWeight1 + nComp2 * nWeight2 + nWSum / 2) / nWSum );
}

void lclSetMixedColor( Color& rDest, const Color& rSrc1, const Color& rSrc2 )
{
    rDest.SetRed( static_cast< sal_uInt8 >( (static_cast< sal_uInt16 >( rSrc1.GetRed() ) + rSrc2.GetRed()) / 2 ) );
    rDest.SetGreen( static_cast< sal_uInt8 >( (static_cast< sal_uInt16 >( rSrc1.GetGreen() ) + rSrc2.GetGreen()) / 2 ) );
    rDest.SetBlue( static_cast< sal_uInt8 >( (static_cast< sal_uInt16 >( rSrc1.GetBlue() ) + rSrc2.GetBlue()) / 2 ) );
}

} // namespace

// additional classes for color reduction -------------------------------------

namespace {

/** Represents an entry in a color list.

    The color stores a weighting value, which increases the more the color is
    used in the document. Heavy-weighted colors will change less than others on
    color reduction.
 */
class XclListColor
{
    DECL_FIXEDMEMPOOL_NEWDEL( XclListColor )

private:
    Color               maColor;        /// The color value of this palette entry.
    sal_uInt32          mnColorId;      /// Unique color ID for color reduction.
    sal_uInt32          mnWeight;       /// Weighting for color reduction.
    bool                mbBaseColor;    /// true = Handle as base color, (don't remove/merge).

public:
    explicit            XclListColor( const Color& rColor, sal_uInt32 nColorId );

    /** Returns the RGB color value of the color. */
    inline const Color& GetColor() const { return maColor; }
    /** Returns the unique ID of the color. */
    inline sal_uInt32   GetColorId() const { return mnColorId; }
    /** Returns the current weighting of the color. */
    inline sal_uInt32   GetWeighting() const { return mnWeight; }
    /** Returns true, if this color is a base color, i.e. it will not be removed or merged. */
    inline bool         IsBaseColor() const { return mbBaseColor; }

    /** Adds the passed weighting to this color. */
    inline void         AddWeighting( sal_uInt32 nWeight ) { mnWeight += nWeight; }
    /** Merges this color with rColor, regarding weighting settings. */
    void                Merge( const XclListColor& rColor );
};

IMPL_FIXEDMEMPOOL_NEWDEL( XclListColor, 100, 100 )

XclListColor::XclListColor( const Color& rColor, sal_uInt32 nColorId ) :
    maColor( rColor ),
    mnColorId( nColorId ),
    mnWeight( 0 )
{
    mbBaseColor =
        ((rColor.GetRed()   == 0x00) || (rColor.GetRed()   == 0xFF)) &&
        ((rColor.GetGreen() == 0x00) || (rColor.GetGreen() == 0xFF)) &&
        ((rColor.GetBlue()  == 0x00) || (rColor.GetBlue()  == 0xFF));
}

void XclListColor::Merge( const XclListColor& rColor )
{
    sal_uInt32 nWeight2 = rColor.GetWeighting();
    // do not change RGB value of base colors
    if( !mbBaseColor )
    {
        maColor.SetRed(   lclGetMergedColorComp( maColor.GetRed(),   mnWeight, rColor.maColor.GetRed(),   nWeight2 ) );
        maColor.SetGreen( lclGetMergedColorComp( maColor.GetGreen(), mnWeight, rColor.maColor.GetGreen(), nWeight2 ) );
        maColor.SetBlue(  lclGetMergedColorComp( maColor.GetBlue(),  mnWeight, rColor.maColor.GetBlue(),  nWeight2 ) );
    }
    AddWeighting( nWeight2 );
}

// ----------------------------------------------------------------------------

/** Data for each inserted original color, represented by a color ID. */
struct XclColorIdData
{
    Color               maColor;        /// The original inserted color.
    sal_uInt32          mnIndex;        /// Maps current color ID to color list or export color vector.
    /** Sets the contents of this struct. */
    inline void         Set( const Color& rColor, sal_uInt32 nIndex ) { maColor = rColor; mnIndex = nIndex; }
};

/** A color that will be written to the Excel file. */
struct XclPaletteColor
{
    Color               maColor;        /// Resulting color to export.
    bool                mbUsed;         /// true = Entry is used in the document.

    inline explicit     XclPaletteColor( const Color& rColor ) : maColor( rColor ), mbUsed( false ) {}
    inline void         SetColor( const Color& rColor ) { maColor = rColor; mbUsed = true; }
};

/** Maps a color list index to a palette index.
    @descr  Used to remap the color ID data vector from list indexes to palette indexes. */
struct XclRemap
{
    sal_uInt32          mnPalIndex;     /// Index to palette.
    bool                mbProcessed;    /// true = List color already processed.

    inline explicit     XclRemap() : mnPalIndex( 0 ), mbProcessed( false ) {}
    inline void         SetIndex( sal_uInt32 nPalIndex )
                            { mnPalIndex = nPalIndex; mbProcessed = true; }
};

/** Stores the nearest palette color index of a list color. */
struct XclNearest
{
    sal_uInt32          mnPalIndex;     /// Index to nearest palette color.
    sal_Int32           mnDist;         /// Distance to palette color.

    inline explicit     XclNearest() : mnPalIndex( 0 ), mnDist( 0 ) {}
};

typedef ::std::vector< XclRemap >   XclRemapVec;
typedef ::std::vector< XclNearest > XclNearestVec;

} // namespace

// ----------------------------------------------------------------------------

class XclExpPaletteImpl
{
public:
    explicit            XclExpPaletteImpl( const XclDefaultPalette& rDefPal );

    /** Inserts the color into the list and updates weighting.
        @param nAutoDefault  The Excel palette index for automatic color.
        @return  A unique ID for this color. */
    sal_uInt32          InsertColor( const Color& rColor, XclExpColorType eType, sal_uInt16 nAutoDefault = 0 );
    /** Returns the color ID representing a fixed Excel palette index (i.e. for auto colors). */
    static sal_uInt32   GetColorIdFromIndex( sal_uInt16 nIndex );

    /** Reduces the color list to the maximum count of the current BIFF version. */
    void                Finalize();

    /** Returns the Excel palette index of the color with passed color ID. */
    sal_uInt16          GetColorIndex( sal_uInt32 nColorId ) const;

    /** Returns a foreground and background color for the two passed color IDs.
        @descr  If rnXclPattern contains a solid pattern, this function tries to find
        the two best fitting colors and a mix pattern (25%, 50% or 75%) for nForeColorId.
        This will result in a better approximation to the passed foreground color. */
    void                GetMixedColors(
                            sal_uInt16& rnXclForeIx, sal_uInt16& rnXclBackIx, sal_uInt8& rnXclPattern,
                            sal_uInt32 nForeColorId, sal_uInt32 nBackColorId ) const;

    /** Returns the RGB color data for a (non-zero-based) Excel palette entry.
        @return  The color from current or default palette or COL_AUTO, if nothing else found. */
    ColorData           GetColorData( sal_uInt16 nXclIndex ) const;
    /** Returns the color for a (non-zero-based) Excel palette entry.
        @return  The color from current or default palette or COL_AUTO, if nothing else found. */
    inline Color        GetColor( sal_uInt16 nXclIndex ) const
                            { return Color( GetColorData( nXclIndex ) ); }

    /** Returns true, if all colors of the palette are equal to default palette colors. */
    bool                IsDefaultPalette() const;
    /** Writes the color list (contents of the palette record) to the passed stream. */
    void                WriteBody( XclExpStream& rStrm );
    void                SaveXml( XclExpXmlStream& rStrm );

private:
    /** Returns the Excel index of a 0-based color index. */
    inline sal_uInt16   GetXclIndex( sal_uInt32 nIndex ) const
                            { return static_cast< sal_uInt16 >( nIndex + EXC_COLOR_USEROFFSET ); }

    /** Returns the original inserted color represented by the color ID nColorId. */
    const Color&        GetOriginalColor( sal_uInt32 nColorId ) const;

    /** Searches for rColor, returns the ordered insertion index for rColor in rnIndex. */
    XclListColor*       SearchListEntry( const Color& rColor, sal_uInt32& rnIndex );
    /** Creates and inserts a new color list entry at the specified list position. */
    XclListColor*       CreateListEntry( const Color& rColor, sal_uInt32 nIndex );

    /** Raw and fast reduction of the palette. */
    void                RawReducePalette( sal_uInt32 nPass );
    /** Reduction of one color using advanced color merging based on color weighting. */
    void                ReduceLeastUsedColor();

    /** Finds the least used color and returns its current list index. */
    sal_uInt32          GetLeastUsedListColor() const;
    /** Returns the list index of the color nearest to rColor.
        @param nIgnore  List index of a color which will be ignored.
        @return  The list index of the found color. */
    sal_uInt32          GetNearestListColor( const Color& rColor, sal_uInt32 nIgnore ) const;
    /** Returns the list index of the color nearest to the color with list index nIndex. */
    sal_uInt32          GetNearestListColor( sal_uInt32 nIndex ) const;

    /** Returns in rnIndex the palette index of the color nearest to rColor.
        @param bDefaultOnly  true = Searches for default colors only (colors never replaced).
        @return  The distance from passed color to found color. */
    sal_Int32           GetNearestPaletteColor(
                            sal_uInt32& rnIndex,
                            const Color& rColor, bool bDefaultOnly ) const;
    /** Returns in rnFirst and rnSecond the palette indexes of the two colors nearest to rColor.
        @return  The minimum distance from passed color to found colors. */
    sal_Int32           GetNearPaletteColors(
                            sal_uInt32& rnFirst, sal_uInt32& rnSecond,
                            const Color& rColor ) const;

private:
    typedef ScfDelList< XclListColor >          XclListColorList;
    typedef ScfRef< XclListColorList >          XclListColorListRef;
    typedef ::std::vector< XclColorIdData >     XclColorIdDataVec;
    typedef ::std::vector< XclPaletteColor >    XclPaletteColorVec;

    const XclDefaultPalette& mrDefPal;      /// The default palette for the current BIFF version.
    XclListColorListRef mxColorList;        /// Working color list.
    XclColorIdDataVec   maColorIdDataVec;   /// Data of all CIDs.
    XclPaletteColorVec  maPalette;          /// Contains resulting colors to export.
    sal_uInt32          mnLastIdx;          /// Last insertion index for search opt.
};

// ----------------------------------------------------------------------------

const sal_uInt32 EXC_PAL_INDEXBASE          = 0xFFFF0000;
const sal_uInt32 EXC_PAL_MAXRAWSIZE         = 1024;

XclExpPaletteImpl::XclExpPaletteImpl( const XclDefaultPalette& rDefPal ) :
    mrDefPal( rDefPal ),
    mxColorList( new XclListColorList ),
    mnLastIdx( 0 )
{
    // initialize maPalette with default colors
    sal_uInt16 nCount = static_cast< sal_uInt16 >( mrDefPal.GetColorCount() );
    maPalette.reserve( nCount );
    for( sal_uInt16 nIdx = 0; nIdx < nCount; ++nIdx )
        maPalette.push_back( XclPaletteColor( mrDefPal.GetDefColor( GetXclIndex( nIdx ) ) ) );

    InsertColor( Color( COL_BLACK ), EXC_COLOR_CELLTEXT );
}

sal_uInt32 XclExpPaletteImpl::InsertColor( const Color& rColor, XclExpColorType eType, sal_uInt16 nAutoDefault )
{
    if( rColor.GetColor() == COL_AUTO )
        return GetColorIdFromIndex( nAutoDefault );

    sal_uInt32 nFoundIdx = 0;
    XclListColor* pEntry = SearchListEntry( rColor, nFoundIdx );
    if( !pEntry || (pEntry->GetColor() != rColor) )
        pEntry = CreateListEntry( rColor, nFoundIdx );
    pEntry->AddWeighting( lclGetWeighting( eType ) );

    return pEntry->GetColorId();
}

sal_uInt32 XclExpPaletteImpl::GetColorIdFromIndex( sal_uInt16 nIndex )
{
    return EXC_PAL_INDEXBASE | nIndex;
}

void XclExpPaletteImpl::Finalize()
{
// --- build initial color ID data vector (maColorIdDataVec) ---

    sal_uInt32 nCount = mxColorList->Count();
    maColorIdDataVec.resize( nCount );
    for( sal_uInt32 nIdx = 0; nIdx < nCount; ++nIdx )
    {
        XclListColor* pListColor = mxColorList->GetObject( nIdx );
        maColorIdDataVec[ pListColor->GetColorId() ].Set( pListColor->GetColor(), nIdx );
    }

// --- loop as long as current color count does not fit into palette of current BIFF ---

    // phase 1: raw reduction (performance reasons, #i36945#)
    sal_uInt32 nPass = 0;
    while( mxColorList->Count() > EXC_PAL_MAXRAWSIZE )
        RawReducePalette( nPass++ );

    // phase 2: precise reduction using advanced color merging based on color weighting
    while( mxColorList->Count() > mrDefPal.GetColorCount() )
        ReduceLeastUsedColor();

// --- #104865# use default palette and replace colors with nearest used colors ---

    nCount = mxColorList->Count();
    XclRemapVec aRemapVec( nCount );
    XclNearestVec aNearestVec( nCount );

    // in each run: search the best fitting color and replace a default color with it
    for( sal_uInt32 nRun = 0; nRun < nCount; ++nRun )
    {
        sal_uInt32 nIndex;
        // find nearest unused default color for each unprocessed list color
        for( nIndex = 0; nIndex < nCount; ++nIndex )
            aNearestVec[ nIndex ].mnDist = aRemapVec[ nIndex ].mbProcessed ? SAL_MAX_INT32 :
                GetNearestPaletteColor( aNearestVec[ nIndex ].mnPalIndex, mxColorList->GetObject( nIndex )->GetColor(), true );
        // find the list color which is nearest to a default color
        sal_uInt32 nFound = 0;
        for( nIndex = 1; nIndex < nCount; ++nIndex )
            if( aNearestVec[ nIndex ].mnDist < aNearestVec[ nFound ].mnDist )
                nFound = nIndex;
        // replace default color with list color
        sal_uInt32 nNearest = aNearestVec[ nFound ].mnPalIndex;
        DBG_ASSERT( mxColorList->GetObject( nFound ), "XclExpPaletteImpl::Finalize - missing a color" );
        DBG_ASSERT( nNearest < maPalette.size(), "XclExpPaletteImpl::Finalize - algorithm error" );
        maPalette[ nNearest ].SetColor( mxColorList->GetObject( nFound )->GetColor() );
        aRemapVec[ nFound ].SetIndex( nNearest );
    }

    // remap color ID data map (maColorIdDataVec) from list indexes to palette indexes
    for( XclColorIdDataVec::iterator aIt = maColorIdDataVec.begin(), aEnd = maColorIdDataVec.end(); aIt != aEnd; ++aIt )
        aIt->mnIndex = aRemapVec[ aIt->mnIndex ].mnPalIndex;
}

sal_uInt16 XclExpPaletteImpl::GetColorIndex( sal_uInt32 nColorId ) const
{
    sal_uInt16 nRet = 0;
    if( nColorId >= EXC_PAL_INDEXBASE )
        nRet = static_cast< sal_uInt16 >( nColorId & ~EXC_PAL_INDEXBASE );
    else if( nColorId < maColorIdDataVec.size() )
        nRet = GetXclIndex( maColorIdDataVec[ nColorId ].mnIndex );
    return nRet;
}

void XclExpPaletteImpl::GetMixedColors(
        sal_uInt16& rnXclForeIx, sal_uInt16& rnXclBackIx, sal_uInt8& rnXclPattern,
        sal_uInt32 nForeColorId, sal_uInt32 nBackColorId ) const
{
    rnXclForeIx = GetColorIndex( nForeColorId );
    rnXclBackIx = GetColorIndex( nBackColorId );
    if( (rnXclPattern != EXC_PATT_SOLID) || (nForeColorId >= maColorIdDataVec.size()) )
        return;

    // now we have solid pattern, and a defined foreground (background doesn't care for solid pattern)

    sal_uInt32 nIndex1, nIndex2;
    Color aForeColor( GetOriginalColor( nForeColorId ) );
    sal_Int32 nFirstDist = GetNearPaletteColors( nIndex1, nIndex2, aForeColor );
    if( (nIndex1 >= maPalette.size()) || (nIndex2 >= maPalette.size()) )
        return;

    Color aColorArr[ 5 ];
    aColorArr[ 0 ] = maPalette[ nIndex1 ].maColor;
    aColorArr[ 4 ] = maPalette[ nIndex2 ].maColor;
    lclSetMixedColor( aColorArr[ 2 ], aColorArr[ 0 ], aColorArr[ 4 ] );
    lclSetMixedColor( aColorArr[ 1 ], aColorArr[ 0 ], aColorArr[ 2 ] );
    lclSetMixedColor( aColorArr[ 3 ], aColorArr[ 2 ], aColorArr[ 4 ] );

    sal_Int32 nMinDist = nFirstDist;
    sal_uInt32 nMinIndex = 0;
    for( sal_uInt32 nCnt = 1; nCnt < 4; ++nCnt )
    {
        sal_Int32 nDist = lclGetColorDistance( aForeColor, aColorArr[ nCnt ] );
        if( nDist < nMinDist )
        {
            nMinDist = nDist;
            nMinIndex = nCnt;
        }
    }
    rnXclForeIx = GetXclIndex( nIndex1 );
    rnXclBackIx = GetXclIndex( nIndex2 );
    if( nMinDist < nFirstDist )
    {
        switch( nMinIndex )
        {
            case 1: rnXclPattern = EXC_PATT_75_PERC;    break;
            case 2: rnXclPattern = EXC_PATT_50_PERC;    break;
            case 3: rnXclPattern = EXC_PATT_25_PERC;    break;
        }
    }
}

ColorData XclExpPaletteImpl::GetColorData( sal_uInt16 nXclIndex ) const
{
    if( nXclIndex >= EXC_COLOR_USEROFFSET )
    {
        sal_uInt32 nIdx = nXclIndex - EXC_COLOR_USEROFFSET;
        if( nIdx < maPalette.size() )
            return maPalette[ nIdx ].maColor.GetColor();
    }
    return mrDefPal.GetDefColorData( nXclIndex );
}

bool XclExpPaletteImpl::IsDefaultPalette() const
{
    bool bDefault = true;
    for( sal_uInt32 nIdx = 0, nSize = static_cast< sal_uInt32 >( maPalette.size() ); bDefault && (nIdx < nSize); ++nIdx )
        bDefault = maPalette[ nIdx ].maColor == mrDefPal.GetDefColor( GetXclIndex( nIdx ) );
    return bDefault;
}

void XclExpPaletteImpl::WriteBody( XclExpStream& rStrm )
{
    rStrm << static_cast< sal_uInt16 >( maPalette.size() );
    for( XclPaletteColorVec::const_iterator aIt = maPalette.begin(), aEnd = maPalette.end(); aIt != aEnd; ++aIt )
        rStrm << aIt->maColor;
}

void XclExpPaletteImpl::SaveXml( XclExpXmlStream& rStrm )
{
    if( !maPalette.size() )
        return;

    sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream();
    rStyleSheet->startElement( XML_colors, FSEND );
    rStyleSheet->startElement( XML_indexedColors, FSEND );
    for( XclPaletteColorVec::const_iterator aIt = maPalette.begin(), aEnd = maPalette.end(); aIt != aEnd; ++aIt )
        rStyleSheet->singleElement( XML_rgbColor,
                XML_rgb,    XclXmlUtils::ToOString( aIt->maColor ).getStr(),
                FSEND );
    rStyleSheet->endElement( XML_indexedColors );
    rStyleSheet->endElement( XML_colors );
}

const Color& XclExpPaletteImpl::GetOriginalColor( sal_uInt32 nColorId ) const
{
    if( nColorId < maColorIdDataVec.size() )
        return maColorIdDataVec[ nColorId ].maColor;
    return maPalette[ 0 ].maColor;
}

XclListColor* XclExpPaletteImpl::SearchListEntry( const Color& rColor, sal_uInt32& rnIndex )
{
    rnIndex = mnLastIdx;
    XclListColor* pEntry = mxColorList->GetObject( rnIndex );

    // search optimization for equal-colored objects occurring repeatedly
    if( pEntry && (pEntry->GetColor() == rColor) )
        return pEntry;

    // binary search for color
    sal_uInt32 nBegIdx = 0;
    sal_uInt32 nEndIdx = mxColorList->Count();
    bool bFound = false;
    while( !bFound && (nBegIdx < nEndIdx) )
    {
        rnIndex = (nBegIdx + nEndIdx) / 2;
        pEntry = mxColorList->GetObject( rnIndex );
        bFound = pEntry->GetColor() == rColor;
        if( !bFound )
        {
            if( pEntry->GetColor().GetColor() < rColor.GetColor() )
                nBegIdx = rnIndex + 1;
            else
                nEndIdx = rnIndex;
        }
    }
    // not found - use end of range as new insertion position
    if( !bFound )
        pEntry = mxColorList->GetObject( rnIndex = nEndIdx );

    mnLastIdx = rnIndex;
    return pEntry;
}

XclListColor* XclExpPaletteImpl::CreateListEntry( const Color& rColor, sal_uInt32 nIndex )
{
    XclListColor* pEntry = new XclListColor( rColor, mxColorList->Count() );
    mxColorList->Insert( pEntry, nIndex );
    return pEntry;
}

void XclExpPaletteImpl::RawReducePalette( sal_uInt32 nPass )
{
    /*  Fast palette reduction - in each call of this function one RGB component
        of each color is reduced to a lower number of distinct values.
        Pass 0: Blue is reduced to 128 distinct values.
        Pass 1: Red is reduced to 128 distinct values.
        Pass 2: Green is reduced to 128 distinct values.
        Pass 3: Blue is reduced to 64 distinct values.
        Pass 4: Red is reduced to 64 distinct values.
        Pass 5: Green is reduced to 64 distinct values.
        And so on...
     */

    XclListColorListRef xOldList = mxColorList;
    mxColorList.reset( new XclListColorList );

    // maps old list indexes to new list indexes, used to update maColorIdDataVec
    ScfUInt32Vec aListIndexMap;
    aListIndexMap.reserve( xOldList->Count() );

    // preparations
    sal_uInt8 nR, nG, nB;
    sal_uInt8& rnComp = ((nPass % 3 == 0) ? nB : ((nPass % 3 == 1) ? nR : nG));
    nPass /= 3;
    DBG_ASSERT( nPass < 7, "XclExpPaletteImpl::RawReducePalette - reduction not terminated" );

    static const sal_uInt8 spnFactor2[] = { 0x81, 0x82, 0x84, 0x88, 0x92, 0xAA, 0xFF };
    sal_uInt8 nFactor1 = static_cast< sal_uInt8 >( 0x02 << nPass );
    sal_uInt8 nFactor2 = spnFactor2[ nPass ];
    sal_uInt8 nFactor3 = static_cast< sal_uInt8 >( 0x40 >> nPass );

    // process each color in the old color list
    for( sal_uInt32 nIdx = 0, nCount = xOldList->Count(); nIdx < nCount; ++nIdx )
    {
        // get the old list entry
        const XclListColor* pOldEntry = xOldList->GetObject( nIdx );
        nR = pOldEntry->GetColor().GetRed();
        nG = pOldEntry->GetColor().GetGreen();
        nB = pOldEntry->GetColor().GetBlue();

        /*  Calculate the new RGB component (rnComp points to one of nR, nG, nB).
            Using integer arithmetic with its rounding errors, the results of
            this calculation are always exactly in the range 0x00 to 0xFF
            (simply cutting the lower bits would darken the colors slightly). */
        sal_uInt32 nNewComp = rnComp;
        nNewComp /= nFactor1;
        nNewComp *= nFactor2;
        nNewComp /= nFactor3;
        rnComp = static_cast< sal_uInt8 >( nNewComp );
        Color aNewColor( nR, nG, nB );

        // find or insert the new color
        sal_uInt32 nFoundIdx = 0;
        XclListColor* pNewEntry = SearchListEntry( aNewColor, nFoundIdx );
        if( !pNewEntry || (pNewEntry->GetColor() != aNewColor) )
            pNewEntry = CreateListEntry( aNewColor, nFoundIdx );
        pNewEntry->AddWeighting( pOldEntry->GetWeighting() );
        aListIndexMap.push_back( nFoundIdx );
    }

    // update color ID data map (maps color IDs to color list indexes), replace old by new list indexes
    for( XclColorIdDataVec::iterator aIt = maColorIdDataVec.begin(), aEnd = maColorIdDataVec.end(); aIt != aEnd; ++aIt )
        aIt->mnIndex = aListIndexMap[ aIt->mnIndex ];
}

void XclExpPaletteImpl::ReduceLeastUsedColor()
{
    // find a list color to remove
    sal_uInt32 nRemove = GetLeastUsedListColor();
    // find its nearest neighbor
    sal_uInt32 nKeep = GetNearestListColor( nRemove );

    // merge both colors to one color, remove one color from list
    XclListColor* pKeepEntry = mxColorList->GetObject( nKeep );
    XclListColor* pRemoveEntry = mxColorList->GetObject( nRemove );
    if( pKeepEntry && pRemoveEntry )
    {
        // merge both colors (if pKeepEntry is a base color, it will not change)
        pKeepEntry->Merge( *pRemoveEntry );
        // remove the less used color, adjust nKeep index if kept color follows removed color
        mxColorList->Delete( nRemove );
        if( nKeep > nRemove ) --nKeep;

        // recalculate color ID data map (maps color IDs to color list indexes)
        for( XclColorIdDataVec::iterator aIt = maColorIdDataVec.begin(), aEnd = maColorIdDataVec.end(); aIt != aEnd; ++aIt )
        {
            if( aIt->mnIndex > nRemove )
                --aIt->mnIndex;
            else if( aIt->mnIndex == nRemove )
                aIt->mnIndex = nKeep;
        }
    }
}

sal_uInt32 XclExpPaletteImpl::GetLeastUsedListColor() const
{
    sal_uInt32 nFound = 0;
    sal_uInt32 nMinW = SAL_MAX_UINT32;

    for( sal_uInt32 nIdx = 0, nCount = mxColorList->Count(); nIdx < nCount; ++nIdx )
    {
        XclListColor* pEntry = mxColorList->GetObject( nIdx );
        // ignore the base colors
        if( !pEntry->IsBaseColor() && (pEntry->GetWeighting() < nMinW) )
        {
            nFound = nIdx;
            nMinW = pEntry->GetWeighting();
        }
    }
    return nFound;
}

sal_uInt32 XclExpPaletteImpl::GetNearestListColor( const Color& rColor, sal_uInt32 nIgnore ) const
{
    sal_uInt32 nFound = 0;
    sal_Int32 nMinD = SAL_MAX_INT32;

    for( sal_uInt32 nIdx = 0, nCount = mxColorList->Count(); nIdx < nCount; ++nIdx )
    {
        if( nIdx != nIgnore )
        {
            if( XclListColor* pEntry = mxColorList->GetObject( nIdx ) )
            {
                sal_Int32 nDist = lclGetColorDistance( rColor, pEntry->GetColor() );
                if( nDist < nMinD )
                {
                    nFound = nIdx;
                    nMinD = nDist;
                }
            }
        }
    }
    return nFound;
}

sal_uInt32 XclExpPaletteImpl::GetNearestListColor( sal_uInt32 nIndex ) const
{
    XclListColor* pEntry = mxColorList->GetObject( nIndex );
    return pEntry ? GetNearestListColor( pEntry->GetColor(), nIndex ) : 0;
}

sal_Int32 XclExpPaletteImpl::GetNearestPaletteColor(
        sal_uInt32& rnIndex, const Color& rColor, bool bDefaultOnly ) const
{
    rnIndex = 0;
    sal_Int32 nDist = SAL_MAX_INT32;

    for( XclPaletteColorVec::const_iterator aIt = maPalette.begin(), aEnd = maPalette.end();
            aIt != aEnd; ++aIt )
    {
        if( !bDefaultOnly || !aIt->mbUsed )
        {
            sal_Int32 nCurrDist = lclGetColorDistance( rColor, aIt->maColor );
            if( nCurrDist < nDist )
            {
                rnIndex = aIt - maPalette.begin();
                nDist = nCurrDist;
            }
        }
    }
    return nDist;
}

sal_Int32 XclExpPaletteImpl::GetNearPaletteColors(
        sal_uInt32& rnFirst, sal_uInt32& rnSecond, const Color& rColor ) const
{
    rnFirst = rnSecond = 0;
    sal_Int32 nDist1 = SAL_MAX_INT32;
    sal_Int32 nDist2 = SAL_MAX_INT32;

    for( XclPaletteColorVec::const_iterator aIt = maPalette.begin(), aEnd = maPalette.end();
            aIt != aEnd; ++aIt )
    {
        sal_Int32 nCurrDist = lclGetColorDistance( rColor, aIt->maColor );
        if( nCurrDist < nDist1 )
        {
            rnSecond = rnFirst;
            nDist2 = nDist1;
            rnFirst = aIt - maPalette.begin();
            nDist1 = nCurrDist;
        }
        else if( nCurrDist < nDist2 )
        {
            rnSecond = aIt - maPalette.begin();
            nDist2 = nCurrDist;
        }
    }
    return nDist1;
}

// ----------------------------------------------------------------------------

XclExpPalette::XclExpPalette( const XclExpRoot& rRoot ) :
    XclDefaultPalette( rRoot ),
    XclExpRecord( EXC_ID_PALETTE )
{
    mxImpl.reset( new XclExpPaletteImpl( *this ) );
    SetRecSize( GetColorCount() * 4 + 2 );
}

XclExpPalette::~XclExpPalette()
{
}

sal_uInt32 XclExpPalette::InsertColor( const Color& rColor, XclExpColorType eType, sal_uInt16 nAutoDefault )
{
    return mxImpl->InsertColor( rColor, eType, nAutoDefault );
}

sal_uInt32 XclExpPalette::GetColorIdFromIndex( sal_uInt16 nIndex )
{
    return XclExpPaletteImpl::GetColorIdFromIndex( nIndex );
}

void XclExpPalette::Finalize()
{
    mxImpl->Finalize();
}

sal_uInt16 XclExpPalette::GetColorIndex( sal_uInt32 nColorId ) const
{
    return mxImpl->GetColorIndex( nColorId );
}

void XclExpPalette::GetMixedColors(
        sal_uInt16& rnXclForeIx, sal_uInt16& rnXclBackIx, sal_uInt8& rnXclPattern,
        sal_uInt32 nForeColorId, sal_uInt32 nBackColorId ) const
{
    return mxImpl->GetMixedColors( rnXclForeIx, rnXclBackIx, rnXclPattern, nForeColorId, nBackColorId );
}

ColorData XclExpPalette::GetColorData( sal_uInt16 nXclIndex ) const
{
    return mxImpl->GetColorData( nXclIndex );
}

void XclExpPalette::Save( XclExpStream& rStrm )
{
    if( !mxImpl->IsDefaultPalette() )
        XclExpRecord::Save( rStrm );
}

void XclExpPalette::SaveXml( XclExpXmlStream& rStrm )
{
    if( !mxImpl->IsDefaultPalette() )
        mxImpl->SaveXml( rStrm );
}

void XclExpPalette::WriteBody( XclExpStream& rStrm )
{
    mxImpl->WriteBody( rStrm );
}

// FONT record - font information =============================================

namespace {

typedef ::std::pair< sal_uInt16, sal_Int16 > WhichAndScript;

sal_Int16 lclCheckFontItems( const SfxItemSet& rItemSet,
        const WhichAndScript& rWAS1, const WhichAndScript& rWAS2, const WhichAndScript& rWAS3 )
{
    if( ScfTools::CheckItem( rItemSet, rWAS1.first, false ) ) return rWAS1.second;
    if( ScfTools::CheckItem( rItemSet, rWAS2.first, false ) ) return rWAS2.second;
    if( ScfTools::CheckItem( rItemSet, rWAS3.first, false ) ) return rWAS3.second;
    return 0;
};

} // namespace

/*static*/ sal_Int16 XclExpFontHelper::GetFirstUsedScript( const XclExpRoot& rRoot, const SfxItemSet& rItemSet )
{
    namespace ApiScriptType = ::com::sun::star::i18n::ScriptType;

    /*  #i17050# #i107170# We need to determine which font items are set in the
        item set, and which script type we should prefer according to the
        current language settings. */

    static const WhichAndScript WAS_LATIN( ATTR_FONT, ::com::sun::star::i18n::ScriptType::LATIN );
    static const WhichAndScript WAS_ASIAN( ATTR_CJK_FONT, ::com::sun::star::i18n::ScriptType::ASIAN );
    static const WhichAndScript WAS_CMPLX( ATTR_CTL_FONT, ::com::sun::star::i18n::ScriptType::COMPLEX );

    /*  #114008# do not let a font from a parent style override an explicit
        cell font. */

    sal_Int16 nDefScript = rRoot.GetDefApiScript();
    sal_Int16 nScript = 0;
    const SfxItemSet* pCurrSet = &rItemSet;

    while( (nScript == 0) && pCurrSet )
    {
        switch( nDefScript )
        {
            case ApiScriptType::LATIN:
                nScript = lclCheckFontItems( *pCurrSet, WAS_LATIN, WAS_CMPLX, WAS_ASIAN );
            break;
            case ApiScriptType::ASIAN:
                nScript = lclCheckFontItems( *pCurrSet, WAS_ASIAN, WAS_CMPLX, WAS_LATIN );
            break;
            case ApiScriptType::COMPLEX:
                nScript = lclCheckFontItems( *pCurrSet, WAS_CMPLX, WAS_ASIAN, WAS_LATIN );
            break;
            default:
                DBG_ERRORFILE( "XclExpFontHelper::GetFirstUsedScript - unknown script type" );
                nScript = ApiScriptType::LATIN;
        };
        pCurrSet = pCurrSet->GetParent();
    }

    return nScript;
}

/*static*/ Font XclExpFontHelper::GetFontFromItemSet( const XclExpRoot& rRoot, const SfxItemSet& rItemSet, sal_Int16 nScript )
{
    namespace ApiScriptType = ::com::sun::star::i18n::ScriptType;

    // if WEAK is passed, guess script type from existing items in the item set
    if( nScript == ApiScriptType::WEAK )
        nScript = GetFirstUsedScript( rRoot, rItemSet );

    // convert to core script type constants
    sal_uInt8 nScScript = SCRIPTTYPE_LATIN;
    switch( nScript )
    {
        case ApiScriptType::LATIN:      nScScript = SCRIPTTYPE_LATIN;   break;
        case ApiScriptType::ASIAN:      nScScript = SCRIPTTYPE_ASIAN;   break;
        case ApiScriptType::COMPLEX:    nScScript = SCRIPTTYPE_COMPLEX; break;
        default:    DBG_ERRORFILE( "XclExpFontHelper::GetFontFromItemSet - unknown script type" );
    }

    // fill the font object
    Font aFont;
    ScPatternAttr::GetFont( aFont, rItemSet, SC_AUTOCOL_RAW, 0, 0, 0, nScScript );
    return aFont;
}

/*static*/ bool XclExpFontHelper::CheckItems( const XclExpRoot& rRoot, const SfxItemSet& rItemSet, sal_Int16 nScript, bool bDeep )
{
    static const sal_uInt16 pnCommonIds[] = {
        ATTR_FONT_UNDERLINE, ATTR_FONT_CROSSEDOUT, ATTR_FONT_CONTOUR,
        ATTR_FONT_SHADOWED, ATTR_FONT_COLOR, ATTR_FONT_LANGUAGE, 0 };
    static const sal_uInt16 pnLatinIds[] = {
        ATTR_FONT, ATTR_FONT_HEIGHT, ATTR_FONT_WEIGHT, ATTR_FONT_POSTURE, 0 };
    static const sal_uInt16 pnAsianIds[] = {
        ATTR_CJK_FONT, ATTR_CJK_FONT_HEIGHT, ATTR_CJK_FONT_WEIGHT, ATTR_CJK_FONT_POSTURE, 0 };
    static const sal_uInt16 pnComplexIds[] = {
        ATTR_CTL_FONT, ATTR_CTL_FONT_HEIGHT, ATTR_CTL_FONT_WEIGHT, ATTR_CTL_FONT_POSTURE, 0 };

    bool bUsed = ScfTools::CheckItems( rItemSet, pnCommonIds, bDeep );
    if( !bUsed )
    {
        namespace ApiScriptType = ::com::sun::star::i18n::ScriptType;
        // if WEAK is passed, guess script type from existing items in the item set
        if( nScript == ApiScriptType::WEAK )
            nScript = GetFirstUsedScript( rRoot, rItemSet );
        // check the correct items
        switch( nScript )
        {
            case ApiScriptType::LATIN:      bUsed = ScfTools::CheckItems( rItemSet, pnLatinIds, bDeep );    break;
            case ApiScriptType::ASIAN:      bUsed = ScfTools::CheckItems( rItemSet, pnAsianIds, bDeep );    break;
            case ApiScriptType::COMPLEX:    bUsed = ScfTools::CheckItems( rItemSet, pnComplexIds, bDeep );  break;
            default:    DBG_ERRORFILE( "XclExpFontHelper::CheckItems - unknown script type" );
        }
    }
    return bUsed;
}

// ----------------------------------------------------------------------------

namespace {

sal_uInt32 lclCalcHash( const XclFontData& rFontData )
{
    sal_uInt32 nHash = rFontData.maName.Len();
    nHash += rFontData.maColor.GetColor() * 2;
    nHash += rFontData.mnWeight * 3;
    nHash += rFontData.mnCharSet * 5;
    nHash += rFontData.mnFamily * 7;
    nHash += rFontData.mnHeight * 11;
    nHash += rFontData.mnUnderline * 13;
    nHash += rFontData.mnEscapem * 17;
    if( rFontData.mbItalic ) nHash += 19;
    if( rFontData.mbStrikeout ) nHash += 23;
    if( rFontData.mbOutline ) nHash += 29;
    if( rFontData.mbShadow ) nHash += 31;
    return nHash;
}

} // namespace

// ----------------------------------------------------------------------------

XclExpFont::XclExpFont( const XclExpRoot& rRoot,
        const XclFontData& rFontData, XclExpColorType eColorType ) :
    XclExpRecord( EXC_ID2_FONT, 14 ),
    XclExpRoot( rRoot ),
    maData( rFontData )
{
    // insert font color into palette
    mnColorId = rRoot.GetPalette().InsertColor( rFontData.maColor, eColorType, EXC_COLOR_FONTAUTO );
    // hash value for faster comparison
    mnHash = lclCalcHash( maData );
    // record size
    sal_Size nStrLen = maData.maName.Len();
    SetRecSize( ((GetBiff() == EXC_BIFF8) ? (nStrLen * 2 + 1) : nStrLen) + 15 );
}

bool XclExpFont::Equals( const XclFontData& rFontData, sal_uInt32 nHash ) const
{
    return (mnHash == nHash) && (maData == rFontData);
}

void XclExpFont::SaveXml( XclExpXmlStream& rStrm )
{
    sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream();
    rStyleSheet->startElement( XML_font, FSEND );
    rStrm.WriteFontData( maData, XML_name );
    // OOXTODO: XML_scheme; //scheme/@val values: "major", "minor", "none"
    rStyleSheet->endElement( XML_font );
}

// private --------------------------------------------------------------------

void XclExpFont::WriteBody( XclExpStream& rStrm )
{
    sal_uInt16 nAttr = EXC_FONTATTR_NONE;
    ::set_flag( nAttr, EXC_FONTATTR_ITALIC, maData.mbItalic );
    ::set_flag( nAttr, EXC_FONTATTR_STRIKEOUT, maData.mbStrikeout );
    ::set_flag( nAttr, EXC_FONTATTR_OUTLINE, maData.mbOutline );
    ::set_flag( nAttr, EXC_FONTATTR_SHADOW, maData.mbShadow );

    DBG_ASSERT( maData.maName.Len() < 256, "XclExpFont::WriteBody - font name too long" );
    XclExpString aFontName;
    if( GetBiff() <= EXC_BIFF5 )
        aFontName.AssignByte( maData.maName, GetTextEncoding(), EXC_STR_8BITLENGTH );
    else
        aFontName.Assign( maData.maName, EXC_STR_FORCEUNICODE | EXC_STR_8BITLENGTH );

    rStrm   << maData.mnHeight
            << nAttr
            << GetPalette().GetColorIndex( mnColorId )
            << maData.mnWeight
            << maData.mnEscapem
            << maData.mnUnderline
            << maData.mnFamily
            << maData.mnCharSet
            << sal_uInt8( 0 )
            << aFontName;
}

// ----------------------------------------------------------------------------

XclExpBlindFont::XclExpBlindFont( const XclExpRoot& rRoot ) :
    XclExpFont( rRoot, XclFontData(), EXC_COLOR_CELLTEXT )
{
}

bool XclExpBlindFont::Equals( const XclFontData& /*rFontData*/, sal_uInt32 /*nHash*/ ) const
{
    return false;
}

void XclExpBlindFont::Save( XclExpStream& /*rStrm*/ )
{
    // do nothing
}

// ============================================================================

XclExpFontBuffer::XclExpFontBuffer( const XclExpRoot& rRoot ) :
    XclExpRoot( rRoot ),
    mnXclMaxSize( 0 )
{
    switch( GetBiff() )
    {
        case EXC_BIFF4: mnXclMaxSize = EXC_FONT_MAXCOUNT4;  break;
        case EXC_BIFF5: mnXclMaxSize = EXC_FONT_MAXCOUNT5;  break;
        case EXC_BIFF8: mnXclMaxSize = EXC_FONT_MAXCOUNT8;  break;
        default:        DBG_ERROR_BIFF();
    }
    InitDefaultFonts();
}

const XclExpFont* XclExpFontBuffer::GetFont( sal_uInt16 nXclFont ) const
{
    return maFontList.GetRecord( nXclFont ).get();
}

const XclFontData& XclExpFontBuffer::GetAppFontData() const
{
    return maFontList.GetRecord( EXC_FONT_APP )->GetFontData(); // exists always
}

sal_uInt16 XclExpFontBuffer::Insert(
        const XclFontData& rFontData, XclExpColorType eColorType, bool bAppFont )
{
    if( bAppFont )
    {
        XclExpFontRef xFont( new XclExpFont( GetRoot(), rFontData, eColorType ) );
        maFontList.ReplaceRecord( xFont, EXC_FONT_APP );
        // #108487# set width of '0' character for column width export
        SetCharWidth( xFont->GetFontData() );
        return EXC_FONT_APP;
    }

    size_t nPos = Find( rFontData );
    if( nPos == EXC_FONTLIST_NOTFOUND )
    {
        // not found in buffer - create new font
        size_t nSize = maFontList.GetSize();
        if( nSize < mnXclMaxSize )
        {
            // possible to insert
            maFontList.AppendNewRecord( new XclExpFont( GetRoot(), rFontData, eColorType ) );
            nPos = nSize;       // old size is last position now
        }
        else
        {
            // buffer is full - ignore new font, use default font
            nPos = EXC_FONT_APP;
        }
    }
    return static_cast< sal_uInt16 >( nPos );
}

sal_uInt16 XclExpFontBuffer::Insert(
        const Font& rFont, XclExpColorType eColorType, bool bAppFont )
{
    return Insert( XclFontData( rFont ), eColorType, bAppFont );
}

sal_uInt16 XclExpFontBuffer::Insert(
        const SvxFont& rFont, XclExpColorType eColorType, bool bAppFont )
{
    return Insert( XclFontData( rFont ), eColorType, bAppFont );
}

sal_uInt16 XclExpFontBuffer::Insert( const SfxItemSet& rItemSet,
        sal_Int16 nScript, XclExpColorType eColorType, bool bAppFont )
{
    // #i17050# #114008# #115495# script type now provided by caller
    Font aFont = XclExpFontHelper::GetFontFromItemSet( GetRoot(), rItemSet, nScript );
    return Insert( aFont, eColorType, bAppFont );
}

sal_uInt16 XclExpFontBuffer::Insert( const ScPatternAttr& rPattern,
        sal_Int16 nScript, XclExpColorType eColorType, bool bAppFont )
{
    return Insert( rPattern.GetItemSet(), nScript, eColorType, bAppFont );
}

void XclExpFontBuffer::Save( XclExpStream& rStrm )
{
    maFontList.Save( rStrm );
}

void XclExpFontBuffer::SaveXml( XclExpXmlStream& rStrm )
{
    if( maFontList.IsEmpty() )
        return;

    sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream();
    rStyleSheet->startElement( XML_fonts,
            XML_count,  OString::valueOf( (sal_Int32) maFontList.GetSize() ).getStr(),
            FSEND );

    maFontList.SaveXml( rStrm );

    rStyleSheet->endElement( XML_fonts );
}

// private --------------------------------------------------------------------

void XclExpFontBuffer::InitDefaultFonts()
{
    XclFontData aFontData;
    aFontData.maName.AssignAscii( "Arial" );
    aFontData.SetScFamily( FAMILY_DONTKNOW );
    aFontData.SetFontEncoding( ScfTools::GetSystemTextEncoding() );
    aFontData.SetScHeight( 200 );   // 200 twips = 10 pt
    aFontData.SetScWeight( WEIGHT_NORMAL );

    switch( GetBiff() )
    {
        case EXC_BIFF5:
        {
            maFontList.AppendNewRecord( new XclExpFont( GetRoot(), aFontData, EXC_COLOR_CELLTEXT ) );
            aFontData.SetScWeight( WEIGHT_BOLD );
            maFontList.AppendNewRecord( new XclExpFont( GetRoot(), aFontData, EXC_COLOR_CELLTEXT ) );
            aFontData.SetScWeight( WEIGHT_NORMAL );
            aFontData.SetScPosture( ITALIC_NORMAL );
            maFontList.AppendNewRecord( new XclExpFont( GetRoot(), aFontData, EXC_COLOR_CELLTEXT ) );
            aFontData.SetScWeight( WEIGHT_BOLD );
            maFontList.AppendNewRecord( new XclExpFont( GetRoot(), aFontData, EXC_COLOR_CELLTEXT ) );
            // the blind font with index 4
            maFontList.AppendNewRecord( new XclExpBlindFont( GetRoot() ) );
            // already add the first user defined font (Excel does it too)
            aFontData.SetScWeight( WEIGHT_NORMAL );
            aFontData.SetScPosture( ITALIC_NONE );
            maFontList.AppendNewRecord( new XclExpFont( GetRoot(), aFontData, EXC_COLOR_CELLTEXT ) );
        }
        break;
        case EXC_BIFF8:
        {
            XclExpFontRef xFont( new XclExpFont( GetRoot(), aFontData, EXC_COLOR_CELLTEXT ) );
            maFontList.AppendRecord( xFont );
            maFontList.AppendRecord( xFont );
            maFontList.AppendRecord( xFont );
            maFontList.AppendRecord( xFont );
            if( GetOutput() == EXC_OUTPUT_BINARY )
                // the blind font with index 4
                maFontList.AppendNewRecord( new XclExpBlindFont( GetRoot() ) );
        }
        break;
        default:
            DBG_ERROR_BIFF();
    }
}

size_t XclExpFontBuffer::Find( const XclFontData& rFontData )
{
    sal_uInt32 nHash = lclCalcHash( rFontData );
    for( size_t nPos = 0, nSize = maFontList.GetSize(); nPos < nSize; ++nPos )
        if( maFontList.GetRecord( nPos )->Equals( rFontData, nHash ) )
            return nPos;
    return EXC_FONTLIST_NOTFOUND;
}

// FORMAT record - number formats =============================================

/** Predicate for search algorithm. */
struct XclExpNumFmtPred
{
    sal_uLong               mnScNumFmt;
    inline explicit     XclExpNumFmtPred( sal_uLong nScNumFmt ) : mnScNumFmt( nScNumFmt ) {}
    inline bool         operator()( const XclExpNumFmt& rFormat ) const
                            { return rFormat.mnScNumFmt == mnScNumFmt; }
};

// ----------------------------------------------------------------------------

XclExpNumFmtBuffer::XclExpNumFmtBuffer( const XclExpRoot& rRoot ) :
    XclExpRoot( rRoot ),
    /*  Compiler needs a hint, this doesn't work: new NfKeywordTable;
        cannot convert from 'class String *' to 'class String (*)[54]'
        The effective result here is class String (*)[54*1] */
    mxFormatter( new SvNumberFormatter( rRoot.GetDoc().GetServiceManager(), LANGUAGE_ENGLISH_US ) ),
    mpKeywordTable( new NfKeywordTable[ 1 ] ),
    mnStdFmt( GetFormatter().GetStandardFormat( ScGlobal::eLnge ) )
{
    switch( GetBiff() )
    {
        case EXC_BIFF5: mnXclOffset = EXC_FORMAT_OFFSET5;   break;
        case EXC_BIFF8: mnXclOffset = EXC_FORMAT_OFFSET8;   break;
        default:        DBG_ERROR_BIFF();
    }

    mxFormatter->FillKeywordTable( *mpKeywordTable, LANGUAGE_ENGLISH_US );
    // remap codes unknown to Excel
    (*mpKeywordTable)[ NF_KEY_NN ] = String( RTL_CONSTASCII_USTRINGPARAM( "DDD" ) );
    (*mpKeywordTable)[ NF_KEY_NNN ] = String( RTL_CONSTASCII_USTRINGPARAM( "DDDD" ) );
    // NNNN gets a separator appended in SvNumberformat::GetMappedFormatString()
    (*mpKeywordTable)[ NF_KEY_NNNN ] = String( RTL_CONSTASCII_USTRINGPARAM( "DDDD" ) );
    // Export the Thai T NatNum modifier.
    (*mpKeywordTable)[ NF_KEY_THAI_T ] = String( RTL_CONSTASCII_USTRINGPARAM( "T" ) );
}

XclExpNumFmtBuffer::~XclExpNumFmtBuffer()
{
    delete[] mpKeywordTable;
}

sal_uInt16 XclExpNumFmtBuffer::Insert( sal_uLong nScNumFmt )
{
    XclExpNumFmtVec::const_iterator aIt =
        ::std::find_if( maFormatMap.begin(), maFormatMap.end(), XclExpNumFmtPred( nScNumFmt ) );
    if( aIt != maFormatMap.end() )
        return aIt->mnXclNumFmt;

    size_t nSize = maFormatMap.size();
    if( nSize < static_cast< size_t >( 0xFFFF - mnXclOffset ) )
    {
        sal_uInt16 nXclNumFmt = static_cast< sal_uInt16 >( nSize + mnXclOffset );
        maFormatMap.push_back( XclExpNumFmt( nScNumFmt, nXclNumFmt ) );
        return nXclNumFmt;
    }

    return 0;
}

void XclExpNumFmtBuffer::Save( XclExpStream& rStrm )
{
    for( XclExpNumFmtVec::const_iterator aIt = maFormatMap.begin(), aEnd = maFormatMap.end(); aIt != aEnd; ++aIt )
        WriteFormatRecord( rStrm, *aIt );
}

void XclExpNumFmtBuffer::SaveXml( XclExpXmlStream& rStrm )
{
    if( !maFormatMap.size() )
        return;

    sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream();
    rStyleSheet->startElement( XML_numFmts,
            XML_count,  OString::valueOf( (sal_Int32) maFormatMap.size() ).getStr(),
            FSEND );
    for( XclExpNumFmtVec::const_iterator aIt = maFormatMap.begin(), aEnd = maFormatMap.end(); aIt != aEnd; ++aIt )
    {
        rStyleSheet->singleElement( XML_numFmt,
                XML_numFmtId,   OString::valueOf( sal_Int32(aIt->mnXclNumFmt) ).getStr(),
                XML_formatCode, XclXmlUtils::ToOString( GetFormatCode( *aIt ) ).getStr(),
                FSEND );
    }
    rStyleSheet->endElement( XML_numFmts );
}

void XclExpNumFmtBuffer::WriteFormatRecord( XclExpStream& rStrm, sal_uInt16 nXclNumFmt, const String& rFormatStr )
{
    XclExpString aExpStr;
    if( GetBiff() <= EXC_BIFF5 )
        aExpStr.AssignByte( rFormatStr, GetTextEncoding(), EXC_STR_8BITLENGTH );
    else
        aExpStr.Assign( rFormatStr );

    rStrm.StartRecord( EXC_ID4_FORMAT, 2 + aExpStr.GetSize() );
    rStrm << nXclNumFmt << aExpStr;
    rStrm.EndRecord();
}

void XclExpNumFmtBuffer::WriteFormatRecord( XclExpStream& rStrm, const XclExpNumFmt& rFormat )
{
    WriteFormatRecord( rStrm, rFormat.mnXclNumFmt, GetFormatCode( rFormat ) );
}

String XclExpNumFmtBuffer::GetFormatCode( const XclExpNumFmt& rFormat )
{
    String aFormatStr;

    if( const SvNumberformat* pEntry = GetFormatter().GetEntry( rFormat.mnScNumFmt ) )
    {
        if( pEntry->GetType() == NUMBERFORMAT_LOGICAL )
        {
            // build Boolean number format
            Color* pColor = 0;
            String aTemp;
            const_cast< SvNumberformat* >( pEntry )->GetOutputString( 1.0, aTemp, &pColor );
            aFormatStr.Append( '"' ).Append( aTemp ).AppendAscii( "\";\"" ).Append( aTemp ).AppendAscii( "\";\"" );
            const_cast< SvNumberformat* >( pEntry )->GetOutputString( 0.0, aTemp, &pColor );
            aFormatStr.Append( aTemp ).Append( '"' );
        }
        else
        {
            LanguageType eLang = pEntry->GetLanguage();
            if( eLang != LANGUAGE_ENGLISH_US )
            {
                xub_StrLen nCheckPos;
                short nType = NUMBERFORMAT_DEFINED;
                sal_uInt32 nKey;
                String aTemp( pEntry->GetFormatstring() );
                mxFormatter->PutandConvertEntry( aTemp, nCheckPos, nType, nKey, eLang, LANGUAGE_ENGLISH_US );
                DBG_ASSERT( nCheckPos == 0, "XclExpNumFmtBuffer::WriteFormatRecord - format code not convertible" );
                pEntry = mxFormatter->GetEntry( nKey );
            }

            aFormatStr = pEntry->GetMappedFormatstring( *mpKeywordTable, *mxFormatter->GetLocaleData() );
            if( aFormatStr.EqualsAscii( "Standard" ) )
                aFormatStr.AssignAscii( "General" );
        }
    }
    else
    {
        DBG_ERRORFILE( "XclExpNumFmtBuffer::WriteFormatRecord - format not found" );
        aFormatStr.AssignAscii( "General" );
    }

    return aFormatStr;
}

// XF, STYLE record - Cell formatting =========================================

bool XclExpCellProt::FillFromItemSet( const SfxItemSet& rItemSet, bool bStyle )
{
    const ScProtectionAttr& rProtItem = GETITEM( rItemSet, ScProtectionAttr, ATTR_PROTECTION );
    mbLocked = rProtItem.GetProtection();
    mbHidden = rProtItem.GetHideFormula() || rProtItem.GetHideCell();
    return ScfTools::CheckItem( rItemSet, ATTR_PROTECTION, bStyle );
}

#if 0
void XclExpCellProt::FillToXF2( sal_uInt8& rnNumFmt ) const
{
    ::set_flag( rnNumFmt, EXC_XF2_LOCKED, mbLocked );
    ::set_flag( rnNumFmt, EXC_XF2_HIDDEN, mbHidden );
}
#endif

void XclExpCellProt::FillToXF3( sal_uInt16& rnProt ) const
{
    ::set_flag( rnProt, EXC_XF_LOCKED, mbLocked );
    ::set_flag( rnProt, EXC_XF_HIDDEN, mbHidden );
}

void XclExpCellProt::SaveXml( XclExpXmlStream& rStrm ) const
{
    rStrm.GetCurrentStream()->singleElement( XML_protection,
            XML_locked,     XclXmlUtils::ToPsz( mbLocked ),
            XML_hidden,     XclXmlUtils::ToPsz( mbHidden ),
            FSEND );
}

// ----------------------------------------------------------------------------

bool XclExpCellAlign::FillFromItemSet(
        const SfxItemSet& rItemSet, bool bForceLineBreak, XclBiff eBiff, bool bStyle )
{
    bool bUsed = false;

    switch( eBiff )
    {
        // ALL 'case's - run through!

        case EXC_BIFF8: // attributes new in BIFF8
        {
            // text indent
            long nTmpIndent = GETITEMVALUE( rItemSet, SfxUInt16Item, ATTR_INDENT, sal_Int32 );
            (nTmpIndent += 100) /= 200; // 1 Excel unit == 10 pt == 200 twips
            mnIndent = limit_cast< sal_uInt8 >( nTmpIndent, 0, 15 );
            bUsed |= ScfTools::CheckItem( rItemSet, ATTR_INDENT, bStyle );

            // shrink to fit
            mbShrink = GETITEMVALUE( rItemSet, SfxBoolItem, ATTR_SHRINKTOFIT, sal_Bool );
            bUsed |= ScfTools::CheckItem( rItemSet, ATTR_SHRINKTOFIT, bStyle );

            // CTL text direction
            SetScFrameDir( GETITEMVALUE( rItemSet, SvxFrameDirectionItem, ATTR_WRITINGDIR, SvxFrameDirection ) );
            bUsed |= ScfTools::CheckItem( rItemSet, ATTR_WRITINGDIR, bStyle );
        }

        case EXC_BIFF5: // attributes new in BIFF5
        case EXC_BIFF4: // attributes new in BIFF4
        {
            // vertical alignment
            SetScVerAlign( GETITEMVALUE( rItemSet, SvxVerJustifyItem, ATTR_VER_JUSTIFY, SvxCellVerJustify ) );
            bUsed |= ScfTools::CheckItem( rItemSet, ATTR_VER_JUSTIFY, bStyle );

            // stacked/rotation
            bool bStacked = GETITEMVALUE( rItemSet, SfxBoolItem, ATTR_STACKED, sal_Bool );
            bUsed |= ScfTools::CheckItem( rItemSet, ATTR_STACKED, bStyle );
            if( bStacked )
            {
                mnRotation = EXC_ROT_STACKED;
            }
            else
            {
                // rotation
                sal_Int32 nScRot = GETITEMVALUE( rItemSet, SfxInt32Item, ATTR_ROTATE_VALUE, sal_Int32 );
                mnRotation = XclTools::GetXclRotation( nScRot );
                bUsed |= ScfTools::CheckItem( rItemSet, ATTR_ROTATE_VALUE, bStyle );
            }
            mnOrient = XclTools::GetXclOrientFromRot( mnRotation );
        }

        case EXC_BIFF3: // attributes new in BIFF3
        {
            // text wrap
            mbLineBreak = bForceLineBreak || GETITEMBOOL( rItemSet, ATTR_LINEBREAK );
            bUsed |= bForceLineBreak || ScfTools::CheckItem( rItemSet, ATTR_LINEBREAK, bStyle );
        }

        case EXC_BIFF2: // attributes new in BIFF2
        {
            // horizontal alignment
            SetScHorAlign( GETITEMVALUE( rItemSet, SvxHorJustifyItem, ATTR_HOR_JUSTIFY, SvxCellHorJustify ) );
            bUsed |= ScfTools::CheckItem( rItemSet, ATTR_HOR_JUSTIFY, bStyle );
        }

        break;
        default:    DBG_ERROR_BIFF();
    }

    return bUsed;
}

#if 0
void XclExpCellAlign::FillToXF2( sal_uInt8& rnFlags ) const
{
    ::insert_value( rnFlags, mnHorAlign, 0, 3 );
}

void XclExpCellAlign::FillToXF3( sal_uInt16& rnAlign ) const
{
    ::insert_value( rnAlign, mnHorAlign, 0, 3 );
    ::set_flag( rnAlign, EXC_XF_LINEBREAK, mbLineBreak );
}

void XclExpCellAlign::FillToXF4( sal_uInt16& rnAlign ) const
{
    FillToXF3( rnAlign );
    ::insert_value( rnAlign, mnVerAlign, 4, 2 );
    ::insert_value( rnAlign, mnOrient, 6, 2 );
}
#endif

void XclExpCellAlign::FillToXF5( sal_uInt16& rnAlign ) const
{
    ::insert_value( rnAlign, mnHorAlign, 0, 3 );
    ::set_flag( rnAlign, EXC_XF_LINEBREAK, mbLineBreak );
    ::insert_value( rnAlign, mnVerAlign, 4, 3 );
    ::insert_value( rnAlign, mnOrient, 8, 2 );
}

void XclExpCellAlign::FillToXF8( sal_uInt16& rnAlign, sal_uInt16& rnMiscAttrib ) const
{
    ::insert_value( rnAlign, mnHorAlign, 0, 3 );
    ::set_flag( rnAlign, EXC_XF_LINEBREAK, mbLineBreak );
    ::insert_value( rnAlign, mnVerAlign, 4, 3 );
    ::insert_value( rnAlign, mnRotation, 8, 8 );
    ::insert_value( rnMiscAttrib, mnIndent, 0, 4 );
    ::set_flag( rnMiscAttrib, EXC_XF8_SHRINK, mbShrink );
    ::insert_value( rnMiscAttrib, mnTextDir, 6, 2 );
}

static const char* ToHorizontalAlignment( sal_uInt8 nHorAlign )
{
    switch( nHorAlign )
    {
        case EXC_XF_HOR_GENERAL:    return "general";
        case EXC_XF_HOR_LEFT:       return "left";
        case EXC_XF_HOR_CENTER:     return "center";
        case EXC_XF_HOR_RIGHT:      return "right";
        case EXC_XF_HOR_FILL:       return "fill";
        case EXC_XF_HOR_JUSTIFY:    return "justify";
        case EXC_XF_HOR_CENTER_AS:  return "centerContinuous";
        case EXC_XF_HOR_DISTRIB:    return "distributed";
    }
    return "*unknown*";
}

static const char* ToVerticalAlignment( sal_uInt8 nVerAlign )
{
    switch( nVerAlign )
    {
        case EXC_XF_VER_TOP:        return "top";
        case EXC_XF_VER_CENTER:     return "center";
        case EXC_XF_VER_BOTTOM:     return "bottom";
        case EXC_XF_VER_JUSTIFY:    return "justify";
        case EXC_XF_VER_DISTRIB:    return "distributed";
    }
    return "*unknown*";
}

void XclExpCellAlign::SaveXml( XclExpXmlStream& rStrm ) const
{
    rStrm.GetCurrentStream()->singleElement( XML_alignment,
            XML_horizontal,         ToHorizontalAlignment( mnHorAlign ),
            XML_vertical,           ToVerticalAlignment( mnVerAlign ),
            XML_textRotation,       OString::valueOf( (sal_Int32) mnRotation ).getStr(),
            XML_wrapText,           XclXmlUtils::ToPsz( mbLineBreak ),
            XML_indent,             OString::valueOf( (sal_Int32) mnIndent ).getStr(),
            // OOXTODO: XML_relativeIndent,     mnIndent?
            // OOXTODO: XML_justifyLastLine,
            XML_shrinkToFit,        XclXmlUtils::ToPsz( mbShrink ),
            // OOXTODO: XML_readingOrder,
            FSEND );
}

// ----------------------------------------------------------------------------

namespace {

void lclGetBorderLine(
        sal_uInt8& rnXclLine, sal_uInt32& rnColorId,
        const SvxBorderLine* pLine, XclExpPalette& rPalette, XclBiff eBiff )
{
    rnXclLine = EXC_LINE_NONE;
    if( pLine )
    {
        sal_uInt16 nOuterWidth = pLine->GetOutWidth();
        sal_uInt16 nDistance = pLine->GetDistance();
        if( nDistance > 0 )
            rnXclLine = EXC_LINE_DOUBLE;
        else if( nOuterWidth > DEF_LINE_WIDTH_2 )
            rnXclLine = EXC_LINE_THICK;
        else if( nOuterWidth > DEF_LINE_WIDTH_1 )
            rnXclLine = EXC_LINE_MEDIUM;
        else if( nOuterWidth > DEF_LINE_WIDTH_0 )
            rnXclLine = EXC_LINE_THIN;
        else if( nOuterWidth > 0 )
            rnXclLine = EXC_LINE_HAIR;
        else
            rnXclLine = EXC_LINE_NONE;
    }
    if( (eBiff == EXC_BIFF2) && (rnXclLine != EXC_LINE_NONE) )
        rnXclLine = EXC_LINE_THIN;

    rnColorId = (pLine && (rnXclLine != EXC_LINE_NONE)) ?
        rPalette.InsertColor( pLine->GetColor(), EXC_COLOR_CELLBORDER ) :
        XclExpPalette::GetColorIdFromIndex( 0 );
}

} // namespace

// ----------------------------------------------------------------------------

XclExpCellBorder::XclExpCellBorder() :
    mnLeftColorId(   XclExpPalette::GetColorIdFromIndex( mnLeftColor ) ),
    mnRightColorId(  XclExpPalette::GetColorIdFromIndex( mnRightColor ) ),
    mnTopColorId(    XclExpPalette::GetColorIdFromIndex( mnTopColor ) ),
    mnBottomColorId( XclExpPalette::GetColorIdFromIndex( mnBottomColor ) ),
    mnDiagColorId(   XclExpPalette::GetColorIdFromIndex( mnDiagColor ) )
{
}

bool XclExpCellBorder::FillFromItemSet(
        const SfxItemSet& rItemSet, XclExpPalette& rPalette, XclBiff eBiff, bool bStyle )
{
    bool bUsed = false;

    switch( eBiff )
    {
        // ALL 'case's - run through!

        case EXC_BIFF8: // attributes new in BIFF8
        {
            const SvxLineItem& rTLBRItem = GETITEM( rItemSet, SvxLineItem, ATTR_BORDER_TLBR );
            sal_uInt8 nTLBRLine;
            sal_uInt32 nTLBRColorId;
            lclGetBorderLine( nTLBRLine, nTLBRColorId, rTLBRItem.GetLine(), rPalette, eBiff );
            mbDiagTLtoBR = (nTLBRLine != EXC_LINE_NONE);

            const SvxLineItem& rBLTRItem = GETITEM( rItemSet, SvxLineItem, ATTR_BORDER_BLTR );
            sal_uInt8 nBLTRLine;
            sal_uInt32 nBLTRColorId;
            lclGetBorderLine( nBLTRLine, nBLTRColorId, rBLTRItem.GetLine(), rPalette, eBiff );
            mbDiagBLtoTR = (nBLTRLine != EXC_LINE_NONE);

            if( ::ScHasPriority( rTLBRItem.GetLine(), rBLTRItem.GetLine() ) )
            {
                mnDiagLine = nTLBRLine;
                mnDiagColorId = nTLBRColorId;
            }
            else
            {
                mnDiagLine = nBLTRLine;
                mnDiagColorId = nBLTRColorId;
            }

            bUsed |= ScfTools::CheckItem( rItemSet, ATTR_BORDER_TLBR, bStyle ) ||
                     ScfTools::CheckItem( rItemSet, ATTR_BORDER_BLTR, bStyle );
        }

        case EXC_BIFF5:
        case EXC_BIFF4:
        case EXC_BIFF3:
        case EXC_BIFF2:
        {
            const SvxBoxItem& rBoxItem = GETITEM( rItemSet, SvxBoxItem, ATTR_BORDER );
            lclGetBorderLine( mnLeftLine,   mnLeftColorId,   rBoxItem.GetLeft(),   rPalette, eBiff );
            lclGetBorderLine( mnRightLine,  mnRightColorId,  rBoxItem.GetRight(),  rPalette, eBiff );
            lclGetBorderLine( mnTopLine,    mnTopColorId,    rBoxItem.GetTop(),    rPalette, eBiff );
            lclGetBorderLine( mnBottomLine, mnBottomColorId, rBoxItem.GetBottom(), rPalette, eBiff );
            bUsed |= ScfTools::CheckItem( rItemSet, ATTR_BORDER, bStyle );
        }

        break;
        default:    DBG_ERROR_BIFF();
    }

    return bUsed;
}

void XclExpCellBorder::SetFinalColors( const XclExpPalette& rPalette )
{
    mnLeftColor   = rPalette.GetColorIndex( mnLeftColorId );
    mnRightColor  = rPalette.GetColorIndex( mnRightColorId );
    mnTopColor    = rPalette.GetColorIndex( mnTopColorId );
    mnBottomColor = rPalette.GetColorIndex( mnBottomColorId );
    mnDiagColor   = rPalette.GetColorIndex( mnDiagColorId );
}

#if 0
void XclExpCellBorder::FillToXF2( sal_uInt8& rnFlags ) const
{
    ::set_flag( rnFlags, EXC_XF2_LEFTLINE,   mnLeftLine   != EXC_LINE_NONE );
    ::set_flag( rnFlags, EXC_XF2_RIGHTLINE,  mnRightLine  != EXC_LINE_NONE );
    ::set_flag( rnFlags, EXC_XF2_TOPLINE,    mnTopLine    != EXC_LINE_NONE );
    ::set_flag( rnFlags, EXC_XF2_BOTTOMLINE, mnBottomLine != EXC_LINE_NONE );
}

void XclExpCellBorder::FillToXF3( sal_uInt32& rnBorder ) const
{
    ::insert_value( rnBorder, mnTopLine,      0, 3 );
    ::insert_value( rnBorder, mnLeftLine,     8, 3 );
    ::insert_value( rnBorder, mnBottomLine,  16, 3 );
    ::insert_value( rnBorder, mnRightLine,   24, 3 );
    ::insert_value( rnBorder, mnTopColor,     3, 5 );
    ::insert_value( rnBorder, mnLeftColor,   11, 5 );
    ::insert_value( rnBorder, mnBottomColor, 19, 5 );
    ::insert_value( rnBorder, mnRightColor,  27, 5 );
}
#endif

void XclExpCellBorder::FillToXF5( sal_uInt32& rnBorder, sal_uInt32& rnArea ) const
{
    ::insert_value( rnBorder, mnTopLine,      0, 3 );
    ::insert_value( rnBorder, mnLeftLine,     3, 3 );
    ::insert_value( rnArea,   mnBottomLine,  22, 3 );
    ::insert_value( rnBorder, mnRightLine,    6, 3 );
    ::insert_value( rnBorder, mnTopColor,     9, 7 );
    ::insert_value( rnBorder, mnLeftColor,   16, 7 );
    ::insert_value( rnArea,   mnBottomColor, 25, 7 );
    ::insert_value( rnBorder, mnRightColor,  23, 7 );
}

void XclExpCellBorder::FillToXF8( sal_uInt32& rnBorder1, sal_uInt32& rnBorder2 ) const
{
    ::insert_value( rnBorder1, mnLeftLine,     0, 4 );
    ::insert_value( rnBorder1, mnRightLine,    4, 4 );
    ::insert_value( rnBorder1, mnTopLine,      8, 4 );
    ::insert_value( rnBorder1, mnBottomLine,  12, 4 );
    ::insert_value( rnBorder1, mnLeftColor,   16, 7 );
    ::insert_value( rnBorder1, mnRightColor,  23, 7 );
    ::insert_value( rnBorder2, mnTopColor,     0, 7 );
    ::insert_value( rnBorder2, mnBottomColor,  7, 7 );
    ::insert_value( rnBorder2, mnDiagColor,   14, 7 );
    ::insert_value( rnBorder2, mnDiagLine,    21, 4 );
    ::set_flag( rnBorder1, EXC_XF_DIAGONAL_TL_TO_BR, mbDiagTLtoBR );
    ::set_flag( rnBorder1, EXC_XF_DIAGONAL_BL_TO_TR, mbDiagBLtoTR );
}

void XclExpCellBorder::FillToCF8( sal_uInt16& rnLine, sal_uInt32& rnColor ) const
{
    ::insert_value( rnLine,  mnLeftLine,     0, 4 );
    ::insert_value( rnLine,  mnRightLine,    4, 4 );
    ::insert_value( rnLine,  mnTopLine,      8, 4 );
    ::insert_value( rnLine,  mnBottomLine,  12, 4 );
    ::insert_value( rnColor, mnLeftColor,    0, 7 );
    ::insert_value( rnColor, mnRightColor,   7, 7 );
    ::insert_value( rnColor, mnTopColor,    16, 7 );
    ::insert_value( rnColor, mnBottomColor, 23, 7 );
}

static const char* ToLineStyle( sal_uInt8 nLineStyle )
{
    switch( nLineStyle )
    {
        case EXC_LINE_NONE:     return "none";
        case EXC_LINE_THIN:     return "thin";
        case EXC_LINE_MEDIUM:   return "medium";
        case EXC_LINE_THICK:    return "thick";
        case EXC_LINE_DOUBLE:   return "double";
        case EXC_LINE_HAIR:     return "hair";
    }
    return "*unknown*";
}

static void lcl_WriteBorder( XclExpXmlStream& rStrm, sal_Int32 nElement, sal_uInt8 nLineStyle, const Color& rColor )
{
    sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream();
    if( nLineStyle == EXC_LINE_NONE )
        rStyleSheet->singleElement( nElement, FSEND );
    else if( rColor == Color( 0, 0, 0, 0 ) )
        rStyleSheet->singleElement( nElement,
                XML_style,  ToLineStyle( nLineStyle ),
                FSEND );
    else
    {
        rStyleSheet->startElement( nElement,
                XML_style,  ToLineStyle( nLineStyle ),
                FSEND );
        rStyleSheet->singleElement( XML_color,
                XML_rgb,    XclXmlUtils::ToOString( rColor ).getStr(),
                FSEND );
        rStyleSheet->endElement( nElement );
    }
}

void XclExpCellBorder::SaveXml( XclExpXmlStream& rStrm ) const
{
    sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream();

    XclExpPalette& rPalette = rStrm.GetRoot().GetPalette();

    rStyleSheet->startElement( XML_border,
            XML_diagonalUp,     XclXmlUtils::ToPsz( mbDiagBLtoTR ),
            XML_diagonalDown,   XclXmlUtils::ToPsz( mbDiagTLtoBR ),
            // OOXTODO: XML_outline,
            FSEND );
    lcl_WriteBorder( rStrm, XML_left,       mnLeftLine,     rPalette.GetColor( mnLeftColor ) );
    lcl_WriteBorder( rStrm, XML_right,      mnRightLine,    rPalette.GetColor( mnRightColor ) );
    lcl_WriteBorder( rStrm, XML_top,        mnTopLine,      rPalette.GetColor( mnTopColor ) );
    lcl_WriteBorder( rStrm, XML_bottom,     mnBottomLine,   rPalette.GetColor( mnBottomColor ) );
    lcl_WriteBorder( rStrm, XML_diagonal,   mnDiagLine,     rPalette.GetColor( mnDiagColor ) );
    // OOXTODO: XML_vertical, XML_horizontal
    rStyleSheet->endElement( XML_border );
}

// ----------------------------------------------------------------------------

XclExpCellArea::XclExpCellArea() :
    mnForeColorId( XclExpPalette::GetColorIdFromIndex( mnForeColor ) ),
    mnBackColorId( XclExpPalette::GetColorIdFromIndex( mnBackColor ) )
{
}

bool XclExpCellArea::FillFromItemSet( const SfxItemSet& rItemSet, XclExpPalette& rPalette, bool bStyle )
{
    const SvxBrushItem& rBrushItem = GETITEM( rItemSet, SvxBrushItem, ATTR_BACKGROUND );
    if( rBrushItem.GetColor().GetTransparency() )
    {
        mnPattern = EXC_PATT_NONE;
        mnForeColorId = XclExpPalette::GetColorIdFromIndex( EXC_COLOR_WINDOWTEXT );
        mnBackColorId = XclExpPalette::GetColorIdFromIndex( EXC_COLOR_WINDOWBACK );
    }
    else
    {
        mnPattern = EXC_PATT_SOLID;
        mnForeColorId = rPalette.InsertColor( rBrushItem.GetColor(), EXC_COLOR_CELLAREA );
        mnBackColorId = XclExpPalette::GetColorIdFromIndex( EXC_COLOR_WINDOWTEXT );
    }
    return ScfTools::CheckItem( rItemSet, ATTR_BACKGROUND, bStyle );
}

void XclExpCellArea::SetFinalColors( const XclExpPalette& rPalette )
{
    rPalette.GetMixedColors( mnForeColor, mnBackColor, mnPattern, mnForeColorId, mnBackColorId );
}

#if 0
void XclExpCellArea::FillToXF2( sal_uInt8& rnFlags ) const
{
    ::set_flag( rnFlags, EXC_XF2_BACKGROUND, mnPattern != EXC_PATT_NONE );
}

void XclExpCellArea::FillToXF3( sal_uInt16& rnArea ) const
{
    ::insert_value( rnArea, mnPattern,    0, 6 );
    ::insert_value( rnArea, mnForeColor,  6, 5 );
    ::insert_value( rnArea, mnBackColor, 11, 5 );
}
#endif

void XclExpCellArea::FillToXF5( sal_uInt32& rnArea ) const
{
    ::insert_value( rnArea, mnPattern,   16, 6 );
    ::insert_value( rnArea, mnForeColor,  0, 7 );
    ::insert_value( rnArea, mnBackColor,  7, 7 );
}

void XclExpCellArea::FillToXF8( sal_uInt32& rnBorder2, sal_uInt16& rnArea ) const
{
    ::insert_value( rnBorder2, mnPattern,   26, 6 );
    ::insert_value( rnArea,    mnForeColor,  0, 7 );
    ::insert_value( rnArea,    mnBackColor,  7, 7 );
}

void XclExpCellArea::FillToCF8( sal_uInt16& rnPattern, sal_uInt16& rnColor ) const
{
    XclCellArea aTmp( *this );
    if( !aTmp.IsTransparent() && (aTmp.mnBackColor == EXC_COLOR_WINDOWTEXT) )
        aTmp.mnBackColor = 0;
    if( aTmp.mnPattern == EXC_PATT_SOLID )
        ::std::swap( aTmp.mnForeColor, aTmp.mnBackColor );
    ::insert_value( rnColor,   aTmp.mnForeColor,  0, 7 );
    ::insert_value( rnColor,   aTmp.mnBackColor,  7, 7 );
    ::insert_value( rnPattern, aTmp.mnPattern,   10, 6 );
}

static const char* ToPatternType( sal_uInt8 nPattern )
{
    switch( nPattern )
    {
        case EXC_PATT_NONE:         return "none";
        case EXC_PATT_SOLID:        return "solid";
        case EXC_PATT_50_PERC:      return "mediumGray";
        case EXC_PATT_75_PERC:      return "darkGray";
        case EXC_PATT_25_PERC:      return "lightGray";
        case EXC_PATT_12_5_PERC:    return "gray125";
        case EXC_PATT_6_25_PERC:    return "gray0625";
    }
    return "*unknown*";
}

void XclExpCellArea::SaveXml( XclExpXmlStream& rStrm ) const
{
    sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream();
    rStyleSheet->startElement( XML_fill,
            FSEND );

    // OOXTODO: XML_gradientFill

    XclExpPalette& rPalette = rStrm.GetRoot().GetPalette();

    if( mnPattern == EXC_PATT_NONE || ( mnForeColor == 0 && mnBackColor == 0 ) )
        rStyleSheet->singleElement( XML_patternFill,
                XML_patternType,    ToPatternType( mnPattern ),
                FSEND );
    else
    {
        rStyleSheet->startElement( XML_patternFill,
                XML_patternType,    ToPatternType( mnPattern ),
                FSEND );
        rStyleSheet->singleElement( XML_fgColor,
                XML_rgb,    XclXmlUtils::ToOString( rPalette.GetColor( mnForeColor ) ).getStr(),
                FSEND );
        rStyleSheet->singleElement( XML_bgColor,
                XML_rgb,    XclXmlUtils::ToOString( rPalette.GetColor( mnBackColor ) ).getStr(),
                FSEND );
        rStyleSheet->endElement( XML_patternFill );
    }

    rStyleSheet->endElement( XML_fill );
}

// ----------------------------------------------------------------------------

XclExpXFId::XclExpXFId() :
    mnXFId( XclExpXFBuffer::GetDefCellXFId() ),
    mnXFIndex( EXC_XF_DEFAULTCELL )
{
}

XclExpXFId::XclExpXFId( sal_uInt32 nXFId ) :
    mnXFId( nXFId ),
    mnXFIndex( EXC_XF_DEFAULTCELL )
{
}

void XclExpXFId::ConvertXFIndex( const XclExpRoot& rRoot )
{
    mnXFIndex = rRoot.GetXFBuffer().GetXFIndex( mnXFId );
}

// ----------------------------------------------------------------------------

XclExpXF::XclExpXF(
        const XclExpRoot& rRoot, const ScPatternAttr& rPattern, sal_Int16 nScript,
        sal_uLong nForceScNumFmt, sal_uInt16 nForceXclFont, bool bForceLineBreak ) 
:   XclXFBase(true),
    XclExpRecord(),
    XclExpRoot(rRoot),
    mpItemSet(0),
    maProtection(),
    maAlignment(),
    maBorder(),
    maArea(),
    mnParentXFId(),
    mnScNumFmt(),
    mnXclFont(),
    mnXclNumFmt(),
    mnBorderId(),
    mnFillId(),
    mnIndexInXFList(0)
{
    mnParentXFId = GetXFBuffer().InsertStyle( rPattern.GetStyleSheet() );
    Init( rPattern.GetItemSet(), nScript, nForceScNumFmt, nForceXclFont, bForceLineBreak, false );
}

XclExpXF::XclExpXF( const XclExpRoot& rRoot, const SfxStyleSheetBase& rStyleSheet ) 
:   XclXFBase(false),
    XclExpRecord(),
    XclExpRoot(rRoot),
    mpItemSet(0),
    maProtection(),
    maAlignment(),
    maBorder(),
    maArea(),
    mnParentXFId(XclExpXFBuffer::GetXFIdFromIndex(EXC_XF_STYLEPARENT)),
    mnScNumFmt(),
    mnXclFont(),
    mnXclNumFmt(),
    mnBorderId(),
    mnFillId(),
    mnIndexInXFList(0)
{
    bool bDefStyle = (rStyleSheet.GetName() == ScGlobal::GetRscString( STR_STYLENAME_STANDARD ));
    sal_Int16 nScript = bDefStyle ? GetDefApiScript() : ::com::sun::star::i18n::ScriptType::WEAK;
    Init( const_cast< SfxStyleSheetBase& >( rStyleSheet ).GetItemSet(), nScript,
        NUMBERFORMAT_ENTRY_NOT_FOUND, EXC_FONT_NOTFOUND, false, bDefStyle );
}

XclExpXF::XclExpXF( const XclExpRoot& rRoot, bool bCellXF ) 
:   XclXFBase(bCellXF),
    XclExpRecord(),
    XclExpRoot(rRoot),
    mpItemSet(0),
    maProtection(),
    maAlignment(),
    maBorder(),
    maArea(),
    mnParentXFId(XclExpXFBuffer::GetXFIdFromIndex(EXC_XF_STYLEPARENT)),
    mnScNumFmt(),
    mnXclFont(),
    mnXclNumFmt(),
    mnBorderId(),
    mnFillId(),
    mnIndexInXFList(0)
{
    InitDefault();
}

bool XclExpXF::Equals( const ScPatternAttr& rPattern,
        sal_uLong nForceScNumFmt, sal_uInt16 nForceXclFont, bool bForceLineBreak ) const
{
    return IsCellXF() && (mpItemSet == &rPattern.GetItemSet()) &&
        (!bForceLineBreak || maAlignment.mbLineBreak) &&
        ((nForceScNumFmt == NUMBERFORMAT_ENTRY_NOT_FOUND) || (mnScNumFmt == nForceScNumFmt)) &&
        ((nForceXclFont == EXC_FONT_NOTFOUND) || (mnXclFont == nForceXclFont));
}

bool XclExpXF::Equals( const SfxStyleSheetBase& rStyleSheet ) const
{
    return IsStyleXF() && (mpItemSet == &const_cast< SfxStyleSheetBase& >( rStyleSheet ).GetItemSet());
}

void XclExpXF::SetFinalColors()
{
    maBorder.SetFinalColors( GetPalette() );
    maArea.SetFinalColors( GetPalette() );
}

bool XclExpXF::Equals( const XclExpXF& rCmpXF ) const
{
    return XclXFBase::Equals( rCmpXF ) &&
        (maProtection == rCmpXF.maProtection) && (maAlignment  == rCmpXF.maAlignment) &&
        (maBorder     == rCmpXF.maBorder)     && (maArea       == rCmpXF.maArea)      &&
        (mnXclFont    == rCmpXF.mnXclFont)    && (mnXclNumFmt  == rCmpXF.mnXclNumFmt) &&
        (mnParentXFId == rCmpXF.mnParentXFId);
}

void XclExpXF::InitDefault()
{
    SetRecHeader( EXC_ID5_XF, (GetBiff() == EXC_BIFF8) ? 20 : 16 );
    mpItemSet = 0;
    mnScNumFmt = NUMBERFORMAT_ENTRY_NOT_FOUND;
    mnXclFont = mnXclNumFmt = 0;
}

void XclExpXF::Init( const SfxItemSet& rItemSet, sal_Int16 nScript,
        sal_uLong nForceScNumFmt, sal_uInt16 nForceXclFont, bool bForceLineBreak, bool bDefStyle )
{
    InitDefault();
    mpItemSet = &rItemSet;

    // cell protection
    mbProtUsed = maProtection.FillFromItemSet( rItemSet, IsStyleXF() );

    // font
    if( nForceXclFont == EXC_FONT_NOTFOUND )
    {
        mnXclFont = GetFontBuffer().Insert( rItemSet, nScript, EXC_COLOR_CELLTEXT, bDefStyle );
        mbFontUsed = XclExpFontHelper::CheckItems( GetRoot(), rItemSet, nScript, IsStyleXF() );
    }
    else
    {
        mnXclFont = nForceXclFont;
        mbFontUsed = true;
    }

    // number format
    mnScNumFmt = (nForceScNumFmt == NUMBERFORMAT_ENTRY_NOT_FOUND) ?
        GETITEMVALUE( rItemSet, SfxUInt32Item, ATTR_VALUE_FORMAT, sal_uLong ) : nForceScNumFmt;
    mnXclNumFmt = GetNumFmtBuffer().Insert( mnScNumFmt );
    mbFmtUsed = ScfTools::CheckItem( rItemSet, ATTR_VALUE_FORMAT, IsStyleXF() );

    // alignment
    mbAlignUsed = maAlignment.FillFromItemSet( rItemSet, bForceLineBreak, GetBiff(), IsStyleXF() );

    // cell border
    mbBorderUsed = maBorder.FillFromItemSet( rItemSet, GetPalette(), GetBiff(), IsStyleXF() );

    // background area
    mbAreaUsed = maArea.FillFromItemSet( rItemSet, GetPalette(), IsStyleXF() );

    // set all b***Used flags to true in "Default"/"Normal" style
    if( bDefStyle )
        SetAllUsedFlags( true );
}

sal_uInt8 XclExpXF::GetUsedFlags() const
{
    sal_uInt8 nUsedFlags = 0;
    /*  In cell XFs a set bit means a used attribute, in style XFs a cleared bit.
        "mbCellXF == mb***Used" evaluates to correct value in cell and style XFs. */
    ::set_flag( nUsedFlags, EXC_XF_DIFF_PROT,   mbCellXF == mbProtUsed );
    ::set_flag( nUsedFlags, EXC_XF_DIFF_FONT,   mbCellXF == mbFontUsed );
    ::set_flag( nUsedFlags, EXC_XF_DIFF_VALFMT, mbCellXF == mbFmtUsed );
    ::set_flag( nUsedFlags, EXC_XF_DIFF_ALIGN,  mbCellXF == mbAlignUsed );
    ::set_flag( nUsedFlags, EXC_XF_DIFF_BORDER, mbCellXF == mbBorderUsed );
    ::set_flag( nUsedFlags, EXC_XF_DIFF_AREA,   mbCellXF == mbAreaUsed );
    return nUsedFlags;
}

void XclExpXF::WriteBody5( XclExpStream& rStrm )
{
    sal_uInt16 nTypeProt = 0, nAlign = 0;
    sal_uInt32 nArea = 0, nBorder = 0;

    ::set_flag( nTypeProt, EXC_XF_STYLE, IsStyleXF() );
    ::insert_value( nTypeProt, mnParent, 4, 12 );
    ::insert_value( nAlign, GetUsedFlags(), 10, 6 );

    maProtection.FillToXF3( nTypeProt );
    maAlignment.FillToXF5( nAlign );
    maBorder.FillToXF5( nBorder, nArea );
    maArea.FillToXF5( nArea );

    rStrm << mnXclFont << mnXclNumFmt << nTypeProt << nAlign << nArea << nBorder;
}

void XclExpXF::WriteBody8( XclExpStream& rStrm )
{
    sal_uInt16 nTypeProt = 0, nAlign = 0, nMiscAttrib = 0, nArea = 0;
    sal_uInt32 nBorder1 = 0, nBorder2 = 0;

    ::set_flag( nTypeProt, EXC_XF_STYLE, IsStyleXF() );
    ::insert_value( nTypeProt, mnParent, 4, 12 );
    ::insert_value( nMiscAttrib, GetUsedFlags(), 10, 6 );

    maProtection.FillToXF3( nTypeProt );
    maAlignment.FillToXF8( nAlign, nMiscAttrib );
    maBorder.FillToXF8( nBorder1, nBorder2 );
    maArea.FillToXF8( nBorder2, nArea );

    rStrm << mnXclFont << mnXclNumFmt << nTypeProt << nAlign << nMiscAttrib << nBorder1 << nBorder2 << nArea;
}

void XclExpXF::WriteBody( XclExpStream& rStrm )
{
    XclExpXFId aParentId( mnParentXFId );
    aParentId.ConvertXFIndex( GetRoot() );
    mnParent = aParentId.mnXFIndex;
    switch( GetBiff() )
    {
        case EXC_BIFF5: WriteBody5( rStrm );    break;
        case EXC_BIFF8: WriteBody8( rStrm );    break;
        default:        DBG_ERROR_BIFF();
    }
}

void XclExpXF::SetXmlIds( sal_uInt32 nBorderId, sal_uInt32 nFillId )
{
    mnBorderId = nBorderId;
    mnFillId   = nFillId;
}

void XclExpXF::SaveXml( XclExpXmlStream& rStrm )
{
    sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream();

    sal_Int32 nXfId = 0;
    if( IsCellXF() )
    {
        sal_uInt16 nXFIndex = rStrm.GetRoot().GetXFBuffer().GetXFIndex( mnParentXFId );
        nXfId = rStrm.GetRoot().GetXFBuffer().GetXmlStyleIndex( nXFIndex );
    }

    rStyleSheet->startElement( XML_xf,
            XML_numFmtId,           OString::valueOf( (sal_Int32) mnXclNumFmt ).getStr(),
            XML_fontId,             OString::valueOf( (sal_Int32) mnXclFont ).getStr(),
            XML_fillId,             OString::valueOf( (sal_Int32) mnFillId ).getStr(),
            XML_borderId,           OString::valueOf( (sal_Int32) mnBorderId ).getStr(),
            XML_xfId,               IsStyleXF() ? NULL : OString::valueOf( nXfId ).getStr(),
            // OOXTODO: XML_quotePrefix,
            // OOXTODO: XML_pivotButton,
            // OOXTODO: XML_applyNumberFormat,  ;
            XML_applyFont,          XclXmlUtils::ToPsz( mbFontUsed ),
            // OOXTODO: XML_applyFill,
            XML_applyBorder,        XclXmlUtils::ToPsz( mbBorderUsed ),
            XML_applyAlignment,     XclXmlUtils::ToPsz( mbAlignUsed ),
            XML_applyProtection,    XclXmlUtils::ToPsz( mbProtUsed ),
            FSEND );
    if( mbAlignUsed )
        maAlignment.SaveXml( rStrm );
    if( mbProtUsed )
        maProtection.SaveXml( rStrm );
    // OOXTODO: XML_extLst
    rStyleSheet->endElement( XML_xf );
}

// ----------------------------------------------------------------------------

XclExpDefaultXF::XclExpDefaultXF( const XclExpRoot& rRoot, bool bCellXF ) :
    XclExpXF( rRoot, bCellXF )
{
}

//UNUSED2008-05  void XclExpDefaultXF::SetParent( sal_uInt32 nParentXFId )
//UNUSED2008-05  {
//UNUSED2008-05      DBG_ASSERT( IsCellXF(), "XclExpDefaultXF::SetParent - not allowed in style XFs" );
//UNUSED2008-05      if( IsCellXF() )
//UNUSED2008-05          mnParentXFId = nParentXFId;
//UNUSED2008-05  }
//UNUSED2008-05
//UNUSED2008-05  void XclExpDefaultXF::SetUsedFlags(
//UNUSED2008-05          bool bProtUsed, bool bFontUsed, bool bFmtUsed,
//UNUSED2008-05          bool bAlignUsed, bool bBorderUsed, bool bAreaUsed )
//UNUSED2008-05  {
//UNUSED2008-05      mbProtUsed    = bProtUsed;
//UNUSED2008-05      mbFontUsed    = bFontUsed;
//UNUSED2008-05      mbFmtUsed     = bFmtUsed;
//UNUSED2008-05      mbAlignUsed   = bAlignUsed;
//UNUSED2008-05      mbBorderUsed  = bBorderUsed;
//UNUSED2008-05      mbAreaUsed    = bAreaUsed;
//UNUSED2008-05  }
//UNUSED2008-05
//UNUSED2008-05  void XclExpDefaultXF::SetProtection( const XclExpCellProt& rProtection )
//UNUSED2008-05  {
//UNUSED2008-05      maProtection = rProtection;
//UNUSED2008-05      mbProtUsed = true;
//UNUSED2008-05  }
//UNUSED2008-05
//UNUSED2008-05  void XclExpDefaultXF::SetAlignment( const XclExpCellAlign& rAlignment )
//UNUSED2008-05  {
//UNUSED2008-05      maAlignment = rAlignment;
//UNUSED2008-05      mbAlignUsed = true;
//UNUSED2008-05  }
//UNUSED2008-05
//UNUSED2008-05  void XclExpDefaultXF::SetBorder( const XclExpCellBorder& rBorder )
//UNUSED2008-05  {
//UNUSED2008-05      maBorder = rBorder;
//UNUSED2008-05      mbBorderUsed = true;
//UNUSED2008-05  }
//UNUSED2008-05
//UNUSED2008-05  void XclExpDefaultXF::SetArea( const XclExpCellArea& rArea )
//UNUSED2008-05  {
//UNUSED2008-05      maArea = rArea;
//UNUSED2008-05      mbAreaUsed = true;
//UNUSED2008-05  }

void XclExpDefaultXF::SetFont( sal_uInt16 nXclFont )
{
    mnXclFont = nXclFont;
    mbFontUsed = true;
}

void XclExpDefaultXF::SetNumFmt( sal_uInt16 nXclNumFmt )
{
    mnXclNumFmt = nXclNumFmt;
    mbFmtUsed = true;
}

// ----------------------------------------------------------------------------

XclExpStyle::XclExpStyle( sal_uInt32 nXFId, const String& rStyleName ) :
    XclExpRecord( EXC_ID_STYLE, 4 ),
    maName( rStyleName ),
    maXFId( nXFId ),
    mnStyleId( EXC_STYLE_USERDEF ),
    mnLevel( EXC_STYLE_NOLEVEL )
{
    DBG_ASSERT( maName.Len(), "XclExpStyle::XclExpStyle - empty style name" );
#ifdef DBG_UTIL
    sal_uInt8 nStyleId, nLevel; // do not use members for debug tests
    DBG_ASSERT( !XclTools::GetBuiltInStyleId( nStyleId, nLevel, maName ),
        "XclExpStyle::XclExpStyle - this is a built-in style" );
#endif
}

XclExpStyle::XclExpStyle( sal_uInt32 nXFId, sal_uInt8 nStyleId, sal_uInt8 nLevel ) :
    XclExpRecord( EXC_ID_STYLE, 4 ),
    maXFId( nXFId ),
    mnStyleId( nStyleId ),
    mnLevel( nLevel )
{
}

void XclExpStyle::WriteBody( XclExpStream& rStrm )
{
    maXFId.ConvertXFIndex( rStrm.GetRoot() );
    ::set_flag( maXFId.mnXFIndex, EXC_STYLE_BUILTIN, IsBuiltIn() );
    rStrm << maXFId.mnXFIndex;

    if( IsBuiltIn() )
    {
        rStrm << mnStyleId << mnLevel;
    }
    else
    {
        XclExpString aNameEx;
        if( rStrm.GetRoot().GetBiff() == EXC_BIFF8 )
            aNameEx.Assign( maName );
        else
            aNameEx.AssignByte( maName, rStrm.GetRoot().GetTextEncoding(), EXC_STR_8BITLENGTH );
        rStrm << aNameEx;
    }
}

static const char* lcl_StyleNameFromId( sal_Int32 nStyleId )
{
    switch( nStyleId )
    {
        case 0:     return "Normal";
        case 3:     return "Comma";
        case 4:     return "Currency";
        case 5:     return "Percent";
        case 6:     return "Comma [0]";
        case 7:     return "Currency [0]";
    }
    return "*unknown*";
}

void XclExpStyle::SaveXml( XclExpXmlStream& rStrm )
{
    OString sName;
    if( IsBuiltIn() )
    {
        sName = OString( lcl_StyleNameFromId( mnStyleId ) );
    }
    else
        sName = XclXmlUtils::ToOString( maName );
    sal_Int32 nXFId = rStrm.GetRoot().GetXFBuffer().GetXmlStyleIndex( maXFId.mnXFId );
    rStrm.GetCurrentStream()->singleElement( XML_cellStyle,
            XML_name,           sName.getStr(),
            XML_xfId,           OString::valueOf( nXFId ).getStr(),
            XML_builtinId,      OString::valueOf( (sal_Int32) mnStyleId ).getStr(),
            // OOXTODO: XML_iLevel,
            // OOXTODO: XML_hidden,
            XML_customBuiltin,  XclXmlUtils::ToPsz( ! IsBuiltIn() ),
            FSEND );
    // OOXTODO: XML_extLst
}

// ----------------------------------------------------------------------------

namespace {

const sal_uInt32 EXC_XFLIST_INDEXBASE   = 0xFFFE0000;
/** Maximum count of XF records to store in the XF list (performance). */
const sal_uInt32 EXC_XFLIST_HARDLIMIT   = 256 * 1024;

bool lclIsBuiltInStyle( const String& rStyleName )
{
    return
        XclTools::IsBuiltInStyleName( rStyleName ) ||
        XclTools::IsCondFormatStyleName( rStyleName );
}

} // namespace

// ----------------------------------------------------------------------------

XclExpXFBuffer::XclExpBuiltInInfo::XclExpBuiltInInfo() :
    mnStyleId( EXC_STYLE_USERDEF ),
    mnLevel( EXC_STYLE_NOLEVEL ),
    mbPredefined( true ),
    mbHasStyleRec( false )
{
}

// ----------------------------------------------------------------------------

/** Predicate for search algorithm. */
struct XclExpBorderPred
{
    const XclExpCellBorder&
                        mrBorder;
    inline explicit     XclExpBorderPred( const XclExpCellBorder& rBorder ) : mrBorder( rBorder ) {}
    bool                operator()( const XclExpCellBorder& rBorder ) const;
};

bool XclExpBorderPred::operator()( const XclExpCellBorder& rBorder ) const
{
    return
        mrBorder.mnLeftColor     == rBorder.mnLeftColor &&
        mrBorder.mnRightColor    == rBorder.mnRightColor &&
        mrBorder.mnTopColor      == rBorder.mnTopColor &&
        mrBorder.mnBottomColor   == rBorder.mnBottomColor &&
        mrBorder.mnDiagColor     == rBorder.mnDiagColor &&
        mrBorder.mnLeftLine      == rBorder.mnLeftLine &&
        mrBorder.mnRightLine     == rBorder.mnRightLine &&
        mrBorder.mnTopLine       == rBorder.mnTopLine &&
        mrBorder.mnBottomLine    == rBorder.mnBottomLine &&
        mrBorder.mnDiagLine      == rBorder.mnDiagLine &&
        mrBorder.mbDiagTLtoBR    == rBorder.mbDiagTLtoBR &&
        mrBorder.mbDiagBLtoTR    == rBorder.mbDiagBLtoTR &&
        mrBorder.mnLeftColorId   == rBorder.mnLeftColorId &&
        mrBorder.mnRightColorId  == rBorder.mnRightColorId &&
        mrBorder.mnTopColorId    == rBorder.mnTopColorId &&
        mrBorder.mnBottomColorId == rBorder.mnBottomColorId &&
        mrBorder.mnDiagColorId   == rBorder.mnDiagColorId;
}

struct XclExpFillPred
{
    const XclExpCellArea&
                        mrFill;
    inline explicit     XclExpFillPred( const XclExpCellArea& rFill ) : mrFill( rFill ) {}
    bool                operator()( const XclExpCellArea& rFill ) const;
};

bool XclExpFillPred::operator()( const XclExpCellArea& rFill ) const
{
    return
        mrFill.mnForeColor      == rFill.mnForeColor &&
        mrFill.mnBackColor      == rFill.mnBackColor &&
        mrFill.mnPattern        == rFill.mnPattern &&
        mrFill.mnForeColorId    == rFill.mnForeColorId &&
        mrFill.mnBackColorId    == rFill.mnBackColorId;
}

static bool XclExpXFBuffer_mbUseMultimapBuffer = true;

XclExpXFBuffer::XclExpXFBuffer( const XclExpRoot& rRoot ) 
:   XclExpRecordBase(),
    XclExpRoot(rRoot),
    maXFList(),
    maStyleList(),
    maBuiltInMap(),
    maXFIndexVec(),
    maStyleIndexes(),
    maCellIndexes(),
    maSortedXFList(),
    maBorders(),
    maFills(),
    maXclExpXFMap()
{
}

void XclExpXFBuffer::Initialize()
{
    InsertDefaultRecords();
    InsertUserStyles();
}

sal_uInt32 XclExpXFBuffer::Insert( const ScPatternAttr* pPattern, sal_Int16 nScript )
{
    return InsertCellXF( pPattern, nScript, NUMBERFORMAT_ENTRY_NOT_FOUND, EXC_FONT_NOTFOUND, false );
}

sal_uInt32 XclExpXFBuffer::InsertWithFont( const ScPatternAttr* pPattern, sal_Int16 nScript,
        sal_uInt16 nForceXclFont, bool bForceLineBreak )
{
    return InsertCellXF( pPattern, nScript, NUMBERFORMAT_ENTRY_NOT_FOUND, nForceXclFont, bForceLineBreak );
}

sal_uInt32 XclExpXFBuffer::InsertWithNumFmt( const ScPatternAttr* pPattern, sal_Int16 nScript, sal_uLong nForceScNumFmt, bool bForceLineBreak )
{
    return InsertCellXF( pPattern, nScript, nForceScNumFmt, EXC_FONT_NOTFOUND, bForceLineBreak );
}

sal_uInt32 XclExpXFBuffer::InsertStyle( const SfxStyleSheetBase* pStyleSheet )
{
    return pStyleSheet ? InsertStyleXF( *pStyleSheet ) : GetXFIdFromIndex( EXC_XF_DEFAULTSTYLE );
}

sal_uInt32 XclExpXFBuffer::GetXFIdFromIndex( sal_uInt16 nXFIndex )
{
    return EXC_XFLIST_INDEXBASE | nXFIndex;
}

sal_uInt32 XclExpXFBuffer::GetDefCellXFId()
{
    return GetXFIdFromIndex( EXC_XF_DEFAULTCELL );
}

const XclExpXF* XclExpXFBuffer::GetXFById( sal_uInt32 nXFId ) const
{
    return maXFList.GetRecord( nXFId ).get();
}

void XclExpXFBuffer::Finalize()
{
    for( size_t nPos = 0, nSize = maXFList.GetSize(); nPos < nSize; ++nPos )
        maXFList.GetRecord( nPos )->SetFinalColors();

    sal_uInt32 nTotalCount = static_cast< sal_uInt32 >( maXFList.GetSize() );
    sal_uInt32 nId;
    maXFIndexVec.resize( nTotalCount, EXC_XF_DEFAULTCELL );
    maStyleIndexes.resize( nTotalCount, EXC_XF_DEFAULTCELL );
    maCellIndexes.resize( nTotalCount, EXC_XF_DEFAULTCELL );

    XclExpBuiltInMap::const_iterator aBuiltInEnd = maBuiltInMap.end();
    /*  nMaxBuiltInXFId used to decide faster whether an XF record is
        user-defined. If the current XF ID is greater than this value,
        maBuiltInMap doesn't need to be searched. */
    sal_uInt32 nMaxBuiltInXFId = maBuiltInMap.empty() ? 0 : maBuiltInMap.rbegin()->first;

    // *** map all built-in XF records (cell and style) *** -------------------

    // do not change XF order -> std::map<> iterates elements in ascending order
    for( XclExpBuiltInMap::const_iterator aIt = maBuiltInMap.begin(); aIt != aBuiltInEnd; ++aIt )
        AppendXFIndex( aIt->first );

    // *** insert all user-defined style XF records, without reduce *** -------

    sal_uInt32 nStyleXFCount = 0;       // counts up to EXC_XF_MAXSTYLECOUNT limit

    for( nId = 0; nId < nTotalCount; ++nId )
    {
        XclExpXFRef xXF = maXFList.GetRecord( nId );
        if( xXF->IsStyleXF() && ((nId > nMaxBuiltInXFId) || (maBuiltInMap.find( nId ) == aBuiltInEnd)) )
        {
            if( nStyleXFCount < EXC_XF_MAXSTYLECOUNT )
            {
                // maximum count of styles not reached
                AppendXFIndex( nId );
                ++nStyleXFCount;
            }
            else
            {
                /*  Maximum count of styles reached - do not append more
                    pointers to XFs; use default style XF instead; do not break
                    the loop to initialize all maXFIndexVec elements. */
                maXFIndexVec[ nId ] = EXC_XF_DEFAULTSTYLE;
            }
        }
    }

    // *** insert all cell XF records *** -------------------------------------

    // start position to search for equal inserted XF records
    size_t nSearchStart = maSortedXFList.GetSize();

    // break the loop if XF limit reached - maXFIndexVec is already initialized with default index
    XclExpXFRef xDefCellXF = maXFList.GetRecord( EXC_XF_DEFAULTCELL );
    for( nId = 0; (nId < nTotalCount) && (maSortedXFList.GetSize() < EXC_XF_MAXCOUNT); ++nId )
    {
        XclExpXFRef xXF = maXFList.GetRecord( nId );
        if( xXF->IsCellXF() && ((nId > nMaxBuiltInXFId) || (maBuiltInMap.find( nId ) == aBuiltInEnd)) )
        {
            // try to find an XF record equal to *xXF, which is already inserted
            sal_uInt16 nFoundIndex = EXC_XF_NOTFOUND;

            // first try if it is equal to the default cell XF
            if( xDefCellXF->Equals( *xXF ) )
            {
                nFoundIndex = EXC_XF_DEFAULTCELL;
            }
            else for( size_t nSearchPos = nSearchStart, nSearchEnd = maSortedXFList.GetSize();
                        (nSearchPos < nSearchEnd) && (nFoundIndex == EXC_XF_NOTFOUND); ++nSearchPos )
            {
                if( maSortedXFList.GetRecord( nSearchPos )->Equals( *xXF ) )
                    nFoundIndex = static_cast< sal_uInt16 >( nSearchPos );
            }

            if( nFoundIndex != EXC_XF_NOTFOUND )
                // equal XF already in the list, use its resulting XF index
                maXFIndexVec[ nId ] = nFoundIndex;
            else
                AppendXFIndex( nId );
        }
    }

    sal_uInt16 nXmlStyleIndex   = 0;
    sal_uInt16 nXmlCellIndex    = 0;

    size_t nXFCount = maSortedXFList.GetSize();
    for( size_t i = 0; i < nXFCount; ++i )
    {
        XclExpXFList::RecordRefType xXF = maSortedXFList.GetRecord( i );
        if( xXF->IsStyleXF() )
            maStyleIndexes[ i ] = nXmlStyleIndex++;
        else
            maCellIndexes[ i ] = nXmlCellIndex++;
    }
}

sal_uInt16 XclExpXFBuffer::GetXFIndex( sal_uInt32 nXFId ) const
{
    sal_uInt16 nXFIndex = EXC_XF_DEFAULTSTYLE;
    if( nXFId >= EXC_XFLIST_INDEXBASE )
        nXFIndex = static_cast< sal_uInt16 >( nXFId & ~EXC_XFLIST_INDEXBASE );
    else if( nXFId < maXFIndexVec.size() )
        nXFIndex = maXFIndexVec[ nXFId ];
    return nXFIndex;
}

sal_Int32 XclExpXFBuffer::GetXmlStyleIndex( sal_uInt32 nXFIndex ) const
{
    DBG_ASSERT( nXFIndex < maStyleIndexes.size(), "XclExpXFBuffer::GetXmlStyleIndex - invalid index!" );
    if( nXFIndex > maStyleIndexes.size() )
        return 0;   // should be caught/debugged via above assert; return "valid" index.
    return maStyleIndexes[ nXFIndex ];
}

sal_Int32 XclExpXFBuffer::GetXmlCellIndex( sal_uInt32 nXFIndex ) const
{
    DBG_ASSERT( nXFIndex < maCellIndexes.size(), "XclExpXFBuffer::GetXmlStyleIndex - invalid index!" );
    if( nXFIndex > maCellIndexes.size() )
        return 0;   // should be caught/debugged via above assert; return "valid" index.
    return maCellIndexes[ nXFIndex ];
}

void XclExpXFBuffer::Save( XclExpStream& rStrm )
{
    // save all XF records contained in the maSortedXFList vector (sorted by XF index)
    maSortedXFList.Save( rStrm );
    // save all STYLE records
    maStyleList.Save( rStrm );
}

static void lcl_GetCellCounts( const XclExpRecordList< XclExpXF >& rXFList, sal_Int32& rCells, sal_Int32& rStyles )
{
    rCells  = 0;
    rStyles = 0;
    size_t nXFCount = rXFList.GetSize();
    for( size_t i = 0; i < nXFCount; ++i )
    {
        XclExpRecordList< XclExpXF >::RecordRefType xXF = rXFList.GetRecord( i );
        if( xXF->IsCellXF() )
            ++rCells;
        else if( xXF->IsStyleXF() )
            ++rStyles;
    }
}

void XclExpXFBuffer::SaveXml( XclExpXmlStream& rStrm )
{
    sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream();

    rStyleSheet->startElement( XML_fills,
            XML_count,  OString::valueOf( (sal_Int32) maFills.size() ).getStr(),
            FSEND );
    for( XclExpFillList::iterator aIt = maFills.begin(), aEnd = maFills.end();
            aIt != aEnd; ++aIt )
    {
        aIt->SaveXml( rStrm );
    }
    rStyleSheet->endElement( XML_fills );

    rStyleSheet->startElement( XML_borders,
            XML_count,  OString::valueOf( (sal_Int32) maBorders.size() ).getStr(),
            FSEND );
    for( XclExpBorderList::iterator aIt = maBorders.begin(), aEnd = maBorders.end();
            aIt != aEnd; ++aIt )
    {
        aIt->SaveXml( rStrm );
    }
    rStyleSheet->endElement( XML_borders );

    // save all XF records contained in the maSortedXFList vector (sorted by XF index)
    sal_Int32 nCells, nStyles;
    lcl_GetCellCounts( maSortedXFList, nCells, nStyles );

    if( nStyles > 0 )
    {
        rStyleSheet->startElement( XML_cellStyleXfs,
                XML_count,  OString::valueOf( nStyles ).getStr(),
                FSEND );
        size_t nXFCount = maSortedXFList.GetSize();
        for( size_t i = 0; i < nXFCount; ++i )
        {
            XclExpXFList::RecordRefType xXF = maSortedXFList.GetRecord( i );
            if( ! xXF->IsStyleXF() )
                continue;
            SaveXFXml( rStrm, *xXF );
        }
        rStyleSheet->endElement( XML_cellStyleXfs );
    }

    if( nCells > 0 )
    {
        rStyleSheet->startElement( XML_cellXfs,
                XML_count,  OString::valueOf( nCells ).getStr(),
                FSEND );
        size_t nXFCount = maSortedXFList.GetSize();
        for( size_t i = 0; i < nXFCount; ++i )
        {
            XclExpXFList::RecordRefType xXF = maSortedXFList.GetRecord( i );
            if( ! xXF->IsCellXF() )
                continue;
            SaveXFXml( rStrm, *xXF );
        }
        rStyleSheet->endElement( XML_cellXfs );
    }

    // save all STYLE records
    rStyleSheet->startElement( XML_cellStyles,
            XML_count,  OString::valueOf( (sal_Int32) maStyleList.GetSize() ).getStr(),
            FSEND );
    maStyleList.SaveXml( rStrm );
    rStyleSheet->endElement( XML_cellStyles );
}

void XclExpXFBuffer::SaveXFXml( XclExpXmlStream& rStrm, XclExpXF& rXF )
{
    XclExpBorderList::iterator aBorderPos =
        std::find_if( maBorders.begin(), maBorders.end(), XclExpBorderPred( rXF.GetBorderData() ) );
    DBG_ASSERT( aBorderPos != maBorders.end(), "XclExpXFBuffer::SaveXml - Invalid @borderId!" );
    XclExpFillList::iterator aFillPos =
        std::find_if( maFills.begin(), maFills.end(), XclExpFillPred( rXF.GetAreaData() ) );
    DBG_ASSERT( aFillPos != maFills.end(), "XclExpXFBuffer::SaveXml - Invalid @fillId!" );

    sal_Int32 nBorderId = 0, nFillId = 0;
    if( aBorderPos != maBorders.end() )
        nBorderId = std::distance( maBorders.begin(), aBorderPos );
    if( aFillPos != maFills.end() )
        nFillId = std::distance( maFills.begin(), aFillPos );

    rXF.SetXmlIds( nBorderId, nFillId );
    rXF.SaveXml( rStrm );
}

void XclExpXFBuffer::impAddMissingValuesFromXFListToXclExpXFMap()
{
    for(size_t nPos(maXclExpXFMap.size()); nPos < maXFList.GetSize(); ++nPos)
    {
        XclExpXF* pValue = maXFList.GetRecord(nPos).get();

        if(pValue)
        {
            const SfxItemSet* pKey = maXFList.GetRecord(nPos)->getItemSet();

            maXclExpXFMap.insert(std::pair< const SfxItemSet*, XclExpXF* >(pKey, pValue));
            pValue->setIndexInXFList(nPos);
        }
        else
        {
            OSL_ENSURE(false, "maXFList has empty entries (!)");
        }
    }
}

sal_uInt32 XclExpXFBuffer::FindXF(const ScPatternAttr& rPattern, sal_uLong nForceScNumFmt, sal_uInt16 nForceXclFont, bool bForceLineBreak) const
{
    // define return value
    sal_uInt32 nXFId(EXC_XFID_NOTFOUND);

    if(XclExpXFBuffer_mbUseMultimapBuffer)
    {
        // add values from maXFList which are not yet in maXclExpXFMap
        const_cast< XclExpXFBuffer* >(this)->impAddMissingValuesFromXFListToXclExpXFMap();

        // get the full range for the pattern set
        typedef std::multimap< const SfxItemSet*, XclExpXF* >::const_iterator CIT;
        typedef std::pair< CIT, CIT > Range;
        const SfxItemSet* pPatternSet = &(rPattern.GetItemSet());
        const Range range(maXclExpXFMap.equal_range(pPatternSet));

        // iterate over evtl. multiple candidates using the pattern set
        for(CIT ite(range.first); ite != range.second; ++ite) 
        {
            XclExpXF* pIte = ite->second;

            if(pIte->Equals(rPattern, nForceScNumFmt, nForceXclFont, bForceLineBreak))
            {
                nXFId = pIte->getIndexInXFList();
                break;
            }
        }
    }
    else
    {
        // old, unbuffered implementation
        for( size_t nPos = 0, nSize = maXFList.GetSize(); nPos < nSize; ++nPos )
            if( maXFList.GetRecord( nPos )->Equals( rPattern, nForceScNumFmt, nForceXclFont, bForceLineBreak ) )
                return static_cast< sal_uInt32 >( nPos );
    }

    return nXFId;
}

sal_uInt32 XclExpXFBuffer::FindXF( const SfxStyleSheetBase& rStyleSheet ) const
{
    if(XclExpXFBuffer_mbUseMultimapBuffer)
    {
        // add values from maXFList which are not yet in maXclExpXFMap
        const_cast< XclExpXFBuffer* >(this)->impAddMissingValuesFromXFListToXclExpXFMap();

        // find entry with given ItemSet (by StyleSheet)
        const SfxItemSet& rItemSet = const_cast< SfxStyleSheetBase& >(rStyleSheet).GetItemSet();
        typedef std::multimap< const SfxItemSet*, XclExpXF* >::const_iterator CIT;
        const CIT aFound(maXclExpXFMap.find(&rItemSet));

        if(aFound != maXclExpXFMap.end())
        {
            return aFound->second->getIndexInXFList();
        }
    }
    else
    {
        // old, unbuffered implementation
        for( size_t nPos = 0, nSize = maXFList.GetSize(); nPos < nSize; ++nPos )
            if( maXFList.GetRecord( nPos )->Equals( rStyleSheet ) )
                return static_cast< sal_uInt32 >( nPos );
    }

    return EXC_XFID_NOTFOUND;
}

sal_uInt32 XclExpXFBuffer::FindBuiltInXF( sal_uInt8 nStyleId, sal_uInt8 nLevel ) const
{
    for( XclExpBuiltInMap::const_iterator aIt = maBuiltInMap.begin(), aEnd = maBuiltInMap.end(); aIt != aEnd; ++aIt )
        if( (aIt->second.mnStyleId == nStyleId) && (aIt->second.mnLevel == nLevel) )
            return aIt->first;
    return EXC_XFID_NOTFOUND;
}

sal_uInt32 XclExpXFBuffer::InsertCellXF( const ScPatternAttr* pPattern, sal_Int16 nScript,
        sal_uLong nForceScNumFmt, sal_uInt16 nForceXclFont, bool bForceLineBreak )
{
    const ScPatternAttr* pDefPattern = GetDoc().GetDefPattern();
    if( !pPattern )
        pPattern = pDefPattern;

    // special handling for default cell formatting
    if( (pPattern == pDefPattern) && !bForceLineBreak &&
        (nForceScNumFmt == NUMBERFORMAT_ENTRY_NOT_FOUND) &&
        (nForceXclFont == EXC_FONT_NOTFOUND) )
    {
        // Is it the first try to insert the default cell format?
        bool& rbPredefined = maBuiltInMap[ EXC_XF_DEFAULTCELL ].mbPredefined;
        if( rbPredefined )
        {
            // replace default cell pattern
            XclExpXFRef xNewXF( new XclExpXF( GetRoot(), *pPattern, nScript ) );
            maXFList.ReplaceRecord( xNewXF, EXC_XF_DEFAULTCELL );

            // need to clear the multimap buffer to force reinsertin of the new element
            if(XclExpXFBuffer_mbUseMultimapBuffer)
            {
                    maXclExpXFMap.clear();
            }

            rbPredefined = false;
        }
        return GetDefCellXFId();
    }

    sal_uInt32 nXFId = FindXF( *pPattern, nForceScNumFmt, nForceXclFont, bForceLineBreak );
    if( nXFId == EXC_XFID_NOTFOUND )
    {
        // not found - insert new cell XF
        if( maXFList.GetSize() < EXC_XFLIST_HARDLIMIT )
        {
            maXFList.AppendNewRecord( new XclExpXF(
                GetRoot(), *pPattern, nScript, nForceScNumFmt, nForceXclFont, bForceLineBreak ) );
            // do not set nXFId before the AppendNewRecord() call - it may insert 2 XFs (style+cell)
            nXFId = static_cast< sal_uInt32 >( maXFList.GetSize() - 1 );
        }
        else
        {
            // list full - fall back to default cell XF
            nXFId = GetDefCellXFId();
        }
    }
    return nXFId;
}

sal_uInt32 XclExpXFBuffer::InsertStyleXF( const SfxStyleSheetBase& rStyleSheet )
{
    // *** try, if it is a built-in style - create new XF or replace existing predefined XF ***

    sal_uInt8 nStyleId, nLevel;
    if( XclTools::GetBuiltInStyleId( nStyleId, nLevel, rStyleSheet.GetName() ) )
    {
        // try to find the built-in XF record (if already created in InsertDefaultRecords())
        sal_uInt32 nXFId = FindBuiltInXF( nStyleId, nLevel );
        if( nXFId == EXC_XFID_NOTFOUND )
        {
            // built-in style XF not yet created - do it now
            XclExpXFRef xXF( new XclExpXF( GetRoot(), rStyleSheet ) );
            nXFId = AppendBuiltInXFWithStyle( xXF, nStyleId, nLevel );
            // this new XF record is not predefined
            maBuiltInMap[ nXFId ].mbPredefined = false;
        }
        else
        {
            DBG_ASSERT( maXFList.HasRecord( nXFId ), "XclExpXFBuffer::InsertStyleXF - built-in XF not found" );
            // XF record still predefined? -> Replace with real XF
            bool& rbPredefined = maBuiltInMap[ nXFId ].mbPredefined;
            if( rbPredefined )
            {
                // replace predefined built-in style (ReplaceRecord() deletes old record)
                maXFList.ReplaceRecord( XclExpXFRef( new XclExpXF( GetRoot(), rStyleSheet ) ), nXFId );

                // need to clear the multimap buffer to force reinsertin of the new element
                if(XclExpXFBuffer_mbUseMultimapBuffer)
                {
                    maXclExpXFMap.clear();
                }

                rbPredefined = false;
            }
        }

        // STYLE already inserted? (may be not, i.e. for RowLevel/ColLevel or Hyperlink styles)
        bool& rbHasStyleRec = maBuiltInMap[ nXFId ].mbHasStyleRec;
        if( !rbHasStyleRec )
        {
            maStyleList.AppendNewRecord( new XclExpStyle( nXFId, nStyleId, nLevel ) );
            rbHasStyleRec = true;
        }

        return nXFId;
    }

    // *** try to find the XF record of a user-defined style ***

    sal_uInt32 nXFId = FindXF( rStyleSheet );
    if( nXFId == EXC_XFID_NOTFOUND )
    {
        // not found - insert new style XF and STYLE
        nXFId = static_cast< sal_uInt32 >( maXFList.GetSize() );
        if( nXFId < EXC_XFLIST_HARDLIMIT )
        {
            maXFList.AppendNewRecord( new XclExpXF( GetRoot(), rStyleSheet ) );
            // create the STYLE record
            if( rStyleSheet.GetName().Len() )
                maStyleList.AppendNewRecord( new XclExpStyle( nXFId, rStyleSheet.GetName() ) );
        }
        else
            // list full - fall back to default style XF
            nXFId = GetXFIdFromIndex( EXC_XF_DEFAULTSTYLE );
    }
    return nXFId;
}

void XclExpXFBuffer::InsertUserStyles()
{
    SfxStyleSheetIterator aStyleIter( GetDoc().GetStyleSheetPool(), SFX_STYLE_FAMILY_PARA );
    for( SfxStyleSheetBase* pStyleSheet = aStyleIter.First(); pStyleSheet; pStyleSheet = aStyleIter.Next() )
        if( pStyleSheet->IsUserDefined() && !lclIsBuiltInStyle( pStyleSheet->GetName() ) )
            InsertStyleXF( *pStyleSheet );
}

sal_uInt32 XclExpXFBuffer::AppendBuiltInXF( XclExpXFRef xXF, sal_uInt8 nStyleId, sal_uInt8 nLevel )
{
    sal_uInt32 nXFId = static_cast< sal_uInt32 >( maXFList.GetSize() );
    maXFList.AppendRecord( xXF );
    XclExpBuiltInInfo& rInfo = maBuiltInMap[ nXFId ];
    rInfo.mnStyleId = nStyleId;
    rInfo.mnLevel = nLevel;
    rInfo.mbPredefined = true;
    return nXFId;
}

sal_uInt32 XclExpXFBuffer::AppendBuiltInXFWithStyle( XclExpXFRef xXF, sal_uInt8 nStyleId, sal_uInt8 nLevel )
{
    sal_uInt32 nXFId = AppendBuiltInXF( xXF, nStyleId, nLevel );
    maStyleList.AppendNewRecord( new XclExpStyle( nXFId, nStyleId, nLevel ) );
    maBuiltInMap[ nXFId ].mbHasStyleRec = true;  // mark existing STYLE record
    return nXFId;
}

static XclExpCellArea lcl_GetPatternFill_None()
{
    XclExpCellArea aFill;
    aFill.mnPattern = EXC_PATT_NONE;
    return aFill;
}

static XclExpCellArea lcl_GetPatternFill_Gray125()
{
    XclExpCellArea aFill;
    aFill.mnPattern     = EXC_PATT_12_5_PERC;
    aFill.mnForeColor   = 0;
    aFill.mnBackColor   = 0;
    return aFill;
}

void XclExpXFBuffer::InsertDefaultRecords()
{
    maFills.push_back( lcl_GetPatternFill_None() );
    maFills.push_back( lcl_GetPatternFill_Gray125() );

    // index 0: default style
    if( SfxStyleSheetBase* pDefStyleSheet = GetStyleSheetPool().Find( ScGlobal::GetRscString( STR_STYLENAME_STANDARD ), SFX_STYLE_FAMILY_PARA ) )
    {
        XclExpXFRef xDefStyle( new XclExpXF( GetRoot(), *pDefStyleSheet ) );
        sal_uInt32 nXFId = AppendBuiltInXFWithStyle( xDefStyle, EXC_STYLE_NORMAL );
        // mark this XF as not predefined, prevents overwriting
        maBuiltInMap[ nXFId ].mbPredefined = false;
    }
    else
    {
        DBG_ERRORFILE( "XclExpXFBuffer::InsertDefaultRecords - default style not found" );
        XclExpXFRef xDefStyle( new XclExpDefaultXF( GetRoot(), false ) );
        xDefStyle->SetAllUsedFlags( true );
        AppendBuiltInXFWithStyle( xDefStyle, EXC_STYLE_NORMAL );
    }

    // index 1-14: RowLevel and ColLevel styles (without STYLE records)
    XclExpDefaultXF aLevelStyle( GetRoot(), false );
    // RowLevel_1, ColLevel_1
    aLevelStyle.SetFont( 1 );
    AppendBuiltInXF( XclExpXFRef( new XclExpDefaultXF( aLevelStyle ) ), EXC_STYLE_ROWLEVEL, 0 );
    AppendBuiltInXF( XclExpXFRef( new XclExpDefaultXF( aLevelStyle ) ), EXC_STYLE_COLLEVEL, 0 );
    // RowLevel_2, ColLevel_2
    aLevelStyle.SetFont( 2 );
    AppendBuiltInXF( XclExpXFRef( new XclExpDefaultXF( aLevelStyle ) ), EXC_STYLE_ROWLEVEL, 1 );
    AppendBuiltInXF( XclExpXFRef( new XclExpDefaultXF( aLevelStyle ) ), EXC_STYLE_COLLEVEL, 1 );
    // RowLevel_3, ColLevel_3 ... RowLevel_7, ColLevel_7
    aLevelStyle.SetFont( 0 );
    for( sal_uInt8 nLevel = 2; nLevel < EXC_STYLE_LEVELCOUNT; ++nLevel )
    {
        AppendBuiltInXF( XclExpXFRef( new XclExpDefaultXF( aLevelStyle ) ), EXC_STYLE_ROWLEVEL, nLevel );
        AppendBuiltInXF( XclExpXFRef( new XclExpDefaultXF( aLevelStyle ) ), EXC_STYLE_COLLEVEL, nLevel );
    }

    // index 15: default hard cell format, placeholder to be able to add more built-in styles
    maXFList.AppendNewRecord( new XclExpDefaultXF( GetRoot(), true ) );
    maBuiltInMap[ EXC_XF_DEFAULTCELL ].mbPredefined = true;

    // index 16-20: other built-in styles
    XclExpDefaultXF aFormatStyle( GetRoot(), false );
    aFormatStyle.SetFont( 1 );
    aFormatStyle.SetNumFmt( 43 );
    AppendBuiltInXFWithStyle( XclExpXFRef( new XclExpDefaultXF( aFormatStyle ) ), EXC_STYLE_COMMA );
    aFormatStyle.SetNumFmt( 41 );
    AppendBuiltInXFWithStyle( XclExpXFRef( new XclExpDefaultXF( aFormatStyle ) ), EXC_STYLE_COMMA_0 );
    aFormatStyle.SetNumFmt( 44 );
    AppendBuiltInXFWithStyle( XclExpXFRef( new XclExpDefaultXF( aFormatStyle ) ), EXC_STYLE_CURRENCY );
    aFormatStyle.SetNumFmt( 42 );
    AppendBuiltInXFWithStyle( XclExpXFRef( new XclExpDefaultXF( aFormatStyle ) ), EXC_STYLE_CURRENCY_0 );
    aFormatStyle.SetNumFmt( 9 );
    AppendBuiltInXFWithStyle( XclExpXFRef( new XclExpDefaultXF( aFormatStyle ) ), EXC_STYLE_PERCENT );

    // other built-in style XF records (i.e. Hyperlink styles) are created on demand

    /*  Insert the real default hard cell format -> 0 is document default pattern.
        Do it here (and not already above) to really have all built-in styles. */
    Insert( 0, GetDefApiScript() );
}

void XclExpXFBuffer::AppendXFIndex( sal_uInt32 nXFId )
{
    DBG_ASSERT( nXFId < maXFIndexVec.size(), "XclExpXFBuffer::AppendXFIndex - XF ID out of range" );
    maXFIndexVec[ nXFId ] = static_cast< sal_uInt16 >( maSortedXFList.GetSize() );
    XclExpXFRef xXF = maXFList.GetRecord( nXFId );
    AddBorderAndFill( *xXF );
    maSortedXFList.AppendRecord( xXF );
    DBG_ASSERT( maXFList.HasRecord( nXFId ), "XclExpXFBuffer::AppendXFIndex - XF not found" );
}

void XclExpXFBuffer::AddBorderAndFill( const XclExpXF& rXF )
{
    if( std::find_if( maBorders.begin(), maBorders.end(), XclExpBorderPred( rXF.GetBorderData() ) ) == maBorders.end() )
    {
        maBorders.push_back( rXF.GetBorderData() );
    }

    if( std::find_if( maFills.begin(), maFills.end(), XclExpFillPred( rXF.GetAreaData() ) ) == maFills.end() )
    {
        maFills.push_back( rXF.GetAreaData() );
    }
}

// ============================================================================

XclExpXmlStyleSheet::XclExpXmlStyleSheet( const XclExpRoot& rRoot )
    : XclExpRoot( rRoot )
{
}

void XclExpXmlStyleSheet::SaveXml( XclExpXmlStream& rStrm )
{
    sax_fastparser::FSHelperPtr aStyleSheet = rStrm.CreateOutputStream(
            OUString::createFromAscii( "xl/styles.xml" ),
            OUString::createFromAscii( "styles.xml" ),
            rStrm.GetCurrentStream()->getOutputStream(),
            "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml",
            "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" );
    rStrm.PushStream( aStyleSheet );

    aStyleSheet->startElement( XML_styleSheet,
            XML_xmlns, "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
            FSEND );

    CreateRecord( EXC_ID_FORMATLIST )->SaveXml( rStrm );
    CreateRecord( EXC_ID_FONTLIST )->SaveXml( rStrm );
    CreateRecord( EXC_ID_XFLIST )->SaveXml( rStrm );
    CreateRecord( EXC_ID_PALETTE )->SaveXml( rStrm );

    aStyleSheet->endElement( XML_styleSheet );

    rStrm.PopStream();
}

// ============================================================================

