LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/sc/source/filter/excel - xename.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 58 298 19.5 %
Date: 2013-07-09 Functions: 16 56 28.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include "xename.hxx"
      21             : 
      22             : #include <map>
      23             : 
      24             : #include "globstr.hrc"
      25             : #include "document.hxx"
      26             : #include "rangenam.hxx"
      27             : #include "dbdata.hxx"
      28             : #include "xehelper.hxx"
      29             : #include "xelink.hxx"
      30             : #include "globalnames.hxx"
      31             : 
      32             : // for filter manager
      33             : #include "excrecds.hxx"
      34             : 
      35             : #include <formula/grammar.hxx>
      36             : 
      37             : using namespace ::oox;
      38             : 
      39             : 
      40             : // ============================================================================
      41             : // *** Helper classes ***
      42             : // ============================================================================
      43             : 
      44             : /** Represents an internal defined name, supports writing it to a NAME record. */
      45           0 : class XclExpName : public XclExpRecord, protected XclExpRoot
      46             : {
      47             : public:
      48             :     /** Creates a standard defined name. */
      49             :     explicit            XclExpName( const XclExpRoot& rRoot, const String& rName );
      50             :     /** Creates a built-in defined name. */
      51             :     explicit            XclExpName( const XclExpRoot& rRoot, sal_Unicode cBuiltIn );
      52             : 
      53             :     /** Sets a token array containing the definition of this name. */
      54             :     void                SetTokenArray( XclTokenArrayRef xTokArr );
      55             :     /** Changes this defined name to be local on the specified Calc sheet. */
      56             :     void                SetLocalTab( SCTAB nScTab );
      57             :     /** Hides or unhides the defined name. */
      58             :     void                SetHidden( bool bHidden = true );
      59             :     /** Changes this name to be the call to a VB macro function or procedure.
      60             :         @param bVBasic  true = Visual Basic macro, false = Sheet macro.
      61             :         @param bFunc  true = Macro function; false = Macro procedure. */
      62             :     void                SetMacroCall( bool bVBasic, bool bFunc );
      63             : 
      64             : 
      65             :     /** Sets the name's symbol value
      66             :         @param sValue   the name's symbolic value */
      67             :     void                SetSymbol( String sValue );
      68             :     /** Returns the name's symbol value */
      69             :     inline const String& GetSymbol() const { return msSymbol; }
      70             : 
      71             :     /** Returns the original name (title) of this defined name. */
      72           0 :     inline const String& GetOrigName() const { return maOrigName; }
      73             :     /** Returns the Excel built-in name index of this defined name.
      74             :         @return  The built-in name index or EXC_BUILTIN_UNKNOWN for user-defined names. */
      75           0 :     inline sal_Unicode  GetBuiltInName() const { return mcBuiltIn; }
      76             : 
      77             :     /** Returns the token array for this defined name. */
      78           0 :     inline XclTokenArrayRef GetTokenArray() const { return mxTokArr; }
      79             : 
      80             :     /** Returns true, if this is a document-global defined name. */
      81           0 :     inline bool         IsGlobal() const { return mnXclTab == EXC_NAME_GLOBAL; }
      82             :     /** Returns the Calc sheet of a local defined name. */
      83           0 :     inline SCTAB        GetScTab() const { return mnScTab; }
      84             : 
      85             :     /** Returns true, if this defined name is volatile. */
      86             :     bool                IsVolatile() const;
      87             :     /** Returns true, if this defined name describes a macro call.
      88             :         @param bFunc  true = Macro function; false = Macro procedure. */
      89             :     bool                IsMacroCall( bool bVBasic, bool bFunc ) const;
      90             : 
      91             :     /** Writes the entire NAME record to the passed stream. */
      92             :     virtual void        Save( XclExpStream& rStrm );
      93             : 
      94             :     virtual void        SaveXml( XclExpXmlStream& rStrm );
      95             : 
      96             : private:
      97             :     /** Writes the body of the NAME record to the passed stream. */
      98             :     virtual void        WriteBody( XclExpStream& rStrm );
      99             : 
     100             : private:
     101             :     String              maOrigName;     /// The original user-defined name.
     102             :     String              msSymbol;       /// The value of the symbol
     103             :     XclExpStringRef     mxName;         /// The name as Excel string object.
     104             :     XclTokenArrayRef    mxTokArr;       /// The definition of the defined name.
     105             :     sal_Unicode         mcBuiltIn;      /// The built-in index for built-in names.
     106             :     SCTAB               mnScTab;        /// The Calc sheet index for local names.
     107             :     sal_uInt16          mnFlags;        /// Additional flags for this defined name.
     108             :     sal_uInt16          mnExtSheet;     /// The 1-based index to a global EXTERNSHEET record.
     109             :     sal_uInt16          mnXclTab;       /// The 1-based Excel sheet index for local names.
     110             : };
     111             : 
     112             : // ----------------------------------------------------------------------------
     113             : 
     114             : class ScRangeData;
     115             : class ScDBData;
     116             : 
     117             : /** Implementation class of the name manager. */
     118          18 : class XclExpNameManagerImpl : protected XclExpRoot
     119             : {
     120             : public:
     121             :     explicit            XclExpNameManagerImpl( const XclExpRoot& rRoot );
     122             : 
     123             :     /** Creates NAME records for built-in and user defined names. */
     124             :     void                Initialize();
     125             : 
     126             :     /** Inserts the Calc name with the passed index and returns the Excel NAME index. */
     127             :     sal_uInt16          InsertName( SCTAB nTab, sal_uInt16 nScNameIdx );
     128             : 
     129             :     /** Inserts a new built-in defined name. */
     130             :     sal_uInt16          InsertBuiltInName( sal_Unicode cBuiltIn, XclTokenArrayRef xTokArr, SCTAB nScTab, const ScRangeList& aRangeList );
     131             :     sal_uInt16          InsertBuiltInName( sal_Unicode cBuiltIn, XclTokenArrayRef xTokArr, const ScRange& aRange );
     132             :     /** Inserts a new defined name. Sets another unused name, if rName already exists. */
     133             :     sal_uInt16          InsertUniqueName( const String& rName, XclTokenArrayRef xTokArr, SCTAB nScTab );
     134             :     /** Returns index of an existing name, or creates a name without definition. */
     135             :     sal_uInt16          InsertRawName( const String& rName );
     136             :     /** Searches or inserts a defined name describing a macro name.
     137             :         @param bVBasic  true = Visual Basic macro; false = Sheet macro.
     138             :         @param bFunc  true = Macro function; false = Macro procedure. */
     139             :     sal_uInt16          InsertMacroCall( const String& rMacroName, bool bVBasic, bool bFunc, bool bHidden );
     140             : 
     141             :     /** Returns the NAME record at the specified position or 0 on error. */
     142             :     const XclExpName*   GetName( sal_uInt16 nNameIdx ) const;
     143             : 
     144             :     /** Writes the entire list of NAME records.
     145             :         @descr  In BIFF7 and lower, writes the entire global link table, which
     146             :             consists of an EXTERNCOUNT record, several EXTERNSHEET records, and
     147             :             the list of NAME records. */
     148             :     void                Save( XclExpStream& rStrm );
     149             : 
     150             :     void                SaveXml( XclExpXmlStream& rStrm );
     151             : 
     152             : private:
     153             :     typedef XclExpRecordList< XclExpName >      XclExpNameList;
     154             :     typedef XclExpNameList::RecordRefType       XclExpNameRef;
     155             : 
     156             :     typedef ::std::map< ::std::pair<SCTAB, sal_uInt16>, sal_uInt16> NamedExpIndexMap;
     157             : 
     158             : private:
     159             :     /**
     160             :      * @param nTab 0-based table index, or SCTAB_GLOBAL for global names.
     161             :      * @param nScIdx calc's name index.
     162             :      *
     163             :      * @return excel's name index.
     164             :      */
     165             :     sal_uInt16          FindNamedExpIndex( SCTAB nTab, sal_uInt16 nScIdx );
     166             : 
     167             :     /** Returns the index of an existing built-in NAME record with the passed definition, otherwise 0. */
     168             :     sal_uInt16          FindBuiltInNameIdx( const String& rName,
     169             :                             const XclTokenArray& rTokArr, bool bDBRange ) const;
     170             :     /** Returns an unused name for the passed name. */
     171             :     String              GetUnusedName( const String& rName ) const;
     172             : 
     173             :     /** Appends a new NAME record to the record list.
     174             :         @return  The 1-based NAME record index used elsewhere in the Excel file. */
     175             :     sal_uInt16          Append( XclExpNameRef xName );
     176             :     /** Creates a new NAME record for the passed user-defined name.
     177             :         @return  The 1-based NAME record index used elsewhere in the Excel file. */
     178             :     sal_uInt16          CreateName( SCTAB nTab, const ScRangeData& rRangeData );
     179             :     /** Creates a new NAME record for the passed database range.
     180             :         @return  The 1-based NAME record index used elsewhere in the Excel file. */
     181             :     sal_uInt16          CreateName( const ScDBData& rDBData );
     182             : 
     183             :     /** Creates NAME records for all built-in names in the document. */
     184             :     void                CreateBuiltInNames();
     185             :     /** Creates NAME records for all user-defined names in the document. */
     186             :     void                CreateUserNames();
     187             : 
     188             : private:
     189             :     /**
     190             :      * Maps Calc's named range to Excel's NAME records.  Global names use
     191             :      * -1 as their table index, whereas sheet-local names have 0-based table
     192             :      *  index.
     193             :      */
     194             :     NamedExpIndexMap    maNamedExpMap;
     195             :     XclExpNameList      maNameList;         /// List of NAME records.
     196             :     size_t              mnFirstUserIdx;     /// List index of first user-defined NAME record.
     197             : };
     198             : 
     199             : // ============================================================================
     200             : // *** Implementation ***
     201             : // ============================================================================
     202             : 
     203           0 : XclExpName::XclExpName( const XclExpRoot& rRoot, const String& rName ) :
     204             :     XclExpRecord( EXC_ID_NAME ),
     205             :     XclExpRoot( rRoot ),
     206             :     maOrigName( rName ),
     207             :     mxName( XclExpStringHelper::CreateString( rRoot, rName, EXC_STR_8BITLENGTH ) ),
     208             :     mcBuiltIn( EXC_BUILTIN_UNKNOWN ),
     209             :     mnScTab( SCTAB_GLOBAL ),
     210             :     mnFlags( EXC_NAME_DEFAULT ),
     211             :     mnExtSheet( EXC_NAME_GLOBAL ),
     212           0 :     mnXclTab( EXC_NAME_GLOBAL )
     213             : {
     214           0 : }
     215             : 
     216           0 : XclExpName::XclExpName( const XclExpRoot& rRoot, sal_Unicode cBuiltIn ) :
     217             :     XclExpRecord( EXC_ID_NAME ),
     218             :     XclExpRoot( rRoot ),
     219             :     mcBuiltIn( cBuiltIn ),
     220             :     mnScTab( SCTAB_GLOBAL ),
     221             :     mnFlags( EXC_NAME_DEFAULT ),
     222             :     mnExtSheet( EXC_NAME_GLOBAL ),
     223           0 :     mnXclTab( EXC_NAME_GLOBAL )
     224             : {
     225             :     // filter source range is hidden in Excel
     226           0 :     if( cBuiltIn == EXC_BUILTIN_FILTERDATABASE )
     227           0 :         SetHidden();
     228             : 
     229             :     // special case for BIFF5/7 filter source range - name appears as plain text without built-in flag
     230           0 :     if( (GetBiff() <= EXC_BIFF5) && (cBuiltIn == EXC_BUILTIN_FILTERDATABASE) )
     231             :     {
     232           0 :         String aName( XclTools::GetXclBuiltInDefName( EXC_BUILTIN_FILTERDATABASE ) );
     233           0 :         mxName = XclExpStringHelper::CreateString( rRoot, aName, EXC_STR_8BITLENGTH );
     234           0 :         maOrigName = XclTools::GetXclBuiltInDefName( cBuiltIn );
     235             :     }
     236             :     else
     237             :     {
     238           0 :         maOrigName =  XclTools::GetBuiltInDefNameXml( cBuiltIn ) ;
     239           0 :         mxName = XclExpStringHelper::CreateString( rRoot, cBuiltIn, EXC_STR_8BITLENGTH );
     240           0 :         ::set_flag( mnFlags, EXC_NAME_BUILTIN );
     241             :     }
     242           0 : }
     243             : 
     244           0 : void XclExpName::SetTokenArray( XclTokenArrayRef xTokArr )
     245             : {
     246           0 :     mxTokArr = xTokArr;
     247           0 : }
     248             : 
     249           0 : void XclExpName::SetLocalTab( SCTAB nScTab )
     250             : {
     251             :     OSL_ENSURE( GetTabInfo().IsExportTab( nScTab ), "XclExpName::SetLocalTab - invalid sheet index" );
     252           0 :     if( GetTabInfo().IsExportTab( nScTab ) )
     253             :     {
     254           0 :         mnScTab = nScTab;
     255           0 :         GetGlobalLinkManager().FindExtSheet( mnExtSheet, mnXclTab, nScTab );
     256             : 
     257             :         // special handling for NAME record
     258           0 :         switch( GetBiff() )
     259             :         {
     260             :             case EXC_BIFF5: // EXTERNSHEET index is positive in NAME record
     261           0 :                 mnExtSheet = ~mnExtSheet + 1;
     262           0 :             break;
     263             :             case EXC_BIFF8: // EXTERNSHEET index not used, but must be created in link table
     264           0 :                 mnExtSheet = 0;
     265           0 :             break;
     266             :             default:    DBG_ERROR_BIFF();
     267             :         }
     268             : 
     269             :         // Excel sheet index is 1-based
     270           0 :         ++mnXclTab;
     271             :     }
     272           0 : }
     273             : 
     274           0 : void XclExpName::SetHidden( bool bHidden )
     275             : {
     276           0 :     ::set_flag( mnFlags, EXC_NAME_HIDDEN, bHidden );
     277           0 : }
     278             : 
     279           0 : void XclExpName::SetMacroCall( bool bVBasic, bool bFunc )
     280             : {
     281           0 :     ::set_flag( mnFlags, EXC_NAME_PROC );
     282           0 :     ::set_flag( mnFlags, EXC_NAME_VB, bVBasic );
     283           0 :     ::set_flag( mnFlags, EXC_NAME_FUNC, bFunc );
     284           0 : }
     285             : 
     286           0 : void XclExpName::SetSymbol( String sSymbol )
     287             : {
     288           0 :     msSymbol = sSymbol;
     289           0 : }
     290             : 
     291           0 : bool XclExpName::IsVolatile() const
     292             : {
     293           0 :     return mxTokArr && mxTokArr->IsVolatile();
     294             : }
     295             : 
     296           0 : bool XclExpName::IsMacroCall( bool bVBasic, bool bFunc ) const
     297             : {
     298             :     return
     299           0 :         (::get_flag( mnFlags, EXC_NAME_VB ) == bVBasic) &&
     300           0 :         (::get_flag( mnFlags, EXC_NAME_FUNC ) == bFunc);
     301             : }
     302             : 
     303           0 : void XclExpName::Save( XclExpStream& rStrm )
     304             : {
     305             :     OSL_ENSURE( mxName && (mxName->Len() > 0), "XclExpName::Save - missing name" );
     306             :     OSL_ENSURE( !(IsGlobal() && ::get_flag( mnFlags, EXC_NAME_BUILTIN )), "XclExpName::Save - global built-in name" );
     307           0 :     SetRecSize( 11 + mxName->GetSize() + (mxTokArr ? mxTokArr->GetSize() : 2) );
     308           0 :     XclExpRecord::Save( rStrm );
     309           0 : }
     310             : 
     311           0 : void XclExpName::SaveXml( XclExpXmlStream& rStrm )
     312             : {
     313           0 :     sax_fastparser::FSHelperPtr& rWorkbook = rStrm.GetCurrentStream();
     314             :     rWorkbook->startElement( XML_definedName,
     315             :             // OOXTODO: XML_comment, "",
     316             :             // OOXTODO: XML_customMenu, "",
     317             :             // OOXTODO: XML_description, "",
     318           0 :             XML_function, XclXmlUtils::ToPsz( ::get_flag( mnFlags, EXC_NAME_VB ) ),
     319             :             // OOXTODO: XML_functionGroupId, "",
     320             :             // OOXTODO: XML_help, "",
     321           0 :             XML_hidden, XclXmlUtils::ToPsz( ::get_flag( mnFlags, EXC_NAME_HIDDEN ) ),
     322           0 :             XML_localSheetId, mnScTab == SCTAB_GLOBAL ? NULL : OString::valueOf( (sal_Int32)mnScTab ).getStr(),
     323             :             XML_name, XclXmlUtils::ToOString( maOrigName ).getStr(),
     324             :             // OOXTODO: XML_publishToServer, "",
     325             :             // OOXTODO: XML_shortcutKey, "",
     326             :             // OOXTODO: XML_statusBar, "",
     327           0 :             XML_vbProcedure, XclXmlUtils::ToPsz( ::get_flag( mnFlags, EXC_NAME_VB ) ),
     328             :             // OOXTODO: XML_workbookParameter, "",
     329             :             // OOXTODO: XML_xlm, "",
     330           0 :             FSEND );
     331           0 :     rWorkbook->writeEscaped( XclXmlUtils::ToOUString( msSymbol ) );
     332           0 :     rWorkbook->endElement( XML_definedName );
     333           0 : }
     334             : 
     335           0 : void XclExpName::WriteBody( XclExpStream& rStrm )
     336             : {
     337           0 :     sal_uInt16 nFmlaSize = mxTokArr ? mxTokArr->GetSize() : 0;
     338             : 
     339           0 :     rStrm   << mnFlags                  // flags
     340           0 :             << sal_uInt8( 0 );          // keyboard shortcut
     341           0 :     mxName->WriteLenField( rStrm );     // length of name
     342           0 :     rStrm   << nFmlaSize                // size of token array
     343           0 :             << mnExtSheet               // BIFF5/7: EXTSHEET index, BIFF8: not used
     344           0 :             << mnXclTab                 // 1-based sheet index for local names
     345           0 :             << sal_uInt32( 0 );         // length of menu/descr/help/status text
     346           0 :     mxName->WriteFlagField( rStrm );    // BIFF8 flag field (no-op in <=BIFF7)
     347           0 :     mxName->WriteBuffer( rStrm );       // character array of the name
     348           0 :     if( mxTokArr )
     349           0 :         mxTokArr->WriteArray( rStrm );  // token array without size
     350           0 : }
     351             : 
     352             : // ----------------------------------------------------------------------------
     353             : 
     354           9 : XclExpNameManagerImpl::XclExpNameManagerImpl( const XclExpRoot& rRoot ) :
     355             :     XclExpRoot( rRoot ),
     356           9 :     mnFirstUserIdx( 0 )
     357             : {
     358           9 : }
     359             : 
     360           9 : void XclExpNameManagerImpl::Initialize()
     361             : {
     362           9 :     CreateBuiltInNames();
     363           9 :     mnFirstUserIdx = maNameList.GetSize();
     364           9 :     CreateUserNames();
     365           9 : }
     366             : 
     367           0 : sal_uInt16 XclExpNameManagerImpl::InsertName( SCTAB nTab, sal_uInt16 nScNameIdx )
     368             : {
     369           0 :     sal_uInt16 nNameIdx = FindNamedExpIndex( nTab, nScNameIdx );
     370           0 :     if (nNameIdx)
     371           0 :         return nNameIdx;
     372             : 
     373           0 :     const ScRangeData* pData = NULL;
     374           0 :     ScRangeName* pRN = (nTab == SCTAB_GLOBAL) ? GetDoc().GetRangeName() : GetDoc().GetRangeName(nTab);
     375           0 :     if (pRN)
     376           0 :         pData = pRN->findByIndex(nScNameIdx);
     377             : 
     378           0 :     if (pData)
     379           0 :         nNameIdx = CreateName(nTab, *pData);
     380             : 
     381           0 :     return nNameIdx;
     382             : }
     383             : 
     384           0 : sal_uInt16 XclExpNameManagerImpl::InsertBuiltInName( sal_Unicode cBuiltIn, XclTokenArrayRef xTokArr, const ScRange& aRange )
     385             : {
     386           0 :     XclExpNameRef xName( new XclExpName( GetRoot(), cBuiltIn ) );
     387           0 :     xName->SetTokenArray( xTokArr );
     388           0 :     xName->SetLocalTab( aRange.aStart.Tab() );
     389           0 :     String sSymbol;
     390           0 :     aRange.Format( sSymbol, SCR_ABS_3D, GetDocPtr(), ScAddress::Details( ::formula::FormulaGrammar::CONV_XL_A1 ) );
     391           0 :     xName->SetSymbol( sSymbol );
     392           0 :     return Append( xName );
     393             : }
     394             : 
     395           0 : sal_uInt16 XclExpNameManagerImpl::InsertBuiltInName( sal_Unicode cBuiltIn, XclTokenArrayRef xTokArr, SCTAB nScTab, const ScRangeList& rRangeList )
     396             : {
     397           0 :     XclExpNameRef xName( new XclExpName( GetRoot(), cBuiltIn ) );
     398           0 :     xName->SetTokenArray( xTokArr );
     399           0 :     xName->SetLocalTab( nScTab );
     400           0 :     String sSymbol;
     401           0 :     rRangeList.Format( sSymbol, SCR_ABS_3D, GetDocPtr(), ::formula::FormulaGrammar::CONV_XL_A1 );
     402           0 :     xName->SetSymbol( sSymbol );
     403           0 :     return Append( xName );
     404             : }
     405             : 
     406           0 : sal_uInt16 XclExpNameManagerImpl::InsertUniqueName(
     407             :         const String& rName, XclTokenArrayRef xTokArr, SCTAB nScTab )
     408             : {
     409             :     OSL_ENSURE( rName.Len(), "XclExpNameManagerImpl::InsertUniqueName - empty name" );
     410           0 :     XclExpNameRef xName( new XclExpName( GetRoot(), GetUnusedName( rName ) ) );
     411           0 :     xName->SetTokenArray( xTokArr );
     412           0 :     xName->SetLocalTab( nScTab );
     413           0 :     return Append( xName );
     414             : }
     415             : 
     416           0 : sal_uInt16 XclExpNameManagerImpl::InsertRawName( const String& rName )
     417             : {
     418             :     // empty name? may occur in broken external Calc tokens
     419           0 :     if( !rName.Len() )
     420           0 :         return 0;
     421             : 
     422             :     // try to find an existing NAME record, regardless of its type
     423           0 :     for( size_t nListIdx = mnFirstUserIdx, nListSize = maNameList.GetSize(); nListIdx < nListSize; ++nListIdx )
     424             :     {
     425           0 :         XclExpNameRef xName = maNameList.GetRecord( nListIdx );
     426           0 :         if( xName->IsGlobal() && (xName->GetOrigName() == rName) )
     427           0 :             return static_cast< sal_uInt16 >( nListIdx + 1 );
     428           0 :     }
     429             : 
     430             :     // create a new NAME record
     431           0 :     XclExpNameRef xName( new XclExpName( GetRoot(), rName ) );
     432           0 :     return Append( xName );
     433             : }
     434             : 
     435           0 : sal_uInt16 XclExpNameManagerImpl::InsertMacroCall( const String& rMacroName, bool bVBasic, bool bFunc, bool bHidden )
     436             : {
     437             :     // empty name? may occur in broken external Calc tokens
     438           0 :     if( !rMacroName.Len() )
     439           0 :         return 0;
     440             : 
     441             :     // try to find an existing NAME record
     442           0 :     for( size_t nListIdx = mnFirstUserIdx, nListSize = maNameList.GetSize(); nListIdx < nListSize; ++nListIdx )
     443             :     {
     444           0 :         XclExpNameRef xName = maNameList.GetRecord( nListIdx );
     445           0 :         if( xName->IsMacroCall( bVBasic, bFunc ) && (xName->GetOrigName() == rMacroName) )
     446           0 :             return static_cast< sal_uInt16 >( nListIdx + 1 );
     447           0 :     }
     448             : 
     449             :     // create a new NAME record
     450           0 :     XclExpNameRef xName( new XclExpName( GetRoot(), rMacroName ) );
     451           0 :     xName->SetMacroCall( bVBasic, bFunc );
     452           0 :     xName->SetHidden( bHidden );
     453             : 
     454             :     // for sheet macros, add a #NAME! error
     455           0 :     if( !bVBasic )
     456           0 :         xName->SetTokenArray( GetFormulaCompiler().CreateErrorFormula( EXC_ERR_NAME ) );
     457             : 
     458           0 :     return Append( xName );
     459             : }
     460             : 
     461           0 : const XclExpName* XclExpNameManagerImpl::GetName( sal_uInt16 nNameIdx ) const
     462             : {
     463             :     OSL_ENSURE( maNameList.HasRecord( nNameIdx - 1 ), "XclExpNameManagerImpl::GetName - wrong record index" );
     464           0 :     return maNameList.GetRecord( nNameIdx - 1 ).get();
     465             : }
     466             : 
     467           3 : void XclExpNameManagerImpl::Save( XclExpStream& rStrm )
     468             : {
     469           3 :     maNameList.Save( rStrm );
     470           3 : }
     471             : 
     472           6 : void XclExpNameManagerImpl::SaveXml( XclExpXmlStream& rStrm )
     473             : {
     474           6 :     if( maNameList.IsEmpty() )
     475          12 :         return;
     476           0 :     sax_fastparser::FSHelperPtr& rWorkbook = rStrm.GetCurrentStream();
     477           0 :     rWorkbook->startElement( XML_definedNames, FSEND );
     478           0 :     maNameList.SaveXml( rStrm );
     479           0 :     rWorkbook->endElement( XML_definedNames );
     480             : }
     481             : 
     482             : // private --------------------------------------------------------------------
     483             : 
     484           0 : sal_uInt16 XclExpNameManagerImpl::FindNamedExpIndex( SCTAB nTab, sal_uInt16 nScIdx )
     485             : {
     486           0 :     NamedExpIndexMap::key_type key = NamedExpIndexMap::key_type(nTab, nScIdx);
     487           0 :     NamedExpIndexMap::const_iterator itr = maNamedExpMap.find(key);
     488           0 :     return (itr == maNamedExpMap.end()) ? 0 : itr->second;
     489             : }
     490             : 
     491           0 : sal_uInt16 XclExpNameManagerImpl::FindBuiltInNameIdx(
     492             :         const String& rName, const XclTokenArray& rTokArr, bool bDBRange ) const
     493             : {
     494             :     /*  Get built-in index from the name. Special case: the database range
     495             :         'unnamed' will be mapped to Excel's built-in '_FilterDatabase' name. */
     496           0 :     sal_Unicode cBuiltIn = (bDBRange && (rName == String(RTL_CONSTASCII_USTRINGPARAM(STR_DB_LOCAL_NONAME)))) ?
     497           0 :         EXC_BUILTIN_FILTERDATABASE : XclTools::GetBuiltInDefNameIndex( rName );
     498             : 
     499           0 :     if( cBuiltIn < EXC_BUILTIN_UNKNOWN )
     500             :     {
     501             :         // try to find the record in existing built-in NAME record list
     502           0 :         for( size_t nPos = 0; nPos < mnFirstUserIdx; ++nPos )
     503             :         {
     504           0 :             XclExpNameRef xName = maNameList.GetRecord( nPos );
     505           0 :             if( xName->GetBuiltInName() == cBuiltIn )
     506             :             {
     507           0 :                 XclTokenArrayRef xTokArr = xName->GetTokenArray();
     508           0 :                 if( xTokArr && (*xTokArr == rTokArr) )
     509           0 :                     return static_cast< sal_uInt16 >( nPos + 1 );
     510             :             }
     511           0 :         }
     512             :     }
     513           0 :     return 0;
     514             : }
     515             : 
     516           0 : String XclExpNameManagerImpl::GetUnusedName( const String& rName ) const
     517             : {
     518           0 :     String aNewName( rName );
     519           0 :     sal_Int32 nAppIdx = 0;
     520           0 :     bool bExist = true;
     521           0 :     while( bExist )
     522             :     {
     523             :         // search the list of user-defined names
     524           0 :         bExist = false;
     525           0 :         for( size_t nPos = mnFirstUserIdx, nSize = maNameList.GetSize(); !bExist && (nPos < nSize); ++nPos )
     526             :         {
     527           0 :             XclExpNameRef xName = maNameList.GetRecord( nPos );
     528           0 :             bExist = xName->GetOrigName() == aNewName;
     529             :             // name exists -> create a new name "<originalname>_<counter>"
     530           0 :             if( bExist )
     531           0 :                 aNewName.Assign( rName ).Append( '_' ).Append( OUString::number( ++nAppIdx ) );
     532           0 :         }
     533             :     }
     534           0 :     return aNewName;
     535             : }
     536             : 
     537           0 : sal_uInt16 XclExpNameManagerImpl::Append( XclExpNameRef xName )
     538             : {
     539           0 :     if( maNameList.GetSize() == 0xFFFF )
     540           0 :         return 0;
     541           0 :     maNameList.AppendRecord( xName );
     542           0 :     return static_cast< sal_uInt16 >( maNameList.GetSize() );  // 1-based
     543             : }
     544             : 
     545           0 : sal_uInt16 XclExpNameManagerImpl::CreateName( SCTAB nTab, const ScRangeData& rRangeData )
     546             : {
     547           0 :     const String& rName = rRangeData.GetName();
     548             : 
     549             :     /*  #i38821# recursive names: first insert the (empty) name object,
     550             :         otherwise a recursive call of this function from the formula compiler
     551             :         with the same defined name will not find it and will create it again. */
     552           0 :     size_t nOldListSize = maNameList.GetSize();
     553           0 :     XclExpNameRef xName( new XclExpName( GetRoot(), rName ) );
     554           0 :     if (nTab != SCTAB_GLOBAL)
     555           0 :         xName->SetLocalTab(nTab);
     556           0 :     sal_uInt16 nNameIdx = Append( xName );
     557             :     // store the index of the NAME record in the lookup map
     558           0 :     NamedExpIndexMap::key_type key = NamedExpIndexMap::key_type(nTab, rRangeData.GetIndex());
     559           0 :     maNamedExpMap[key] = nNameIdx;
     560             : 
     561             :     /*  Create the definition formula.
     562             :         This may cause recursive creation of other defined names. */
     563           0 :     if( const ScTokenArray* pScTokArr = const_cast< ScRangeData& >( rRangeData ).GetCode() )
     564             :     {
     565           0 :         XclTokenArrayRef xTokArr = GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_NAME, *pScTokArr );
     566           0 :         xName->SetTokenArray( xTokArr );
     567             : 
     568           0 :         String sSymbol;
     569           0 :         rRangeData.GetSymbol( sSymbol, formula::FormulaGrammar::GRAM_ENGLISH_XL_A1 );
     570           0 :         xName->SetSymbol( sSymbol );
     571             : 
     572             :         /*  Try to replace by existing built-in name - complete token array is
     573             :             needed for comparison, and due to the recursion problem above this
     574             :             cannot be done earlier. If a built-in name is found, the created NAME
     575             :             record for this name and all following records in the list must be
     576             :             deleted, otherwise they may contain wrong name list indexes. */
     577           0 :         sal_uInt16 nBuiltInIdx = FindBuiltInNameIdx( rName, *xTokArr, false );
     578           0 :         if( nBuiltInIdx != 0 )
     579             :         {
     580             :             // delete the new NAME records
     581           0 :             while( maNameList.GetSize() > nOldListSize )
     582           0 :                 maNameList.RemoveRecord( maNameList.GetSize() - 1 );
     583             :             // use index of the found built-in NAME record
     584           0 :             key = NamedExpIndexMap::key_type(nTab, rRangeData.GetIndex());
     585           0 :             maNamedExpMap[key] = nNameIdx = nBuiltInIdx;
     586           0 :         }
     587             :     }
     588             : 
     589           0 :     return nNameIdx;
     590             : }
     591             : 
     592           9 : void XclExpNameManagerImpl::CreateBuiltInNames()
     593             : {
     594           9 :     ScDocument& rDoc = GetDoc();
     595           9 :     XclExpTabInfo& rTabInfo = GetTabInfo();
     596             : 
     597             :     /*  #i2394# built-in defined names must be sorted by the name of the
     598             :         containing sheet. Example: SheetA!Print_Range must be stored *before*
     599             :         SheetB!Print_Range, regardless of the position of SheetA in the document! */
     600          23 :     for( SCTAB nScTabIdx = 0, nScTabCount = rTabInfo.GetScTabCount(); nScTabIdx < nScTabCount; ++nScTabIdx )
     601             :     {
     602             :         // find real sheet index from the nScTabIdx counter
     603          14 :         SCTAB nScTab = rTabInfo.GetRealScTab( nScTabIdx );
     604             :         // create NAME records for all built-in names of this sheet
     605          14 :         if( rTabInfo.IsExportTab( nScTab ) )
     606             :         {
     607             :             // *** 1) print ranges *** ----------------------------------------
     608             : 
     609          14 :             if( rDoc.HasPrintRange() )
     610             :             {
     611          14 :                 ScRangeList aRangeList;
     612          14 :                 for( sal_uInt16 nIdx = 0, nCount = rDoc.GetPrintRangeCount( nScTab ); nIdx < nCount; ++nIdx )
     613             :                 {
     614           0 :                     ScRange aRange( *rDoc.GetPrintRange( nScTab, nIdx ) );
     615             :                     // Calc document does not care about sheet index in print ranges
     616           0 :                     aRange.aStart.SetTab( nScTab );
     617           0 :                     aRange.aEnd.SetTab( nScTab );
     618           0 :                     aRange.Justify();
     619           0 :                     aRangeList.Append( aRange );
     620             :                 }
     621             :                 // create the NAME record (do not warn if ranges are shrunken)
     622          14 :                 GetAddressConverter().ValidateRangeList( aRangeList, false );
     623          14 :                 if( !aRangeList.empty() )
     624           0 :                     GetNameManager().InsertBuiltInName( EXC_BUILTIN_PRINTAREA, aRangeList );
     625             :             }
     626             : 
     627             :             // *** 2) print titles *** ----------------------------------------
     628             : 
     629          14 :             ScRangeList aTitleList;
     630             :             // repeated columns
     631          14 :             if( const ScRange* pColRange = rDoc.GetRepeatColRange( nScTab ) )
     632             :                 aTitleList.Append( ScRange(
     633           0 :                     pColRange->aStart.Col(), 0, nScTab,
     634           0 :                     pColRange->aEnd.Col(), GetXclMaxPos().Row(), nScTab ) );
     635             :             // repeated rows
     636          14 :             if( const ScRange* pRowRange = rDoc.GetRepeatRowRange( nScTab ) )
     637             :                 aTitleList.Append( ScRange(
     638             :                     0, pRowRange->aStart.Row(), nScTab,
     639           0 :                     GetXclMaxPos().Col(), pRowRange->aEnd.Row(), nScTab ) );
     640             :             // create the NAME record
     641          14 :             GetAddressConverter().ValidateRangeList( aTitleList, false );
     642          14 :             if( !aTitleList.empty() )
     643           0 :                 GetNameManager().InsertBuiltInName( EXC_BUILTIN_PRINTTITLES, aTitleList );
     644             : 
     645             :             // *** 3) filter ranges *** ---------------------------------------
     646             : 
     647          14 :             if( GetBiff() == EXC_BIFF8 )
     648          14 :                 GetFilterManager().InitTabFilter( nScTab );
     649             :         }
     650             :     }
     651           9 : }
     652             : 
     653           9 : void XclExpNameManagerImpl::CreateUserNames()
     654             : {
     655           9 :     const ScRangeName& rNamedRanges = GetNamedRanges();
     656           9 :     ScRangeName::const_iterator itr = rNamedRanges.begin(), itrEnd = rNamedRanges.end();
     657           9 :     for (; itr != itrEnd; ++itr)
     658             :     {
     659             :         // skip definitions of shared formulas
     660           0 :         if (!itr->second->HasType(RT_SHARED) && !FindNamedExpIndex(SCTAB_GLOBAL, itr->second->GetIndex()))
     661           0 :             CreateName(SCTAB_GLOBAL, *itr->second);
     662             :     }
     663             :     //look at every sheet for local range names
     664           9 :     ScRangeName::TabNameCopyMap rLocalNames;
     665           9 :     GetDoc().GetAllTabRangeNames(rLocalNames);
     666           9 :     ScRangeName::TabNameCopyMap::iterator tabIt = rLocalNames.begin(), tabItEnd = rLocalNames.end();
     667           9 :     for (; tabIt != tabItEnd; ++tabIt)
     668             :     {
     669           0 :         itr = tabIt->second->begin(), itrEnd = tabIt->second->end();
     670           0 :         for (; itr != itrEnd; ++itr)
     671             :         {
     672             :             // skip definitions of shared formulas
     673           0 :             if (!itr->second->HasType(RT_SHARED) && !FindNamedExpIndex(tabIt->first, itr->second->GetIndex()))
     674           0 :                 CreateName(tabIt->first, *itr->second);
     675             :         }
     676           9 :     }
     677           9 : }
     678             : 
     679             : // ----------------------------------------------------------------------------
     680             : 
     681           9 : XclExpNameManager::XclExpNameManager( const XclExpRoot& rRoot ) :
     682             :     XclExpRoot( rRoot ),
     683           9 :     mxImpl( new XclExpNameManagerImpl( rRoot ) )
     684             : {
     685           9 : }
     686             : 
     687          18 : XclExpNameManager::~XclExpNameManager()
     688             : {
     689          18 : }
     690             : 
     691           9 : void XclExpNameManager::Initialize()
     692             : {
     693           9 :     mxImpl->Initialize();
     694           9 : }
     695             : 
     696           0 : sal_uInt16 XclExpNameManager::InsertName( SCTAB nTab, sal_uInt16 nScNameIdx )
     697             : {
     698           0 :     return mxImpl->InsertName( nTab, nScNameIdx );
     699             : }
     700             : 
     701           0 : sal_uInt16 XclExpNameManager::InsertBuiltInName( sal_Unicode cBuiltIn, const ScRange& rRange )
     702             : {
     703           0 :     XclTokenArrayRef xTokArr = GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_NAME, rRange );
     704           0 :     return mxImpl->InsertBuiltInName( cBuiltIn, xTokArr, rRange );
     705             : }
     706             : 
     707           0 : sal_uInt16 XclExpNameManager::InsertBuiltInName( sal_Unicode cBuiltIn, const ScRangeList& rRangeList )
     708             : {
     709           0 :     sal_uInt16 nNameIdx = 0;
     710           0 :     if( !rRangeList.empty() )
     711             :     {
     712           0 :         XclTokenArrayRef xTokArr = GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_NAME, rRangeList );
     713           0 :         nNameIdx = mxImpl->InsertBuiltInName( cBuiltIn, xTokArr, rRangeList.front()->aStart.Tab(), rRangeList );
     714             :     }
     715           0 :     return nNameIdx;
     716             : }
     717             : 
     718           0 : sal_uInt16 XclExpNameManager::InsertUniqueName(
     719             :         const String& rName, XclTokenArrayRef xTokArr, SCTAB nScTab )
     720             : {
     721           0 :     return mxImpl->InsertUniqueName( rName, xTokArr, nScTab );
     722             : }
     723             : 
     724           0 : sal_uInt16 XclExpNameManager::InsertRawName( const String& rName )
     725             : {
     726           0 :     return mxImpl->InsertRawName( rName );
     727             : }
     728             : 
     729           0 : sal_uInt16 XclExpNameManager::InsertMacroCall( const String& rMacroName, bool bVBasic, bool bFunc, bool bHidden )
     730             : {
     731           0 :     return mxImpl->InsertMacroCall( rMacroName, bVBasic, bFunc, bHidden );
     732             : }
     733             : 
     734           0 : const String& XclExpNameManager::GetOrigName( sal_uInt16 nNameIdx ) const
     735             : {
     736           0 :     const XclExpName* pName = mxImpl->GetName( nNameIdx );
     737           0 :     return pName ? pName->GetOrigName() : EMPTY_STRING;
     738             : }
     739             : 
     740           0 : SCTAB XclExpNameManager::GetScTab( sal_uInt16 nNameIdx ) const
     741             : {
     742           0 :     const XclExpName* pName = mxImpl->GetName( nNameIdx );
     743           0 :     return pName ? pName->GetScTab() : SCTAB_GLOBAL;
     744             : }
     745             : 
     746           0 : bool XclExpNameManager::IsVolatile( sal_uInt16 nNameIdx ) const
     747             : {
     748           0 :     const XclExpName* pName = mxImpl->GetName( nNameIdx );
     749           0 :     return pName && pName->IsVolatile();
     750             : }
     751             : 
     752           3 : void XclExpNameManager::Save( XclExpStream& rStrm )
     753             : {
     754           3 :     mxImpl->Save( rStrm );
     755           3 : }
     756             : 
     757           6 : void XclExpNameManager::SaveXml( XclExpXmlStream& rStrm )
     758             : {
     759           6 :     mxImpl->SaveXml( rStrm );
     760          21 : }
     761             : 
     762             : // ============================================================================
     763             : 
     764             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10