LCOV - code coverage report
Current view: top level - sc/source/ui/unoobj - funcuno.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 2 313 0.6 %
Date: 2012-08-25 Functions: 1 66 1.5 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 624 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 :            : /*************************************************************************
       3                 :            :  *
       4                 :            :  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       5                 :            :  *
       6                 :            :  * Copyright 2000, 2010 Oracle and/or its affiliates.
       7                 :            :  *
       8                 :            :  * OpenOffice.org - a multi-platform office productivity suite
       9                 :            :  *
      10                 :            :  * This file is part of OpenOffice.org.
      11                 :            :  *
      12                 :            :  * OpenOffice.org is free software: you can redistribute it and/or modify
      13                 :            :  * it under the terms of the GNU Lesser General Public License version 3
      14                 :            :  * only, as published by the Free Software Foundation.
      15                 :            :  *
      16                 :            :  * OpenOffice.org is distributed in the hope that it will be useful,
      17                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      18                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19                 :            :  * GNU Lesser General Public License version 3 for more details
      20                 :            :  * (a copy is included in the LICENSE file that accompanied this code).
      21                 :            :  *
      22                 :            :  * You should have received a copy of the GNU Lesser General Public License
      23                 :            :  * version 3 along with OpenOffice.org.  If not, see
      24                 :            :  * <http://www.openoffice.org/license.html>
      25                 :            :  * for a copy of the LGPLv3 License.
      26                 :            :  *
      27                 :            :  ************************************************************************/
      28                 :            : 
      29                 :            : #include <sfx2/app.hxx>
      30                 :            : #include <svl/itemprop.hxx>
      31                 :            : 
      32                 :            : #include "scitems.hxx"
      33                 :            : #include "funcuno.hxx"
      34                 :            : #include "miscuno.hxx"
      35                 :            : #include "cellsuno.hxx"
      36                 :            : #include "scdll.hxx"
      37                 :            : #include "document.hxx"
      38                 :            : #include "compiler.hxx"
      39                 :            : #include "formula/errorcodes.hxx"
      40                 :            : #include "callform.hxx"
      41                 :            : #include "addincol.hxx"
      42                 :            : #include "rangeseq.hxx"
      43                 :            : #include "cell.hxx"
      44                 :            : #include "docoptio.hxx"
      45                 :            : #include "optuno.hxx"
      46                 :            : #include <docuno.hxx>
      47                 :            : // for lcl_CopyData:
      48                 :            : #include "markdata.hxx"
      49                 :            : #include "patattr.hxx"
      50                 :            : #include "docpool.hxx"
      51                 :            : #include "attrib.hxx"
      52                 :            : #include "clipparam.hxx"
      53                 :            : #include "dociter.hxx"
      54                 :            : 
      55                 :            : using namespace com::sun::star;
      56                 :            : 
      57                 :            : //------------------------------------------------------------------------
      58                 :            : 
      59                 :            : //  registered as implementation for service FunctionAccess,
      60                 :            : //  also supports service SpreadsheetDocumentSettings (to set null date etc.)
      61                 :            : 
      62                 :            : #define SCFUNCTIONACCESS_SERVICE    "com.sun.star.sheet.FunctionAccess"
      63                 :            : #define SCDOCSETTINGS_SERVICE       "com.sun.star.sheet.SpreadsheetDocumentSettings"
      64                 :            : 
      65                 :            : //------------------------------------------------------------------------
      66                 :            : 
      67                 :            : // helper to use cached document if not in use, temporary document otherwise
      68                 :            : 
      69                 :            : class ScTempDocSource
      70                 :            : {
      71                 :            : private:
      72                 :            :     ScTempDocCache& rCache;
      73                 :            :     ScDocument*     pTempDoc;
      74                 :            : 
      75                 :            :     static ScDocument*  CreateDocument();       // create and initialize doc
      76                 :            : 
      77                 :            : public:
      78                 :            :                 ScTempDocSource( ScTempDocCache& rDocCache );
      79                 :            :                 ~ScTempDocSource();
      80                 :            : 
      81                 :            :     ScDocument*     GetDocument();
      82                 :            : };
      83                 :            : 
      84                 :            : //------------------------------------------------------------------------
      85                 :            : 
      86                 :          0 : ScDocument* ScTempDocSource::CreateDocument()
      87                 :            : {
      88         [ #  # ]:          0 :     ScDocument* pDoc = new ScDocument;                  // SCDOCMODE_DOCUMENT
      89                 :          0 :     pDoc->MakeTable( 0 );
      90                 :          0 :     return pDoc;
      91                 :            : }
      92                 :            : 
      93                 :          0 : ScTempDocSource::ScTempDocSource( ScTempDocCache& rDocCache ) :
      94                 :            :     rCache( rDocCache ),
      95                 :          0 :     pTempDoc( NULL )
      96                 :            : {
      97         [ #  # ]:          0 :     if ( rCache.IsInUse() )
      98                 :          0 :         pTempDoc = CreateDocument();
      99                 :            :     else
     100                 :            :     {
     101                 :          0 :         rCache.SetInUse( sal_True );
     102         [ #  # ]:          0 :         if ( !rCache.GetDocument() )
     103                 :          0 :             rCache.SetDocument( CreateDocument() );
     104                 :            :     }
     105                 :          0 : }
     106                 :            : 
     107                 :          0 : ScTempDocSource::~ScTempDocSource()
     108                 :            : {
     109         [ #  # ]:          0 :     if ( pTempDoc )
     110         [ #  # ]:          0 :         delete pTempDoc;
     111                 :            :     else
     112                 :          0 :         rCache.SetInUse( false );
     113                 :          0 : }
     114                 :            : 
     115                 :          0 : ScDocument* ScTempDocSource::GetDocument()
     116                 :            : {
     117         [ #  # ]:          0 :     if ( pTempDoc )
     118                 :          0 :         return pTempDoc;
     119                 :            :     else
     120                 :          0 :         return rCache.GetDocument();
     121                 :            : }
     122                 :            : 
     123                 :            : //------------------------------------------------------------------------
     124                 :            : 
     125                 :          0 : ScTempDocCache::ScTempDocCache() :
     126                 :            :     pDoc( NULL ),
     127                 :          0 :     bInUse( false )
     128                 :            : {
     129                 :          0 : }
     130                 :            : 
     131                 :          0 : ScTempDocCache::~ScTempDocCache()
     132                 :            : {
     133                 :            :     OSL_ENSURE( !bInUse, "ScTempDocCache dtor: bInUse" );
     134         [ #  # ]:          0 :     delete pDoc;
     135                 :          0 : }
     136                 :            : 
     137                 :          0 : void ScTempDocCache::SetDocument( ScDocument* pNew )
     138                 :            : {
     139                 :            :     OSL_ENSURE( !pDoc, "ScTempDocCache::SetDocument: already set" );
     140                 :          0 :     pDoc = pNew;
     141                 :          0 : }
     142                 :            : 
     143                 :          0 : void ScTempDocCache::Clear()
     144                 :            : {
     145                 :            :     OSL_ENSURE( !bInUse, "ScTempDocCache::Clear: bInUse" );
     146         [ #  # ]:          0 :     delete pDoc;
     147                 :          0 :     pDoc = NULL;
     148                 :          0 : }
     149                 :            : 
     150                 :            : //------------------------------------------------------------------------
     151                 :            : 
     152                 :            : //  copy results from one document into another
     153                 :            : //! merge this with ScAreaLink::Refresh
     154                 :            : //! copy directly without a clipboard document?
     155                 :            : 
     156                 :          0 : sal_Bool lcl_CopyData( ScDocument* pSrcDoc, const ScRange& rSrcRange,
     157                 :            :                     ScDocument* pDestDoc, const ScAddress& rDestPos )
     158                 :            : {
     159                 :          0 :     SCTAB nSrcTab = rSrcRange.aStart.Tab();
     160                 :          0 :     SCTAB nDestTab = rDestPos.Tab();
     161                 :            : 
     162                 :            :     ScRange aNewRange( rDestPos, ScAddress(
     163                 :          0 :                 rSrcRange.aEnd.Col() - rSrcRange.aStart.Col() + rDestPos.Col(),
     164                 :          0 :                 rSrcRange.aEnd.Row() - rSrcRange.aStart.Row() + rDestPos.Row(),
     165                 :          0 :                 nDestTab ) );
     166                 :            : 
     167 [ #  # ][ #  # ]:          0 :     ScDocument* pClipDoc = new ScDocument( SCDOCMODE_CLIP );
     168         [ #  # ]:          0 :     ScMarkData aSourceMark;
     169         [ #  # ]:          0 :     aSourceMark.SelectOneTable( nSrcTab );      // for CopyToClip
     170         [ #  # ]:          0 :     aSourceMark.SetMarkArea( rSrcRange );
     171         [ #  # ]:          0 :     ScClipParam aClipParam(rSrcRange, false);
     172         [ #  # ]:          0 :     pSrcDoc->CopyToClip(aClipParam, pClipDoc, &aSourceMark, false);
     173                 :            : 
     174 [ #  # ][ #  # ]:          0 :     if ( pClipDoc->HasAttrib( 0,0,nSrcTab, MAXCOL,MAXROW,nSrcTab,
     175                 :          0 :                                 HASATTR_MERGED | HASATTR_OVERLAPPED ) )
     176                 :            :     {
     177 [ #  # ][ #  # ]:          0 :         ScPatternAttr aPattern( pSrcDoc->GetPool() );
     178 [ #  # ][ #  # ]:          0 :         aPattern.GetItemSet().Put( ScMergeAttr() );             // Defaults
                 [ #  # ]
     179 [ #  # ][ #  # ]:          0 :         aPattern.GetItemSet().Put( ScMergeFlagAttr() );
                 [ #  # ]
     180 [ #  # ][ #  # ]:          0 :         pClipDoc->ApplyPatternAreaTab( 0,0, MAXCOL,MAXROW, nSrcTab, aPattern );
     181                 :            :     }
     182                 :            : 
     183                 :            :     // If the range contains formula cells with default number format,
     184                 :            :     // apply a number format for the formula result
     185         [ #  # ]:          0 :     ScCellIterator aIter( pClipDoc, rSrcRange );
     186         [ #  # ]:          0 :     ScBaseCell* pCell = aIter.GetFirst();
     187         [ #  # ]:          0 :     while (pCell)
     188                 :            :     {
     189         [ #  # ]:          0 :         if (pCell->GetCellType() == CELLTYPE_FORMULA)
     190                 :            :         {
     191                 :          0 :             ScAddress aCellPos = aIter.GetPos();
     192         [ #  # ]:          0 :             sal_uInt32 nFormat = pClipDoc->GetNumberFormat(aCellPos);
     193         [ #  # ]:          0 :             if ( (nFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0 )
     194                 :            :             {
     195         [ #  # ]:          0 :                 ScFormulaCell* pFCell = static_cast<ScFormulaCell*>(pCell);
     196         [ #  # ]:          0 :                 sal_uInt16 nErrCode = pFCell->GetErrCode();
     197 [ #  # ][ #  # ]:          0 :                 if ( nErrCode == 0 && pFCell->IsValue() )
         [ #  # ][ #  # ]
     198                 :            :                 {
     199 [ #  # ][ #  # ]:          0 :                     sal_uInt32 nNewFormat = pFCell->GetStandardFormat( *pClipDoc->GetFormatTable(), nFormat );
     200         [ #  # ]:          0 :                     if ( nNewFormat != nFormat )
     201                 :          0 :                         pClipDoc->ApplyAttr( aCellPos.Col(), aCellPos.Row(), aCellPos.Tab(),
     202   [ #  #  #  # ]:          0 :                                              SfxUInt32Item( ATTR_VALUE_FORMAT, nNewFormat ) );
                 [ #  # ]
     203                 :            :                 }
     204                 :            :             }
     205                 :            :         }
     206         [ #  # ]:          0 :         pCell = aIter.GetNext();
     207                 :            :     }
     208                 :            : 
     209         [ #  # ]:          0 :     ScMarkData aDestMark;
     210         [ #  # ]:          0 :     aDestMark.SelectOneTable( nDestTab );
     211         [ #  # ]:          0 :     aDestMark.SetMarkArea( aNewRange );
     212         [ #  # ]:          0 :     pDestDoc->CopyFromClip( aNewRange, aDestMark, IDF_ALL & ~IDF_FORMULA, NULL, pClipDoc, false );
     213                 :            : 
     214 [ #  # ][ #  # ]:          0 :     delete pClipDoc;
     215 [ #  # ][ #  # ]:          0 :     return sal_True;
                 [ #  # ]
     216                 :            : }
     217                 :            : 
     218                 :            : //------------------------------------------------------------------------
     219                 :            : 
     220                 :          0 : ScFunctionAccess::ScFunctionAccess() :
     221                 :            :     pOptions( NULL ),
     222                 :            :     aPropertyMap( ScDocOptionsHelper::GetPropertyMap() ),
     223                 :            :     mbArray( true ),    // default according to behaviour of older Office versions
     224 [ #  # ][ #  # ]:          0 :     mbValid( true )
                 [ #  # ]
     225                 :            : {
     226 [ #  # ][ #  # ]:          0 :     StartListening( *SFX_APP() );       // for SFX_HINT_DEINITIALIZING
     227                 :          0 : }
     228                 :            : 
     229 [ #  # ][ #  # ]:          0 : ScFunctionAccess::~ScFunctionAccess()
                 [ #  # ]
     230                 :            : {
     231 [ #  # ][ #  # ]:          0 :     delete pOptions;
     232         [ #  # ]:          0 : }
     233                 :            : 
     234                 :          0 : void ScFunctionAccess::Notify( SfxBroadcaster&, const SfxHint& rHint )
     235                 :            : {
     236   [ #  #  #  # ]:          0 :     if ( rHint.ISA(SfxSimpleHint) &&
                 [ #  # ]
     237                 :          0 :         ((SfxSimpleHint&)rHint).GetId() == SFX_HINT_DEINITIALIZING )
     238                 :            :     {
     239                 :            :         //  document must not be used anymore
     240                 :          0 :         aDocCache.Clear();
     241                 :          0 :         mbValid = false;
     242                 :            :     }
     243                 :          0 : }
     244                 :            : 
     245                 :            : // stuff for exService_...
     246                 :            : 
     247                 :          0 : uno::Reference<uno::XInterface> SAL_CALL ScFunctionAccess_CreateInstance(
     248                 :            :                         const uno::Reference<lang::XMultiServiceFactory>& )
     249                 :            : {
     250         [ #  # ]:          0 :     SolarMutexGuard aGuard;
     251         [ #  # ]:          0 :     ScDLL::Init();
     252 [ #  # ][ #  # ]:          0 :     static uno::Reference< uno::XInterface > xInst((::cppu::OWeakObject*) new ScFunctionAccess);
         [ #  # ][ #  # ]
                 [ #  # ]
     253         [ #  # ]:          0 :     return xInst;
     254                 :            : }
     255                 :            : 
     256                 :        181 : rtl::OUString ScFunctionAccess::getImplementationName_Static()
     257                 :            : {
     258                 :        181 :     return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "stardiv.StarCalc.ScFunctionAccess" ));
     259                 :            : }
     260                 :            : 
     261                 :          0 : uno::Sequence<rtl::OUString> ScFunctionAccess::getSupportedServiceNames_Static()
     262                 :            : {
     263                 :          0 :     uno::Sequence<rtl::OUString> aRet(1);
     264         [ #  # ]:          0 :     rtl::OUString* pArray = aRet.getArray();
     265         [ #  # ]:          0 :     pArray[0] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( SCFUNCTIONACCESS_SERVICE ));
     266                 :          0 :     return aRet;
     267                 :            : }
     268                 :            : 
     269                 :            : // XServiceInfo
     270                 :            : 
     271                 :          0 : rtl::OUString SAL_CALL ScFunctionAccess::getImplementationName() throw(uno::RuntimeException)
     272                 :            : {
     273                 :          0 :     return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "ScFunctionAccess") );
     274                 :            : }
     275                 :            : 
     276                 :          0 : sal_Bool SAL_CALL ScFunctionAccess::supportsService( const rtl::OUString& rServiceName )
     277                 :            :                                                     throw(uno::RuntimeException)
     278                 :            : {
     279         [ #  # ]:          0 :     String aServiceStr(rServiceName);
     280         [ #  # ]:          0 :     return aServiceStr.EqualsAscii( SCFUNCTIONACCESS_SERVICE ) ||
     281 [ #  # ][ #  # ]:          0 :            aServiceStr.EqualsAscii( SCDOCSETTINGS_SERVICE );
         [ #  # ][ #  # ]
     282                 :            : }
     283                 :            : 
     284                 :          0 : uno::Sequence<rtl::OUString> SAL_CALL ScFunctionAccess::getSupportedServiceNames()
     285                 :            :                                                     throw(uno::RuntimeException)
     286                 :            : {
     287                 :          0 :     uno::Sequence<rtl::OUString> aRet(2);
     288         [ #  # ]:          0 :     rtl::OUString* pArray = aRet.getArray();
     289         [ #  # ]:          0 :     pArray[0] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( SCFUNCTIONACCESS_SERVICE ));
     290         [ #  # ]:          0 :     pArray[1] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( SCDOCSETTINGS_SERVICE ));
     291                 :          0 :     return aRet;
     292                 :            : }
     293                 :            : 
     294                 :            : // XPropertySet (document settings)
     295                 :            : 
     296                 :          0 : uno::Reference<beans::XPropertySetInfo> SAL_CALL ScFunctionAccess::getPropertySetInfo()
     297                 :            :                                                         throw(uno::RuntimeException)
     298                 :            : {
     299         [ #  # ]:          0 :     SolarMutexGuard aGuard;
     300                 :            :     static uno::Reference<beans::XPropertySetInfo> aRef(
     301 [ #  # ][ #  # ]:          0 :         new SfxItemPropertySetInfo( aPropertyMap ));
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     302         [ #  # ]:          0 :     return aRef;
     303                 :            : }
     304                 :            : 
     305                 :          0 : void SAL_CALL ScFunctionAccess::setPropertyValue(
     306                 :            :                         const rtl::OUString& aPropertyName, const uno::Any& aValue )
     307                 :            :                 throw(beans::UnknownPropertyException, beans::PropertyVetoException,
     308                 :            :                         lang::IllegalArgumentException, lang::WrappedTargetException,
     309                 :            :                         uno::RuntimeException)
     310                 :            : {
     311         [ #  # ]:          0 :     SolarMutexGuard aGuard;
     312                 :            : 
     313         [ #  # ]:          0 :     if ( aPropertyName == "IsArrayFunction" )
     314                 :            :     {
     315         [ #  # ]:          0 :         if( !(aValue >>= mbArray) )
     316         [ #  # ]:          0 :             throw lang::IllegalArgumentException();
     317                 :            :     }
     318                 :            :     else
     319                 :            :     {
     320         [ #  # ]:          0 :         if ( !pOptions )
     321 [ #  # ][ #  # ]:          0 :             pOptions = new ScDocOptions();
     322                 :            : 
     323                 :            :         // options aren't initialized from configuration - always get the same default behaviour
     324                 :            : 
     325         [ #  # ]:          0 :         sal_Bool bDone = ScDocOptionsHelper::setPropertyValue( *pOptions, aPropertyMap, aPropertyName, aValue );
     326         [ #  # ]:          0 :         if (!bDone)
     327         [ #  # ]:          0 :             throw beans::UnknownPropertyException();
     328         [ #  # ]:          0 :     }
     329                 :          0 : }
     330                 :            : 
     331                 :          0 : uno::Any SAL_CALL ScFunctionAccess::getPropertyValue( const rtl::OUString& aPropertyName )
     332                 :            :                 throw(beans::UnknownPropertyException, lang::WrappedTargetException,
     333                 :            :                         uno::RuntimeException)
     334                 :            : {
     335         [ #  # ]:          0 :     SolarMutexGuard aGuard;
     336                 :            : 
     337         [ #  # ]:          0 :     if ( aPropertyName == "IsArrayFunction" )
     338         [ #  # ]:          0 :         return uno::Any( mbArray );
     339                 :            : 
     340         [ #  # ]:          0 :     if ( !pOptions )
     341 [ #  # ][ #  # ]:          0 :         pOptions = new ScDocOptions();
     342                 :            : 
     343                 :            :     // options aren't initialized from configuration - always get the same default behaviour
     344                 :            : 
     345 [ #  # ][ #  # ]:          0 :     return ScDocOptionsHelper::getPropertyValue( *pOptions, aPropertyMap, aPropertyName );
     346                 :            : }
     347                 :            : 
     348                 :          0 : SC_IMPL_DUMMY_PROPERTY_LISTENER( ScFunctionAccess )
     349                 :            : 
     350                 :            : // XFunctionAccess
     351                 :            : 
     352                 :          0 : sal_Bool lcl_AddFunctionToken( ScTokenArray& rArray, const rtl::OUString& rName,const ScCompiler& rCompiler )
     353                 :            : {
     354                 :            :     // function names are always case-insensitive
     355         [ #  # ]:          0 :     rtl::OUString aUpper = ScGlobal::pCharClass->uppercase(rName);
     356                 :            : 
     357                 :            :     // same options as in ScCompiler::IsOpCode:
     358                 :            :     // 1. built-in function name
     359                 :            : 
     360 [ #  # ][ #  # ]:          0 :     OpCode eOp = rCompiler.GetEnglishOpCode( aUpper );
                 [ #  # ]
     361         [ #  # ]:          0 :     if ( eOp != ocNone )
     362                 :            :     {
     363         [ #  # ]:          0 :         rArray.AddOpCode( eOp );
     364                 :          0 :         return true;
     365                 :            :     }
     366                 :            : 
     367                 :            :     // 2. old add in functions
     368                 :            : 
     369 [ #  # ][ #  # ]:          0 :     if (ScGlobal::GetFuncCollection()->findByName(aUpper))
                 [ #  # ]
     370                 :            :     {
     371         [ #  # ]:          0 :         rArray.AddExternal(aUpper.getStr());
     372                 :          0 :         return true;
     373                 :            :     }
     374                 :            : 
     375                 :            :     // 3. new (uno) add in functions
     376                 :            : 
     377                 :            :     rtl::OUString aIntName =
     378 [ #  # ][ #  # ]:          0 :         ScGlobal::GetAddInCollection()->FindFunction(aUpper, false);
     379         [ #  # ]:          0 :     if (!aIntName.isEmpty())
     380                 :            :     {
     381         [ #  # ]:          0 :         rArray.AddExternal(aIntName.getStr());     // international name
     382                 :          0 :         return true;
     383                 :            :     }
     384                 :            : 
     385                 :          0 :     return false;       // no valid function name
     386                 :            : }
     387                 :            : 
     388                 :          0 : void lcl_AddRef( ScTokenArray& rArray, long nStartRow, long nColCount, long nRowCount )
     389                 :            : {
     390                 :            :     ScComplexRefData aRef;
     391                 :          0 :     aRef.InitFlags();
     392                 :          0 :     aRef.Ref1.nTab = 0;
     393                 :          0 :     aRef.Ref2.nTab = 0;
     394                 :          0 :     aRef.Ref1.nCol = 0;
     395                 :          0 :     aRef.Ref1.nRow = (SCROW) nStartRow;
     396                 :          0 :     aRef.Ref2.nCol = (SCCOL) (nColCount - 1);
     397                 :          0 :     aRef.Ref2.nRow = (SCROW) (nStartRow + nRowCount - 1);
     398         [ #  # ]:          0 :     rArray.AddDoubleReference(aRef);
     399                 :          0 : }
     400                 :            : 
     401                 :            : class SimpleVisitor
     402                 :            : {
     403                 :            : protected:
     404                 :            :     bool mbArgError;
     405                 :            :     ScDocument* mpDoc;
     406                 :            : public:
     407                 :          0 :     SimpleVisitor( ScDocument* pDoc ) : mbArgError( false ), mpDoc( pDoc ) {}
     408                 :            :     // could possibly just get away with JUST the following overload
     409                 :            :     // 1) virtual void visitElem( long& nCol, long& nRow, const double& elem )
     410                 :            :     // 2) virtual void visitElem( long& nCol, long& nRow, const rtl::OUString& elem )
     411                 :            :     // 3) virtual void visitElem( long& nCol, long& nRow, const uno::Any& elem )
     412                 :            :     // the other types methods are here just to reflect the orig code and for
     413                 :            :     // completeness.
     414                 :            : 
     415                 :          0 :     void visitElem( long nCol, long nRow, const sal_Int16& elem )
     416                 :            :     {
     417         [ #  # ]:          0 :         mpDoc->SetValue( (SCCOL) nCol, (SCROW) nRow, 0, elem );
     418                 :          0 :     }
     419                 :          0 :     void visitElem( long nCol, long nRow, const sal_Int32& elem )
     420                 :            :     {
     421         [ #  # ]:          0 :         mpDoc->SetValue( (SCCOL) nCol, (SCROW) nRow, 0, elem );
     422                 :          0 :     }
     423                 :          0 :     void visitElem( long nCol, long nRow, const double& elem )
     424                 :            :     {
     425                 :          0 :         mpDoc->SetValue( (SCCOL) nCol, (SCROW) nRow, 0, elem );
     426                 :          0 :     }
     427                 :          0 :     void visitElem( long nCol, long nRow, const rtl::OUString& elem )
     428                 :            :     {
     429         [ #  # ]:          0 :         if ( !elem.isEmpty() )
     430                 :            :             mpDoc->PutCell( (SCCOL) nCol, (SCROW) nRow, 0,
     431         [ #  # ]:          0 :                                         new ScStringCell( elem ) );
     432                 :          0 :     }
     433                 :          0 :     void visitElem( long nCol, long nRow, const uno::Any& rElement )
     434                 :            :     {
     435                 :          0 :         uno::TypeClass eElemClass = rElement.getValueTypeClass();
     436         [ #  # ]:          0 :         if ( eElemClass == uno::TypeClass_VOID )
     437                 :            :         {
     438                 :            :             // leave empty
     439                 :            :         }
     440 [ #  # ][ #  # ]:          0 :         else if ( eElemClass == uno::TypeClass_BYTE ||
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     441                 :            :                     eElemClass == uno::TypeClass_SHORT ||
     442                 :            :                     eElemClass == uno::TypeClass_UNSIGNED_SHORT ||
     443                 :            :                     eElemClass == uno::TypeClass_LONG ||
     444                 :            :                     eElemClass == uno::TypeClass_UNSIGNED_LONG ||
     445                 :            :                     eElemClass == uno::TypeClass_FLOAT ||
     446                 :            :                     eElemClass == uno::TypeClass_DOUBLE )
     447                 :            :         {
     448                 :            :             //  accept integer types because Basic passes a floating point
     449                 :            :             //  variable as byte, short or long if it's an integer number.
     450                 :          0 :             double fVal(0.0);
     451                 :          0 :             rElement >>= fVal;
     452         [ #  # ]:          0 :             visitElem( nCol, nRow, fVal );
     453                 :            :         }
     454         [ #  # ]:          0 :         else if ( eElemClass == uno::TypeClass_STRING )
     455                 :            :         {
     456                 :          0 :             rtl::OUString aUStr;
     457                 :          0 :             rElement >>= aUStr;
     458         [ #  # ]:          0 :             visitElem( nCol, nRow, aUStr );
     459                 :            :         }
     460                 :            :         else
     461                 :          0 :             mbArgError = true;
     462                 :          0 :     }
     463                 :          0 :     bool hasArgError() const { return mbArgError; }
     464                 :            : };
     465                 :            : 
     466                 :            : template< class seq >
     467                 :          0 : class SequencesContainer
     468                 :            : {
     469                 :            :     uno::Sequence< uno::Sequence< seq > > maSeq;
     470                 :            : 
     471                 :            :     long& mrDocRow;
     472                 :            :     bool mbOverflow;
     473                 :            :     bool mbArgError;
     474                 :            :     ScDocument* mpDoc;
     475                 :            :     ScTokenArray& mrTokenArr;
     476                 :            : 
     477                 :            : public:
     478                 :          0 :     SequencesContainer( const uno::Any& rArg, ScTokenArray& rTokenArr, long& rDocRow, ScDocument* pDoc ) :
     479                 :          0 :         mrDocRow( rDocRow ), mbOverflow(false), mbArgError(false), mpDoc( pDoc ), mrTokenArr( rTokenArr )
     480                 :            :     {
     481   [ #  #  #  #  :          0 :         rArg >>= maSeq;
          #  #  #  #  #  
                      # ]
     482                 :          0 :     }
     483                 :            : 
     484                 :          0 :     void process()
     485                 :            :     {
     486                 :          0 :         SimpleVisitor aVisitor(mpDoc);
     487                 :          0 :         long nStartRow = mrDocRow;
     488                 :          0 :         long nRowCount = maSeq.getLength();
     489                 :          0 :         long nMaxColCount = 0;
     490                 :          0 :         const uno::Sequence< seq >* pRowArr = maSeq.getConstArray();
     491 [ #  # ][ #  # ]:          0 :         for ( long nRow=0; nRow<nRowCount; nRow++ )
         [ #  # ][ #  # ]
                 [ #  # ]
     492                 :            :         {
     493                 :          0 :             long nColCount = pRowArr[nRow].getLength();
     494   [ #  #  #  #  :          0 :             if ( nColCount > nMaxColCount )
          #  #  #  #  #  
                      # ]
     495                 :          0 :                 nMaxColCount = nColCount;
     496                 :          0 :             const seq* pColArr = pRowArr[nRow].getConstArray();
     497 [ #  # ][ #  # ]:          0 :             for (long nCol=0; nCol<nColCount; nCol++)
         [ #  # ][ #  # ]
                 [ #  # ]
     498 [ #  # ][ #  # ]:          0 :                 if ( nCol <= MAXCOL && mrDocRow <= MAXROW )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     499 [ #  # ][ #  # ]:          0 :                     aVisitor.visitElem( nCol, mrDocRow, pColArr[ nCol ] );
         [ #  # ][ #  # ]
                 [ #  # ]
     500                 :            :                 else
     501                 :          0 :                     mbOverflow=true;
     502                 :          0 :             mrDocRow++;
     503                 :            :         }
     504                 :          0 :         mbArgError = aVisitor.hasArgError();
     505         [ #  # ]:          0 :         if ( nRowCount && nMaxColCount && !mbOverflow )
           [ #  #  #  # ]
                 [ #  # ]
           [ #  #  #  # ]
                 [ #  # ]
           [ #  #  #  # ]
                 [ #  # ]
           [ #  #  #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     506 [ #  # ][ #  # ]:          0 :             lcl_AddRef( mrTokenArr, nStartRow, nMaxColCount, nRowCount );
         [ #  # ][ #  # ]
                 [ #  # ]
     507                 :          0 :     }
     508                 :          0 :     bool getOverflow() const { return mbOverflow; }
     509                 :          0 :     bool getArgError() const { return mbArgError; }
     510                 :            : };
     511                 :            : 
     512                 :            : template <class T>
     513                 :            : class ArrayOfArrayProc
     514                 :            : {
     515                 :            : public:
     516                 :          0 : static void processSequences( ScDocument* pDoc, const uno::Any& rArg, ScTokenArray& rTokenArr,
     517                 :            :                                 long& rDocRow, sal_Bool& rArgErr, sal_Bool& rOverflow )
     518                 :            : {
     519 [ #  # ][ #  # ]:          0 :     SequencesContainer< T > aContainer( rArg, rTokenArr, rDocRow, pDoc );
         [ #  # ][ #  # ]
                 [ #  # ]
     520 [ #  # ][ #  # ]:          0 :     aContainer.process();
         [ #  # ][ #  # ]
                 [ #  # ]
     521                 :          0 :     rArgErr = aContainer.getArgError();
     522   [ #  #  #  #  :          0 :     rOverflow = aContainer.getOverflow();
          #  #  #  #  #  
                      # ]
     523                 :          0 : }
     524                 :            : };
     525                 :            : 
     526                 :          0 : uno::Any SAL_CALL ScFunctionAccess::callFunction( const rtl::OUString& aName,
     527                 :            :                             const uno::Sequence<uno::Any>& aArguments )
     528                 :            :                 throw(container::NoSuchElementException, lang::IllegalArgumentException,
     529                 :            :                         uno::RuntimeException)
     530                 :            : {
     531         [ #  # ]:          0 :     SolarMutexGuard aGuard;
     532                 :            : 
     533         [ #  # ]:          0 :     if (!mbValid)
     534         [ #  # ]:          0 :         throw uno::RuntimeException();
     535                 :            : 
     536                 :            :     // use cached document if not in use, temporary document otherwise
     537                 :            :     //  (deleted in ScTempDocSource dtor)
     538         [ #  # ]:          0 :     ScTempDocSource aSource( aDocCache );
     539                 :          0 :     ScDocument* pDoc = aSource.GetDocument();
     540                 :            :     const static SCTAB nTempSheet = 1;
     541                 :            :     // Create an extra tab to contain the Function Cell
     542                 :            :     // this will allow full rows to be used.
     543 [ #  # ][ #  # ]:          0 :     if ( !pDoc->HasTable( nTempSheet ) )
     544         [ #  # ]:          0 :         pDoc->MakeTable( nTempSheet );
     545                 :            : 
     546                 :            :     /// TODO: check
     547                 :          0 :     ScAddress aAdr;
     548         [ #  # ]:          0 :     ScCompiler aCompiler(pDoc,aAdr);
     549 [ #  # ][ #  # ]:          0 :     aCompiler.SetGrammar(pDoc->GetGrammar());
     550                 :            : 
     551                 :            :     //
     552                 :            :     //  find function
     553                 :            :     //
     554                 :            : 
     555         [ #  # ]:          0 :     ScTokenArray aTokenArr;
     556 [ #  # ][ #  # ]:          0 :     if ( !lcl_AddFunctionToken( aTokenArr, aName,aCompiler ) )
     557                 :            :     {
     558                 :            :         // function not found
     559         [ #  # ]:          0 :         throw container::NoSuchElementException();
     560                 :            :     }
     561                 :            : 
     562                 :            :     //
     563                 :            :     //  set options (null date, etc.)
     564                 :            :     //
     565                 :            : 
     566         [ #  # ]:          0 :     if ( pOptions )
     567         [ #  # ]:          0 :         pDoc->SetDocOptions( *pOptions );
     568                 :            : 
     569                 :            :     //
     570                 :            :     //  add arguments to token array
     571                 :            :     //
     572                 :            : 
     573                 :          0 :     sal_Bool bArgErr = false;
     574                 :          0 :     sal_Bool bOverflow = false;
     575                 :          0 :     long nDocRow = 0;
     576                 :          0 :     long nArgCount = aArguments.getLength();
     577                 :          0 :     const uno::Any* pArgArr = aArguments.getConstArray();
     578                 :            : 
     579         [ #  # ]:          0 :     aTokenArr.AddOpCode(ocOpen);
     580         [ #  # ]:          0 :     for (long nPos=0; nPos<nArgCount; nPos++)
     581                 :            :     {
     582         [ #  # ]:          0 :         if ( nPos > 0 )
     583         [ #  # ]:          0 :             aTokenArr.AddOpCode(ocSep);
     584                 :            : 
     585                 :          0 :         const uno::Any& rArg = pArgArr[nPos];
     586                 :            : 
     587                 :          0 :         uno::TypeClass eClass = rArg.getValueTypeClass();
     588                 :          0 :         uno::Type aType = rArg.getValueType();
     589 [ #  # ][ #  # ]:          0 :         if ( eClass == uno::TypeClass_BYTE ||
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     590                 :            :              eClass == uno::TypeClass_BOOLEAN ||
     591                 :            :              eClass == uno::TypeClass_SHORT ||
     592                 :            :              eClass == uno::TypeClass_UNSIGNED_SHORT ||
     593                 :            :              eClass == uno::TypeClass_LONG ||
     594                 :            :              eClass == uno::TypeClass_UNSIGNED_LONG ||
     595                 :            :              eClass == uno::TypeClass_FLOAT ||
     596                 :            :              eClass == uno::TypeClass_DOUBLE )
     597                 :            :         {
     598                 :            :             //  accept integer types because Basic passes a floating point
     599                 :            :             //  variable as byte, short or long if it's an integer number.
     600                 :          0 :             double fVal = 0;
     601                 :          0 :             rArg >>= fVal;
     602         [ #  # ]:          0 :             aTokenArr.AddDouble( fVal );
     603                 :            :         }
     604         [ #  # ]:          0 :         else if ( eClass == uno::TypeClass_STRING )
     605                 :            :         {
     606                 :          0 :             rtl::OUString aUStr;
     607                 :          0 :             rArg >>= aUStr;
     608         [ #  # ]:          0 :             String aStr( aUStr );
     609 [ #  # ][ #  # ]:          0 :             aTokenArr.AddString( aStr.GetBuffer() );
     610                 :            :         }
     611 [ #  # ][ #  # ]:          0 :         else if ( aType.equals( getCppuType( (uno::Sequence< uno::Sequence<sal_Int16> > *)0 ) ) )
     612                 :            :         {
     613         [ #  # ]:          0 :             ArrayOfArrayProc<sal_Int16>::processSequences( pDoc, rArg, aTokenArr, nDocRow, bArgErr, bOverflow );
     614                 :            :         }
     615 [ #  # ][ #  # ]:          0 :         else if ( aType.equals( getCppuType( (uno::Sequence< uno::Sequence<sal_Int32> > *)0 ) ) )
     616                 :            :         {
     617         [ #  # ]:          0 :             ArrayOfArrayProc<sal_Int32>::processSequences( pDoc, rArg, aTokenArr, nDocRow, bArgErr, bOverflow );
     618                 :            :         }
     619 [ #  # ][ #  # ]:          0 :         else if ( aType.equals( getCppuType( (uno::Sequence< uno::Sequence<double> > *)0 ) ) )
     620                 :            :         {
     621         [ #  # ]:          0 :             ArrayOfArrayProc<double>::processSequences( pDoc, rArg, aTokenArr, nDocRow, bArgErr, bOverflow );
     622                 :            :         }
     623 [ #  # ][ #  # ]:          0 :         else if ( aType.equals( getCppuType( (uno::Sequence< uno::Sequence<rtl::OUString> > *)0 ) ) )
     624                 :            :         {
     625         [ #  # ]:          0 :             ArrayOfArrayProc<rtl::OUString>::processSequences( pDoc, rArg, aTokenArr, nDocRow, bArgErr, bOverflow );
     626                 :            :         }
     627 [ #  # ][ #  # ]:          0 :         else if ( aType.equals( getCppuType( (uno::Sequence< uno::Sequence<uno::Any> > *)0 ) ) )
     628                 :            :         {
     629         [ #  # ]:          0 :             ArrayOfArrayProc<uno::Any>::processSequences( pDoc, rArg, aTokenArr, nDocRow, bArgErr, bOverflow );
     630                 :            :         }
     631 [ #  # ][ #  # ]:          0 :         else if ( aType.equals( getCppuType( (uno::Reference<table::XCellRange>*)0 ) ) )
     632                 :            :         {
     633                 :            :             // currently, only our own cell ranges are supported
     634                 :            : 
     635         [ #  # ]:          0 :             uno::Reference<table::XCellRange> xRange(rArg, uno::UNO_QUERY);
     636         [ #  # ]:          0 :             ScCellRangesBase* pImpl = ScCellRangesBase::getImplementation( xRange );
     637         [ #  # ]:          0 :             if ( pImpl )
     638                 :            :             {
     639         [ #  # ]:          0 :                 ScDocument* pSrcDoc = pImpl->GetDocument();
     640                 :          0 :                 const ScRangeList& rRanges = pImpl->GetRangeList();
     641 [ #  # ][ #  # ]:          0 :                 if ( pSrcDoc && rRanges.size() == 1 )
         [ #  # ][ #  # ]
     642                 :            :                 {
     643         [ #  # ]:          0 :                     ScRange aSrcRange = *rRanges[ 0 ];
     644                 :            : 
     645                 :          0 :                     long nStartRow = nDocRow;
     646                 :          0 :                     long nColCount = aSrcRange.aEnd.Col() - aSrcRange.aStart.Col() + 1;
     647                 :          0 :                     long nRowCount = aSrcRange.aEnd.Row() - aSrcRange.aStart.Row() + 1;
     648                 :            : 
     649         [ #  # ]:          0 :                     if ( nStartRow + nRowCount > MAXROWCOUNT )
     650                 :          0 :                         bOverflow = sal_True;
     651                 :            :                     else
     652                 :            :                     {
     653                 :            :                         // copy data
     654 [ #  # ][ #  # ]:          0 :                         if ( !lcl_CopyData( pSrcDoc, aSrcRange, pDoc, ScAddress( 0, (SCROW)nDocRow, 0 ) ) )
     655                 :          0 :                             bOverflow = sal_True;
     656                 :            :                     }
     657                 :            : 
     658                 :          0 :                     nDocRow += nRowCount;
     659         [ #  # ]:          0 :                     if ( !bOverflow )
     660         [ #  # ]:          0 :                         lcl_AddRef( aTokenArr, nStartRow, nColCount, nRowCount );
     661                 :            :                 }
     662                 :            :                 else
     663                 :          0 :                     bArgErr = sal_True;
     664                 :            :             }
     665                 :            :             else
     666                 :          0 :                 bArgErr = sal_True;
     667                 :            :         }
     668                 :            :         else
     669                 :          0 :             bArgErr = sal_True;                 // invalid type
     670                 :          0 :     }
     671         [ #  # ]:          0 :     aTokenArr.AddOpCode(ocClose);
     672         [ #  # ]:          0 :     aTokenArr.AddOpCode(ocStop);
     673                 :            : 
     674                 :            :     //
     675                 :            :     //  execute formula
     676                 :            :     //
     677                 :            : 
     678                 :          0 :     uno::Any aRet;
     679 [ #  # ][ #  # ]:          0 :     if ( !bArgErr && !bOverflow && nDocRow <= MAXROWCOUNT )
                 [ #  # ]
     680                 :            :     {
     681                 :          0 :         ScAddress aFormulaPos( 0, 0, nTempSheet );
     682                 :            :         // GRAM_PODF_A1 doesn't really matter for the token array but fits with
     683                 :            :         // other API compatibility grammars.
     684                 :            :         ScFormulaCell* pFormula = new ScFormulaCell( pDoc, aFormulaPos,
     685 [ #  # ][ #  # ]:          0 :                 &aTokenArr, formula::FormulaGrammar::GRAM_PODF_A1, (sal_uInt8)(mbArray ? MM_FORMULA : MM_NONE) );
                 [ #  # ]
     686 [ #  # ][ #  # ]:          0 :         pDoc->PutCell( aFormulaPos, pFormula );     //! necessary?
     687                 :            : 
     688                 :            :         //  call GetMatrix before GetErrCode because GetMatrix always recalculates
     689                 :            :         //  if there is no matrix result
     690                 :            : 
     691 [ #  # ][ #  # ]:          0 :         const ScMatrix* pMat = mbArray ? pFormula->GetMatrix() : 0;
     692         [ #  # ]:          0 :         sal_uInt16 nErrCode = pFormula->GetErrCode();
     693         [ #  # ]:          0 :         if ( nErrCode == 0 )
     694                 :            :         {
     695         [ #  # ]:          0 :             if ( pMat )
     696                 :            :             {
     697                 :            :                 // array result
     698         [ #  # ]:          0 :                 ScRangeToSequence::FillMixedArray( aRet, pMat );
     699                 :            :             }
     700 [ #  # ][ #  # ]:          0 :             else if ( pFormula->IsValue() )
     701                 :            :             {
     702                 :            :                 // numeric value
     703 [ #  # ][ #  # ]:          0 :                 aRet <<= (double) pFormula->GetValue();
     704                 :            :             }
     705                 :            :             else
     706                 :            :             {
     707                 :            :                 // string result
     708         [ #  # ]:          0 :                 rtl::OUString aStrVal = pFormula->GetString();
     709         [ #  # ]:          0 :                 aRet <<= aStrVal;
     710                 :            :             }
     711                 :            :         }
     712         [ #  # ]:          0 :         else if ( nErrCode == NOTAVAILABLE )
     713                 :            :         {
     714                 :            :             // #N/A: leave result empty, no exception
     715                 :            :         }
     716                 :            :         else
     717                 :            :         {
     718                 :            :             //  any other error: IllegalArgumentException
     719                 :          0 :             bArgErr = sal_True;
     720                 :            :         }
     721                 :            : 
     722         [ #  # ]:          0 :         pDoc->DeleteAreaTab( 0, 0, MAXCOL, MAXROW, 0, IDF_ALL );
     723         [ #  # ]:          0 :         pDoc->DeleteAreaTab( 0, 0, 0, 0, nTempSheet, IDF_ALL );
     724                 :            :     }
     725                 :            : 
     726         [ #  # ]:          0 :     if (bOverflow)
     727         [ #  # ]:          0 :         throw uno::RuntimeException();
     728                 :            : 
     729         [ #  # ]:          0 :     if (bArgErr)
     730         [ #  # ]:          0 :         throw lang::IllegalArgumentException();
     731                 :            : 
     732 [ #  # ][ #  # ]:          0 :     return aRet;
         [ #  # ][ #  # ]
     733                 :            : }
     734                 :            : 
     735                 :            : 
     736                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10