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