/* -*- 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace com::sun::star::uno { class XComponentContext; } using namespace com::sun::star::i18n; using namespace com::sun::star::uno; using namespace com::sun::star::lang; using namespace com::sun::star; using i18npool::DataLocaleLibrary; typedef OUString const * (* MyFuncOUString_Type)( sal_Int16&); typedef OUString const ** (* MyFunc_Type2)( sal_Int16&, sal_Int16& ); typedef OUString const *** (* MyFunc_Type3)( sal_Int16&, sal_Int16&, sal_Int16& ); typedef OUString const * (* MyFunc_FormatCode)( sal_Int16&, sal_Unicode const *&, sal_Unicode const *& ); #ifndef DISABLE_DYNLOADING #ifdef SAL_DLLPREFIX // mostly "lib*.so" constexpr const char* lcl_DATA_EN = SAL_DLLPREFIX "localedata_en" SAL_DLLEXTENSION; constexpr const char* lcl_DATA_ES = SAL_DLLPREFIX "localedata_es" SAL_DLLEXTENSION; constexpr const char* lcl_DATA_EURO = SAL_DLLPREFIX "localedata_euro" SAL_DLLEXTENSION; constexpr const char* lcl_DATA_OTHERS = SAL_DLLPREFIX "localedata_others" SAL_DLLEXTENSION; #else // mostly "*.dll" constexpr const char* lcl_DATA_EN = "localedata_en" SAL_DLLEXTENSION; constexpr const char* lcl_DATA_ES = "localedata_es" SAL_DLLEXTENSION; constexpr const char* lcl_DATA_EURO = "localedata_euro" SAL_DLLEXTENSION; constexpr const char* lcl_DATA_OTHERS = "localedata_others" SAL_DLLEXTENSION; #endif static const char* getLibraryName(DataLocaleLibrary aLib) { switch(aLib) { case DataLocaleLibrary::EN: return lcl_DATA_EN; case DataLocaleLibrary::ES: return lcl_DATA_ES; case DataLocaleLibrary::EURO: return lcl_DATA_EURO; case DataLocaleLibrary::OTHERS: return lcl_DATA_OTHERS; } return nullptr; } constexpr struct { const char* pLocale; i18npool::DataLocaleLibrary pLib; } aLibTable[] = { { "en_US", DataLocaleLibrary::EN }, { "en_AU", DataLocaleLibrary::EN }, { "en_BZ", DataLocaleLibrary::EN }, { "en_CA", DataLocaleLibrary::EN }, { "en_GB", DataLocaleLibrary::EN }, { "en_IE", DataLocaleLibrary::EN }, { "en_JM", DataLocaleLibrary::EN }, { "en_NZ", DataLocaleLibrary::EN }, { "en_PH", DataLocaleLibrary::EN }, { "en_TT", DataLocaleLibrary::EN }, { "en_ZA", DataLocaleLibrary::EN }, { "en_ZW", DataLocaleLibrary::EN }, { "en_NA", DataLocaleLibrary::EN }, { "en_GH", DataLocaleLibrary::EN }, { "en_MW", DataLocaleLibrary::EN }, { "en_GM", DataLocaleLibrary::EN }, { "en_BW", DataLocaleLibrary::EN }, { "en_ZM", DataLocaleLibrary::EN }, { "en_LK", DataLocaleLibrary::EN }, { "en_NG", DataLocaleLibrary::EN }, { "en_KE", DataLocaleLibrary::EN }, { "en_DK", DataLocaleLibrary::EN }, { "en_MU", DataLocaleLibrary::EN }, { "es_ES", DataLocaleLibrary::ES }, { "es_AR", DataLocaleLibrary::ES }, { "es_BO", DataLocaleLibrary::ES }, { "es_CL", DataLocaleLibrary::ES }, { "es_CO", DataLocaleLibrary::ES }, { "es_CR", DataLocaleLibrary::ES }, { "es_DO", DataLocaleLibrary::ES }, { "es_EC", DataLocaleLibrary::ES }, { "es_GT", DataLocaleLibrary::ES }, { "es_HN", DataLocaleLibrary::ES }, { "es_MX", DataLocaleLibrary::ES }, { "es_NI", DataLocaleLibrary::ES }, { "es_PA", DataLocaleLibrary::ES }, { "es_PE", DataLocaleLibrary::ES }, { "es_PR", DataLocaleLibrary::ES }, { "es_PY", DataLocaleLibrary::ES }, { "es_SV", DataLocaleLibrary::ES }, { "es_UY", DataLocaleLibrary::ES }, { "es_VE", DataLocaleLibrary::ES }, { "gl_ES", DataLocaleLibrary::ES }, { "oc_ES_aranes", DataLocaleLibrary::ES }, { "de_DE", DataLocaleLibrary::EURO }, { "de_AT", DataLocaleLibrary::EURO }, { "de_CH", DataLocaleLibrary::EURO }, { "de_LI", DataLocaleLibrary::EURO }, { "de_LU", DataLocaleLibrary::EURO }, { "fr_FR", DataLocaleLibrary::EURO }, { "fr_BE", DataLocaleLibrary::EURO }, { "fr_CA", DataLocaleLibrary::EURO }, { "fr_CH", DataLocaleLibrary::EURO }, { "fr_LU", DataLocaleLibrary::EURO }, { "fr_MC", DataLocaleLibrary::EURO }, { "fr_BF", DataLocaleLibrary::EURO }, { "fr_CI", DataLocaleLibrary::EURO }, { "fr_ML", DataLocaleLibrary::EURO }, { "fr_SN", DataLocaleLibrary::EURO }, { "fr_BJ", DataLocaleLibrary::EURO }, { "fr_NE", DataLocaleLibrary::EURO }, { "fr_TG", DataLocaleLibrary::EURO }, { "fr_GN", DataLocaleLibrary::EURO }, { "it_IT", DataLocaleLibrary::EURO }, { "it_CH", DataLocaleLibrary::EURO }, { "sl_SI", DataLocaleLibrary::EURO }, { "sv_SE", DataLocaleLibrary::EURO }, { "sv_FI", DataLocaleLibrary::EURO }, { "ca_ES", DataLocaleLibrary::EURO }, { "ca_ES_valencia", DataLocaleLibrary::EURO }, { "cs_CZ", DataLocaleLibrary::EURO }, { "sk_SK", DataLocaleLibrary::EURO }, { "da_DK", DataLocaleLibrary::EURO }, { "el_GR", DataLocaleLibrary::EURO }, { "fi_FI", DataLocaleLibrary::EURO }, { "is_IS", DataLocaleLibrary::EURO }, { "nl_BE", DataLocaleLibrary::EURO }, { "nl_NL", DataLocaleLibrary::EURO }, { "no_NO", DataLocaleLibrary::EURO }, { "nn_NO", DataLocaleLibrary::EURO }, { "nb_NO", DataLocaleLibrary::EURO }, { "nds_DE", DataLocaleLibrary::EURO }, { "pl_PL", DataLocaleLibrary::EURO }, { "pt_PT", DataLocaleLibrary::EURO }, { "pt_BR", DataLocaleLibrary::EURO }, // needs to be in EURO because inherits from pt_PT { "pt_MZ", DataLocaleLibrary::EURO }, // needs to be in EURO because inherits from pt_PT { "ru_RU", DataLocaleLibrary::EURO }, { "tr_TR", DataLocaleLibrary::EURO }, { "tt_RU", DataLocaleLibrary::EURO }, { "et_EE", DataLocaleLibrary::EURO }, { "vro_EE", DataLocaleLibrary::EURO }, { "lb_LU", DataLocaleLibrary::EURO }, { "lt_LT", DataLocaleLibrary::EURO }, { "lv_LV", DataLocaleLibrary::EURO }, { "uk_UA", DataLocaleLibrary::EURO }, { "ro_RO", DataLocaleLibrary::EURO }, { "cy_GB", DataLocaleLibrary::EURO }, { "bg_BG", DataLocaleLibrary::EURO }, { "sr_Latn_ME", DataLocaleLibrary::EURO }, { "sr_Latn_RS", DataLocaleLibrary::EURO }, { "sr_Latn_CS", DataLocaleLibrary::EURO }, { "sr_ME", DataLocaleLibrary::EURO }, { "sr_RS", DataLocaleLibrary::EURO }, { "sr_CS", DataLocaleLibrary::EURO }, { "hr_HR", DataLocaleLibrary::EURO }, { "bs_BA", DataLocaleLibrary::EURO }, { "eu_ES", DataLocaleLibrary::EURO }, { "fo_FO", DataLocaleLibrary::EURO }, { "ga_IE", DataLocaleLibrary::EURO }, { "gd_GB", DataLocaleLibrary::EURO }, { "ka_GE", DataLocaleLibrary::EURO }, { "be_BY", DataLocaleLibrary::EURO }, { "kl_GL", DataLocaleLibrary::EURO }, { "mk_MK", DataLocaleLibrary::EURO }, { "br_FR", DataLocaleLibrary::EURO }, { "la_VA", DataLocaleLibrary::EURO }, { "cv_RU", DataLocaleLibrary::EURO }, { "wa_BE", DataLocaleLibrary::EURO }, { "fur_IT", DataLocaleLibrary::EURO }, { "gsc_FR", DataLocaleLibrary::EURO }, { "fy_NL", DataLocaleLibrary::EURO }, { "oc_FR_lengadoc", DataLocaleLibrary::EURO }, { "mt_MT", DataLocaleLibrary::EURO }, { "sc_IT", DataLocaleLibrary::EURO }, { "ast_ES", DataLocaleLibrary::EURO }, { "ltg_LV", DataLocaleLibrary::EURO }, { "hsb_DE", DataLocaleLibrary::EURO }, { "dsb_DE", DataLocaleLibrary::EURO }, { "rue_SK", DataLocaleLibrary::EURO }, { "an_ES", DataLocaleLibrary::EURO }, { "myv_RU", DataLocaleLibrary::EURO }, { "lld_IT", DataLocaleLibrary::EURO }, { "cu_RU", DataLocaleLibrary::EURO }, { "vec_IT", DataLocaleLibrary::EURO }, { "szl_PL", DataLocaleLibrary::EURO }, { "lij_IT", DataLocaleLibrary::EURO }, { "ja_JP", DataLocaleLibrary::OTHERS }, { "ko_KR", DataLocaleLibrary::OTHERS }, { "zh_CN", DataLocaleLibrary::OTHERS }, { "zh_HK", DataLocaleLibrary::OTHERS }, { "zh_SG", DataLocaleLibrary::OTHERS }, { "zh_TW", DataLocaleLibrary::OTHERS }, { "zh_MO", DataLocaleLibrary::OTHERS }, { "en_HK", DataLocaleLibrary::OTHERS }, // needs to be in OTHERS instead of EN because currency inherited from zh_HK { "ar_EG", DataLocaleLibrary::OTHERS }, { "ar_DZ", DataLocaleLibrary::OTHERS }, { "ar_LB", DataLocaleLibrary::OTHERS }, { "ar_SA", DataLocaleLibrary::OTHERS }, { "ar_TN", DataLocaleLibrary::OTHERS }, { "he_IL", DataLocaleLibrary::OTHERS }, { "hi_IN", DataLocaleLibrary::OTHERS }, { "kn_IN", DataLocaleLibrary::OTHERS }, { "ta_IN", DataLocaleLibrary::OTHERS }, { "te_IN", DataLocaleLibrary::OTHERS }, { "gu_IN", DataLocaleLibrary::OTHERS }, { "mr_IN", DataLocaleLibrary::OTHERS }, { "pa_IN", DataLocaleLibrary::OTHERS }, { "bn_IN", DataLocaleLibrary::OTHERS }, { "or_IN", DataLocaleLibrary::OTHERS }, { "en_IN", DataLocaleLibrary::OTHERS }, // keep in OTHERS for IN { "ml_IN", DataLocaleLibrary::OTHERS }, { "bn_BD", DataLocaleLibrary::OTHERS }, { "th_TH", DataLocaleLibrary::OTHERS }, { "af_ZA", DataLocaleLibrary::OTHERS }, { "hu_HU", DataLocaleLibrary::OTHERS }, { "id_ID", DataLocaleLibrary::OTHERS }, { "ms_MY", DataLocaleLibrary::OTHERS }, { "en_MY", DataLocaleLibrary::OTHERS }, // needs to be in OTHERS instead of EN because currency inherited from ms_MY { "ia", DataLocaleLibrary::OTHERS }, { "mn_Cyrl_MN", DataLocaleLibrary::OTHERS }, { "az_AZ", DataLocaleLibrary::OTHERS }, { "sw_TZ", DataLocaleLibrary::OTHERS }, { "km_KH", DataLocaleLibrary::OTHERS }, { "lo_LA", DataLocaleLibrary::OTHERS }, { "rw_RW", DataLocaleLibrary::OTHERS }, { "eo", DataLocaleLibrary::OTHERS }, { "dz_BT", DataLocaleLibrary::OTHERS }, { "ne_NP", DataLocaleLibrary::OTHERS }, { "zu_ZA", DataLocaleLibrary::OTHERS }, { "nso_ZA", DataLocaleLibrary::OTHERS }, { "vi_VN", DataLocaleLibrary::OTHERS }, { "tn_ZA", DataLocaleLibrary::OTHERS }, { "xh_ZA", DataLocaleLibrary::OTHERS }, { "st_ZA", DataLocaleLibrary::OTHERS }, { "ss_ZA", DataLocaleLibrary::OTHERS }, { "ve_ZA", DataLocaleLibrary::OTHERS }, { "nr_ZA", DataLocaleLibrary::OTHERS }, { "ts_ZA", DataLocaleLibrary::OTHERS }, { "kmr_Latn_TR", DataLocaleLibrary::OTHERS }, { "ak_GH", DataLocaleLibrary::OTHERS }, { "af_NA", DataLocaleLibrary::OTHERS }, { "am_ET", DataLocaleLibrary::OTHERS }, { "ti_ER", DataLocaleLibrary::OTHERS }, { "tg_TJ", DataLocaleLibrary::OTHERS }, { "ky_KG", DataLocaleLibrary::OTHERS }, { "kk_KZ", DataLocaleLibrary::OTHERS }, { "fa_IR", DataLocaleLibrary::OTHERS }, { "ha_Latn_GH", DataLocaleLibrary::OTHERS }, { "ee_GH", DataLocaleLibrary::OTHERS }, { "sg_CF", DataLocaleLibrary::OTHERS }, { "lg_UG", DataLocaleLibrary::OTHERS }, { "uz_UZ", DataLocaleLibrary::OTHERS }, { "ln_CD", DataLocaleLibrary::OTHERS }, { "hy_AM", DataLocaleLibrary::OTHERS }, { "hil_PH", DataLocaleLibrary::OTHERS }, { "so_SO", DataLocaleLibrary::OTHERS }, { "gug_PY", DataLocaleLibrary::OTHERS }, { "tk_TM", DataLocaleLibrary::OTHERS }, { "my_MM", DataLocaleLibrary::OTHERS }, { "shs_CA", DataLocaleLibrary::OTHERS }, { "tpi_PG", DataLocaleLibrary::OTHERS }, { "ar_OM", DataLocaleLibrary::OTHERS }, { "ug_CN", DataLocaleLibrary::OTHERS }, { "om_ET", DataLocaleLibrary::OTHERS }, { "plt_MG", DataLocaleLibrary::OTHERS }, { "mai_IN", DataLocaleLibrary::OTHERS }, { "yi_US", DataLocaleLibrary::OTHERS }, { "haw_US", DataLocaleLibrary::OTHERS }, { "lif_NP", DataLocaleLibrary::OTHERS }, { "ur_PK", DataLocaleLibrary::OTHERS }, { "ht_HT", DataLocaleLibrary::OTHERS }, { "jbo", DataLocaleLibrary::OTHERS }, { "kab_DZ", DataLocaleLibrary::OTHERS }, { "pt_AO", DataLocaleLibrary::OTHERS }, { "pjt_AU", DataLocaleLibrary::OTHERS }, { "pap_BQ", DataLocaleLibrary::OTHERS }, { "pap_CW", DataLocaleLibrary::OTHERS }, { "ebo_CG", DataLocaleLibrary::OTHERS }, { "tyx_CG", DataLocaleLibrary::OTHERS }, { "axk_CG", DataLocaleLibrary::OTHERS }, { "beq_CG", DataLocaleLibrary::OTHERS }, { "bkw_CG", DataLocaleLibrary::OTHERS }, { "bvx_CG", DataLocaleLibrary::OTHERS }, { "dde_CG", DataLocaleLibrary::OTHERS }, { "iyx_CG", DataLocaleLibrary::OTHERS }, { "kkw_CG", DataLocaleLibrary::OTHERS }, { "kng_CG", DataLocaleLibrary::OTHERS }, { "ldi_CG", DataLocaleLibrary::OTHERS }, { "mdw_CG", DataLocaleLibrary::OTHERS }, { "mkw_CG", DataLocaleLibrary::OTHERS }, { "njx_CG", DataLocaleLibrary::OTHERS }, { "ngz_CG", DataLocaleLibrary::OTHERS }, { "njy_CG", DataLocaleLibrary::OTHERS }, { "puu_CG", DataLocaleLibrary::OTHERS }, { "sdj_CG", DataLocaleLibrary::OTHERS }, { "tek_CG", DataLocaleLibrary::OTHERS }, { "tsa_CG", DataLocaleLibrary::OTHERS }, { "vif_CG", DataLocaleLibrary::OTHERS }, { "xku_CG", DataLocaleLibrary::OTHERS }, { "yom_CG", DataLocaleLibrary::OTHERS }, { "sid_ET", DataLocaleLibrary::OTHERS }, { "bo_CN", DataLocaleLibrary::OTHERS }, { "bo_IN", DataLocaleLibrary::OTHERS }, { "ar_AE", DataLocaleLibrary::OTHERS }, { "ar_KW", DataLocaleLibrary::OTHERS }, { "bm_ML", DataLocaleLibrary::OTHERS }, { "pui_CO", DataLocaleLibrary::OTHERS }, { "lgr_SB", DataLocaleLibrary::OTHERS }, { "mos_BF", DataLocaleLibrary::OTHERS }, { "ny_MW", DataLocaleLibrary::OTHERS }, { "ar_BH", DataLocaleLibrary::OTHERS }, { "ar_IQ", DataLocaleLibrary::OTHERS }, { "ar_JO", DataLocaleLibrary::OTHERS }, { "ar_LY", DataLocaleLibrary::OTHERS }, { "ar_MA", DataLocaleLibrary::OTHERS }, { "ar_QA", DataLocaleLibrary::OTHERS }, { "ar_SY", DataLocaleLibrary::OTHERS }, { "ar_YE", DataLocaleLibrary::OTHERS }, { "ilo_PH", DataLocaleLibrary::OTHERS }, { "ha_Latn_NG", DataLocaleLibrary::OTHERS }, { "min_ID", DataLocaleLibrary::OTHERS }, { "sun_ID", DataLocaleLibrary::OTHERS }, { "en_IL", DataLocaleLibrary::OTHERS }, // needs to be in OTHERS instead of EN because inherits from he_IL { "pdc_US", DataLocaleLibrary::OTHERS }, { "dv_MV", DataLocaleLibrary::OTHERS }, { "mfe_MU", DataLocaleLibrary::OTHERS }, { "sat_IN", DataLocaleLibrary::OTHERS }, { "sat_Olck_IN", DataLocaleLibrary::OTHERS } }; #else #include "localedata_static.hxx" #endif const sal_Unicode cUnder = '_'; const sal_Unicode cHyphen = '-'; const sal_Int16 nbOfLocales = SAL_N_ELEMENTS(aLibTable); namespace i18npool { // static Sequence< CalendarItem > LocaleDataImpl::downcastCalendarItems( const Sequence< CalendarItem2 > & rCi ) { return comphelper::containerToSequence(rCi); } // static Calendar LocaleDataImpl::downcastCalendar( const Calendar2 & rC ) { Calendar aCal( downcastCalendarItems( rC.Days), downcastCalendarItems( rC.Months), downcastCalendarItems( rC.Eras), rC.StartOfWeek, rC.MinimumNumberOfDaysForFirstWeek, rC.Default, rC.Name ); return aCal; } LocaleDataImpl::LocaleDataImpl() { } LocaleDataImpl::~LocaleDataImpl() { } LocaleDataItem SAL_CALL LocaleDataImpl::getLocaleItem( const Locale& rLocale ) { MyFuncOUString_Type func = reinterpret_cast(getFunctionSymbol( rLocale, "getLocaleItem" )); if ( func ) { sal_Int16 dataItemCount = 0; OUString const *dataItem = func(dataItemCount); LocaleDataItem item{ dataItem[0], dataItem[1], dataItem[2], dataItem[3], dataItem[4], dataItem[5], dataItem[6], dataItem[7], dataItem[8], dataItem[9], dataItem[10], dataItem[11], dataItem[12], dataItem[13], dataItem[14], dataItem[15], dataItem[16], dataItem[17] }; return item; } else { LocaleDataItem item1; return item1; } } LocaleDataItem2 SAL_CALL LocaleDataImpl::getLocaleItem2( const Locale& rLocale ) { MyFuncOUString_Type func = reinterpret_cast(getFunctionSymbol( rLocale, "getLocaleItem" )); if ( func ) { sal_Int16 dataItemCount = 0; OUString const *dataItem = func(dataItemCount); assert(dataItemCount >= 18); LocaleDataItem2 item{ dataItem[0], dataItem[1], dataItem[2], dataItem[3], dataItem[4], dataItem[5], dataItem[6], dataItem[7], dataItem[8], dataItem[9], dataItem[10], dataItem[11], dataItem[12], dataItem[13], dataItem[14], dataItem[15], dataItem[16], dataItem[17], dataItemCount >= 19 ? dataItem[18] : OUString() }; return item; } else { LocaleDataItem2 item1; return item1; } } #ifndef DISABLE_DYNLOADING extern "C" { static void thisModule() {} } #endif namespace { // implement the lookup table as a safe static object class lcl_LookupTableHelper { public: lcl_LookupTableHelper(); ~lcl_LookupTableHelper(); oslGenericFunction getFunctionSymbolByName( const OUString& localeName, const char* pFunction, std::optional& rOutCachedItem ); private: std::mutex maMutex; ::std::vector< LocaleDataLookupTableItem > maLookupTable; }; // from instance.hxx: Helper base class for a late-initialized // (default-constructed) static variable, implementing the double-checked // locking pattern correctly. // usage: lcl_LookupTableHelper & rLookupTable = lcl_LookupTableStatic::get(); // retrieves the singleton lookup table instance lcl_LookupTableHelper& lcl_LookupTableStatic() { static lcl_LookupTableHelper SINGLETON; return SINGLETON; } lcl_LookupTableHelper::lcl_LookupTableHelper() { } lcl_LookupTableHelper::~lcl_LookupTableHelper() { for ( const LocaleDataLookupTableItem& item : maLookupTable ) { delete item.module; } } oslGenericFunction lcl_LookupTableHelper::getFunctionSymbolByName( const OUString& localeName, const char* pFunction, std::optional& rOutCachedItem ) { OUString aFallback; bool bFallback = (localeName.indexOf( cUnder) < 0); if (bFallback) { Locale aLocale; aLocale.Language = localeName; Locale aFbLocale = MsLangId::getFallbackLocale( aLocale); if (aFbLocale == aLocale) bFallback = false; // may be a "language-only-locale" like Interlingua (ia) else aFallback = LocaleDataImpl::getFirstLocaleServiceName( aFbLocale); } for (const auto & i : aLibTable) { if (localeName.equalsAscii(i.pLocale) || (bFallback && aFallback.equalsAscii(i.pLocale))) { #ifndef DISABLE_DYNLOADING { std::unique_lock aGuard( maMutex ); for (LocaleDataLookupTableItem & rCurrent : maLookupTable) { if (rCurrent.dllName == i.pLib) { rOutCachedItem.emplace( rCurrent ); rOutCachedItem->localeName = i.pLocale; OString sSymbolName = OString::Concat(pFunction) + "_" + rOutCachedItem->localeName; return rOutCachedItem->module->getFunctionSymbol( sSymbolName.getStr()); } } } // Library not loaded, load it and add it to the list. std::unique_ptr module(new osl::Module()); if ( module->loadRelative(&thisModule, getLibraryName(i.pLib)) ) { std::unique_lock aGuard( maMutex ); auto pTmpModule = module.get(); maLookupTable.emplace_back(i.pLib, module.release(), i.pLocale); rOutCachedItem.emplace( maLookupTable.back() ); OString sSymbolName = OString::Concat(pFunction) + "_" + rOutCachedItem->localeName; return pTmpModule->getFunctionSymbol(sSymbolName.getStr()); } else module.reset(); #else (void) rOutCachedItem; if( strcmp(pFunction, "getAllCalendars") == 0 ) return i.getAllCalendars; else if( strcmp(pFunction, "getAllCurrencies") == 0 ) return i.getAllCurrencies; else if( strcmp(pFunction, "getAllFormats0") == 0 ) return i.getAllFormats0; else if( strcmp(pFunction, "getBreakIteratorRules") == 0 ) return i.getBreakIteratorRules; else if( strcmp(pFunction, "getCollationOptions") == 0 ) return i.getCollationOptions; else if( strcmp(pFunction, "getCollatorImplementation") == 0 ) return i.getCollatorImplementation; else if( strcmp(pFunction, "getContinuousNumberingLevels") == 0 ) return i.getContinuousNumberingLevels; else if( strcmp(pFunction, "getDateAcceptancePatterns") == 0 ) return i.getDateAcceptancePatterns; else if( strcmp(pFunction, "getFollowPageWords") == 0 ) return i.getFollowPageWords; else if( strcmp(pFunction, "getForbiddenCharacters") == 0 ) return i.getForbiddenCharacters; else if( strcmp(pFunction, "getIndexAlgorithm") == 0 ) return i.getIndexAlgorithm; else if( strcmp(pFunction, "getLCInfo") == 0 ) return i.getLCInfo; else if( strcmp(pFunction, "getLocaleItem") == 0 ) return i.getLocaleItem; else if( strcmp(pFunction, "getOutlineNumberingLevels") == 0 ) return i.getOutlineNumberingLevels; else if( strcmp(pFunction, "getReservedWords") == 0 ) return i.getReservedWords; else if( strcmp(pFunction, "getSearchOptions") == 0 ) return i.getSearchOptions; else if( strcmp(pFunction, "getTransliterations") == 0 ) return i.getTransliterations; else if( strcmp(pFunction, "getUnicodeScripts") == 0 ) return i.getUnicodeScripts; else if( strcmp(pFunction, "getAllFormats1") == 0 ) return i.getAllFormats1; #endif } } return nullptr; } } // anonymous namespace // REF values equal offsets of counts within getAllCalendars() data structure! #define REF_DAYS 0 #define REF_MONTHS 1 #define REF_GMONTHS 2 #define REF_PMONTHS 3 #define REF_ERAS 4 #define REF_OFFSET_COUNT 5 Sequence< CalendarItem2 > &LocaleDataImpl::getCalendarItemByName(const OUString& name, const Locale& rLocale, const Sequence< Calendar2 >& calendarsSeq, sal_Int16 item) { if (ref_name != name) { OUString aLocStr, id; sal_Int32 nLastUnder = name.lastIndexOf( cUnder); SAL_WARN_IF( nLastUnder < 1, "i18npool", "LocaleDataImpl::getCalendarItemByName - no '_' or first in name can't be right: " << name); if (nLastUnder >= 0) { aLocStr = name.copy( 0, nLastUnder); if (nLastUnder + 1 < name.getLength()) id = name.copy( nLastUnder + 1); } Locale loc( LanguageTag::convertToLocale( aLocStr.replace( cUnder, cHyphen))); Sequence < Calendar2 > cals; if (loc == rLocale) { cals = calendarsSeq; } else { cals = getAllCalendars2(loc); } auto pCal = std::find_if(std::cbegin(cals), std::cend(cals), [&id](const Calendar2& rCal) { return id == rCal.Name; }); if (pCal != std::cend(cals)) ref_cal = *pCal; else { // Referred locale not found, return name for en_US locale. cals = getAllCalendars2( Locale(u"en"_ustr, u"US"_ustr, OUString()) ); if (!cals.hasElements()) throw RuntimeException(); ref_cal = cals.getConstArray()[0]; } ref_name = name; } switch (item) { case REF_DAYS: return ref_cal.Days; case REF_MONTHS: return ref_cal.Months; case REF_GMONTHS: return ref_cal.GenitiveMonths; case REF_PMONTHS: return ref_cal.PartitiveMonths; default: OSL_FAIL( "LocaleDataImpl::getCalendarItemByName: unhandled REF_* case"); [[fallthrough]]; case REF_ERAS: return ref_cal.Eras; } } Sequence< CalendarItem2 > LocaleDataImpl::getCalendarItems( OUString const * allCalendars, sal_Int16 & rnOffset, const sal_Int16 nWhichItem, const sal_Int16 nCalendar, const Locale & rLocale, const Sequence< Calendar2 > & calendarsSeq ) { Sequence< CalendarItem2 > aItems; if ( allCalendars[rnOffset] == std::u16string_view(u"ref") ) { aItems = getCalendarItemByName( allCalendars[rnOffset+1], rLocale, calendarsSeq, nWhichItem); rnOffset += 2; } else { const sal_Int32 nSize = allCalendars[nWhichItem][nCalendar]; aItems.realloc( nSize); switch (nWhichItem) { case REF_DAYS: case REF_MONTHS: case REF_GMONTHS: case REF_PMONTHS: for (CalendarItem2& rItem : asNonConstRange(aItems)) { rItem = CalendarItem2{ allCalendars[rnOffset], allCalendars[rnOffset+1], allCalendars[rnOffset+2], allCalendars[rnOffset+3]}; rnOffset += 4; } break; case REF_ERAS: // Absent narrow name. for (CalendarItem2& rItem : asNonConstRange(aItems)) { rItem = CalendarItem2{ allCalendars[rnOffset], allCalendars[rnOffset+1], allCalendars[rnOffset+2], OUString()}; rnOffset += 3; } break; default: OSL_FAIL( "LocaleDataImpl::getCalendarItems: unhandled REF_* case"); } } return aItems; } Sequence< Calendar2 > SAL_CALL LocaleDataImpl::getAllCalendars2( const Locale& rLocale ) { OUString const * allCalendars = nullptr; MyFuncOUString_Type func = reinterpret_cast(getFunctionSymbol( rLocale, "getAllCalendars" )); if ( func ) { sal_Int16 calendarsCount = 0; allCalendars = func(calendarsCount); Sequence< Calendar2 > calendarsSeq(calendarsCount); auto calendarsSeqRange = asNonConstRange(calendarsSeq); sal_Int16 offset = REF_OFFSET_COUNT; for(sal_Int16 i = 0; i < calendarsCount; i++) { OUString calendarID(allCalendars[offset]); offset++; bool defaultCalendar = allCalendars[offset][0] != 0; offset++; Sequence< CalendarItem2 > days = getCalendarItems( allCalendars, offset, REF_DAYS, i, rLocale, calendarsSeq); Sequence< CalendarItem2 > months = getCalendarItems( allCalendars, offset, REF_MONTHS, i, rLocale, calendarsSeq); Sequence< CalendarItem2 > gmonths = getCalendarItems( allCalendars, offset, REF_GMONTHS, i, rLocale, calendarsSeq); Sequence< CalendarItem2 > pmonths = getCalendarItems( allCalendars, offset, REF_PMONTHS, i, rLocale, calendarsSeq); Sequence< CalendarItem2 > eras = getCalendarItems( allCalendars, offset, REF_ERAS, i, rLocale, calendarsSeq); OUString startOfWeekDay(allCalendars[offset]); offset++; sal_Int16 minimalDaysInFirstWeek = allCalendars[offset][0]; offset++; calendarsSeqRange[i] = Calendar2(days, months, gmonths, pmonths, eras, startOfWeekDay, minimalDaysInFirstWeek, defaultCalendar, calendarID); } return calendarsSeq; } else { return {}; } } Sequence< Calendar > SAL_CALL LocaleDataImpl::getAllCalendars( const Locale& rLocale ) { const Sequence< Calendar2 > aCal2( getAllCalendars2( rLocale)); std::vector aCal1; aCal1.reserve(aCal2.getLength()); std::transform(aCal2.begin(), aCal2.end(), std::back_inserter(aCal1), [](const Calendar2& rCal2) { return downcastCalendar(rCal2); }); return comphelper::containerToSequence(aCal1); } Sequence< Currency2 > SAL_CALL LocaleDataImpl::getAllCurrencies2( const Locale& rLocale ) { MyFuncOUString_Type func = reinterpret_cast(getFunctionSymbol( rLocale, "getAllCurrencies" )); if ( func ) { sal_Int16 currencyCount = 0; OUString const *allCurrencies = func(currencyCount); Sequence< Currency2 > seq(currencyCount); auto seqRange = asNonConstRange(seq); for(int i = 0, nOff = 0; i < currencyCount; i++, nOff += 8 ) { seqRange[i] = Currency2( allCurrencies[nOff], // string ID allCurrencies[nOff+1], // string Symbol allCurrencies[nOff+2], // string BankSymbol allCurrencies[nOff+3], // string Name allCurrencies[nOff+4][0] != 0, // boolean Default allCurrencies[nOff+5][0] != 0, // boolean UsedInCompatibleFormatCodes allCurrencies[nOff+6][0], // short DecimalPlaces allCurrencies[nOff+7][0] != 0 // boolean LegacyOnly ); } return seq; } else { return {}; } } Sequence< Currency > SAL_CALL LocaleDataImpl::getAllCurrencies( const Locale& rLocale ) { return comphelper::containerToSequence(getAllCurrencies2(rLocale)); } Sequence< FormatElement > SAL_CALL LocaleDataImpl::getAllFormats( const Locale& rLocale ) { const int SECTIONS = 2; struct FormatSection { MyFunc_FormatCode func; sal_Unicode const *from; sal_Unicode const *to; OUString const *formatArray; sal_Int16 formatCount; FormatSection() : func(nullptr), from(nullptr), to(nullptr), formatArray(nullptr), formatCount(0) {} sal_Int16 getFunc( LocaleDataImpl& rLocaleData, const Locale& rL, const char* pName ) { func = reinterpret_cast( rLocaleData.getFunctionSymbol( rL, pName)); if (func) formatArray = func( formatCount, from, to); return formatCount; } } section[SECTIONS]; sal_Int32 formatCount; formatCount = section[0].getFunc( *this, rLocale, "getAllFormats0"); formatCount += section[1].getFunc( *this, rLocale, "getAllFormats1"); Sequence< FormatElement > seq(formatCount); auto seqRange = asNonConstRange(seq); sal_Int32 f = 0; for (const FormatSection & s : section) { OUString const * const formatArray = s.formatArray; if ( formatArray ) { for (int i = 0, nOff = 0; i < s.formatCount; ++i, nOff += 7, ++f) { seqRange[f] = FormatElement( formatArray[nOff].replaceAll(s.from, s.to), formatArray[nOff + 1], formatArray[nOff + 2], formatArray[nOff + 3], formatArray[nOff + 4], formatArray[nOff + 5][0], formatArray[nOff + 6][0] != 0); } } } return seq; } Sequence< OUString > SAL_CALL LocaleDataImpl::getDateAcceptancePatterns( const Locale& rLocale ) { MyFuncOUString_Type func = reinterpret_cast(getFunctionSymbol( rLocale, "getDateAcceptancePatterns" )); if (func) { sal_Int16 patternsCount = 0; OUString const *patternsArray = func( patternsCount ); Sequence< OUString > seq( patternsCount ); auto seqRange = asNonConstRange(seq); for (sal_Int16 i = 0; i < patternsCount; ++i) { seqRange[i] = patternsArray[i]; } return seq; } else { return {}; } } #define COLLATOR_OFFSET_ALGO 0 #define COLLATOR_OFFSET_DEFAULT 1 #define COLLATOR_OFFSET_RULE 2 #define COLLATOR_ELEMENTS 3 OUString LocaleDataImpl::getCollatorRuleByAlgorithm( const Locale& rLocale, std::u16string_view algorithm ) { MyFuncOUString_Type func = reinterpret_cast(getFunctionSymbol( rLocale, "getCollatorImplementation" )); if ( func ) { sal_Int16 collatorCount = 0; OUString const *collatorArray = func(collatorCount); for(sal_Int16 i = 0; i < collatorCount; i++) if (algorithm == collatorArray[i * COLLATOR_ELEMENTS + COLLATOR_OFFSET_ALGO]) return collatorArray[i * COLLATOR_ELEMENTS + COLLATOR_OFFSET_RULE]; } return OUString(); } Sequence< Implementation > SAL_CALL LocaleDataImpl::getCollatorImplementations( const Locale& rLocale ) { MyFuncOUString_Type func = reinterpret_cast(getFunctionSymbol( rLocale, "getCollatorImplementation" )); if ( func ) { sal_Int16 collatorCount = 0; OUString const *collatorArray = func(collatorCount); Sequence< Implementation > seq(collatorCount); auto seqRange = asNonConstRange(seq); for(sal_Int16 i = 0; i < collatorCount; i++) { seqRange[i] = Implementation( collatorArray[i * COLLATOR_ELEMENTS + COLLATOR_OFFSET_ALGO], collatorArray[i * COLLATOR_ELEMENTS + COLLATOR_OFFSET_DEFAULT][0] != 0); } return seq; } else { return {}; } } Sequence< OUString > SAL_CALL LocaleDataImpl::getCollationOptions( const Locale& rLocale ) { MyFuncOUString_Type func = reinterpret_cast(getFunctionSymbol( rLocale, "getCollationOptions" )); if ( func ) { sal_Int16 optionsCount = 0; OUString const *optionsArray = func(optionsCount); Sequence< OUString > seq(optionsCount); auto seqRange = asNonConstRange(seq); for(sal_Int16 i = 0; i < optionsCount; i++) { seqRange[i] = optionsArray[i]; } return seq; } else { return {}; } } Sequence< OUString > SAL_CALL LocaleDataImpl::getSearchOptions( const Locale& rLocale ) { MyFuncOUString_Type func = reinterpret_cast(getFunctionSymbol( rLocale, "getSearchOptions" )); if ( func ) { sal_Int16 optionsCount = 0; OUString const *optionsArray = func(optionsCount); return Sequence< OUString >(optionsArray, optionsCount); } else { return {}; } } OUString const * LocaleDataImpl::getIndexArray(const Locale& rLocale, sal_Int16& indexCount) { MyFuncOUString_Type func = reinterpret_cast(getFunctionSymbol( rLocale, "getIndexAlgorithm" )); if (func) return func(indexCount); return nullptr; } Sequence< OUString > LocaleDataImpl::getIndexAlgorithm( const Locale& rLocale ) { sal_Int16 indexCount = 0; OUString const *indexArray = getIndexArray(rLocale, indexCount); if ( indexArray ) { Sequence< OUString > seq(indexCount); auto seqRange = asNonConstRange(seq); for(sal_Int16 i = 0; i < indexCount; i++) { seqRange[i] = indexArray[i*5]; } return seq; } else { return {}; } } OUString LocaleDataImpl::getDefaultIndexAlgorithm( const Locale& rLocale ) { sal_Int16 indexCount = 0; OUString const *indexArray = getIndexArray(rLocale, indexCount); if ( indexArray ) { for(sal_Int16 i = 0; i < indexCount; i++) { if (indexArray[i*5 + 3][0]) return indexArray[i*5]; } } return OUString(); } bool LocaleDataImpl::hasPhonetic( const Locale& rLocale ) { sal_Int16 indexCount = 0; OUString const *indexArray = getIndexArray(rLocale, indexCount); if ( indexArray ) { for(sal_Int16 i = 0; i < indexCount; i++) { if (indexArray[i*5 + 4][0]) return true; } } return false; } OUString const * LocaleDataImpl::getIndexArrayForAlgorithm(const Locale& rLocale, std::u16string_view algorithm) { sal_Int16 indexCount = 0; OUString const *indexArray = getIndexArray(rLocale, indexCount); if ( indexArray ) { for(sal_Int16 i = 0; i < indexCount; i++) { if (algorithm == indexArray[i*5]) return indexArray+i*5; } } return nullptr; } bool LocaleDataImpl::isPhonetic( const Locale& rLocale, std::u16string_view algorithm ) { OUString const *indexArray = getIndexArrayForAlgorithm(rLocale, algorithm); return indexArray && indexArray[4][0]; } OUString LocaleDataImpl::getIndexKeysByAlgorithm( const Locale& rLocale, std::u16string_view algorithm ) { OUString const *indexArray = getIndexArrayForAlgorithm(rLocale, algorithm); return indexArray ? (OUString::Concat(u"0-9") + indexArray[2]) : OUString(); } OUString LocaleDataImpl::getIndexModuleByAlgorithm( const Locale& rLocale, std::u16string_view algorithm ) { OUString const *indexArray = getIndexArrayForAlgorithm(rLocale, algorithm); return indexArray ? indexArray[1] : OUString(); } Sequence< UnicodeScript > LocaleDataImpl::getUnicodeScripts( const Locale& rLocale ) { MyFuncOUString_Type func = reinterpret_cast(getFunctionSymbol( rLocale, "getUnicodeScripts" )); if ( func ) { sal_Int16 scriptCount = 0; OUString const *scriptArray = func(scriptCount); Sequence< UnicodeScript > seq(scriptCount); auto seqRange = asNonConstRange(seq); for(sal_Int16 i = 0; i < scriptCount; i++) { seqRange[i] = UnicodeScript( o3tl::toInt32(scriptArray[i].subView(0, 1)) ); } return seq; } else { return {}; } } Sequence< OUString > LocaleDataImpl::getFollowPageWords( const Locale& rLocale ) { MyFuncOUString_Type func = reinterpret_cast(getFunctionSymbol( rLocale, "getFollowPageWords" )); if ( func ) { sal_Int16 wordCount = 0; OUString const *wordArray = func(wordCount); return Sequence< OUString >(wordArray, wordCount); } else { return {}; } } Sequence< OUString > SAL_CALL LocaleDataImpl::getTransliterations( const Locale& rLocale ) { MyFuncOUString_Type func = reinterpret_cast(getFunctionSymbol( rLocale, "getTransliterations" )); if ( func ) { sal_Int16 transliterationsCount = 0; const OUString *transliterationsArray = func(transliterationsCount); return Sequence< OUString >(transliterationsArray, transliterationsCount); } else { return {}; } } LanguageCountryInfo SAL_CALL LocaleDataImpl::getLanguageCountryInfo( const Locale& rLocale ) { MyFuncOUString_Type func = reinterpret_cast(getFunctionSymbol( rLocale, "getLCInfo" )); if ( func ) { sal_Int16 LCInfoCount = 0; OUString const *LCInfoArray = func(LCInfoCount); LanguageCountryInfo info{LCInfoArray[0], LCInfoArray[1], LCInfoArray[2], LCInfoArray[3], LCInfoArray[4]}; return info; } else { LanguageCountryInfo info1; return info1; } } ForbiddenCharacters SAL_CALL LocaleDataImpl::getForbiddenCharacters( const Locale& rLocale ) { MyFuncOUString_Type func = reinterpret_cast(getFunctionSymbol( rLocale, "getForbiddenCharacters" )); if ( func ) { sal_Int16 LCForbiddenCharactersCount = 0; OUString const *LCForbiddenCharactersArray = func(LCForbiddenCharactersCount); assert(LCForbiddenCharactersCount == 3); ForbiddenCharacters chars{ LCForbiddenCharactersArray[0], LCForbiddenCharactersArray[1]}; return chars; } else { ForbiddenCharacters chars1; return chars1; } } OUString LocaleDataImpl::getHangingCharacters( const Locale& rLocale ) { MyFuncOUString_Type func = reinterpret_cast(getFunctionSymbol( rLocale, "getForbiddenCharacters" )); if ( func ) { sal_Int16 LCForbiddenCharactersCount = 0; const OUString *LCForbiddenCharactersArray = func(LCForbiddenCharactersCount); assert(LCForbiddenCharactersCount == 3); return LCForbiddenCharactersArray[2]; } return OUString(); } Sequence< OUString > LocaleDataImpl::getBreakIteratorRules( const Locale& rLocale ) { MyFuncOUString_Type func = reinterpret_cast(getFunctionSymbol( rLocale, "getBreakIteratorRules" )); if ( func ) { sal_Int16 LCBreakIteratorRuleCount = 0; OUString const *LCBreakIteratorRulesArray = func(LCBreakIteratorRuleCount); return Sequence< OUString >(LCBreakIteratorRulesArray, LCBreakIteratorRuleCount); } else { return {}; } } Sequence< OUString > SAL_CALL LocaleDataImpl::getReservedWord( const Locale& rLocale ) { MyFuncOUString_Type func = reinterpret_cast(getFunctionSymbol( rLocale, "getReservedWords" )); if ( func ) { sal_Int16 LCReservedWordsCount = 0; OUString const *LCReservedWordsArray = func(LCReservedWordsCount); return Sequence< OUString >(LCReservedWordsArray, LCReservedWordsCount); } else { return {}; } } Sequence< Sequence > LocaleDataImpl::getContinuousNumberingLevels( const lang::Locale& rLocale ) { // load symbol MyFunc_Type2 func = reinterpret_cast(getFunctionSymbol( rLocale, "getContinuousNumberingLevels" )); if ( func ) { // invoke function sal_Int16 nStyles; sal_Int16 nAttributes; OUString const ** p0 = func( nStyles, nAttributes ); // allocate memory for nAttributes attributes for each of the nStyles styles. Sequence< Sequence > pv( nStyles ); auto pvRange = asNonConstRange(pv); for( auto& i : pvRange ) { i = Sequence( nAttributes ); } OUString const ** pStyle = p0; for( int i=0; i(sVal.toInt32()); break; case 2: rVal.Name = "Suffix"; rVal.Value <<= sVal; break; case 3: rVal.Name = "Transliteration"; rVal.Value <<= sVal; break; case 4: rVal.Name = "NatNum"; rVal.Value <<= static_cast(sVal.toInt32()); break; default: OSL_ASSERT(false); } } } return pv; } return Sequence< Sequence >(); } // OutlineNumbering helper class namespace { struct OutlineNumberingLevel_Impl { OUString sPrefix; sal_Int16 nNumType; //css::style::NumberingType OUString sSuffix; sal_Unicode cBulletChar; OUString sBulletFontName; sal_Int16 nParentNumbering; sal_Int32 nLeftMargin; sal_Int32 nSymbolTextDistance; sal_Int32 nFirstLineOffset; sal_Int16 nAdjust; OUString sTransliteration; sal_Int32 nNatNum; }; class OutlineNumbering : public cppu::WeakImplHelper < container::XIndexAccess > { // OutlineNumbering helper class std::unique_ptr m_pOutlineLevels; sal_Int16 m_nCount; public: OutlineNumbering(std::unique_ptr pOutlineLevels, int nLevels); //XIndexAccess virtual sal_Int32 SAL_CALL getCount( ) override; virtual Any SAL_CALL getByIndex( sal_Int32 Index ) override; //XElementAccess virtual Type SAL_CALL getElementType( ) override; virtual sal_Bool SAL_CALL hasElements( ) override; }; } Sequence< Reference > LocaleDataImpl::getOutlineNumberingLevels( const lang::Locale& rLocale ) { // load symbol MyFunc_Type3 func = reinterpret_cast(getFunctionSymbol( rLocale, "getOutlineNumberingLevels" )); if ( func ) { int i; // invoke function sal_Int16 nStyles; sal_Int16 nLevels; sal_Int16 nAttributes; OUString const *** p0 = func( nStyles, nLevels, nAttributes ); Sequence< Reference > aRet( nStyles ); auto aRetRange = asNonConstRange(aRet); OUString const *** pStyle = p0; for( i=0; i level(new OutlineNumberingLevel_Impl[ nLevels+1 ]); OUString const ** pLevel = pStyle[i]; for( j = 0; j < nLevels; j++ ) { OUString const * pAttribute = pLevel[j]; for( int k=0; k(tmp.toInt32()); break; case 2: level[j].sSuffix = tmp; break; case 3: level[j].cBulletChar = sal::static_int_cast(tmp.toUInt32(16)); break; // base 16 case 4: level[j].sBulletFontName = tmp; break; case 5: level[j].nParentNumbering = sal::static_int_cast(tmp.toInt32()); break; case 6: level[j].nLeftMargin = tmp.toInt32(); break; case 7: level[j].nSymbolTextDistance = tmp.toInt32(); break; case 8: level[j].nFirstLineOffset = tmp.toInt32(); break; case 9: level[j].nAdjust = sal::static_int_cast(tmp.toInt32()); break; case 10: level[j].sTransliteration = tmp; break; case 11: level[j].nNatNum = tmp.toInt32(); break; default: OSL_ASSERT(false); } } } level[j].sPrefix.clear(); level[j].nNumType = 0; level[j].sSuffix.clear(); level[j].nAdjust = 0; level[j].cBulletChar = 0; level[j].sBulletFontName.clear(); level[j].nParentNumbering = 0; level[j].nLeftMargin = 0; level[j].nSymbolTextDistance = 0; level[j].nFirstLineOffset = 0; level[j].sTransliteration.clear(); level[j].nNatNum = 0; aRetRange[i] = new OutlineNumbering( std::move(level), nLevels ); } return aRet; } else { return {}; } } // helper functions oslGenericFunction LocaleDataImpl::getFunctionSymbol( const Locale& rLocale, const char* pFunction ) { lcl_LookupTableHelper & rLookupTable = lcl_LookupTableStatic(); if (moCachedItem && moCachedItem->equals(rLocale)) { OString sSymbolName = OString::Concat(pFunction) + "_" + moCachedItem->localeName; return moCachedItem->module->getFunctionSymbol(sSymbolName.getStr()); } oslGenericFunction pSymbol = nullptr; std::optional oCachedItem; // Load function with name __ or _ and // fallbacks. pSymbol = rLookupTable.getFunctionSymbolByName( LocaleDataImpl::getFirstLocaleServiceName( rLocale), pFunction, oCachedItem); if (!pSymbol) { ::std::vector< OUString > aFallbacks( LocaleDataImpl::getFallbackLocaleServiceNames( rLocale)); for (const auto& rFallback : aFallbacks) { pSymbol = rLookupTable.getFunctionSymbolByName(rFallback, pFunction, oCachedItem); if (pSymbol) break; } } if (!pSymbol) { // load default function with name _en_US pSymbol = rLookupTable.getFunctionSymbolByName(u"en_US"_ustr, pFunction, oCachedItem); } if (!pSymbol) // Appropriate symbol could not be found. Give up. throw RuntimeException(); if (oCachedItem) moCachedItem = std::move(oCachedItem); if (moCachedItem) moCachedItem->aLocale = rLocale; return pSymbol; } Sequence< Locale > SAL_CALL LocaleDataImpl::getAllInstalledLocaleNames() { Sequence< lang::Locale > seq( nbOfLocales ); auto seqRange = asNonConstRange(seq); sal_Int16 nInstalled = 0; for(const auto & i : aLibTable) { OUString name = OUString::createFromAscii( i.pLocale ); // Check if the locale is really available and not just in the table, // don't allow fall backs. std::optional oCachedItem; if (lcl_LookupTableStatic().getFunctionSymbolByName( name, "getLocaleItem", oCachedItem )) { if( oCachedItem ) moCachedItem = std::move( oCachedItem ); seqRange[nInstalled++] = LanguageTag::convertToLocale( name.replace( cUnder, cHyphen), false); } } if ( nInstalled < nbOfLocales ) seq.realloc( nInstalled ); // reflect reality return seq; } using namespace ::com::sun::star::container; using namespace ::com::sun::star::beans; OutlineNumbering::OutlineNumbering(std::unique_ptr pOutlnLevels, int nLevels) : m_pOutlineLevels(std::move(pOutlnLevels)), m_nCount(sal::static_int_cast(nLevels)) { } sal_Int32 OutlineNumbering::getCount( ) { return m_nCount; } Any OutlineNumbering::getByIndex( sal_Int32 nIndex ) { if(nIndex < 0 || nIndex >= m_nCount) throw IndexOutOfBoundsException(); const OutlineNumberingLevel_Impl* pTemp = m_pOutlineLevels.get(); pTemp += nIndex; Any aRet; Sequence aOutlineNumbering(12); PropertyValue* pValues = aOutlineNumbering.getArray(); pValues[0].Name = "Prefix"; pValues[0].Value <<= pTemp->sPrefix; pValues[1].Name = "NumberingType"; pValues[1].Value <<= pTemp->nNumType; pValues[2].Name = "Suffix"; pValues[2].Value <<= pTemp->sSuffix; pValues[3].Name = "BulletChar"; pValues[3].Value <<= OUString(&pTemp->cBulletChar, 1); pValues[4].Name = "BulletFontName"; pValues[4].Value <<= pTemp->sBulletFontName; pValues[5].Name = "ParentNumbering"; pValues[5].Value <<= pTemp->nParentNumbering; pValues[6].Name = "LeftMargin"; pValues[6].Value <<= pTemp->nLeftMargin; pValues[7].Name = "SymbolTextDistance"; pValues[7].Value <<= pTemp->nSymbolTextDistance; pValues[8].Name = "FirstLineOffset"; pValues[8].Value <<= pTemp->nFirstLineOffset; pValues[9].Name = "Adjust"; pValues[9].Value <<= pTemp->nAdjust; pValues[10].Name = "Transliteration"; pValues[10].Value <<= pTemp->sTransliteration; pValues[11].Name = "NatNum"; pValues[11].Value <<= pTemp->nNatNum; aRet <<= aOutlineNumbering; return aRet; } Type OutlineNumbering::getElementType( ) { return cppu::UnoType>::get(); } sal_Bool OutlineNumbering::hasElements( ) { return m_nCount > 0; } OUString SAL_CALL LocaleDataImpl::getImplementationName() { return u"com.sun.star.i18n.LocaleDataImpl"_ustr; } sal_Bool SAL_CALL LocaleDataImpl::supportsService(const OUString& rServiceName) { return cppu::supportsService(this, rServiceName); } Sequence< OUString > SAL_CALL LocaleDataImpl::getSupportedServiceNames() { Sequence< OUString > aRet { u"com.sun.star.i18n.LocaleData"_ustr, u"com.sun.star.i18n.LocaleData2"_ustr }; return aRet; } // static OUString LocaleDataImpl::getFirstLocaleServiceName( const css::lang::Locale & rLocale ) { if (rLocale.Language == I18NLANGTAG_QLT) return rLocale.Variant.replace( cHyphen, cUnder); else if (!rLocale.Country.isEmpty()) return rLocale.Language + "_" + rLocale.Country; else return rLocale.Language; } // static ::std::vector< OUString > LocaleDataImpl::getFallbackLocaleServiceNames( const css::lang::Locale & rLocale ) { ::std::vector< OUString > aVec; if (rLocale.Language == I18NLANGTAG_QLT) { aVec = LanguageTag( rLocale).getFallbackStrings( false); for (auto& rItem : aVec) { rItem = rItem.replace(cHyphen, cUnder); } } else if (!rLocale.Country.isEmpty()) { aVec.push_back( rLocale.Language); } // else nothing, language-only was the first return aVec; } } extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * com_sun_star_i18n_LocaleDataImpl_get_implementation( css::uno::XComponentContext *, css::uno::Sequence const &) { return cppu::acquire(new i18npool::LocaleDataImpl()); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */