LCOV - code coverage report
Current view: top level - scaddins/source/datefunc - datefunc.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 176 315 55.9 %
Date: 2015-06-13 12:38:46 Functions: 37 56 66.1 %
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 "datefunc.hxx"
      21             : #include "datefunc.hrc"
      22             : #include <com/sun/star/util/Date.hpp>
      23             : #include <cppuhelper/factory.hxx>
      24             : #include <cppuhelper/supportsservice.hxx>
      25             : #include <osl/diagnose.h>
      26             : #include <rtl/ustrbuf.hxx>
      27             : #include <tools/rcid.h>
      28             : #include <tools/resmgr.hxx>
      29             : 
      30             : using namespace ::com::sun::star;
      31             : 
      32             : #define ADDIN_SERVICE           "com.sun.star.sheet.AddIn"
      33             : #define MY_SERVICE              "com.sun.star.sheet.addin.DateFunctions"
      34             : #define MY_IMPLNAME             "com.sun.star.sheet.addin.DateFunctionsImpl"
      35             : 
      36             : #define STR_FROM_ANSI( s )      OUString( s, strlen( s ), RTL_TEXTENCODING_MS_1252 )
      37             : 
      38             : const sal_uInt32 ScaList::nStartSize = 16;
      39             : const sal_uInt32 ScaList::nIncrSize = 16;
      40             : 
      41         171 : ScaList::ScaList() :
      42         171 :     pData( new void*[ nStartSize ] ),
      43             :     nSize( nStartSize ),
      44             :     nCount( 0 ),
      45         342 :     nCurr( 0 )
      46             : {
      47         171 : }
      48             : 
      49          90 : ScaList::~ScaList()
      50             : {
      51          90 :     delete[] pData;
      52          90 : }
      53             : 
      54           0 : void ScaList::_Grow()
      55             : {
      56           0 :     nSize += nIncrSize;
      57             : 
      58           0 :     void** pNewData = new void*[ nSize ];
      59           0 :     memcpy( pNewData, pData, nCount * sizeof( void* ) );
      60             : 
      61           0 :     delete[] pData;
      62           0 :     pData = pNewData;
      63           0 : }
      64             : 
      65         160 : ScaStringList::~ScaStringList()
      66             : {
      67         240 :     for( OUString* pStr = First(); pStr; pStr = Next() )
      68         160 :         delete pStr;
      69          80 : }
      70             : 
      71        2660 : ScaResId::ScaResId( sal_uInt16 nId, ResMgr& rResMgr ) :
      72        2660 :     ResId( nId, rResMgr )
      73             : {
      74        2660 : }
      75             : 
      76             : #define UNIQUE              false   // function name does not exist in Calc
      77             : 
      78             : #define STDPAR              false   // all parameters are described
      79             : #define INTPAR              true    // first parameter is internal
      80             : 
      81             : #define FUNCDATA( FuncName, ParamCount, Category, Double, IntPar )  \
      82             :     { "get" #FuncName, DATE_FUNCNAME_##FuncName, DATE_FUNCDESC_##FuncName, DATE_DEFFUNCNAME_##FuncName, ParamCount, Category, Double, IntPar }
      83             : 
      84             : const ScaFuncDataBase pFuncDataArr[] =
      85             : {
      86             :     FUNCDATA( DiffWeeks,    3, ScaCat_DateTime, UNIQUE, INTPAR ),
      87             :     FUNCDATA( DiffMonths,   3, ScaCat_DateTime, UNIQUE, INTPAR ),
      88             :     FUNCDATA( DiffYears,    3, ScaCat_DateTime, UNIQUE, INTPAR ),
      89             :     FUNCDATA( IsLeapYear,   1, ScaCat_DateTime, UNIQUE, INTPAR ),
      90             :     FUNCDATA( DaysInMonth,  1, ScaCat_DateTime, UNIQUE, INTPAR ),
      91             :     FUNCDATA( DaysInYear,   1, ScaCat_DateTime, UNIQUE, INTPAR ),
      92             :     FUNCDATA( WeeksInYear,  1, ScaCat_DateTime, UNIQUE, INTPAR ),
      93             :     FUNCDATA( Rot13,        1, ScaCat_Text,     UNIQUE, STDPAR )
      94             : };
      95             : 
      96             : #undef FUNCDATA
      97             : 
      98         152 : ScaFuncData::ScaFuncData( const ScaFuncDataBase& rBaseData, ResMgr& rResMgr ) :
      99             :     aIntName( OUString::createFromAscii( rBaseData.pIntName ) ),
     100             :     nUINameID( rBaseData.nUINameID ),
     101             :     nDescrID( rBaseData.nDescrID ),
     102             :     nCompListID( rBaseData.nCompListID ),
     103             :     nParamCount( rBaseData.nParamCount ),
     104             :     eCat( rBaseData.eCat ),
     105             :     bDouble( rBaseData.bDouble ),
     106         152 :     bWithOpt( rBaseData.bWithOpt )
     107             : {
     108         152 :     ScaResStringArrLoader aArrLoader( RID_DATE_DEFFUNCTION_NAMES, nCompListID, rResMgr );
     109         152 :     const ResStringArray& rArr = aArrLoader.GetStringArray();
     110             : 
     111         456 :     for( sal_uInt32 nIndex = 0; nIndex < rArr.Count(); nIndex++ )
     112         456 :         aCompList.Append( rArr.GetString( nIndex ) );
     113         152 : }
     114             : 
     115         160 : ScaFuncData::~ScaFuncData()
     116             : {
     117         160 : }
     118             : 
     119         532 : sal_uInt16 ScaFuncData::GetStrIndex( sal_uInt16 nParam ) const
     120             : {
     121         532 :     if( !bWithOpt )
     122          38 :         nParam++;
     123         532 :     return (nParam > nParamCount) ? (nParamCount * 2) : (nParam * 2);
     124             : }
     125             : 
     126             : 
     127          19 : ScaFuncDataList::ScaFuncDataList( ResMgr& rResMgr ) :
     128          19 :     nLast( 0xFFFFFFFF )
     129             : {
     130         171 :     for( sal_uInt16 nIndex = 0; nIndex < SAL_N_ELEMENTS(pFuncDataArr); nIndex++ )
     131         152 :         Append( new ScaFuncData( pFuncDataArr[ nIndex ], rResMgr ) );
     132          19 : }
     133             : 
     134          30 : ScaFuncDataList::~ScaFuncDataList()
     135             : {
     136          90 :     for( ScaFuncData* pFData = First(); pFData; pFData = Next() )
     137          80 :         delete pFData;
     138          20 : }
     139             : 
     140        1012 : const ScaFuncData* ScaFuncDataList::Get( const OUString& rProgrammaticName ) const
     141             : {
     142        1012 :     if( aLastName == rProgrammaticName )
     143         836 :         return Get( nLast );
     144             : 
     145         792 :     for( sal_uInt32 nIndex = 0; nIndex < Count(); nIndex++ )
     146             :     {
     147         792 :         const ScaFuncData* pCurr = Get( nIndex );
     148         792 :         if( pCurr->Is( rProgrammaticName ) )
     149             :         {
     150         176 :             const_cast< ScaFuncDataList* >( this )->aLastName = rProgrammaticName;
     151         176 :             const_cast< ScaFuncDataList* >( this )->nLast = nIndex;
     152         176 :             return pCurr;
     153             :         }
     154             :     }
     155           0 :     return NULL;
     156             : }
     157             : 
     158         684 : ScaFuncRes::ScaFuncRes( ResId& rResId, ResMgr& rResMgr, sal_uInt16 nIndex, OUString& rRet ) :
     159         684 :     Resource( rResId )
     160             : {
     161         684 :     rRet = ScaResId(nIndex, rResMgr).toString();
     162         684 :     FreeResource();
     163         684 : }
     164             : 
     165             : //  entry points for service registration / instantiation
     166          20 : uno::Reference< uno::XInterface > SAL_CALL ScaDateAddIn_CreateInstance(
     167             :         const uno::Reference< lang::XMultiServiceFactory >& )
     168             : {
     169          20 :     return static_cast<cppu::OWeakObject*>(new ScaDateAddIn());
     170             : }
     171             : 
     172             : extern "C" {
     173             : 
     174          20 : SAL_DLLPUBLIC_EXPORT void * SAL_CALL date_component_getFactory(
     175             :     const sal_Char * pImplName, void * pServiceManager, void * /*pRegistryKey*/ )
     176             : {
     177          20 :     void* pRet = 0;
     178             : 
     179         100 :     if ( pServiceManager &&
     180         100 :             OUString::createFromAscii( pImplName ) == ScaDateAddIn::getImplementationName_Static() )
     181             :     {
     182             :         uno::Reference< lang::XSingleServiceFactory > xFactory( cppu::createOneInstanceFactory(
     183             :                 static_cast< lang::XMultiServiceFactory* >( pServiceManager ),
     184             :                 ScaDateAddIn::getImplementationName_Static(),
     185             :                 ScaDateAddIn_CreateInstance,
     186          20 :                 ScaDateAddIn::getSupportedServiceNames_Static() ) );
     187             : 
     188          20 :         if (xFactory.is())
     189             :         {
     190          20 :             xFactory->acquire();
     191          20 :             pRet = xFactory.get();
     192          20 :         }
     193             :     }
     194             : 
     195          20 :     return pRet;
     196             : }
     197             : 
     198             : }   // extern C
     199             : 
     200             : //  "normal" service implementation
     201          20 : ScaDateAddIn::ScaDateAddIn() :
     202             :     pDefLocales( NULL ),
     203             :     pResMgr( NULL ),
     204          20 :     pFuncDataList( NULL )
     205             : {
     206          20 : }
     207             : 
     208          33 : ScaDateAddIn::~ScaDateAddIn()
     209             : {
     210          11 :     delete pFuncDataList;
     211          11 :     delete pResMgr;
     212          11 :     delete[] pDefLocales;
     213          22 : }
     214             : 
     215             : static const sal_Char*  pLang[] = { "de", "en" };
     216             : static const sal_Char*  pCoun[] = { "DE", "US" };
     217             : static const sal_uInt32 nNumOfLoc = SAL_N_ELEMENTS( pLang );
     218             : 
     219           3 : void ScaDateAddIn::InitDefLocales()
     220             : {
     221           3 :     pDefLocales = new lang::Locale[ nNumOfLoc ];
     222             : 
     223           9 :     for( sal_uInt32 nIndex = 0; nIndex < nNumOfLoc; nIndex++ )
     224             :     {
     225           6 :         pDefLocales[ nIndex ].Language = OUString::createFromAscii( pLang[ nIndex ] );
     226           6 :         pDefLocales[ nIndex ].Country = OUString::createFromAscii( pCoun[ nIndex ] );
     227             :     }
     228           3 : }
     229             : 
     230          48 : const lang::Locale& ScaDateAddIn::GetLocale( sal_uInt32 nIndex )
     231             : {
     232          48 :     if( !pDefLocales )
     233           3 :         InitDefLocales();
     234             : 
     235          48 :     return (nIndex < sizeof( pLang )) ? pDefLocales[ nIndex ] : aFuncLoc;
     236             : }
     237             : 
     238        2204 : ResMgr& ScaDateAddIn::GetResMgr() throw( uno::RuntimeException )
     239             : {
     240        2204 :     if( !pResMgr )
     241             :     {
     242           0 :         InitData();     // try to get resource manager
     243           0 :         if( !pResMgr )
     244           0 :             throw uno::RuntimeException();
     245             :     }
     246        2204 :     return *pResMgr;
     247             : }
     248             : 
     249          19 : void ScaDateAddIn::InitData()
     250             : {
     251          19 :     delete pResMgr;
     252          19 :     pResMgr = ResMgr::CreateResMgr("date", LanguageTag(aFuncLoc));
     253          19 :     delete pFuncDataList;
     254             : 
     255          19 :     pFuncDataList = pResMgr ? new ScaFuncDataList( *pResMgr ) : NULL;
     256             : 
     257          19 :     if( pDefLocales )
     258             :     {
     259           0 :         delete pDefLocales;
     260           0 :         pDefLocales = NULL;
     261             :     }
     262          19 : }
     263             : 
     264         152 : OUString ScaDateAddIn::GetDisplFuncStr( sal_uInt16 nResId ) throw( uno::RuntimeException )
     265             : {
     266         152 :     return ScaResStringLoader( RID_DATE_FUNCTION_NAMES, nResId, GetResMgr() ).GetString();
     267             : }
     268             : 
     269         684 : OUString ScaDateAddIn::GetFuncDescrStr( sal_uInt16 nResId, sal_uInt16 nStrIndex ) throw( uno::RuntimeException )
     270             : {
     271         684 :     OUString aRet;
     272             : 
     273        1368 :     ScaResPublisher aResPubl( ScaResId( RID_DATE_FUNCTION_DESCRIPTIONS, GetResMgr() ) );
     274         684 :     ScaResId aResId( nResId, GetResMgr() );
     275         684 :     aResId.SetRT( RSC_RESOURCE );
     276             : 
     277         684 :     if( aResPubl.IsAvailableRes( aResId ) )
     278         684 :         ScaFuncRes aSubRes( aResId, GetResMgr(), nStrIndex, aRet );
     279             : 
     280         684 :     aResPubl.FreeResource();
     281        1368 :     return aRet;
     282             : }
     283             : 
     284          41 : OUString ScaDateAddIn::getImplementationName_Static()
     285             : {
     286          41 :     return OUString( MY_IMPLNAME );
     287             : }
     288             : 
     289          21 : uno::Sequence< OUString > ScaDateAddIn::getSupportedServiceNames_Static()
     290             : {
     291          21 :     uno::Sequence< OUString > aRet( 2 );
     292          21 :     OUString* pArray = aRet.getArray();
     293          21 :     pArray[0] = ADDIN_SERVICE;
     294          21 :     pArray[1] = MY_SERVICE;
     295          21 :     return aRet;
     296             : }
     297             : 
     298             : // XServiceName
     299          19 : OUString SAL_CALL ScaDateAddIn::getServiceName() throw( uno::RuntimeException, std::exception )
     300             : {
     301             :     // name of specific AddIn service
     302          19 :     return OUString( MY_SERVICE );
     303             : }
     304             : 
     305             : // XServiceInfo
     306           1 : OUString SAL_CALL ScaDateAddIn::getImplementationName() throw( uno::RuntimeException, std::exception )
     307             : {
     308           1 :     return getImplementationName_Static();
     309             : }
     310             : 
     311           0 : sal_Bool SAL_CALL ScaDateAddIn::supportsService( const OUString& aServiceName ) throw( uno::RuntimeException, std::exception )
     312             : {
     313           0 :     return cppu::supportsService(this, aServiceName);
     314             : }
     315             : 
     316           1 : uno::Sequence< OUString > SAL_CALL ScaDateAddIn::getSupportedServiceNames() throw( uno::RuntimeException, std::exception )
     317             : {
     318           1 :     return getSupportedServiceNames_Static();
     319             : }
     320             : 
     321             : // XLocalizable
     322          19 : void SAL_CALL ScaDateAddIn::setLocale( const lang::Locale& eLocale ) throw( uno::RuntimeException, std::exception )
     323             : {
     324          19 :     aFuncLoc = eLocale;
     325          19 :     InitData();     // change of locale invalidates resources!
     326          19 : }
     327             : 
     328           0 : lang::Locale SAL_CALL ScaDateAddIn::getLocale() throw( uno::RuntimeException, std::exception )
     329             : {
     330           0 :     return aFuncLoc;
     331             : }
     332             : 
     333           0 : OUString SAL_CALL ScaDateAddIn::getProgrammaticFuntionName( const OUString& ) throw( uno::RuntimeException, std::exception )
     334             : {
     335             :     //  not used by calc
     336             :     //  (but should be implemented for other uses of the AddIn service)
     337           0 :     return OUString();
     338             : }
     339             : 
     340         152 : OUString SAL_CALL ScaDateAddIn::getDisplayFunctionName( const OUString& aProgrammaticName ) throw( uno::RuntimeException, std::exception )
     341             : {
     342         152 :     OUString aRet;
     343             : 
     344         152 :     const ScaFuncData* pFData = pFuncDataList->Get( aProgrammaticName );
     345         152 :     if( pFData )
     346             :     {
     347         152 :         aRet = GetDisplFuncStr( pFData->GetUINameID() );
     348         152 :         if( pFData->IsDouble() )
     349           0 :             aRet += STR_FROM_ANSI( "_ADD" );
     350             :     }
     351             :     else
     352             :     {
     353           0 :         aRet = STR_FROM_ANSI( "UNKNOWNFUNC_" );
     354           0 :         aRet += aProgrammaticName;
     355             :     }
     356             : 
     357         152 :     return aRet;
     358             : }
     359             : 
     360         152 : OUString SAL_CALL ScaDateAddIn::getFunctionDescription( const OUString& aProgrammaticName ) throw( uno::RuntimeException, std::exception )
     361             : {
     362         152 :     OUString aRet;
     363             : 
     364         152 :     const ScaFuncData* pFData = pFuncDataList->Get( aProgrammaticName );
     365         152 :     if( pFData )
     366         152 :         aRet = GetFuncDescrStr( pFData->GetDescrID(), 1 );
     367             : 
     368         152 :     return aRet;
     369             : }
     370             : 
     371         266 : OUString SAL_CALL ScaDateAddIn::getDisplayArgumentName(
     372             :         const OUString& aProgrammaticName, sal_Int32 nArgument ) throw( uno::RuntimeException, std::exception )
     373             : {
     374         266 :     OUString aRet;
     375             : 
     376         266 :     const ScaFuncData* pFData = pFuncDataList->Get( aProgrammaticName );
     377         266 :     if( pFData && (nArgument <= 0xFFFF) )
     378             :     {
     379         266 :         sal_uInt16 nStr = pFData->GetStrIndex( static_cast< sal_uInt16 >( nArgument ) );
     380         266 :         if( nStr )
     381         266 :             aRet = GetFuncDescrStr( pFData->GetDescrID(), nStr );
     382             :         else
     383           0 :             aRet = STR_FROM_ANSI( "internal" );
     384             :     }
     385             : 
     386         266 :     return aRet;
     387             : }
     388             : 
     389         266 : OUString SAL_CALL ScaDateAddIn::getArgumentDescription(
     390             :         const OUString& aProgrammaticName, sal_Int32 nArgument ) throw( uno::RuntimeException, std::exception )
     391             : {
     392         266 :     OUString aRet;
     393             : 
     394         266 :     const ScaFuncData* pFData = pFuncDataList->Get( aProgrammaticName );
     395         266 :     if( pFData && (nArgument <= 0xFFFF) )
     396             :     {
     397         266 :         sal_uInt16 nStr = pFData->GetStrIndex( static_cast< sal_uInt16 >( nArgument ) );
     398         266 :         if( nStr )
     399         266 :             aRet = GetFuncDescrStr( pFData->GetDescrID(), nStr + 1 );
     400             :         else
     401           0 :             aRet = STR_FROM_ANSI( "for internal use only" );
     402             :     }
     403             : 
     404         266 :     return aRet;
     405             : }
     406             : 
     407         152 : OUString SAL_CALL ScaDateAddIn::getProgrammaticCategoryName(
     408             :         const OUString& aProgrammaticName ) throw( uno::RuntimeException, std::exception )
     409             : {
     410         152 :     OUString aRet;
     411             : 
     412         152 :     const ScaFuncData* pFData = pFuncDataList->Get( aProgrammaticName );
     413         152 :     if( pFData )
     414             :     {
     415         152 :         switch( pFData->GetCategory() )
     416             :         {
     417         133 :             case ScaCat_DateTime:   aRet = STR_FROM_ANSI( "Date&Time" );    break;
     418          19 :             case ScaCat_Text:       aRet = STR_FROM_ANSI( "Text" );         break;
     419           0 :             case ScaCat_Finance:    aRet = STR_FROM_ANSI( "Financial" );    break;
     420           0 :             case ScaCat_Inf:        aRet = STR_FROM_ANSI( "Information" );  break;
     421           0 :             case ScaCat_Math:       aRet = STR_FROM_ANSI( "Mathematical" ); break;
     422           0 :             case ScaCat_Tech:       aRet = STR_FROM_ANSI( "Technical" );    break;
     423             :             // coverity[dead_error_begin] - following conditions exist to avoid compiler warning
     424             :             default:
     425           0 :                 break;
     426             :         }
     427             :     }
     428             : 
     429         152 :     if( aRet.isEmpty() )
     430           0 :         aRet = STR_FROM_ANSI( "Add-In" );
     431         152 :     return aRet;
     432             : }
     433             : 
     434           0 : OUString SAL_CALL ScaDateAddIn::getDisplayCategoryName(
     435             :         const OUString& aProgrammaticName ) throw( uno::RuntimeException, std::exception )
     436             : {
     437           0 :     return getProgrammaticCategoryName( aProgrammaticName );
     438             : }
     439             : 
     440             : // XCompatibilityNames
     441          24 : uno::Sequence< sheet::LocalizedName > SAL_CALL ScaDateAddIn::getCompatibilityNames(
     442             :         const OUString& aProgrammaticName ) throw( uno::RuntimeException, std::exception )
     443             : {
     444          24 :     const ScaFuncData* pFData = pFuncDataList->Get( aProgrammaticName );
     445          24 :     if( !pFData )
     446           0 :         return uno::Sequence< sheet::LocalizedName >( 0 );
     447             : 
     448          24 :     const ScaStringList& rStrList = pFData->GetCompNameList();
     449          24 :     sal_uInt32 nCount = rStrList.Count();
     450             : 
     451          24 :     uno::Sequence< sheet::LocalizedName > aRet( nCount );
     452          24 :     sheet::LocalizedName* pArray = aRet.getArray();
     453             : 
     454          72 :     for( sal_uInt32 nIndex = 0; nIndex < nCount; nIndex++ )
     455          48 :         pArray[ nIndex ] = sheet::LocalizedName( GetLocale( nIndex ), *rStrList.Get( nIndex ) );
     456             : 
     457          24 :     return aRet;
     458             : }
     459             : 
     460             : namespace {
     461             : 
     462             : // auxiliary functions
     463           0 : bool IsLeapYear( sal_uInt16 nYear )
     464             : {
     465           0 :     return ((((nYear % 4) == 0) && ((nYear % 100) != 0)) || ((nYear % 400) == 0));
     466             : }
     467             : 
     468           0 : sal_uInt16 DaysInMonth( sal_uInt16 nMonth, sal_uInt16 nYear )
     469             : {
     470             :     static const sal_uInt16 aDaysInMonth[12] = { 31, 28, 31, 30, 31, 30,
     471             :                                         31, 31, 30, 31, 30, 31 };
     472             : 
     473           0 :     if ( nMonth != 2 )
     474           0 :         return aDaysInMonth[nMonth-1];
     475             :     else
     476             :     {
     477           0 :         if ( IsLeapYear(nYear) )
     478           0 :             return aDaysInMonth[nMonth-1] + 1;
     479             :         else
     480           0 :             return aDaysInMonth[nMonth-1];
     481             :     }
     482             : }
     483             : 
     484             : /**
     485             :  * Convert a date to a count of days starting from 01/01/0001
     486             :  *
     487             :  * The internal representation of a Date used in this Addin
     488             :  * is the number of days between 01/01/0001 and the date
     489             :  * this function converts a Day , Month, Year representation
     490             :  * to this internal Date value.
     491             :  */
     492             : 
     493           0 : sal_Int32 DateToDays( sal_uInt16 nDay, sal_uInt16 nMonth, sal_uInt16 nYear )
     494             : {
     495           0 :     sal_Int32 nDays = ((sal_Int32)nYear-1) * 365;
     496           0 :     nDays += ((nYear-1) / 4) - ((nYear-1) / 100) + ((nYear-1) / 400);
     497             : 
     498           0 :     for( sal_uInt16 i = 1; i < nMonth; i++ )
     499           0 :         nDays += DaysInMonth(i,nYear);
     500           0 :     nDays += nDay;
     501             : 
     502           0 :     return nDays;
     503             : }
     504             : 
     505             : /**
     506             :  * Convert a count of days starting from 01/01/0001 to a date
     507             :  *
     508             :  * The internal representation of a Date used in this Addin
     509             :  * is the number of days between 01/01/0001 and the date
     510             :  * this function converts this internal Date value
     511             :  * to a Day , Month, Year representation of a Date.
     512             :  */
     513             : 
     514           0 : void DaysToDate( sal_Int32 nDays,
     515             :                 sal_uInt16& rDay, sal_uInt16& rMonth, sal_uInt16& rYear )
     516             :         throw( lang::IllegalArgumentException )
     517             : {
     518           0 :     if( nDays < 0 )
     519           0 :         throw lang::IllegalArgumentException();
     520             : 
     521             :     sal_Int32   nTempDays;
     522           0 :     sal_Int32   i = 0;
     523             :     bool    bCalc;
     524             : 
     525           0 :     do
     526             :     {
     527           0 :         nTempDays = nDays;
     528           0 :         rYear = (sal_uInt16)((nTempDays / 365) - i);
     529           0 :         nTempDays -= ((sal_Int32) rYear -1) * 365;
     530           0 :         nTempDays -= (( rYear -1) / 4) - (( rYear -1) / 100) + ((rYear -1) / 400);
     531           0 :         bCalc = false;
     532           0 :         if ( nTempDays < 1 )
     533             :         {
     534           0 :             i++;
     535           0 :             bCalc = true;
     536             :         }
     537             :         else
     538             :         {
     539           0 :             if ( nTempDays > 365 )
     540             :             {
     541           0 :                 if ( (nTempDays != 366) || !IsLeapYear( rYear ) )
     542             :                 {
     543           0 :                     i--;
     544           0 :                     bCalc = true;
     545             :                 }
     546             :             }
     547             :         }
     548             :     }
     549             :     while ( bCalc );
     550             : 
     551           0 :     rMonth = 1;
     552           0 :     while ( (sal_Int32)nTempDays > DaysInMonth( rMonth, rYear ) )
     553             :     {
     554           0 :         nTempDays -= DaysInMonth( rMonth, rYear );
     555           0 :         rMonth++;
     556             :     }
     557           0 :     rDay = (sal_uInt16)nTempDays;
     558           0 : }
     559             : 
     560             : /**
     561             :  * Get the null date used by the spreadsheet document
     562             :  *
     563             :  * The internal representation of a Date used in this Addin
     564             :  * is the number of days between 01/01/0001 and the date
     565             :  * this function returns this internal Date value for the document null date
     566             :  *
     567             :  */
     568           0 : sal_Int32 GetNullDate( const uno::Reference< beans::XPropertySet >& xOptions )
     569             :         throw( uno::RuntimeException )
     570             : {
     571           0 :     if (xOptions.is())
     572             :     {
     573             :         try
     574             :         {
     575           0 :             uno::Any aAny = xOptions->getPropertyValue(
     576           0 :                                         OUString( "NullDate" ) );
     577           0 :             util::Date aDate;
     578           0 :             if ( aAny >>= aDate )
     579           0 :                 return DateToDays( aDate.Day, aDate.Month, aDate.Year );
     580             :         }
     581           0 :         catch (uno::Exception&)
     582             :         {
     583             :         }
     584             :     }
     585             : 
     586             :     // no null date available -> no calculations possible
     587           0 :     throw uno::RuntimeException();
     588             : }
     589             : 
     590             : }
     591             : // XDateFunctions
     592             : 
     593             : /**
     594             :  * Get week difference between 2 dates
     595             :  *
     596             :  * new Weeks(date1,date2,mode) function for StarCalc
     597             :  *
     598             :  * Two modes of operation are provided.
     599             :  * The first is just a simple division by 7 calculation.
     600             :  *
     601             :  * The second calculates the diffence by week of year.
     602             :  *
     603             :  * The International Standard IS-8601 has decreed that Monday
     604             :  * shall be the first day of the week.
     605             :  *
     606             :  * A week that lies partly in one year and partly in annother
     607             :  * is assigned a number in the year in which most of its days lie.
     608             :  *
     609             :  * That means that week 1 of any year is the week that contains the 4. January
     610             :  *
     611             :  * The internal representation of a Date used in the Addin is the number of days based on 01/01/0001
     612             :  *
     613             :  * A WeekDay can be then calculated by subtracting 1 and calculating the rest of
     614             :  * a division by 7, which gives a 0 - 6 value for Monday - Sunday
     615             :  *
     616             :  * Using the 4. January rule explained above the formula
     617             :  *
     618             :  *  nWeek1= ( nDays1 - nJan4 + ( (nJan4-1) % 7 ) ) / 7 + 1;
     619             :  *
     620             :  * calculates a number between 0-53 for each day which is in the same year as nJan4
     621             :  * where 0 means that this week belonged to the year before.
     622             :  *
     623             :  * If a day in the same or another year is used in this formula this calculates
     624             :  * an calendar week offset from a given 4. January
     625             :  *
     626             :  *  nWeek2 = ( nDays2 - nJan4 + ( (nJan4-1) % 7 ) ) / 7 + 1;
     627             :  *
     628             :  * The 4.January of first Date Argument can thus be used to calculate
     629             :  * the week difference by calendar weeks which is then nWeek = nWeek2 - nWeek1
     630             :  *
     631             :  * which can be optimized to
     632             :  *
     633             :  * nWeek = ( (nDays2-nJan4+((nJan4-1)%7))/7 ) - ( (nDays1-nJan4+((nJan4-1)%7))/7 )
     634             :  *
     635             :  * Note: All calculations are operating on the long integer data type
     636             :  * % is the modulo operator in C which calculates the rest of an Integer division
     637             :  *
     638             :  *
     639             :  * mode 0 is the interval between the dates in month, that is days / 7
     640             :  *
     641             :  * mode 1 is the difference by week of year
     642             :  *
     643             :  */
     644             : 
     645           0 : sal_Int32 SAL_CALL ScaDateAddIn::getDiffWeeks(
     646             :         const uno::Reference< beans::XPropertySet >& xOptions,
     647             :         sal_Int32 nStartDate, sal_Int32 nEndDate,
     648             :         sal_Int32 nMode ) throw( uno::RuntimeException, lang::IllegalArgumentException, std::exception )
     649             : {
     650           0 :     sal_Int32 nNullDate = GetNullDate( xOptions );
     651             : 
     652           0 :     sal_Int32 nDays1 = nStartDate + nNullDate;
     653           0 :     sal_Int32 nDays2 = nEndDate + nNullDate;
     654             : 
     655             :     sal_Int32 nRet;
     656             : 
     657           0 :     if ( nMode == 1 )
     658             :     {
     659             :         sal_uInt16 nDay,nMonth,nYear;
     660           0 :         DaysToDate( nDays1, nDay, nMonth, nYear );
     661           0 :         sal_Int32 nJan4 = DateToDays( 4, 1, nYear );
     662             : 
     663           0 :         nRet = ( (nDays2-nJan4+((nJan4-1)%7))/7 ) - ( (nDays1-nJan4+((nJan4-1)%7))/7 );
     664             :     }
     665             :     else
     666             :     {
     667           0 :         nRet = (nDays2 - nDays1) / 7;
     668             :     }
     669           0 :     return nRet;
     670             : }
     671             : 
     672             : /**
     673             :  * Get month difference between 2 dates
     674             :  * =Month(start, end, mode) Function for StarCalc
     675             :  *
     676             :  * two modes are provided
     677             :  *
     678             :  * mode 0 is the interval between the dates in month
     679             :  *
     680             :  * mode 1 is the difference in calendar month
     681             :  */
     682           0 : sal_Int32 SAL_CALL ScaDateAddIn::getDiffMonths(
     683             :         const uno::Reference< beans::XPropertySet >& xOptions,
     684             :         sal_Int32 nStartDate, sal_Int32 nEndDate,
     685             :         sal_Int32 nMode ) throw( uno::RuntimeException, lang::IllegalArgumentException, std::exception )
     686             : {
     687           0 :     sal_Int32 nNullDate = GetNullDate( xOptions );
     688             : 
     689           0 :     sal_Int32 nDays1 = nStartDate + nNullDate;
     690           0 :     sal_Int32 nDays2 = nEndDate + nNullDate;
     691             : 
     692             :     sal_uInt16 nDay1,nMonth1,nYear1;
     693             :     sal_uInt16 nDay2,nMonth2,nYear2;
     694           0 :     DaysToDate(nDays1,nDay1,nMonth1,nYear1);
     695           0 :     DaysToDate(nDays2,nDay2,nMonth2,nYear2);
     696             : 
     697           0 :     sal_Int32 nRet = nMonth2 - nMonth1 + (nYear2 - nYear1) * 12;
     698           0 :     if ( nMode == 1 || nDays1 == nDays2 ) return nRet;
     699             : 
     700           0 :     if ( nDays1 < nDays2 )
     701             :     {
     702           0 :         if ( nDay1 > nDay2 )
     703             :         {
     704           0 :             nRet -= 1;
     705             :         }
     706             :     }
     707             :     else
     708             :     {
     709           0 :         if ( nDay1 < nDay2 )
     710             :         {
     711           0 :             nRet += 1;
     712             :         }
     713             :     }
     714             : 
     715           0 :     return nRet;
     716             : }
     717             : 
     718             : /**
     719             :  * Get Year difference between 2 dates
     720             :  *
     721             :  * two modes are provided
     722             :  *
     723             :  * mode 0 is the interval between the dates in years
     724             :  *
     725             :  * mode 1 is the difference in calendar years
     726             :  */
     727           0 : sal_Int32 SAL_CALL ScaDateAddIn::getDiffYears(
     728             :         const uno::Reference< beans::XPropertySet >& xOptions,
     729             :         sal_Int32 nStartDate, sal_Int32 nEndDate,
     730             :         sal_Int32 nMode ) throw( uno::RuntimeException, lang::IllegalArgumentException, std::exception )
     731             : {
     732           0 :     if ( nMode != 1 )
     733           0 :         return getDiffMonths( xOptions, nStartDate, nEndDate, nMode ) / 12;
     734             : 
     735           0 :     sal_Int32 nNullDate = GetNullDate( xOptions );
     736             : 
     737           0 :     sal_Int32 nDays1 = nStartDate + nNullDate;
     738           0 :     sal_Int32 nDays2 = nEndDate + nNullDate;
     739             : 
     740             :     sal_uInt16 nDay1,nMonth1,nYear1;
     741             :     sal_uInt16 nDay2,nMonth2,nYear2;
     742           0 :     DaysToDate(nDays1,nDay1,nMonth1,nYear1);
     743           0 :     DaysToDate(nDays2,nDay2,nMonth2,nYear2);
     744             : 
     745           0 :     return nYear2 - nYear1;
     746             : }
     747             : 
     748             : /**
     749             :  * Check if a Date is in a leap year in the Gregorian calendar
     750             :  */
     751           0 : sal_Int32 SAL_CALL ScaDateAddIn::getIsLeapYear(
     752             :         const uno::Reference< beans::XPropertySet >& xOptions,
     753             :         sal_Int32 nDate ) throw( uno::RuntimeException, lang::IllegalArgumentException, std::exception )
     754             : {
     755           0 :     sal_Int32 nNullDate = GetNullDate( xOptions );
     756           0 :     sal_Int32 nDays = nDate + nNullDate;
     757             : 
     758             :     sal_uInt16 nDay, nMonth, nYear;
     759           0 :     DaysToDate(nDays,nDay,nMonth,nYear);
     760             : 
     761           0 :     return (sal_Int32)IsLeapYear(nYear);
     762             : }
     763             : 
     764             : /**
     765             :  * Get the Number of Days in the month for a date
     766             :  */
     767           0 : sal_Int32 SAL_CALL ScaDateAddIn::getDaysInMonth(
     768             :         const uno::Reference<beans::XPropertySet>& xOptions,
     769             :         sal_Int32 nDate ) throw( uno::RuntimeException, lang::IllegalArgumentException, std::exception )
     770             : {
     771           0 :     sal_Int32 nNullDate = GetNullDate( xOptions );
     772           0 :     sal_Int32 nDays = nDate + nNullDate;
     773             : 
     774             :     sal_uInt16 nDay, nMonth, nYear;
     775           0 :     DaysToDate(nDays,nDay,nMonth,nYear);
     776             : 
     777           0 :     return DaysInMonth( nMonth, nYear );
     778             : }
     779             : 
     780             : /**
     781             :  * Get number of days in the year of a date specified
     782             :  */
     783           0 : sal_Int32 SAL_CALL ScaDateAddIn::getDaysInYear(
     784             :         const uno::Reference< beans::XPropertySet >& xOptions,
     785             :         sal_Int32 nDate ) throw( uno::RuntimeException, lang::IllegalArgumentException, std::exception )
     786             : {
     787           0 :     sal_Int32 nNullDate = GetNullDate( xOptions );
     788           0 :     sal_Int32 nDays = nDate + nNullDate;
     789             : 
     790             :     sal_uInt16 nDay, nMonth, nYear;
     791           0 :     DaysToDate(nDays,nDay,nMonth,nYear);
     792             : 
     793           0 :     return ( IsLeapYear(nYear) ? 366 : 365 );
     794             : }
     795             : 
     796             : /**
     797             :  * Get number of weeks in the year for a date
     798             :  *
     799             :  * Most years have 52 weeks, but years that start on a Thursday
     800             :  * and leep years that start on a Wednesday have 53 weeks
     801             :  *
     802             :  * The International Standard IS-8601 has decreed that Monday
     803             :  * shall be the first day of the week.
     804             :  *
     805             :  * A WeekDay can be calculated by subtracting 1 and calculating the rest of
     806             :  * a division by 7 from the internal date represention
     807             :  * which gives a 0 - 6 value for Monday - Sunday
     808             :  *
     809             :  * @see #IsLeapYear #WeekNumber
     810             :  */
     811           0 : sal_Int32 SAL_CALL ScaDateAddIn::getWeeksInYear(
     812             :         const uno::Reference< beans::XPropertySet >& xOptions,
     813             :         sal_Int32 nDate ) throw( uno::RuntimeException, lang::IllegalArgumentException, std::exception )
     814             : {
     815           0 :     sal_Int32 nNullDate = GetNullDate( xOptions );
     816           0 :     sal_Int32 nDays = nDate + nNullDate;
     817             : 
     818             :     sal_uInt16 nDay, nMonth, nYear;
     819           0 :     DaysToDate(nDays,nDay,nMonth,nYear);
     820             : 
     821           0 :     sal_Int32 nJan1WeekDay = ( DateToDays(1,1,nYear) - 1) % 7;
     822             : 
     823             :     sal_Int32 nRet;
     824           0 :     if ( nJan1WeekDay == 3 )        /* Thursday */
     825           0 :         nRet = 53;
     826           0 :     else if ( nJan1WeekDay == 2 )   /* Wednesday */
     827           0 :         nRet = ( IsLeapYear(nYear) ? 53 : 52 );
     828             :     else
     829           0 :         nRet = 52;
     830             : 
     831           0 :     return nRet;
     832             : }
     833             : 
     834             : /**
     835             :  * Encrypt or decrypt a string using ROT13 algorithm
     836             :  *
     837             :  * This function rotates each character by 13 in the alphabet.
     838             :  * Only the characters 'a' ... 'z' and 'A' ... 'Z' are modified.
     839             :  */
     840           3 : OUString SAL_CALL ScaDateAddIn::getRot13( const OUString& aSrcString ) throw( uno::RuntimeException, lang::IllegalArgumentException, std::exception )
     841             : {
     842           3 :     OUStringBuffer aBuffer( aSrcString );
     843          18 :     for( sal_Int32 nIndex = 0; nIndex < aBuffer.getLength(); nIndex++ )
     844             :     {
     845          15 :         sal_Unicode cChar = aBuffer[nIndex];
     846          21 :         if( ((cChar >= 'a') && (cChar <= 'z') && ((cChar += 13) > 'z')) ||
     847           9 :             ((cChar >= 'A') && (cChar <= 'Z') && ((cChar += 13) > 'Z')) )
     848           6 :             cChar -= 26;
     849          15 :         aBuffer[nIndex] = cChar;
     850             :     }
     851           3 :     return aBuffer.makeStringAndClear();
     852             : }
     853             : 
     854             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11