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

Generated by: LCOV version 1.10