/**************************************************************
 * 
 * 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.
 * 
 *************************************************************/



#include "oox/xls/defnamesbuffer.hxx"

#include <com/sun/star/sheet/ComplexReference.hpp>
#include <com/sun/star/sheet/ExternalReference.hpp>
#include <com/sun/star/sheet/NamedRangeFlag.hpp>
#include <com/sun/star/sheet/ReferenceFlags.hpp>
#include <com/sun/star/sheet/SingleReference.hpp>
#include <com/sun/star/sheet/XFormulaTokens.hpp>
#include <com/sun/star/sheet/XPrintAreas.hpp>
#include <rtl/ustrbuf.hxx>
#include "oox/helper/attributelist.hxx"
#include "oox/helper/containerhelper.hxx"
#include "oox/helper/propertyset.hxx"
#include "oox/xls/addressconverter.hxx"
#include "oox/xls/biffinputstream.hxx"
#include "oox/xls/externallinkbuffer.hxx"
#include "oox/xls/formulaparser.hxx"
#include "oox/xls/worksheetbuffer.hxx"

namespace oox {
namespace xls {

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

using namespace ::com::sun::star::sheet;
using namespace ::com::sun::star::table;
using namespace ::com::sun::star::uno;

using ::rtl::OUString;
using ::rtl::OUStringBuffer;

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

namespace {

const sal_uInt32 BIFF12_DEFNAME_HIDDEN      = 0x00000001;
const sal_uInt32 BIFF12_DEFNAME_FUNC        = 0x00000002;
const sal_uInt32 BIFF12_DEFNAME_VBNAME      = 0x00000004;
const sal_uInt32 BIFF12_DEFNAME_MACRO       = 0x00000008;
const sal_uInt32 BIFF12_DEFNAME_CALCEXP     = 0x00000010;
const sal_uInt32 BIFF12_DEFNAME_BUILTIN     = 0x00000020;
const sal_uInt32 BIFF12_DEFNAME_PUBLISHED   = 0x00008000;
const sal_uInt32 BIFF12_DEFNAME_WBPARAM     = 0x00010000;

const sal_uInt16 BIFF_DEFNAME_HIDDEN        = 0x0001;
const sal_uInt16 BIFF_DEFNAME_FUNC          = 0x0002;
const sal_uInt16 BIFF_DEFNAME_VBNAME        = 0x0004;
const sal_uInt16 BIFF_DEFNAME_MACRO         = 0x0008;
const sal_uInt16 BIFF_DEFNAME_CALCEXP       = 0x0010;
const sal_uInt16 BIFF_DEFNAME_BUILTIN       = 0x0020;
const sal_uInt16 BIFF_DEFNAME_BIG           = 0x1000;

const sal_uInt8 BIFF2_DEFNAME_FUNC          = 0x02;     /// BIFF2 function/command flag.

const sal_uInt16 BIFF_DEFNAME_GLOBAL        = 0;        /// 0 = Globally defined name.

const sal_uInt16 BIFF_REFFLAG_COL1REL       = 0x0001;
const sal_uInt16 BIFF_REFFLAG_ROW1REL       = 0x0002;
const sal_uInt16 BIFF_REFFLAG_COL2REL       = 0x0004;
const sal_uInt16 BIFF_REFFLAG_ROW2REL       = 0x0008;

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

const sal_Char* const spcLegacyPrefix = "Excel_BuiltIn_";
const sal_Char* const spcOoxPrefix = "_xlnm.";

const sal_Char* const sppcBaseNames[] =
{
    "Consolidate_Area",
    "Auto_Open",
    "Auto_Close",
    "Extract",
    "Database",
    "Criteria",
    "Print_Area",
    "Print_Titles",
    "Recorder",
    "Data_Form",
    "Auto_Activate",
    "Auto_Deactivate",
    "Sheet_Title",
    "_FilterDatabase"
};

/** Localized names for _xlnm._FilterDatabase as used in BIFF5. */
const sal_Char* const sppcFilterDbNames[] =
{
    "_FilterDatabase",      // English
    "_FilterDatenbank"      // German
};

OUString lclGetBaseName( sal_Unicode cBuiltinId )
{
    OSL_ENSURE( cBuiltinId < STATIC_ARRAY_SIZE( sppcBaseNames ), "lclGetBaseName - unsupported built-in identifier" );
    OUStringBuffer aBuffer;
    if( cBuiltinId < STATIC_ARRAY_SIZE( sppcBaseNames ) )
        aBuffer.appendAscii( sppcBaseNames[ cBuiltinId ] );
    else
        aBuffer.append( static_cast< sal_Int32 >( cBuiltinId ) );
    return aBuffer.makeStringAndClear();
}

OUString lclGetPrefixedName( sal_Unicode cBuiltinId )
{
    return OUStringBuffer().appendAscii( spcOoxPrefix ).append( lclGetBaseName( cBuiltinId ) ).makeStringAndClear();
}

/** returns the built-in name identifier from a perfixed built-in name, e.g. '_xlnm.Print_Area'. */
sal_Unicode lclGetBuiltinIdFromPrefixedName( const OUString& rModelName )
{
    OUString aPrefix = OUString::createFromAscii( spcOoxPrefix );
    sal_Int32 nPrefixLen = aPrefix.getLength();
    if( rModelName.matchIgnoreAsciiCase( aPrefix ) )
    {
        for( sal_Unicode cBuiltinId = 0; cBuiltinId < STATIC_ARRAY_SIZE( sppcBaseNames ); ++cBuiltinId )
        {
            OUString aBaseName = lclGetBaseName( cBuiltinId );
            sal_Int32 nBaseNameLen = aBaseName.getLength();
            if( (rModelName.getLength() == nPrefixLen + nBaseNameLen) && rModelName.matchIgnoreAsciiCase( aBaseName, nPrefixLen ) )
                return cBuiltinId;
        }
    }
    return BIFF_DEFNAME_UNKNOWN;
}

/** returns the built-in name identifier from a built-in base name, e.g. 'Print_Area'. */
sal_Unicode lclGetBuiltinIdFromBaseName( const OUString& rModelName )
{
    for( sal_Unicode cBuiltinId = 0; cBuiltinId < STATIC_ARRAY_SIZE( sppcBaseNames ); ++cBuiltinId )
        if( rModelName.equalsIgnoreAsciiCaseAscii( sppcBaseNames[ cBuiltinId ] ) )
            return cBuiltinId;
    return BIFF_DEFNAME_UNKNOWN;
}

bool lclIsFilterDatabaseName( const OUString& rModelName )
{
    for( const sal_Char* const* ppcName = sppcFilterDbNames; ppcName < STATIC_ARRAY_END( sppcFilterDbNames ); ++ppcName )
        if( rModelName.equalsIgnoreAsciiCaseAscii( *ppcName ) )
            return true;
    return false;
}

OUString lclGetUpcaseModelName( const OUString& rModelName )
{
    // TODO: i18n?
    return rModelName.toAsciiUpperCase();
}

void lclConvertRefFlags( sal_Int32& ornFlags, sal_Int32& ornAbsPos, sal_Int32& ornRelPos, sal_Int32 nBasePos, sal_Int32 nApiRelFlag, bool bRel )
{
    if( getFlag( ornFlags, nApiRelFlag ) && !bRel )
    {
        // convert relative to absolute
        setFlag( ornFlags, nApiRelFlag, false );
        ornAbsPos = nBasePos + ornRelPos;
    }
    else if( !getFlag( ornFlags, nApiRelFlag ) && bRel )
    {
        // convert absolute to relative
        setFlag( ornFlags, nApiRelFlag, true );
        ornRelPos = ornAbsPos - nBasePos;
    }
}

void lclConvertSingleRefFlags( SingleReference& orApiRef, const CellAddress& rBaseAddr, bool bColRel, bool bRowRel )
{
    using namespace ::com::sun::star::sheet::ReferenceFlags;
    lclConvertRefFlags(
        orApiRef.Flags, orApiRef.Column, orApiRef.RelativeColumn,
        rBaseAddr.Column, COLUMN_RELATIVE, bColRel );
    lclConvertRefFlags(
        orApiRef.Flags, orApiRef.Row, orApiRef.RelativeRow,
        rBaseAddr.Row, ROW_RELATIVE, bRowRel );
}

Any lclConvertReference( const Any& rRefAny, const CellAddress& rBaseAddr, sal_uInt16 nRelFlags )
{
    if( rRefAny.has< SingleReference >() && !getFlag( nRelFlags, BIFF_REFFLAG_COL2REL ) && !getFlag( nRelFlags, BIFF_REFFLAG_ROW2REL ) )
    {
        SingleReference aApiRef;
        rRefAny >>= aApiRef;
        lclConvertSingleRefFlags( aApiRef, rBaseAddr, getFlag( nRelFlags, BIFF_REFFLAG_COL1REL ), getFlag( nRelFlags, BIFF_REFFLAG_ROW1REL ) );
        return Any( aApiRef );
    }
    if( rRefAny.has< ComplexReference >() )
    {
        ComplexReference aApiRef;
        rRefAny >>= aApiRef;
        lclConvertSingleRefFlags( aApiRef.Reference1, rBaseAddr, getFlag( nRelFlags, BIFF_REFFLAG_COL1REL ), getFlag( nRelFlags, BIFF_REFFLAG_ROW1REL ) );
        lclConvertSingleRefFlags( aApiRef.Reference2, rBaseAddr, getFlag( nRelFlags, BIFF_REFFLAG_COL2REL ), getFlag( nRelFlags, BIFF_REFFLAG_ROW2REL ) );
        return Any( aApiRef );
    }
    return Any();
}

} // namespace

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

DefinedNameModel::DefinedNameModel() :
    mnSheet( -1 ),
    mnFuncGroupId( -1 ),
    mbMacro( false ),
    mbFunction( false ),
    mbVBName( false ),
    mbHidden( false )
{
}

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

DefinedNameBase::DefinedNameBase( const WorkbookHelper& rHelper ) :
    WorkbookHelper( rHelper )
{
}

const OUString& DefinedNameBase::getUpcaseModelName() const
{
    if( maUpModelName.getLength() == 0 )
        maUpModelName = lclGetUpcaseModelName( maModel.maName );
    return maUpModelName;
}

Any DefinedNameBase::getReference( const CellAddress& rBaseAddr ) const
{
    if( maRefAny.hasValue() && (maModel.maName.getLength() >= 2) && (maModel.maName[ 0 ] == '\x01') )
    {
        sal_Unicode cFlagsChar = getUpcaseModelName()[ 1 ];
        if( ('A' <= cFlagsChar) && (cFlagsChar <= 'P') )
        {
            sal_uInt16 nRelFlags = static_cast< sal_uInt16 >( cFlagsChar - 'A' );
            if( maRefAny.has< ExternalReference >() )
            {
                ExternalReference aApiExtRef;
                maRefAny >>= aApiExtRef;
                Any aRefAny = lclConvertReference( aApiExtRef.Reference, rBaseAddr, nRelFlags );
                if( aRefAny.hasValue() )
                {
                    aApiExtRef.Reference <<= aRefAny;
                    return Any( aApiExtRef );
                }
            }
            else
            {
                return lclConvertReference( maRefAny, rBaseAddr, nRelFlags );
            }
        }
    }
    return Any();
}

ApiTokenSequence DefinedNameBase::importOoxFormula( sal_Int16 nBaseSheet )
{
    return (maModel.maFormula.getLength() > 0) ?
        getFormulaParser().importFormula( CellAddress( nBaseSheet, 0, 0 ), maModel.maFormula ) :
        getFormulaParser().convertErrorToFormula( BIFF_ERR_NAME );
}

ApiTokenSequence DefinedNameBase::importBiff12Formula( sal_Int16 nBaseSheet, SequenceInputStream& rStrm )
{
    return getFormulaParser().importFormula( CellAddress( nBaseSheet, 0, 0 ), FORMULATYPE_DEFINEDNAME, rStrm );
}

ApiTokenSequence DefinedNameBase::importBiffFormula( sal_Int16 nBaseSheet, BiffInputStream& rStrm, const sal_uInt16* pnFmlaSize )
{
    return (!pnFmlaSize || (*pnFmlaSize > 0)) ?
        getFormulaParser().importFormula( CellAddress( nBaseSheet, 0, 0 ), FORMULATYPE_DEFINEDNAME, rStrm, pnFmlaSize ) :
        getFormulaParser().convertErrorToFormula( BIFF_ERR_NAME );
}

void DefinedNameBase::extractReference( const ApiTokenSequence& rTokens )
{
    OSL_ENSURE( (getFilterType() == FILTER_BIFF) && (getBiff() <= BIFF4), "DefinedNameBase::extractReference - unexpected call" );
    maRefAny = getFormulaParser().extractReference( rTokens );
}

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

DefinedName::DefinedName( const WorkbookHelper& rHelper ) :
    DefinedNameBase( rHelper ),
    mnTokenIndex( -1 ),
    mcBuiltinId( BIFF_DEFNAME_UNKNOWN ),
    mnFmlaSize( 0 )
{
}

void DefinedName::importDefinedName( const AttributeList& rAttribs )
{
    maModel.maName        = rAttribs.getXString( XML_name, OUString() );
    maModel.mnSheet       = rAttribs.getInteger( XML_localSheetId, -1 );
    maModel.mnFuncGroupId = rAttribs.getInteger( XML_functionGroupId, -1 );
    maModel.mbMacro       = rAttribs.getBool( XML_xlm, false );
    maModel.mbFunction    = rAttribs.getBool( XML_function, false );
    maModel.mbVBName      = rAttribs.getBool( XML_vbProcedure, false );
    maModel.mbHidden      = rAttribs.getBool( XML_hidden, false );
    mnCalcSheet = (maModel.mnSheet >= 0) ? getWorksheets().getCalcSheetIndex( maModel.mnSheet ) : -1;

    /*  Detect built-in state from name itself, there is no built-in flag.
        Built-in names are prexixed with '_xlnm.' instead. */
    mcBuiltinId = lclGetBuiltinIdFromPrefixedName( maModel.maName );
}

void DefinedName::setFormula( const OUString& rFormula )
{
    maModel.maFormula = rFormula;
}

void DefinedName::importDefinedName( SequenceInputStream& rStrm )
{
    sal_uInt32 nFlags;
    rStrm >> nFlags;
    rStrm.skip( 1 );    // keyboard shortcut
    rStrm >> maModel.mnSheet >> maModel.maName;
    mnCalcSheet = (maModel.mnSheet >= 0) ? getWorksheets().getCalcSheetIndex( maModel.mnSheet ) : -1;

    // macro function/command, hidden flag
    maModel.mnFuncGroupId = extractValue< sal_Int32 >( nFlags, 6, 9 );
    maModel.mbMacro       = getFlag( nFlags, BIFF12_DEFNAME_MACRO );
    maModel.mbFunction    = getFlag( nFlags, BIFF12_DEFNAME_FUNC );
    maModel.mbVBName      = getFlag( nFlags, BIFF12_DEFNAME_VBNAME );
    maModel.mbHidden      = getFlag( nFlags, BIFF12_DEFNAME_HIDDEN );

    // get built-in name index from name
    if( getFlag( nFlags, BIFF12_DEFNAME_BUILTIN ) )
        mcBuiltinId = lclGetBuiltinIdFromBaseName( maModel.maName );

    // store token array data
    sal_Int64 nRecPos = rStrm.tell();
    sal_Int32 nFmlaSize = rStrm.readInt32();
    rStrm.skip( nFmlaSize );
    sal_Int32 nAddDataSize = rStrm.readInt32();
    if( !rStrm.isEof() && (nFmlaSize > 0) && (nAddDataSize >= 0) && (rStrm.getRemaining() >= nAddDataSize) )
    {
        sal_Int32 nTotalSize = 8 + nFmlaSize + nAddDataSize;
        mxFormula.reset( new StreamDataSequence );
        rStrm.seek( nRecPos );
        rStrm.readData( *mxFormula, nTotalSize );
    }
}

void DefinedName::importDefinedName( BiffInputStream& rStrm, sal_Int16 nCalcSheet )
{
    BiffType eBiff = getBiff();
    sal_uInt16 nFlags = 0;
    sal_Int16 nRefId = BIFF_DEFNAME_GLOBAL;
    sal_Int16 nTabId = BIFF_DEFNAME_GLOBAL;
    sal_uInt8 nNameLen = 0, nShortCut = 0;

    switch( eBiff )
    {
        case BIFF2:
        {
            sal_uInt8 nFlagsBiff2;
            rStrm >> nFlagsBiff2;
            rStrm.skip( 1 );
            rStrm >> nShortCut >> nNameLen;
            mnFmlaSize = rStrm.readuInt8();
            setFlag( nFlags, BIFF_DEFNAME_FUNC, getFlag( nFlagsBiff2, BIFF2_DEFNAME_FUNC ) );
            maModel.maName = rStrm.readCharArrayUC( nNameLen, getTextEncoding(), true );
        }
        break;
        case BIFF3:
        case BIFF4:
            rStrm >> nFlags >> nShortCut >> nNameLen >> mnFmlaSize;
            maModel.maName = rStrm.readCharArrayUC( nNameLen, getTextEncoding(), true );
        break;
        case BIFF5:
            rStrm >> nFlags >> nShortCut >> nNameLen >> mnFmlaSize >> nRefId >> nTabId;
            rStrm.skip( 4 );
            maModel.maName = rStrm.readCharArrayUC( nNameLen, getTextEncoding(), true );
        break;
        case BIFF8:
            rStrm >> nFlags >> nShortCut >> nNameLen >> mnFmlaSize >> nRefId >> nTabId;
            rStrm.skip( 4 );
            maModel.maName = rStrm.readUniStringBody( nNameLen, true );
        break;
        case BIFF_UNKNOWN: break;
    }

    // macro function/command, hidden flag
    maModel.mnFuncGroupId = extractValue< sal_Int32 >( nFlags, 6, 6 );
    maModel.mbMacro       = getFlag( nFlags, BIFF_DEFNAME_MACRO );
    maModel.mbFunction    = getFlag( nFlags, BIFF_DEFNAME_FUNC );
    maModel.mbVBName      = getFlag( nFlags, BIFF_DEFNAME_VBNAME );
    maModel.mbHidden      = getFlag( nFlags, BIFF_DEFNAME_HIDDEN );

    // get built-in name index from name
    if( getFlag( nFlags, BIFF_DEFNAME_BUILTIN ) )
    {
        // name may be the built-in identifier or the built-in base name
        if( maModel.maName.getLength() == 1 )
            mcBuiltinId = maModel.maName[ 0 ];
        else
            mcBuiltinId = lclGetBuiltinIdFromBaseName( maModel.maName );
    }
    /*  In BIFF5, '_FilterDatabase' appears as hidden user name without
        built-in flag, and even worse, localized. */
    else if( (eBiff == BIFF5) && lclIsFilterDatabaseName( maModel.maName ) )
    {
        mcBuiltinId = BIFF_DEFNAME_FILTERDATABASE;
    }

    // get sheet index for sheet-local names in BIFF5-BIFF8
    switch( getBiff() )
    {
        case BIFF2:
        case BIFF3:
        case BIFF4:
            // BIFF2-BIFF4: all defined names are sheet-local
            mnCalcSheet = nCalcSheet;
        break;
        case BIFF5:
            // #i44019# nTabId may be invalid, resolve nRefId to sheet index
            if( nRefId != BIFF_DEFNAME_GLOBAL )
                if( const ExternalLink* pExtLink = getExternalLinks().getExternalLink( nRefId ).get() )
                    if( pExtLink->getLinkType() == LINKTYPE_INTERNAL )
                        mnCalcSheet = pExtLink->getCalcSheetIndex();
        break;
        case BIFF8:
            // convert one-based worksheet index to zero-based Calc sheet index
            OSL_ENSURE( nTabId >= 0, "DefinedName::importDefinedName - invalid local sheet index" );
            if( nTabId != BIFF_DEFNAME_GLOBAL )
                mnCalcSheet = getWorksheets().getCalcSheetIndex( nTabId - 1 );
        break;
        case BIFF_UNKNOWN:
        break;
    }

    if( (getBiff() <= BIFF4) && maModel.mbHidden && (maModel.maName.getLength() > 1) && (maModel.maName[ 0 ] == '\x01') )
    {
        /*  Read the token array of special internal names containing addresses
            for BIFF3-BIFF4 3D references immediately. It is expected that
            these names contain a simple cell reference or range reference.
            Other regular defined names and external names rely on existence of
            this reference. */
        ApiTokenSequence aTokens = importBiffFormula( mnCalcSheet, rStrm, &mnFmlaSize );
        extractReference( aTokens );
    }
    else
    {
        /*  Store record position of other defined names to be able to import
            token array later. This is needed to correctly resolve references
            to names that are stored later in the defined names list following
            this name. */
        mxBiffStrm.reset( new BiffInputStreamPos( rStrm ) );
    }
}

void DefinedName::createNameObject()
{
    // do not create names for (macro) functions or VBA procedures
    // #163146# do not ignore hidden names (may be regular names created by VBA scripts)
    if( /*maModel.mbHidden ||*/ maModel.mbFunction || maModel.mbVBName )
        return;

    // skip BIFF names without stream position (e.g. BIFF3-BIFF4 internal 3D references)
    if( (getFilterType() == FILTER_BIFF) && !mxBiffStrm.get() )
        return;

    // convert original name to final Calc name (TODO: filter invalid characters from model name)
    maCalcName = isBuiltinName() ? lclGetPrefixedName( mcBuiltinId ) : maModel.maName;

    // #163146# do not rename sheet-local names by default, this breaks VBA scripts
#if 0
    // append sheet index for local names in multi-sheet documents
    if( isWorkbookFile() && !isGlobalName() )
        maCalcName = OUStringBuffer( maCalcName ).append( sal_Unicode( '_' ) ).
            append( static_cast< sal_Int32 >( mnCalcSheet + 1 ) ).makeStringAndClear();
#endif

    // special flags for this name
    sal_Int32 nNameFlags = 0;
    using namespace ::com::sun::star::sheet::NamedRangeFlag;
    if( !isGlobalName() ) switch( mcBuiltinId )
    {
        case BIFF_DEFNAME_CRITERIA:     nNameFlags = FILTER_CRITERIA;               break;
        case BIFF_DEFNAME_PRINTAREA:    nNameFlags = PRINT_AREA;                    break;
        case BIFF_DEFNAME_PRINTTITLES:  nNameFlags = COLUMN_HEADER | ROW_HEADER;    break;
    }

    // create the name and insert it into the document, maCalcName will be changed to the resulting name
    mxNamedRange = createNamedRangeObject( maCalcName, maModel.mnSheet, nNameFlags );
    // index of this defined name used in formula token arrays
    PropertySet aPropSet( mxNamedRange );
    aPropSet.getProperty( mnTokenIndex, PROP_TokenIndex );
}

void DefinedName::convertFormula()
{
    Reference< XFormulaTokens > xTokens( mxNamedRange, UNO_QUERY );
    if( !xTokens.is() )
        return;

    // convert and set formula of the defined name
    ApiTokenSequence aTokens;
    switch( getFilterType() )
    {
        case FILTER_OOXML:
        {
            if( mxFormula.get() )
            {
                SequenceInputStream aStrm( *mxFormula );
                aTokens = importBiff12Formula( mnCalcSheet, aStrm );
            }
            else
                aTokens = importOoxFormula( mnCalcSheet );
        }
        break;
        case FILTER_BIFF:
        {
            OSL_ENSURE( mxBiffStrm.get(), "DefinedName::convertFormula - missing BIFF stream" );
            if( mxBiffStrm.get() )
            {
                BiffInputStream& rStrm = mxBiffStrm->getStream();
                BiffInputStreamPosGuard aStrmGuard( rStrm );
                if( mxBiffStrm->restorePosition() )
                    aTokens = importBiffFormula( mnCalcSheet, rStrm, &mnFmlaSize );
            }
        }
        break;
        case FILTER_UNKNOWN:
        break;
    }
    xTokens->setTokens( aTokens );

    // set built-in names (print ranges, repeated titles, filter ranges)
    if( !isGlobalName() ) switch( mcBuiltinId )
    {
        case BIFF_DEFNAME_PRINTAREA:
        {
            Reference< XPrintAreas > xPrintAreas( getSheetFromDoc( mnCalcSheet ), UNO_QUERY );
            ApiCellRangeList aPrintRanges;
            getFormulaParser().extractCellRangeList( aPrintRanges, xTokens->getTokens(), false, mnCalcSheet );
            if( xPrintAreas.is() && !aPrintRanges.empty() )
                xPrintAreas->setPrintAreas( ContainerHelper::vectorToSequence( aPrintRanges ) );
        }
        break;
        case BIFF_DEFNAME_PRINTTITLES:
        {
            Reference< XPrintAreas > xPrintAreas( getSheetFromDoc( mnCalcSheet ), UNO_QUERY );
            ApiCellRangeList aTitleRanges;
            getFormulaParser().extractCellRangeList( aTitleRanges, xTokens->getTokens(), false, mnCalcSheet );
            if( xPrintAreas.is() && !aTitleRanges.empty() )
            {
                bool bHasRowTitles = false;
                bool bHasColTitles = false;
                const CellAddress& rMaxPos = getAddressConverter().getMaxAddress();
                for( ApiCellRangeList::const_iterator aIt = aTitleRanges.begin(), aEnd = aTitleRanges.end(); (aIt != aEnd) && (!bHasRowTitles || !bHasColTitles); ++aIt )
                {
                    bool bFullRow = (aIt->StartColumn == 0) && (aIt->EndColumn >= rMaxPos.Column);
                    bool bFullCol = (aIt->StartRow == 0) && (aIt->EndRow >= rMaxPos.Row);
                    if( !bHasRowTitles && bFullRow && !bFullCol )
                    {
                        xPrintAreas->setTitleRows( *aIt );
                        xPrintAreas->setPrintTitleRows( sal_True );
                        bHasRowTitles = true;
                    }
                    else if( !bHasColTitles && bFullCol && !bFullRow )
                    {
                        xPrintAreas->setTitleColumns( *aIt );
                        xPrintAreas->setPrintTitleColumns( sal_True );
                        bHasColTitles = true;
                    }
                }
            }
        }
        break;
    }
}

bool DefinedName::getAbsoluteRange( CellRangeAddress& orRange ) const
{
    /*  ScNamedRangeObj::XCellRangeReferrer::getReferredCells is buggy with
        relative references, so we extract an absolute reference by hand. */
    Reference< XFormulaTokens > xTokens( mxNamedRange, UNO_QUERY );
    return xTokens.is() && getFormulaParser().extractCellRange( orRange, xTokens->getTokens(), false );
}

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

DefinedNamesBuffer::DefinedNamesBuffer( const WorkbookHelper& rHelper ) :
    WorkbookHelper( rHelper ),
    mnCalcSheet( -1 )
{
}

void DefinedNamesBuffer::setLocalCalcSheet( sal_Int16 nCalcSheet )
{
    OSL_ENSURE( (getFilterType() == FILTER_BIFF) && (getBiff() <= BIFF4),
        "DefinedNamesBuffer::setLocalCalcSheet - invalid call" );
    mnCalcSheet = nCalcSheet;
}

DefinedNameRef DefinedNamesBuffer::importDefinedName( const AttributeList& rAttribs )
{
    DefinedNameRef xDefName = createDefinedName();
    xDefName->importDefinedName( rAttribs );
    return xDefName;
}

void DefinedNamesBuffer::importDefinedName( SequenceInputStream& rStrm )
{
    createDefinedName()->importDefinedName( rStrm );
}

void DefinedNamesBuffer::importDefinedName( BiffInputStream& rStrm )
{
    createDefinedName()->importDefinedName( rStrm, mnCalcSheet );
}

void DefinedNamesBuffer::finalizeImport()
{
    // first insert all names without formula definition into the document, and insert them into the maps
    for( DefNameVector::iterator aIt = maDefNames.begin(), aEnd = maDefNames.end(); aIt != aEnd; ++aIt )
    {
        DefinedNameRef xDefName = *aIt;
        xDefName->createNameObject();
        // map by sheet index and original model name
        maModelNameMap[ SheetNameKey( xDefName->getLocalCalcSheet(), xDefName->getUpcaseModelName() ) ] = xDefName;
        // map by sheet index and built-in identifier
        if( !xDefName->isGlobalName() && xDefName->isBuiltinName() )
            maBuiltinMap[ BuiltinKey( xDefName->getLocalCalcSheet(), xDefName->getBuiltinId() ) ] = xDefName;
        // map by API formula token identifier
        sal_Int32 nTokenIndex = xDefName->getTokenIndex();
        if( nTokenIndex >= 0 )
            maTokenIdMap[ nTokenIndex ] = xDefName;
    }

    /*  Now convert all name formulas, so that the formula parser can find all
        names in case of circular dependencies. */
    maDefNames.forEachMem( &DefinedName::convertFormula );
}

DefinedNameRef DefinedNamesBuffer::getByIndex( sal_Int32 nIndex ) const
{
    return maDefNames.get( nIndex );
}

DefinedNameRef DefinedNamesBuffer::getByTokenIndex( sal_Int32 nIndex ) const
{
    return maTokenIdMap.get( nIndex );
}

DefinedNameRef DefinedNamesBuffer::getByModelName( const OUString& rModelName, sal_Int16 nCalcSheet ) const
{
    OUString aUpcaseName = lclGetUpcaseModelName( rModelName );
    DefinedNameRef xDefName = maModelNameMap.get( SheetNameKey( nCalcSheet, aUpcaseName ) );
    // lookup global name, if no local name exists
    if( !xDefName && (nCalcSheet >= 0) )
        xDefName = maModelNameMap.get( SheetNameKey( -1, aUpcaseName ) );
    return xDefName;
}

DefinedNameRef DefinedNamesBuffer::getByBuiltinId( sal_Unicode cBuiltinId, sal_Int16 nCalcSheet ) const
{
    return maBuiltinMap.get( BuiltinKey( nCalcSheet, cBuiltinId ) );
}

DefinedNameRef DefinedNamesBuffer::createDefinedName()
{
    DefinedNameRef xDefName( new DefinedName( *this ) );
    maDefNames.push_back( xDefName );
    return xDefName;
}

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

} // namespace xls
} // namespace oox
