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

Generated by: LCOV version 1.11