diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
commit | ed5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch) | |
tree | 7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /scaddins/source/datefunc | |
parent | Initial commit. (diff) | |
download | libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.tar.xz libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.zip |
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'scaddins/source/datefunc')
-rw-r--r-- | scaddins/source/datefunc/date.component | 27 | ||||
-rw-r--r-- | scaddins/source/datefunc/datefunc.cxx | 688 | ||||
-rw-r--r-- | scaddins/source/datefunc/datefunc.hxx | 189 | ||||
-rw-r--r-- | scaddins/source/datefunc/deffuncname.hxx | 70 |
4 files changed, 974 insertions, 0 deletions
diff --git a/scaddins/source/datefunc/date.component b/scaddins/source/datefunc/date.component new file mode 100644 index 000000000..7337d98c9 --- /dev/null +++ b/scaddins/source/datefunc/date.component @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + --> + +<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.sheet.addin.DateFunctionsImpl" + constructor="scaddins_ScaDateAddIn_get_implementation" single-instance="true"> + <service name="com.sun.star.sheet.AddIn"/> + <service name="com.sun.star.sheet.addin.DateFunctions"/> + </implementation> +</component> diff --git a/scaddins/source/datefunc/datefunc.cxx b/scaddins/source/datefunc/datefunc.cxx new file mode 100644 index 000000000..92492b29d --- /dev/null +++ b/scaddins/source/datefunc/datefunc.cxx @@ -0,0 +1,688 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "datefunc.hxx" +#include <datefunc.hrc> +#include <strings.hrc> +#include <com/sun/star/util/Date.hpp> +#include <cppuhelper/factory.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <cppuhelper/weak.hxx> +#include <rtl/ustrbuf.hxx> +#include <unotools/resmgr.hxx> +#include <i18nlangtag/languagetag.hxx> +#include <algorithm> +#include <cmath> +#include "deffuncname.hxx" + +using namespace ::com::sun::star; + +constexpr OUStringLiteral ADDIN_SERVICE = u"com.sun.star.sheet.AddIn"; +constexpr OUStringLiteral MY_SERVICE = u"com.sun.star.sheet.addin.DateFunctions"; +constexpr OUStringLiteral MY_IMPLNAME = u"com.sun.star.sheet.addin.DateFunctionsImpl"; + +#define UNIQUE false // function name does not exist in Calc + +#define STDPAR false // all parameters are described +#define INTPAR true // first parameter is internal + +#define FUNCDATA( FuncName, ParamCount, Category, Double, IntPar ) \ + { "get" #FuncName, DATE_FUNCNAME_##FuncName, DATE_FUNCDESC_##FuncName, DATE_DEFFUNCNAME_##FuncName, ParamCount, Category, Double, IntPar } + +const ScaFuncDataBase pFuncDataArr[] = +{ + FUNCDATA( DiffWeeks, 3, ScaCategory::DateTime, UNIQUE, INTPAR ), + FUNCDATA( DiffMonths, 3, ScaCategory::DateTime, UNIQUE, INTPAR ), + FUNCDATA( DiffYears, 3, ScaCategory::DateTime, UNIQUE, INTPAR ), + FUNCDATA( IsLeapYear, 1, ScaCategory::DateTime, UNIQUE, INTPAR ), + FUNCDATA( DaysInMonth, 1, ScaCategory::DateTime, UNIQUE, INTPAR ), + FUNCDATA( DaysInYear, 1, ScaCategory::DateTime, UNIQUE, INTPAR ), + FUNCDATA( WeeksInYear, 1, ScaCategory::DateTime, UNIQUE, INTPAR ), + FUNCDATA( Rot13, 1, ScaCategory::Text, UNIQUE, STDPAR ) +}; + +#undef FUNCDATA + +ScaFuncData::ScaFuncData(const ScaFuncDataBase& rBaseData) : + aIntName( OUString::createFromAscii( rBaseData.pIntName ) ), + pUINameID( rBaseData.pUINameID ), + pDescrID( rBaseData.pDescrID ), + nParamCount( rBaseData.nParamCount ), + eCat( rBaseData.eCat ), + bDouble( rBaseData.bDouble ), + bWithOpt( rBaseData.bWithOpt ) +{ + aCompList.push_back(OUString::createFromAscii(rBaseData.pCompListID[0])); + aCompList.push_back(OUString::createFromAscii(rBaseData.pCompListID[1])); +} + +sal_uInt16 ScaFuncData::GetStrIndex( sal_uInt16 nParam ) const +{ + if( !bWithOpt ) + nParam++; + return (nParam > nParamCount) ? (nParamCount * 2) : (nParam * 2); +} + +static void InitScaFuncDataList(ScaFuncDataList& rList) +{ + for (const auto & nIndex : pFuncDataArr) + rList.push_back(ScaFuncData(nIndex)); +} + +// entry points for service registration / instantiation + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +scaddins_ScaDateAddIn_get_implementation( + css::uno::XComponentContext* , css::uno::Sequence<css::uno::Any> const&) +{ + return cppu::acquire(new ScaDateAddIn()); +} + + +// "normal" service implementation +ScaDateAddIn::ScaDateAddIn() +{ +} + +static const char* pLang[] = { "de", "en" }; +static const char* pCoun[] = { "DE", "US" }; +const sal_uInt32 nNumOfLoc = SAL_N_ELEMENTS( pLang ); + +void ScaDateAddIn::InitDefLocales() +{ + pDefLocales.reset(new lang::Locale[ nNumOfLoc ]); + + for( sal_uInt32 nIndex = 0; nIndex < nNumOfLoc; nIndex++ ) + { + pDefLocales[ nIndex ].Language = OUString::createFromAscii( pLang[ nIndex ] ); + pDefLocales[ nIndex ].Country = OUString::createFromAscii( pCoun[ nIndex ] ); + } +} + +const lang::Locale& ScaDateAddIn::GetLocale( sal_uInt32 nIndex ) +{ + if( !pDefLocales ) + InitDefLocales(); + + return (nIndex < nNumOfLoc) ? pDefLocales[ nIndex ] : aFuncLoc; +} + +void ScaDateAddIn::InitData() +{ + aResLocale = Translate::Create("sca", LanguageTag(aFuncLoc)); + pFuncDataList.reset(); + + pFuncDataList.reset(new ScaFuncDataList); + InitScaFuncDataList(*pFuncDataList); + + if( pDefLocales ) + { + pDefLocales.reset(); + } +} + +OUString ScaDateAddIn::GetFuncDescrStr(const TranslateId* pResId, sal_uInt16 nStrIndex) +{ + return ScaResId(pResId[nStrIndex - 1]); +} + +// XServiceName +OUString SAL_CALL ScaDateAddIn::getServiceName() +{ + // name of specific AddIn service + return MY_SERVICE; +} + +// XServiceInfo +OUString SAL_CALL ScaDateAddIn::getImplementationName() +{ + return MY_IMPLNAME; +} + +sal_Bool SAL_CALL ScaDateAddIn::supportsService( const OUString& aServiceName ) +{ + return cppu::supportsService(this, aServiceName); +} + +uno::Sequence< OUString > SAL_CALL ScaDateAddIn::getSupportedServiceNames() +{ + return { ADDIN_SERVICE, MY_SERVICE }; +} + +// XLocalizable +void SAL_CALL ScaDateAddIn::setLocale( const lang::Locale& eLocale ) +{ + aFuncLoc = eLocale; + InitData(); // change of locale invalidates resources! +} + +lang::Locale SAL_CALL ScaDateAddIn::getLocale() +{ + return aFuncLoc; +} + +OUString SAL_CALL ScaDateAddIn::getProgrammaticFuntionName( const OUString& ) +{ + // not used by calc + // (but should be implemented for other uses of the AddIn service) + return OUString(); +} + +OUString SAL_CALL ScaDateAddIn::getDisplayFunctionName( const OUString& aProgrammaticName ) +{ + OUString aRet; + + auto fDataIt = std::find_if(pFuncDataList->begin(), pFuncDataList->end(), + FindScaFuncData( aProgrammaticName ) ); + if( fDataIt != pFuncDataList->end() ) + { + aRet = ScaResId(fDataIt->GetUINameID()); + if( fDataIt->IsDouble() ) + aRet += "_ADD"; + } + else + { + aRet = "UNKNOWNFUNC_" + aProgrammaticName; + } + + return aRet; +} + +OUString SAL_CALL ScaDateAddIn::getFunctionDescription( const OUString& aProgrammaticName ) +{ + OUString aRet; + + auto fDataIt = std::find_if(pFuncDataList->begin(), pFuncDataList->end(), + FindScaFuncData( aProgrammaticName ) ); + if( fDataIt != pFuncDataList->end() ) + aRet = GetFuncDescrStr( fDataIt->GetDescrID(), 1 ); + + return aRet; +} + +OUString SAL_CALL ScaDateAddIn::getDisplayArgumentName( + const OUString& aProgrammaticName, sal_Int32 nArgument ) +{ + OUString aRet; + + auto fDataIt = std::find_if(pFuncDataList->begin(), pFuncDataList->end(), + FindScaFuncData( aProgrammaticName ) ); + if( fDataIt != pFuncDataList->end() && (nArgument <= 0xFFFF) ) + { + sal_uInt16 nStr = fDataIt->GetStrIndex( static_cast< sal_uInt16 >( nArgument ) ); + if( nStr ) + aRet = GetFuncDescrStr( fDataIt->GetDescrID(), nStr ); + else + aRet = "internal"; + } + + return aRet; +} + +OUString SAL_CALL ScaDateAddIn::getArgumentDescription( + const OUString& aProgrammaticName, sal_Int32 nArgument ) +{ + OUString aRet; + + auto fDataIt = std::find_if(pFuncDataList->begin(), pFuncDataList->end(), + FindScaFuncData( aProgrammaticName ) ); + if( fDataIt != pFuncDataList->end() && (nArgument <= 0xFFFF) ) + { + sal_uInt16 nStr = fDataIt->GetStrIndex( static_cast< sal_uInt16 >( nArgument ) ); + if( nStr ) + aRet = GetFuncDescrStr( fDataIt->GetDescrID(), nStr + 1 ); + else + aRet = "for internal use only"; + } + + return aRet; +} + +OUString SAL_CALL ScaDateAddIn::getProgrammaticCategoryName( + const OUString& aProgrammaticName ) +{ + OUString aRet; + + auto fDataIt = std::find_if(pFuncDataList->begin(), pFuncDataList->end(), + FindScaFuncData( aProgrammaticName ) ); + if( fDataIt != pFuncDataList->end() ) + { + switch( fDataIt->GetCategory() ) + { + case ScaCategory::DateTime: aRet = "Date&Time"; break; + case ScaCategory::Text: aRet = "Text"; break; + case ScaCategory::Finance: aRet = "Financial"; break; + case ScaCategory::Inf: aRet = "Information"; break; + case ScaCategory::Math: aRet = "Mathematical"; break; + case ScaCategory::Tech: aRet = "Technical"; break; + } + } + + if( aRet.isEmpty() ) + aRet = "Add-In"; + return aRet; +} + +OUString SAL_CALL ScaDateAddIn::getDisplayCategoryName( + const OUString& aProgrammaticName ) +{ + return getProgrammaticCategoryName( aProgrammaticName ); +} + +// XCompatibilityNames +uno::Sequence< sheet::LocalizedName > SAL_CALL ScaDateAddIn::getCompatibilityNames( + const OUString& aProgrammaticName ) +{ + auto fDataIt = std::find_if(pFuncDataList->begin(), pFuncDataList->end(), + FindScaFuncData( aProgrammaticName ) ); + if( fDataIt == pFuncDataList->end() ) + return uno::Sequence< sheet::LocalizedName >( 0 ); + + const std::vector<OUString>& rStrList = fDataIt->GetCompNameList(); + sal_uInt32 nCount = rStrList.size(); + + uno::Sequence< sheet::LocalizedName > aRet( nCount ); + sheet::LocalizedName* pArray = aRet.getArray(); + + for( sal_uInt32 nIndex = 0; nIndex < nCount; nIndex++ ) + pArray[ nIndex ] = sheet::LocalizedName( GetLocale( nIndex ), rStrList.at( nIndex ) ); + + return aRet; +} + +namespace { + +// auxiliary functions +bool IsLeapYear( sal_uInt16 nYear ) +{ + return ((((nYear % 4) == 0) && ((nYear % 100) != 0)) || ((nYear % 400) == 0)); +} + +sal_uInt16 DaysInMonth( sal_uInt16 nMonth, sal_uInt16 nYear ) +{ + static const sal_uInt16 aDaysInMonth[12] = { 31, 28, 31, 30, 31, 30, + 31, 31, 30, 31, 30, 31 }; + + if ( nMonth != 2 ) + return aDaysInMonth[nMonth-1]; + else + { + if ( IsLeapYear(nYear) ) + return aDaysInMonth[nMonth-1] + 1; + else + return aDaysInMonth[nMonth-1]; + } +} + +/** + * Convert a date to a count of days starting from 01/01/0001 + * + * The internal representation of a Date used in this Addin + * is the number of days between 01/01/0001 and the date + * this function converts a Day , Month, Year representation + * to this internal Date value. + */ + +sal_Int32 DateToDays( sal_uInt16 nDay, sal_uInt16 nMonth, sal_uInt16 nYear ) +{ + sal_Int32 nDays = (static_cast<sal_Int32>(nYear)-1) * 365; + nDays += ((nYear-1) / 4) - ((nYear-1) / 100) + ((nYear-1) / 400); + + for( sal_uInt16 i = 1; i < nMonth; i++ ) + nDays += DaysInMonth(i,nYear); + nDays += nDay; + + return nDays; +} + +/** + * Convert a count of days starting from 01/01/0001 to a date + * + * The internal representation of a Date used in this Addin + * is the number of days between 01/01/0001 and the date + * this function converts this internal Date value + * to a Day , Month, Year representation of a Date. + * + * @throws lang::IllegalArgumentException + */ + +void DaysToDate( sal_Int32 nDays, + sal_uInt16& rDay, sal_uInt16& rMonth, sal_uInt16& rYear ) +{ + if( nDays < 0 ) + throw lang::IllegalArgumentException(); + + sal_Int32 nTempDays; + sal_Int32 i = 0; + bool bCalc; + + do + { + nTempDays = nDays; + rYear = static_cast<sal_uInt16>((nTempDays / 365) - i); + nTempDays -= (static_cast<sal_Int32>(rYear) -1) * 365; + nTempDays -= (( rYear -1) / 4) - (( rYear -1) / 100) + ((rYear -1) / 400); + bCalc = false; + if ( nTempDays < 1 ) + { + i++; + bCalc = true; + } + else + { + if ( nTempDays > 365 ) + { + if ( (nTempDays != 366) || !IsLeapYear( rYear ) ) + { + i--; + bCalc = true; + } + } + } + } + while ( bCalc ); + + rMonth = 1; + while ( nTempDays > DaysInMonth( rMonth, rYear ) ) + { + nTempDays -= DaysInMonth( rMonth, rYear ); + rMonth++; + } + rDay = static_cast<sal_uInt16>(nTempDays); +} + +/** + * Get the null date used by the spreadsheet document + * + * The internal representation of a Date used in this Addin + * is the number of days between 01/01/0001 and the date + * this function returns this internal Date value for the document null date + * + * @throws uno::RuntimeException + */ +sal_Int32 GetNullDate( const uno::Reference< beans::XPropertySet >& xOptions ) +{ + if (xOptions.is()) + { + try + { + uno::Any aAny = xOptions->getPropertyValue( "NullDate" ); + util::Date aDate; + if ( aAny >>= aDate ) + return DateToDays( aDate.Day, aDate.Month, aDate.Year ); + } + catch (uno::Exception&) + { + } + } + + // no null date available -> no calculations possible + throw uno::RuntimeException(); +} + +} +// XDateFunctions + +/** + * Get week difference between 2 dates + * + * new Weeks(date1,date2,mode) function for StarCalc + * + * Two modes of operation are provided. + * mode 0 is just a simple division by 7 calculation. + * + * mode 1 calculates the difference by week adhering to ISO8601. + * + * The International Standard IS-8601 states that Monday is the first + * day of the week. The Gregorian Calendar is used for all dates, + * proleptic in case of dates before 1582-10-15. + * + * The (consecutive) week number of a date is + * std::floor( (date + NullDate - 1), 7.0 ), + * with weeks starting on Monday, and week 0 + * starting on Monday, 0001-01-01 Gregorian. + * + * Weeks(d2,d1,m) is defined as -Weeks(d1,d2,m). + * + */ + +sal_Int32 SAL_CALL ScaDateAddIn::getDiffWeeks( + const uno::Reference< beans::XPropertySet >& xOptions, + sal_Int32 nStartDate, sal_Int32 nEndDate, + sal_Int32 nMode ) +{ + if ( nMode == 0 ) + { + return ( nEndDate - nStartDate ) / 7; + } + else if ( nMode == 1 ) + { + sal_Int32 nNullDate = GetNullDate( xOptions ); + sal_Int32 nDays1 = nStartDate + nNullDate - 1; + sal_Int32 nDays2 = nEndDate + nNullDate - 1; + + return ( std::floor( nDays2 / 7.0 ) - std::floor( nDays1 / 7.0 ) ); + } + else + throw lang::IllegalArgumentException(); +} + +/** + * Get month difference between 2 dates + * =Month(start, end, mode) Function for StarCalc + * + * two modes are provided + * + * mode 0 is the interval between the dates in month + * + * mode 1 is the difference in calendar month + */ +sal_Int32 SAL_CALL ScaDateAddIn::getDiffMonths( + const uno::Reference< beans::XPropertySet >& xOptions, + sal_Int32 nStartDate, sal_Int32 nEndDate, + sal_Int32 nMode ) +{ + if (nMode != 0 && nMode != 1) + throw lang::IllegalArgumentException(); + + sal_Int32 nNullDate = GetNullDate( xOptions ); + + sal_Int32 nDays1 = nStartDate + nNullDate; + sal_Int32 nDays2 = nEndDate + nNullDate; + + sal_uInt16 nDay1,nMonth1,nYear1; + sal_uInt16 nDay2,nMonth2,nYear2; + DaysToDate(nDays1,nDay1,nMonth1,nYear1); + DaysToDate(nDays2,nDay2,nMonth2,nYear2); + + sal_Int32 nRet = nMonth2 - nMonth1 + (nYear2 - nYear1) * 12; + if ( nMode == 1 || nDays1 == nDays2 ) return nRet; + + if ( nDays1 < nDays2 ) + { + if ( nDay1 > nDay2 ) + { + nRet -= 1; + } + } + else + { + if ( nDay1 < nDay2 ) + { + nRet += 1; + } + } + + return nRet; +} + +/** + * Get Year difference between 2 dates + * + * two modes are provided + * + * mode 0 is the interval between the dates in years + * + * mode 1 is the difference in calendar years + */ +sal_Int32 SAL_CALL ScaDateAddIn::getDiffYears( + const uno::Reference< beans::XPropertySet >& xOptions, + sal_Int32 nStartDate, sal_Int32 nEndDate, + sal_Int32 nMode ) +{ + if (nMode != 0 && nMode != 1) + throw lang::IllegalArgumentException(); + + if ( nMode != 1 ) + return getDiffMonths( xOptions, nStartDate, nEndDate, nMode ) / 12; + + sal_Int32 nNullDate = GetNullDate( xOptions ); + + sal_Int32 nDays1 = nStartDate + nNullDate; + sal_Int32 nDays2 = nEndDate + nNullDate; + + sal_uInt16 nDay1,nMonth1,nYear1; + sal_uInt16 nDay2,nMonth2,nYear2; + DaysToDate(nDays1,nDay1,nMonth1,nYear1); + DaysToDate(nDays2,nDay2,nMonth2,nYear2); + + return nYear2 - nYear1; +} + +/** + * Check if a Date is in a leap year in the Gregorian calendar + */ +sal_Int32 SAL_CALL ScaDateAddIn::getIsLeapYear( + const uno::Reference< beans::XPropertySet >& xOptions, + sal_Int32 nDate ) +{ + sal_Int32 nNullDate = GetNullDate( xOptions ); + sal_Int32 nDays = nDate + nNullDate; + + sal_uInt16 nDay, nMonth, nYear; + DaysToDate(nDays,nDay,nMonth,nYear); + + return static_cast<sal_Int32>(IsLeapYear(nYear)); +} + +/** + * Get the Number of Days in the month for a date + */ +sal_Int32 SAL_CALL ScaDateAddIn::getDaysInMonth( + const uno::Reference<beans::XPropertySet>& xOptions, + sal_Int32 nDate ) +{ + sal_Int32 nNullDate = GetNullDate( xOptions ); + sal_Int32 nDays = nDate + nNullDate; + + sal_uInt16 nDay, nMonth, nYear; + DaysToDate(nDays,nDay,nMonth,nYear); + + return DaysInMonth( nMonth, nYear ); +} + +/** + * Get number of days in the year of a date specified + */ +sal_Int32 SAL_CALL ScaDateAddIn::getDaysInYear( + const uno::Reference< beans::XPropertySet >& xOptions, + sal_Int32 nDate ) +{ + sal_Int32 nNullDate = GetNullDate( xOptions ); + sal_Int32 nDays = nDate + nNullDate; + + sal_uInt16 nDay, nMonth, nYear; + DaysToDate(nDays,nDay,nMonth,nYear); + + return ( IsLeapYear(nYear) ? 366 : 365 ); +} + +/** + * Get number of weeks in the year for a date + * + * Most years have 52 weeks, but years that start on a Thursday + * and leap years that start on a Wednesday have 53 weeks + * + * The International Standard IS-8601 has decreed that Monday + * shall be the first day of the week. + * + * A WeekDay can be calculated by subtracting 1 and calculating the rest of + * a division by 7 from the internal date representation + * which gives a 0 - 6 value for Monday - Sunday + * + * @see #IsLeapYear #WeekNumber + */ +sal_Int32 SAL_CALL ScaDateAddIn::getWeeksInYear( + const uno::Reference< beans::XPropertySet >& xOptions, + sal_Int32 nDate ) +{ + sal_Int32 nNullDate = GetNullDate( xOptions ); + sal_Int32 nDays = nDate + nNullDate; + + sal_uInt16 nDay, nMonth, nYear; + DaysToDate(nDays,nDay,nMonth,nYear); + + sal_Int32 nJan1WeekDay = ( DateToDays(1,1,nYear) - 1) % 7; + + sal_Int32 nRet; + if ( nJan1WeekDay == 3 ) /* Thursday */ + nRet = 53; + else if ( nJan1WeekDay == 2 ) /* Wednesday */ + nRet = ( IsLeapYear(nYear) ? 53 : 52 ); + else + nRet = 52; + + return nRet; +} + +/** + * Encrypt or decrypt a string using ROT13 algorithm + * + * This function rotates each character by 13 in the alphabet. + * Only the characters 'a' ... 'z' and 'A' ... 'Z' are modified. + */ +OUString SAL_CALL ScaDateAddIn::getRot13( const OUString& aSrcString ) +{ + OUStringBuffer aBuffer( aSrcString ); + for( sal_Int32 nIndex = 0; nIndex < aBuffer.getLength(); nIndex++ ) + { + sal_Unicode cChar = aBuffer[nIndex]; + if( (cChar >= 'a') && (cChar <= 'z')) + { + cChar += 13; + if (cChar > 'z') + cChar -= 26; + } + else if( (cChar >= 'A') && (cChar <= 'Z') ) + { + cChar += 13; + if (cChar > 'Z') + cChar -= 26; + } + aBuffer[nIndex] = cChar; + } + return aBuffer.makeStringAndClear(); +} + +OUString ScaDateAddIn::ScaResId(TranslateId aId) +{ + return Translate::get(aId, aResLocale); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/scaddins/source/datefunc/datefunc.hxx b/scaddins/source/datefunc/datefunc.hxx new file mode 100644 index 000000000..0dd6b5fa2 --- /dev/null +++ b/scaddins/source/datefunc/datefunc.hxx @@ -0,0 +1,189 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +// date functions add in + +#pragma once + +#include <vector> +#include <memory> +#include <com/sun/star/lang/XServiceName.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/sheet/XAddIn.hpp> +#include <com/sun/star/sheet/XCompatibilityNames.hpp> +#include <com/sun/star/sheet/addin/XDateFunctions.hpp> +#include <com/sun/star/sheet/addin/XMiscFunctions.hpp> +#include <cppuhelper/implbase.hxx> +#include <unotools/resmgr.hxx> + +namespace com::sun::star::lang { class XMultiServiceFactory; } + +enum class ScaCategory +{ + DateTime, + Text, + Finance, + Inf, + Math, + Tech +}; + +struct ScaFuncDataBase +{ + const char* pIntName; // internal name (get***) + TranslateId pUINameID; // resource ID to UI name + const TranslateId* pDescrID; // resource ID to description, parameter names and ~ description + const char** pCompListID; // list of valid names + sal_uInt16 nParamCount; // number of named / described parameters + ScaCategory eCat; // function category + bool bDouble; // name already exist in Calc + bool bWithOpt; // first parameter is internal +}; + +class ScaFuncData final +{ +private: + OUString aIntName; // internal name (get***) + TranslateId pUINameID; // resource ID to UI name + const TranslateId* pDescrID; // leads also to parameter descriptions! + sal_uInt16 nParamCount; // num of parameters + std::vector<OUString> aCompList; // list of all valid names + ScaCategory eCat; // function category + bool bDouble; // name already exist in Calc + bool bWithOpt; // first parameter is internal + +public: + ScaFuncData(const ScaFuncDataBase& rBaseData); + + const TranslateId & GetUINameID() const { return pUINameID; } + const TranslateId* GetDescrID() const { return pDescrID; } + ScaCategory GetCategory() const { return eCat; } + bool IsDouble() const { return bDouble; } + + sal_uInt16 GetStrIndex( sal_uInt16 nParam ) const; + bool Is( std::u16string_view rCompare ) const + { return aIntName == rCompare; } + + const std::vector<OUString>& GetCompNameList() const { return aCompList; } +}; + +typedef std::vector<ScaFuncData> ScaFuncDataList; + +// Predicate for use with std::find_if +struct FindScaFuncData +{ + const OUString& m_rId; + explicit FindScaFuncData( const OUString& rId ) : m_rId(rId) {} + bool operator() ( ScaFuncData const & rCandidate ) const { return rCandidate.Is(m_rId); } +}; + + +// THE AddIn class for date functions + +class ScaDateAddIn : public ::cppu::WeakImplHelper< + css::sheet::XAddIn, + css::sheet::XCompatibilityNames, + css::sheet::addin::XDateFunctions, + css::sheet::addin::XMiscFunctions, + css::lang::XServiceName, + css::lang::XServiceInfo > +{ +private: + css::lang::Locale aFuncLoc; + std::unique_ptr< css::lang::Locale[] > pDefLocales; + std::locale aResLocale; + std::unique_ptr< ScaFuncDataList > pFuncDataList; + + + void InitDefLocales(); + const css::lang::Locale& GetLocale( sal_uInt32 nIndex ); + void InitData(); + + /// @throws css::uno::RuntimeException + OUString GetFuncDescrStr(const TranslateId* pResId, sal_uInt16 nStrIndex); + +public: + ScaDateAddIn(); + + OUString ScaResId(TranslateId aId); + + // XAddIn + virtual OUString SAL_CALL getProgrammaticFuntionName( const OUString& aDisplayName ) override; + virtual OUString SAL_CALL getDisplayFunctionName( const OUString& aProgrammaticName ) override; + virtual OUString SAL_CALL getFunctionDescription( const OUString& aProgrammaticName ) override; + virtual OUString SAL_CALL getDisplayArgumentName( const OUString& aProgrammaticName, sal_Int32 nArgument ) override; + virtual OUString SAL_CALL getArgumentDescription( const OUString& aProgrammaticName, sal_Int32 nArgument ) override; + virtual OUString SAL_CALL getProgrammaticCategoryName( const OUString& aProgrammaticName ) override; + virtual OUString SAL_CALL getDisplayCategoryName( const OUString& aProgrammaticName ) override; + + // XCompatibilityNames + virtual css::uno::Sequence< css::sheet::LocalizedName > SAL_CALL getCompatibilityNames( const OUString& aProgrammaticName ) override; + + // XLocalizable + virtual void SAL_CALL setLocale( const css::lang::Locale& eLocale ) override; + virtual css::lang::Locale SAL_CALL getLocale() override; + + // XServiceName + virtual OUString SAL_CALL getServiceName() override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; + + // methods from own interfaces start here + + // XDateFunctions + virtual sal_Int32 SAL_CALL getDiffWeeks( + const css::uno::Reference< css::beans::XPropertySet >& xOptions, + sal_Int32 nEndDate, sal_Int32 nStartDate, + sal_Int32 nMode ) override; + + virtual sal_Int32 SAL_CALL getDiffMonths( + const css::uno::Reference< css::beans::XPropertySet >& xOptions, + sal_Int32 nEndDate, sal_Int32 nStartDate, + sal_Int32 nMode ) override; + + virtual sal_Int32 SAL_CALL getDiffYears( + const css::uno::Reference< css::beans::XPropertySet >& xOptions, + sal_Int32 nEndDate, sal_Int32 nStartDate, + sal_Int32 nMode ) override; + + virtual sal_Int32 SAL_CALL getIsLeapYear( + const css::uno::Reference< css::beans::XPropertySet >& xOptions, + sal_Int32 nDate ) override; + + virtual sal_Int32 SAL_CALL getDaysInMonth( + const css::uno::Reference< css::beans::XPropertySet >& xOptions, + sal_Int32 nDate ) override; + + virtual sal_Int32 SAL_CALL getDaysInYear( + const css::uno::Reference< css::beans::XPropertySet >& xOptions, + sal_Int32 nDate ) override; + + virtual sal_Int32 SAL_CALL getWeeksInYear( + const css::uno::Reference< css::beans::XPropertySet >& xOptions, + sal_Int32 nDate ) override; + + // XMiscFunctions + virtual OUString SAL_CALL getRot13( + const OUString& aSrcText ) override; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/scaddins/source/datefunc/deffuncname.hxx b/scaddins/source/datefunc/deffuncname.hxx new file mode 100644 index 000000000..493ef9393 --- /dev/null +++ b/scaddins/source/datefunc/deffuncname.hxx @@ -0,0 +1,70 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +static const char* DATE_DEFFUNCNAME_DiffWeeks[2] = +{ + "WOCHEN", + "WEEKS" +}; + +static const char* DATE_DEFFUNCNAME_DiffMonths[2] = +{ + "MONATE", + "MONTHS" +}; + +static const char* DATE_DEFFUNCNAME_DiffYears[2] = +{ + "JAHRE", + "YEARS" +}; + +static const char* DATE_DEFFUNCNAME_IsLeapYear[2] = +{ + "ISTSCHALTJAHR", + "ISLEAPYEAR" +}; + +static const char* DATE_DEFFUNCNAME_DaysInMonth[2] = +{ + "TAGEIMMONAT", + "DAYSINMONTH" +}; + +static const char* DATE_DEFFUNCNAME_DaysInYear[2] = +{ + "TAGEIMJAHR", + "DAYSINYEAR" +}; + +static const char* DATE_DEFFUNCNAME_WeeksInYear[2] = +{ + "WOCHENIMJAHR", + "WEEKSINYEAR" +}; + +static const char* DATE_DEFFUNCNAME_Rot13[2] = +{ + "ROT13", + "ROT13" +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |