LCOV - code coverage report
Current view: top level - sc/source/filter/excel - xename.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 300 0.0 %
Date: 2014-04-14 Functions: 0 56 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10