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

Generated by: LCOV version 1.10