Version 6.4.0.0.beta1, tag libreoffice-6.4.0.0.beta1
[LibreOffice.git] / i18npool / source / localedata / localedata.cxx
blob0679407cc81b4bc751ee43aa22a6e1093089f796
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <memory>
21 #include <com/sun/star/beans/PropertyValue.hpp>
22 #include <com/sun/star/container/XIndexAccess.hpp>
23 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
24 #include <com/sun/star/text/HoriOrientation.hpp>
25 #include <comphelper/sequence.hxx>
26 #include <cppuhelper/implbase.hxx>
27 #include <cppuhelper/supportsservice.hxx>
28 #include <localedata.hxx>
29 #include <i18nlangtag/mslangid.hxx>
30 #include <i18nlangtag/languagetag.hxx>
31 #include <rtl/ustrbuf.hxx>
32 #include <sal/log.hxx>
33 #include <osl/diagnose.h>
34 #include <string.h>
35 #include <rtl/instance.hxx>
36 #include <sal/macros.h>
38 namespace com::sun::star::uno { class XComponentContext; }
40 using namespace com::sun::star::i18n;
41 using namespace com::sun::star::uno;
42 using namespace com::sun::star::lang;
43 using namespace com::sun::star;
45 typedef sal_Unicode** (* MyFunc_Type)( sal_Int16&);
46 typedef sal_Unicode const *** (* MyFunc_Type2)( sal_Int16&, sal_Int16& );
47 typedef sal_Unicode const **** (* MyFunc_Type3)( sal_Int16&, sal_Int16&, sal_Int16& );
48 typedef sal_Unicode const * const * (* MyFunc_FormatCode)( sal_Int16&, sal_Unicode const *&, sal_Unicode const *& );
50 #ifndef DISABLE_DYNLOADING
52 static const char *lcl_DATA_EN = "localedata_en";
53 static const char *lcl_DATA_ES = "localedata_es";
54 static const char *lcl_DATA_EURO = "localedata_euro";
55 static const char *lcl_DATA_OTHERS = "localedata_others";
57 #endif
59 #ifndef DISABLE_DYNLOADING
61 static const struct {
62 const char* pLocale;
63 const char* pLib;
64 } aLibTable[] = {
65 { "en_US", lcl_DATA_EN },
66 { "en_AU", lcl_DATA_EN },
67 { "en_BZ", lcl_DATA_EN },
68 { "en_CA", lcl_DATA_EN },
69 { "en_GB", lcl_DATA_EN },
70 { "en_IE", lcl_DATA_EN },
71 { "en_JM", lcl_DATA_EN },
72 { "en_NZ", lcl_DATA_EN },
73 { "en_PH", lcl_DATA_EN },
74 { "en_TT", lcl_DATA_EN },
75 { "en_ZA", lcl_DATA_EN },
76 { "en_ZW", lcl_DATA_EN },
77 { "en_NA", lcl_DATA_EN },
78 { "en_GH", lcl_DATA_EN },
79 { "en_MW", lcl_DATA_EN },
80 { "en_GM", lcl_DATA_EN },
81 { "en_BW", lcl_DATA_EN },
82 { "en_ZM", lcl_DATA_EN },
83 { "en_LK", lcl_DATA_EN },
84 { "en_NG", lcl_DATA_EN },
86 { "es_ES", lcl_DATA_ES },
87 { "es_AR", lcl_DATA_ES },
88 { "es_BO", lcl_DATA_ES },
89 { "es_CL", lcl_DATA_ES },
90 { "es_CO", lcl_DATA_ES },
91 { "es_CR", lcl_DATA_ES },
92 { "es_DO", lcl_DATA_ES },
93 { "es_EC", lcl_DATA_ES },
94 { "es_GT", lcl_DATA_ES },
95 { "es_HN", lcl_DATA_ES },
96 { "es_MX", lcl_DATA_ES },
97 { "es_NI", lcl_DATA_ES },
98 { "es_PA", lcl_DATA_ES },
99 { "es_PE", lcl_DATA_ES },
100 { "es_PR", lcl_DATA_ES },
101 { "es_PY", lcl_DATA_ES },
102 { "es_SV", lcl_DATA_ES },
103 { "es_UY", lcl_DATA_ES },
104 { "es_VE", lcl_DATA_ES },
105 { "gl_ES", lcl_DATA_ES },
107 { "de_DE", lcl_DATA_EURO },
108 { "de_AT", lcl_DATA_EURO },
109 { "de_CH", lcl_DATA_EURO },
110 { "de_LI", lcl_DATA_EURO },
111 { "de_LU", lcl_DATA_EURO },
112 { "fr_FR", lcl_DATA_EURO },
113 { "fr_BE", lcl_DATA_EURO },
114 { "fr_CA", lcl_DATA_EURO },
115 { "fr_CH", lcl_DATA_EURO },
116 { "fr_LU", lcl_DATA_EURO },
117 { "fr_MC", lcl_DATA_EURO },
118 { "fr_BF", lcl_DATA_EURO },
119 { "fr_CI", lcl_DATA_EURO },
120 { "fr_ML", lcl_DATA_EURO },
121 { "fr_SN", lcl_DATA_EURO },
122 { "fr_BJ", lcl_DATA_EURO },
123 { "fr_NE", lcl_DATA_EURO },
124 { "fr_TG", lcl_DATA_EURO },
125 { "it_IT", lcl_DATA_EURO },
126 { "it_CH", lcl_DATA_EURO },
127 { "sl_SI", lcl_DATA_EURO },
128 { "sv_SE", lcl_DATA_EURO },
129 { "sv_FI", lcl_DATA_EURO },
130 { "ca_ES", lcl_DATA_EURO },
131 { "ca_ES_valencia", lcl_DATA_EURO },
132 { "cs_CZ", lcl_DATA_EURO },
133 { "sk_SK", lcl_DATA_EURO },
134 { "da_DK", lcl_DATA_EURO },
135 { "el_GR", lcl_DATA_EURO },
136 { "fi_FI", lcl_DATA_EURO },
137 { "is_IS", lcl_DATA_EURO },
138 { "nl_BE", lcl_DATA_EURO },
139 { "nl_NL", lcl_DATA_EURO },
140 { "no_NO", lcl_DATA_EURO },
141 { "nn_NO", lcl_DATA_EURO },
142 { "nb_NO", lcl_DATA_EURO },
143 { "nds_DE", lcl_DATA_EURO },
144 { "pl_PL", lcl_DATA_EURO },
145 { "pt_BR", lcl_DATA_EURO },
146 { "pt_PT", lcl_DATA_EURO },
147 { "ru_RU", lcl_DATA_EURO },
148 { "tr_TR", lcl_DATA_EURO },
149 { "tt_RU", lcl_DATA_EURO },
150 { "et_EE", lcl_DATA_EURO },
151 { "lb_LU", lcl_DATA_EURO },
152 { "lt_LT", lcl_DATA_EURO },
153 { "lv_LV", lcl_DATA_EURO },
154 { "uk_UA", lcl_DATA_EURO },
155 { "ro_RO", lcl_DATA_EURO },
156 { "cy_GB", lcl_DATA_EURO },
157 { "bg_BG", lcl_DATA_EURO },
158 { "sr_Latn_ME", lcl_DATA_EURO },
159 { "sr_Latn_RS", lcl_DATA_EURO },
160 { "sr_Latn_CS", lcl_DATA_EURO },
161 { "sr_ME", lcl_DATA_EURO },
162 { "sr_RS", lcl_DATA_EURO },
163 { "sr_CS", lcl_DATA_EURO },
164 { "hr_HR", lcl_DATA_EURO },
165 { "bs_BA", lcl_DATA_EURO },
166 { "eu_ES", lcl_DATA_EURO },
167 { "fo_FO", lcl_DATA_EURO },
168 { "ga_IE", lcl_DATA_EURO },
169 { "gd_GB", lcl_DATA_EURO },
170 { "ka_GE", lcl_DATA_EURO },
171 { "be_BY", lcl_DATA_EURO },
172 { "kl_GL", lcl_DATA_EURO },
173 { "mk_MK", lcl_DATA_EURO },
174 { "br_FR", lcl_DATA_EURO },
175 { "la_VA", lcl_DATA_EURO },
176 { "cv_RU", lcl_DATA_EURO },
177 { "wa_BE", lcl_DATA_EURO },
178 { "fur_IT", lcl_DATA_EURO },
179 { "gsc_FR", lcl_DATA_EURO },
180 { "fy_NL", lcl_DATA_EURO },
181 { "oc_FR", lcl_DATA_EURO },
182 { "mt_MT", lcl_DATA_EURO },
183 { "sc_IT", lcl_DATA_EURO },
184 { "ast_ES", lcl_DATA_EURO },
185 { "ltg_LV", lcl_DATA_EURO },
186 { "hsb_DE", lcl_DATA_EURO },
187 { "dsb_DE", lcl_DATA_EURO },
188 { "rue_SK", lcl_DATA_EURO },
189 { "an_ES", lcl_DATA_EURO },
190 { "myv_RU", lcl_DATA_EURO },
191 { "lld_IT", lcl_DATA_EURO },
192 { "cu_RU", lcl_DATA_EURO },
193 { "vec_IT", lcl_DATA_EURO },
194 { "szl_PL", lcl_DATA_EURO },
196 { "ja_JP", lcl_DATA_OTHERS },
197 { "ko_KR", lcl_DATA_OTHERS },
198 { "zh_CN", lcl_DATA_OTHERS },
199 { "zh_HK", lcl_DATA_OTHERS },
200 { "zh_SG", lcl_DATA_OTHERS },
201 { "zh_TW", lcl_DATA_OTHERS },
202 { "zh_MO", lcl_DATA_OTHERS },
204 { "ar_EG", lcl_DATA_OTHERS },
205 { "ar_DZ", lcl_DATA_OTHERS },
206 { "ar_LB", lcl_DATA_OTHERS },
207 { "ar_SA", lcl_DATA_OTHERS },
208 { "ar_TN", lcl_DATA_OTHERS },
209 { "he_IL", lcl_DATA_OTHERS },
210 { "hi_IN", lcl_DATA_OTHERS },
211 { "kn_IN", lcl_DATA_OTHERS },
212 { "ta_IN", lcl_DATA_OTHERS },
213 { "te_IN", lcl_DATA_OTHERS },
214 { "gu_IN", lcl_DATA_OTHERS },
215 { "mr_IN", lcl_DATA_OTHERS },
216 { "pa_IN", lcl_DATA_OTHERS },
217 { "bn_IN", lcl_DATA_OTHERS },
218 { "or_IN", lcl_DATA_OTHERS },
219 { "en_IN", lcl_DATA_OTHERS },
220 { "ml_IN", lcl_DATA_OTHERS },
221 { "bn_BD", lcl_DATA_OTHERS },
222 { "th_TH", lcl_DATA_OTHERS },
224 { "af_ZA", lcl_DATA_OTHERS },
225 { "hu_HU", lcl_DATA_OTHERS },
226 { "id_ID", lcl_DATA_OTHERS },
227 { "ms_MY", lcl_DATA_OTHERS },
228 { "en_MY", lcl_DATA_OTHERS },
229 { "ia", lcl_DATA_OTHERS },
230 { "mn_Cyrl_MN", lcl_DATA_OTHERS },
231 { "az_AZ", lcl_DATA_OTHERS },
232 { "sw_TZ", lcl_DATA_OTHERS },
233 { "km_KH", lcl_DATA_OTHERS },
234 { "lo_LA", lcl_DATA_OTHERS },
235 { "rw_RW", lcl_DATA_OTHERS },
236 { "eo", lcl_DATA_OTHERS },
237 { "dz_BT", lcl_DATA_OTHERS },
238 { "ne_NP", lcl_DATA_OTHERS },
239 { "zu_ZA", lcl_DATA_OTHERS },
240 { "nso_ZA", lcl_DATA_OTHERS },
241 { "vi_VN", lcl_DATA_OTHERS },
242 { "tn_ZA", lcl_DATA_OTHERS },
243 { "xh_ZA", lcl_DATA_OTHERS },
244 { "st_ZA", lcl_DATA_OTHERS },
245 { "ss_ZA", lcl_DATA_OTHERS },
246 { "ve_ZA", lcl_DATA_OTHERS },
247 { "nr_ZA", lcl_DATA_OTHERS },
248 { "ts_ZA", lcl_DATA_OTHERS },
249 { "kmr_Latn_TR", lcl_DATA_OTHERS },
250 { "ak_GH", lcl_DATA_OTHERS },
251 { "af_NA", lcl_DATA_OTHERS },
252 { "am_ET", lcl_DATA_OTHERS },
253 { "ti_ER", lcl_DATA_OTHERS },
254 { "tg_TJ", lcl_DATA_OTHERS },
255 { "ky_KG", lcl_DATA_OTHERS },
256 { "kk_KZ", lcl_DATA_OTHERS },
257 { "fa_IR", lcl_DATA_OTHERS },
258 { "ha_Latn_GH", lcl_DATA_OTHERS },
259 { "ee_GH", lcl_DATA_OTHERS },
260 { "sg_CF", lcl_DATA_OTHERS },
261 { "lg_UG", lcl_DATA_OTHERS },
262 { "uz_UZ", lcl_DATA_OTHERS },
263 { "ln_CD", lcl_DATA_OTHERS },
264 { "hy_AM", lcl_DATA_OTHERS },
265 { "hil_PH", lcl_DATA_OTHERS },
266 { "so_SO", lcl_DATA_OTHERS },
267 { "gug_PY", lcl_DATA_OTHERS },
268 { "tk_TM", lcl_DATA_OTHERS },
269 { "my_MM", lcl_DATA_OTHERS },
270 { "shs_CA", lcl_DATA_OTHERS },
271 { "tpi_PG", lcl_DATA_OTHERS },
272 { "ar_OM", lcl_DATA_OTHERS },
273 { "ug_CN", lcl_DATA_OTHERS },
274 { "om_ET", lcl_DATA_OTHERS },
275 { "plt_MG", lcl_DATA_OTHERS },
276 { "mai_IN", lcl_DATA_OTHERS },
277 { "yi_US", lcl_DATA_OTHERS },
278 { "haw_US", lcl_DATA_OTHERS },
279 { "lif_NP", lcl_DATA_OTHERS },
280 { "ur_PK", lcl_DATA_OTHERS },
281 { "ht_HT", lcl_DATA_OTHERS },
282 { "jbo", lcl_DATA_OTHERS },
283 { "kab_DZ", lcl_DATA_OTHERS },
284 { "pt_AO", lcl_DATA_OTHERS },
285 { "pjt_AU", lcl_DATA_OTHERS },
286 { "pap_BQ", lcl_DATA_OTHERS },
287 { "pap_CW", lcl_DATA_OTHERS },
288 { "ebo_CG", lcl_DATA_OTHERS },
289 { "tyx_CG", lcl_DATA_OTHERS },
290 { "axk_CG", lcl_DATA_OTHERS },
291 { "beq_CG", lcl_DATA_OTHERS },
292 { "bkw_CG", lcl_DATA_OTHERS },
293 { "bvx_CG", lcl_DATA_OTHERS },
294 { "dde_CG", lcl_DATA_OTHERS },
295 { "iyx_CG", lcl_DATA_OTHERS },
296 { "kkw_CG", lcl_DATA_OTHERS },
297 { "kng_CG", lcl_DATA_OTHERS },
298 { "ldi_CG", lcl_DATA_OTHERS },
299 { "mdw_CG", lcl_DATA_OTHERS },
300 { "mkw_CG", lcl_DATA_OTHERS },
301 { "njx_CG", lcl_DATA_OTHERS },
302 { "ngz_CG", lcl_DATA_OTHERS },
303 { "njy_CG", lcl_DATA_OTHERS },
304 { "puu_CG", lcl_DATA_OTHERS },
305 { "sdj_CG", lcl_DATA_OTHERS },
306 { "tek_CG", lcl_DATA_OTHERS },
307 { "tsa_CG", lcl_DATA_OTHERS },
308 { "vif_CG", lcl_DATA_OTHERS },
309 { "xku_CG", lcl_DATA_OTHERS },
310 { "yom_CG", lcl_DATA_OTHERS },
311 { "sid_ET", lcl_DATA_OTHERS },
312 { "bo_CN", lcl_DATA_OTHERS },
313 { "bo_IN", lcl_DATA_OTHERS },
314 { "ar_AE", lcl_DATA_OTHERS },
315 { "ar_KW", lcl_DATA_OTHERS },
316 { "bm_ML", lcl_DATA_OTHERS },
317 { "pui_CO", lcl_DATA_OTHERS },
318 { "lgr_SB", lcl_DATA_OTHERS },
319 { "mos_BF", lcl_DATA_OTHERS },
320 { "ny_MW", lcl_DATA_OTHERS },
321 { "ar_BH", lcl_DATA_OTHERS },
322 { "ar_IQ", lcl_DATA_OTHERS },
323 { "ar_JO", lcl_DATA_OTHERS },
324 { "ar_LY", lcl_DATA_OTHERS },
325 { "ar_MA", lcl_DATA_OTHERS },
326 { "ar_QA", lcl_DATA_OTHERS },
327 { "ar_SY", lcl_DATA_OTHERS },
328 { "ar_YE", lcl_DATA_OTHERS },
329 { "ilo_PH", lcl_DATA_OTHERS },
330 { "ha_Latn_NG", lcl_DATA_OTHERS }
333 #else
335 #include "localedata_static.hxx"
337 #endif
339 static const sal_Unicode cUnder = '_';
340 static const sal_Unicode cHyphen = '-';
342 static const sal_Int16 nbOfLocales = SAL_N_ELEMENTS(aLibTable);
344 struct LocaleDataLookupTableItem
346 const sal_Char* dllName;
347 osl::Module *module;
348 const sal_Char* localeName;
349 css::lang::Locale aLocale;
351 LocaleDataLookupTableItem(const sal_Char *name, osl::Module* m, const sal_Char* lname) : dllName(name), module(m), localeName(lname)
354 bool equals(const css::lang::Locale& rLocale)
356 return (rLocale == aLocale);
360 namespace i18npool {
362 // static
363 Sequence< CalendarItem > LocaleDataImpl::downcastCalendarItems( const Sequence< CalendarItem2 > & rCi )
365 return comphelper::containerToSequence<CalendarItem>(rCi);
369 // static
370 Calendar LocaleDataImpl::downcastCalendar( const Calendar2 & rC )
372 Calendar aCal(
373 downcastCalendarItems( rC.Days),
374 downcastCalendarItems( rC.Months),
375 downcastCalendarItems( rC.Eras),
376 rC.StartOfWeek,
377 rC.MinimumNumberOfDaysForFirstWeek,
378 rC.Default,
379 rC.Name
381 return aCal;
385 LocaleDataImpl::LocaleDataImpl()
388 LocaleDataImpl::~LocaleDataImpl()
393 LocaleDataItem SAL_CALL
394 LocaleDataImpl::getLocaleItem( const Locale& rLocale )
396 MyFunc_Type func = reinterpret_cast<MyFunc_Type>(getFunctionSymbol( rLocale, "getLocaleItem" ));
398 if ( func ) {
399 sal_Int16 dataItemCount = 0;
400 sal_Unicode **dataItem = func(dataItemCount);
402 LocaleDataItem item(
403 dataItem[0],
404 dataItem[1],
405 dataItem[2],
406 dataItem[3],
407 dataItem[4],
408 dataItem[5],
409 dataItem[6],
410 dataItem[7],
411 dataItem[8],
412 dataItem[9],
413 dataItem[10],
414 dataItem[11],
415 dataItem[12],
416 dataItem[13],
417 dataItem[14],
418 dataItem[15],
419 dataItem[16],
420 dataItem[17]
422 return item;
424 else {
425 LocaleDataItem item1;
426 return item1;
431 LocaleDataItem2 SAL_CALL
432 LocaleDataImpl::getLocaleItem2( const Locale& rLocale )
434 MyFunc_Type func = reinterpret_cast<MyFunc_Type>(getFunctionSymbol( rLocale, "getLocaleItem" ));
436 if ( func ) {
437 sal_Int16 dataItemCount = 0;
438 sal_Unicode **dataItem = func(dataItemCount);
440 assert(dataItemCount >= 18);
442 LocaleDataItem2 item(
443 dataItem[0],
444 dataItem[1],
445 dataItem[2],
446 dataItem[3],
447 dataItem[4],
448 dataItem[5],
449 dataItem[6],
450 dataItem[7],
451 dataItem[8],
452 dataItem[9],
453 dataItem[10],
454 dataItem[11],
455 dataItem[12],
456 dataItem[13],
457 dataItem[14],
458 dataItem[15],
459 dataItem[16],
460 dataItem[17],
461 dataItemCount >= 19 ? dataItem[18] : OUString()
463 return item;
465 else {
466 LocaleDataItem2 item1;
467 return item1;
471 #ifndef DISABLE_DYNLOADING
473 extern "C" { static void thisModule() {} }
475 #endif
477 namespace
480 // implement the lookup table as a safe static object
481 class lcl_LookupTableHelper
483 public:
484 lcl_LookupTableHelper();
485 ~lcl_LookupTableHelper();
487 oslGenericFunction getFunctionSymbolByName(
488 const OUString& localeName, const sal_Char* pFunction,
489 std::unique_ptr<LocaleDataLookupTableItem>* pOutCachedItem );
491 private:
492 ::osl::Mutex maMutex;
493 ::std::vector< LocaleDataLookupTableItem > maLookupTable;
496 // from instance.hxx: Helper base class for a late-initialized
497 // (default-constructed) static variable, implementing the double-checked
498 // locking pattern correctly.
499 // usage: lcl_LookupTableHelper & rLookupTable = lcl_LookupTableStatic::get();
500 // retrieves the singleton lookup table instance
501 struct lcl_LookupTableStatic : public ::rtl::Static< lcl_LookupTableHelper, lcl_LookupTableStatic >
504 lcl_LookupTableHelper::lcl_LookupTableHelper()
508 lcl_LookupTableHelper::~lcl_LookupTableHelper()
510 for ( const LocaleDataLookupTableItem& item : maLookupTable ) {
511 delete item.module;
515 oslGenericFunction lcl_LookupTableHelper::getFunctionSymbolByName(
516 const OUString& localeName, const sal_Char* pFunction,
517 std::unique_ptr<LocaleDataLookupTableItem>* pOutCachedItem )
519 OUString aFallback;
520 bool bFallback = (localeName.indexOf( cUnder) < 0);
521 if (bFallback)
523 Locale aLocale;
524 aLocale.Language = localeName;
525 Locale aFbLocale = MsLangId::getFallbackLocale( aLocale);
526 if (aFbLocale == aLocale)
527 bFallback = false; // may be a "language-only-locale" like Interlingua (ia)
528 else
529 aFallback = LocaleDataImpl::getFirstLocaleServiceName( aFbLocale);
532 for (const auto & i : aLibTable)
534 if (localeName.equalsAscii(i.pLocale) ||
535 (bFallback && aFallback.equalsAscii(i.pLocale)))
537 #ifndef DISABLE_DYNLOADING
539 ::osl::MutexGuard aGuard( maMutex );
540 for (LocaleDataLookupTableItem & rCurrent : maLookupTable)
542 if (rCurrent.dllName == i.pLib)
544 OSL_ASSERT( pOutCachedItem );
545 if( pOutCachedItem )
547 (*pOutCachedItem).reset(new LocaleDataLookupTableItem( rCurrent ));
548 (*pOutCachedItem)->localeName = i.pLocale;
549 OString sSymbolName = rtl::OStringView(pFunction) + "_" +
550 (*pOutCachedItem)->localeName;
551 return (*pOutCachedItem)->module->getFunctionSymbol(
552 sSymbolName.getStr());
554 else
555 return nullptr;
559 // Library not loaded, load it and add it to the list.
560 #ifdef SAL_DLLPREFIX
561 OString sModuleName = // mostly "lib*.so"
562 SAL_DLLPREFIX + rtl::OStringView(i.pLib) + SAL_DLLEXTENSION;
563 #else
564 OString sModuleName = // mostly "*.dll"
565 rtl::OStringView(i.pLib) + SAL_DLLEXTENSION;
566 #endif
567 std::unique_ptr<osl::Module> module(new osl::Module());
568 if ( module->loadRelative(&thisModule, sModuleName.getStr()) )
570 ::osl::MutexGuard aGuard( maMutex );
571 auto pTmpModule = module.get();
572 maLookupTable.emplace_back(i.pLib, module.release(), i.pLocale);
573 OSL_ASSERT( pOutCachedItem );
574 if( pOutCachedItem )
576 pOutCachedItem->reset(new LocaleDataLookupTableItem( maLookupTable.back() ));
577 OString sSymbolName = rtl::OStringView(pFunction) + "_" + (*pOutCachedItem)->localeName;
578 return pTmpModule->getFunctionSymbol(sSymbolName.getStr());
580 else
581 return nullptr;
583 else
584 module.reset();
585 #else
586 (void) pOutCachedItem;
588 if( strcmp(pFunction, "getAllCalendars") == 0 )
589 return i.getAllCalendars;
590 else if( strcmp(pFunction, "getAllCurrencies") == 0 )
591 return i.getAllCurrencies;
592 else if( strcmp(pFunction, "getAllFormats0") == 0 )
593 return i.getAllFormats0;
594 else if( strcmp(pFunction, "getBreakIteratorRules") == 0 )
595 return i.getBreakIteratorRules;
596 else if( strcmp(pFunction, "getCollationOptions") == 0 )
597 return i.getCollationOptions;
598 else if( strcmp(pFunction, "getCollatorImplementation") == 0 )
599 return i.getCollatorImplementation;
600 else if( strcmp(pFunction, "getContinuousNumberingLevels") == 0 )
601 return i.getContinuousNumberingLevels;
602 else if( strcmp(pFunction, "getDateAcceptancePatterns") == 0 )
603 return i.getDateAcceptancePatterns;
604 else if( strcmp(pFunction, "getFollowPageWords") == 0 )
605 return i.getFollowPageWords;
606 else if( strcmp(pFunction, "getForbiddenCharacters") == 0 )
607 return i.getForbiddenCharacters;
608 else if( strcmp(pFunction, "getIndexAlgorithm") == 0 )
609 return i.getIndexAlgorithm;
610 else if( strcmp(pFunction, "getLCInfo") == 0 )
611 return i.getLCInfo;
612 else if( strcmp(pFunction, "getLocaleItem") == 0 )
613 return i.getLocaleItem;
614 else if( strcmp(pFunction, "getOutlineNumberingLevels") == 0 )
615 return i.getOutlineNumberingLevels;
616 else if( strcmp(pFunction, "getReservedWords") == 0 )
617 return i.getReservedWords;
618 else if( strcmp(pFunction, "getSearchOptions") == 0 )
619 return i.getSearchOptions;
620 else if( strcmp(pFunction, "getTransliterations") == 0 )
621 return i.getTransliterations;
622 else if( strcmp(pFunction, "getUnicodeScripts") == 0 )
623 return i.getUnicodeScripts;
624 else if( strcmp(pFunction, "getAllFormats1") == 0 )
625 return i.getAllFormats1;
626 #endif
629 return nullptr;
632 } // anonymous namespace
635 // REF values equal offsets of counts within getAllCalendars() data structure!
636 #define REF_DAYS 0
637 #define REF_MONTHS 1
638 #define REF_GMONTHS 2
639 #define REF_PMONTHS 3
640 #define REF_ERAS 4
641 #define REF_OFFSET_COUNT 5
643 Sequence< CalendarItem2 > &LocaleDataImpl::getCalendarItemByName(const OUString& name,
644 const Locale& rLocale, const Sequence< Calendar2 >& calendarsSeq, sal_Int16 item)
646 if (ref_name != name) {
647 OUString aLocStr, id;
648 sal_Int32 nLastUnder = name.lastIndexOf( cUnder);
649 SAL_WARN_IF( nLastUnder < 1, "i18npool",
650 "LocaleDataImpl::getCalendarItemByName - no '_' or first in name can't be right: " << name);
651 if (nLastUnder >= 0)
653 aLocStr = name.copy( 0, nLastUnder);
654 if (nLastUnder + 1 < name.getLength())
655 id = name.copy( nLastUnder + 1);
657 Locale loc( LanguageTag::convertToLocale( aLocStr.replace( cUnder, cHyphen)));
658 Sequence < Calendar2 > cals;
659 if (loc == rLocale) {
660 cals = calendarsSeq;
661 } else {
662 cals = getAllCalendars2(loc);
664 auto pCal = std::find_if(std::cbegin(cals), std::cend(cals),
665 [&id](const Calendar2& rCal) { return id == rCal.Name; });
666 if (pCal != std::cend(cals))
667 ref_cal = *pCal;
668 else {
669 // Referred locale not found, return name for en_US locale.
670 cals = getAllCalendars2( Locale("en", "US", OUString()) );
671 if (!cals.hasElements())
672 throw RuntimeException();
673 ref_cal = cals.getConstArray()[0];
675 ref_name = name;
677 switch (item)
679 case REF_DAYS:
680 return ref_cal.Days;
681 case REF_MONTHS:
682 return ref_cal.Months;
683 case REF_GMONTHS:
684 return ref_cal.GenitiveMonths;
685 case REF_PMONTHS:
686 return ref_cal.PartitiveMonths;
687 default:
688 OSL_FAIL( "LocaleDataImpl::getCalendarItemByName: unhandled REF_* case");
689 [[fallthrough]];
690 case REF_ERAS:
691 return ref_cal.Eras;
695 Sequence< CalendarItem2 > LocaleDataImpl::getCalendarItems(
696 sal_Unicode const * const * const allCalendars, sal_Int16 & rnOffset,
697 const sal_Int16 nWhichItem, const sal_Int16 nCalendar,
698 const Locale & rLocale, const Sequence< Calendar2 > & calendarsSeq )
700 Sequence< CalendarItem2 > aItems;
701 if ( OUString( allCalendars[rnOffset] ) == "ref" )
703 aItems = getCalendarItemByName( OUString( allCalendars[rnOffset+1]), rLocale, calendarsSeq, nWhichItem);
704 rnOffset += 2;
706 else
708 const sal_Int32 nSize = allCalendars[nWhichItem][nCalendar];
709 aItems.realloc( nSize);
710 switch (nWhichItem)
712 case REF_DAYS:
713 case REF_MONTHS:
714 case REF_GMONTHS:
715 case REF_PMONTHS:
716 for (CalendarItem2& rItem : aItems)
718 CalendarItem2 item( allCalendars[rnOffset], allCalendars[rnOffset+1],
719 allCalendars[rnOffset+2], allCalendars[rnOffset+3]);
720 rItem = item;
721 rnOffset += 4;
723 break;
724 case REF_ERAS:
725 // Absent narrow name.
726 for (CalendarItem2& rItem : aItems)
728 CalendarItem2 item( allCalendars[rnOffset], allCalendars[rnOffset+1],
729 allCalendars[rnOffset+2], OUString());
730 rItem = item;
731 rnOffset += 3;
733 break;
734 default:
735 OSL_FAIL( "LocaleDataImpl::getCalendarItems: unhandled REF_* case");
738 return aItems;
741 Sequence< Calendar2 > SAL_CALL
742 LocaleDataImpl::getAllCalendars2( const Locale& rLocale )
745 sal_Unicode const * const * allCalendars = nullptr;
747 MyFunc_Type func = reinterpret_cast<MyFunc_Type>(getFunctionSymbol( rLocale, "getAllCalendars" ));
749 if ( func ) {
750 sal_Int16 calendarsCount = 0;
751 allCalendars = func(calendarsCount);
753 Sequence< Calendar2 > calendarsSeq(calendarsCount);
754 sal_Int16 offset = REF_OFFSET_COUNT;
755 for(sal_Int16 i = 0; i < calendarsCount; i++) {
756 OUString calendarID(allCalendars[offset]);
757 offset++;
758 bool defaultCalendar = allCalendars[offset][0] != 0;
759 offset++;
760 Sequence< CalendarItem2 > days = getCalendarItems( allCalendars, offset, REF_DAYS, i,
761 rLocale, calendarsSeq);
762 Sequence< CalendarItem2 > months = getCalendarItems( allCalendars, offset, REF_MONTHS, i,
763 rLocale, calendarsSeq);
764 Sequence< CalendarItem2 > gmonths = getCalendarItems( allCalendars, offset, REF_GMONTHS, i,
765 rLocale, calendarsSeq);
766 Sequence< CalendarItem2 > pmonths = getCalendarItems( allCalendars, offset, REF_PMONTHS, i,
767 rLocale, calendarsSeq);
768 Sequence< CalendarItem2 > eras = getCalendarItems( allCalendars, offset, REF_ERAS, i,
769 rLocale, calendarsSeq);
770 OUString startOfWeekDay(allCalendars[offset]);
771 offset++;
772 sal_Int16 minimalDaysInFirstWeek = allCalendars[offset][0];
773 offset++;
774 Calendar2 aCalendar(days, months, gmonths, pmonths, eras, startOfWeekDay,
775 minimalDaysInFirstWeek, defaultCalendar, calendarID);
776 calendarsSeq[i] = aCalendar;
778 return calendarsSeq;
780 else {
781 Sequence< Calendar2 > seq1(0);
782 return seq1;
787 Sequence< Calendar > SAL_CALL
788 LocaleDataImpl::getAllCalendars( const Locale& rLocale )
790 const Sequence< Calendar2 > aCal2( getAllCalendars2( rLocale));
791 std::vector<Calendar> aCal1;
792 aCal1.reserve(aCal2.getLength());
793 std::transform(aCal2.begin(), aCal2.end(), std::back_inserter(aCal1),
794 [](const Calendar2& rCal2) { return downcastCalendar(rCal2); });
795 return comphelper::containerToSequence(aCal1);
799 Sequence< Currency2 > SAL_CALL
800 LocaleDataImpl::getAllCurrencies2( const Locale& rLocale )
802 MyFunc_Type func = reinterpret_cast<MyFunc_Type>(getFunctionSymbol( rLocale, "getAllCurrencies" ));
804 if ( func ) {
805 sal_Int16 currencyCount = 0;
806 sal_Unicode **allCurrencies = func(currencyCount);
808 Sequence< Currency2 > seq(currencyCount);
809 for(int i = 0, nOff = 0; i < currencyCount; i++, nOff += 8 ) {
810 Currency2 cur(
811 allCurrencies[nOff], // string ID
812 allCurrencies[nOff+1], // string Symbol
813 allCurrencies[nOff+2], // string BankSymbol
814 allCurrencies[nOff+3], // string Name
815 allCurrencies[nOff+4][0] != 0, // boolean Default
816 allCurrencies[nOff+5][0] != 0, // boolean UsedInCompatibleFormatCodes
817 allCurrencies[nOff+6][0], // short DecimalPlaces
818 allCurrencies[nOff+7][0] != 0 // boolean LegacyOnly
820 seq[i] = cur;
822 return seq;
824 else {
825 Sequence< Currency2 > seq1(0);
826 return seq1;
831 Sequence< Currency > SAL_CALL
832 LocaleDataImpl::getAllCurrencies( const Locale& rLocale )
834 return comphelper::containerToSequence<Currency>(getAllCurrencies2(rLocale));
838 Sequence< FormatElement > SAL_CALL
839 LocaleDataImpl::getAllFormats( const Locale& rLocale )
841 const int SECTIONS = 2;
842 struct FormatSection
844 MyFunc_FormatCode func;
845 sal_Unicode const *from;
846 sal_Unicode const *to;
847 sal_Unicode const *const *formatArray;
848 sal_Int16 formatCount;
850 FormatSection() : func(nullptr), from(nullptr), to(nullptr), formatArray(nullptr), formatCount(0) {}
851 sal_Int16 getFunc( LocaleDataImpl& rLocaleData, const Locale& rL, const char* pName )
853 func = reinterpret_cast<MyFunc_FormatCode>( rLocaleData.getFunctionSymbol( rL, pName));
854 if (func)
855 formatArray = func( formatCount, from, to);
856 return formatCount;
858 } section[SECTIONS];
860 sal_Int32 formatCount;
861 formatCount = section[0].getFunc( *this, rLocale, "getAllFormats0");
862 formatCount += section[1].getFunc( *this, rLocale, "getAllFormats1");
864 Sequence< FormatElement > seq(formatCount);
865 sal_Int32 f = 0;
866 for (const FormatSection & s : section)
868 sal_Unicode const * const * const formatArray = s.formatArray;
869 if ( formatArray )
871 for (int i = 0, nOff = 0; i < s.formatCount; ++i, nOff += 7, ++f)
873 FormatElement elem(
874 OUString(formatArray[nOff]).replaceAll(s.from, s.to),
875 formatArray[nOff + 1],
876 formatArray[nOff + 2],
877 formatArray[nOff + 3],
878 formatArray[nOff + 4],
879 formatArray[nOff + 5][0],
880 formatArray[nOff + 6][0] != 0);
881 seq[f] = elem;
885 return seq;
889 Sequence< OUString > SAL_CALL
890 LocaleDataImpl::getDateAcceptancePatterns( const Locale& rLocale )
892 MyFunc_Type func = reinterpret_cast<MyFunc_Type>(getFunctionSymbol( rLocale, "getDateAcceptancePatterns" ));
894 if (func)
896 sal_Int16 patternsCount = 0;
897 sal_Unicode **patternsArray = func( patternsCount );
898 Sequence< OUString > seq( patternsCount );
899 for (sal_Int16 i = 0; i < patternsCount; ++i)
901 seq[i] = OUString( patternsArray[i] );
903 return seq;
905 else
907 Sequence< OUString > seq(0);
908 return seq;
913 #define COLLATOR_OFFSET_ALGO 0
914 #define COLLATOR_OFFSET_DEFAULT 1
915 #define COLLATOR_OFFSET_RULE 2
916 #define COLLATOR_ELEMENTS 3
918 OUString
919 LocaleDataImpl::getCollatorRuleByAlgorithm( const Locale& rLocale, const OUString& algorithm )
921 MyFunc_Type func = reinterpret_cast<MyFunc_Type>(getFunctionSymbol( rLocale, "getCollatorImplementation" ));
922 if ( func ) {
923 sal_Int16 collatorCount = 0;
924 sal_Unicode **collatorArray = func(collatorCount);
925 for(sal_Int16 i = 0; i < collatorCount; i++)
926 if (algorithm == collatorArray[i * COLLATOR_ELEMENTS + COLLATOR_OFFSET_ALGO])
927 return OUString(collatorArray[i * COLLATOR_ELEMENTS + COLLATOR_OFFSET_RULE]);
929 return OUString();
933 Sequence< Implementation > SAL_CALL
934 LocaleDataImpl::getCollatorImplementations( const Locale& rLocale )
936 MyFunc_Type func = reinterpret_cast<MyFunc_Type>(getFunctionSymbol( rLocale, "getCollatorImplementation" ));
938 if ( func ) {
939 sal_Int16 collatorCount = 0;
940 sal_Unicode **collatorArray = func(collatorCount);
941 Sequence< Implementation > seq(collatorCount);
942 for(sal_Int16 i = 0; i < collatorCount; i++) {
943 Implementation impl(collatorArray[i * COLLATOR_ELEMENTS + COLLATOR_OFFSET_ALGO],
944 collatorArray[i * COLLATOR_ELEMENTS + COLLATOR_OFFSET_DEFAULT][0] != 0);
945 seq[i] = impl;
947 return seq;
949 else {
950 Sequence< Implementation > seq1(0);
951 return seq1;
955 Sequence< OUString > SAL_CALL
956 LocaleDataImpl::getCollationOptions( const Locale& rLocale )
958 MyFunc_Type func = reinterpret_cast<MyFunc_Type>(getFunctionSymbol( rLocale, "getCollationOptions" ));
960 if ( func ) {
961 sal_Int16 optionsCount = 0;
962 sal_Unicode **optionsArray = func(optionsCount);
963 Sequence< OUString > seq(optionsCount);
964 for(sal_Int16 i = 0; i < optionsCount; i++) {
965 seq[i] = OUString( optionsArray[i] );
967 return seq;
969 else {
970 Sequence< OUString > seq1(0);
971 return seq1;
975 Sequence< OUString > SAL_CALL
976 LocaleDataImpl::getSearchOptions( const Locale& rLocale )
978 MyFunc_Type func = reinterpret_cast<MyFunc_Type>(getFunctionSymbol( rLocale, "getSearchOptions" ));
980 if ( func ) {
981 sal_Int16 optionsCount = 0;
982 sal_Unicode **optionsArray = func(optionsCount);
983 Sequence< OUString > seq(optionsCount);
984 for(sal_Int16 i = 0; i < optionsCount; i++) {
985 seq[i] = OUString( optionsArray[i] );
987 return seq;
989 else {
990 Sequence< OUString > seq1(0);
991 return seq1;
995 sal_Unicode **
996 LocaleDataImpl::getIndexArray(const Locale& rLocale, sal_Int16& indexCount)
998 MyFunc_Type func = reinterpret_cast<MyFunc_Type>(getFunctionSymbol( rLocale, "getIndexAlgorithm" ));
1000 if (func)
1001 return func(indexCount);
1002 return nullptr;
1005 Sequence< OUString >
1006 LocaleDataImpl::getIndexAlgorithm( const Locale& rLocale )
1008 sal_Int16 indexCount = 0;
1009 sal_Unicode **indexArray = getIndexArray(rLocale, indexCount);
1011 if ( indexArray ) {
1012 Sequence< OUString > seq(indexCount);
1013 for(sal_Int16 i = 0; i < indexCount; i++) {
1014 seq[i] = indexArray[i*5];
1016 return seq;
1018 else {
1019 Sequence< OUString > seq1(0);
1020 return seq1;
1024 OUString
1025 LocaleDataImpl::getDefaultIndexAlgorithm( const Locale& rLocale )
1027 sal_Int16 indexCount = 0;
1028 sal_Unicode **indexArray = getIndexArray(rLocale, indexCount);
1030 if ( indexArray ) {
1031 for(sal_Int16 i = 0; i < indexCount; i++) {
1032 if (indexArray[i*5 + 3][0])
1033 return OUString(indexArray[i*5]);
1036 return OUString();
1039 bool
1040 LocaleDataImpl::hasPhonetic( const Locale& rLocale )
1042 sal_Int16 indexCount = 0;
1043 sal_Unicode **indexArray = getIndexArray(rLocale, indexCount);
1045 if ( indexArray ) {
1046 for(sal_Int16 i = 0; i < indexCount; i++) {
1047 if (indexArray[i*5 + 4][0])
1048 return true;
1051 return false;
1054 sal_Unicode **
1055 LocaleDataImpl::getIndexArrayForAlgorithm(const Locale& rLocale, const OUString& algorithm)
1057 sal_Int16 indexCount = 0;
1058 sal_Unicode **indexArray = getIndexArray(rLocale, indexCount);
1059 if ( indexArray ) {
1060 for(sal_Int16 i = 0; i < indexCount; i++) {
1061 if (algorithm == indexArray[i*5])
1062 return indexArray+i*5;
1065 return nullptr;
1068 bool
1069 LocaleDataImpl::isPhonetic( const Locale& rLocale, const OUString& algorithm )
1071 sal_Unicode **indexArray = getIndexArrayForAlgorithm(rLocale, algorithm);
1072 return indexArray && indexArray[4][0];
1075 OUString
1076 LocaleDataImpl::getIndexKeysByAlgorithm( const Locale& rLocale, const OUString& algorithm )
1078 sal_Unicode **indexArray = getIndexArrayForAlgorithm(rLocale, algorithm);
1079 return indexArray ? (OUStringLiteral("0-9") + indexArray[2]) : OUString();
1082 OUString
1083 LocaleDataImpl::getIndexModuleByAlgorithm( const Locale& rLocale, const OUString& algorithm )
1085 sal_Unicode **indexArray = getIndexArrayForAlgorithm(rLocale, algorithm);
1086 return indexArray ? OUString(indexArray[1]) : OUString();
1089 Sequence< UnicodeScript >
1090 LocaleDataImpl::getUnicodeScripts( const Locale& rLocale )
1092 MyFunc_Type func = reinterpret_cast<MyFunc_Type>(getFunctionSymbol( rLocale, "getUnicodeScripts" ));
1094 if ( func ) {
1095 sal_Int16 scriptCount = 0;
1096 sal_Unicode **scriptArray = func(scriptCount);
1097 Sequence< UnicodeScript > seq(scriptCount);
1098 for(sal_Int16 i = 0; i < scriptCount; i++) {
1099 seq[i] = UnicodeScript( OUString(scriptArray[i]).toInt32() );
1101 return seq;
1103 else {
1104 Sequence< UnicodeScript > seq1(0);
1105 return seq1;
1109 Sequence< OUString >
1110 LocaleDataImpl::getFollowPageWords( const Locale& rLocale )
1112 MyFunc_Type func = reinterpret_cast<MyFunc_Type>(getFunctionSymbol( rLocale, "getFollowPageWords" ));
1114 if ( func ) {
1115 sal_Int16 wordCount = 0;
1116 sal_Unicode **wordArray = func(wordCount);
1117 Sequence< OUString > seq(wordCount);
1118 for(sal_Int16 i = 0; i < wordCount; i++) {
1119 seq[i] = OUString(wordArray[i]);
1121 return seq;
1123 else {
1124 Sequence< OUString > seq1(0);
1125 return seq1;
1129 Sequence< OUString > SAL_CALL
1130 LocaleDataImpl::getTransliterations( const Locale& rLocale )
1132 MyFunc_Type func = reinterpret_cast<MyFunc_Type>(getFunctionSymbol( rLocale, "getTransliterations" ));
1134 if ( func ) {
1135 sal_Int16 transliterationsCount = 0;
1136 sal_Unicode **transliterationsArray = func(transliterationsCount);
1138 Sequence< OUString > seq(transliterationsCount);
1139 for(int i = 0; i < transliterationsCount; i++) {
1140 OUString elem(transliterationsArray[i]);
1141 seq[i] = elem;
1143 return seq;
1145 else {
1146 Sequence< OUString > seq1(0);
1147 return seq1;
1154 LanguageCountryInfo SAL_CALL
1155 LocaleDataImpl::getLanguageCountryInfo( const Locale& rLocale )
1157 MyFunc_Type func = reinterpret_cast<MyFunc_Type>(getFunctionSymbol( rLocale, "getLCInfo" ));
1159 if ( func ) {
1160 sal_Int16 LCInfoCount = 0;
1161 sal_Unicode **LCInfoArray = func(LCInfoCount);
1162 LanguageCountryInfo info(LCInfoArray[0],
1163 LCInfoArray[1],
1164 LCInfoArray[2],
1165 LCInfoArray[3],
1166 LCInfoArray[4]);
1167 return info;
1169 else {
1170 LanguageCountryInfo info1;
1171 return info1;
1177 ForbiddenCharacters SAL_CALL
1178 LocaleDataImpl::getForbiddenCharacters( const Locale& rLocale )
1180 MyFunc_Type func = reinterpret_cast<MyFunc_Type>(getFunctionSymbol( rLocale, "getForbiddenCharacters" ));
1182 if ( func ) {
1183 sal_Int16 LCForbiddenCharactersCount = 0;
1184 sal_Unicode **LCForbiddenCharactersArray = func(LCForbiddenCharactersCount);
1185 ForbiddenCharacters chars(LCForbiddenCharactersArray[0], LCForbiddenCharactersArray[1]);
1186 return chars;
1188 else {
1189 ForbiddenCharacters chars1;
1190 return chars1;
1194 OUString
1195 LocaleDataImpl::getHangingCharacters( const Locale& rLocale )
1197 MyFunc_Type func = reinterpret_cast<MyFunc_Type>(getFunctionSymbol( rLocale, "getForbiddenCharacters" ));
1199 if ( func ) {
1200 sal_Int16 LCForbiddenCharactersCount = 0;
1201 sal_Unicode **LCForbiddenCharactersArray = func(LCForbiddenCharactersCount);
1202 return OUString(LCForbiddenCharactersArray[2]);
1205 return OUString();
1208 Sequence< OUString >
1209 LocaleDataImpl::getBreakIteratorRules( const Locale& rLocale )
1211 MyFunc_Type func = reinterpret_cast<MyFunc_Type>(getFunctionSymbol( rLocale, "getBreakIteratorRules" ));
1213 if ( func ) {
1214 sal_Int16 LCBreakIteratorRuleCount = 0;
1215 sal_Unicode **LCBreakIteratorRulesArray = func(LCBreakIteratorRuleCount);
1216 Sequence< OUString > seq(LCBreakIteratorRuleCount);
1217 for(int i = 0; i < LCBreakIteratorRuleCount; i++) {
1218 OUString elem(LCBreakIteratorRulesArray[i]);
1219 seq[i] = elem;
1221 return seq;
1223 else {
1224 Sequence< OUString > seq1(0);
1225 return seq1;
1230 Sequence< OUString > SAL_CALL
1231 LocaleDataImpl::getReservedWord( const Locale& rLocale )
1233 MyFunc_Type func = reinterpret_cast<MyFunc_Type>(getFunctionSymbol( rLocale, "getReservedWords" ));
1235 if ( func ) {
1236 sal_Int16 LCReservedWordsCount = 0;
1237 sal_Unicode **LCReservedWordsArray = func(LCReservedWordsCount);
1238 Sequence< OUString > seq(LCReservedWordsCount);
1239 for(int i = 0; i < LCReservedWordsCount; i++) {
1240 OUString elem(LCReservedWordsArray[i]);
1241 seq[i] = elem;
1243 return seq;
1245 else {
1246 Sequence< OUString > seq1(0);
1247 return seq1;
1252 Sequence< Sequence<beans::PropertyValue> >
1253 LocaleDataImpl::getContinuousNumberingLevels( const lang::Locale& rLocale )
1255 // load symbol
1256 MyFunc_Type2 func = reinterpret_cast<MyFunc_Type2>(getFunctionSymbol( rLocale, "getContinuousNumberingLevels" ));
1258 if ( func )
1260 int i;
1261 // invoke function
1262 sal_Int16 nStyles;
1263 sal_Int16 nAttributes;
1264 sal_Unicode const *** p0 = func( nStyles, nAttributes );
1266 // allocate memory for nAttributes attributes for each of the nStyles styles.
1267 Sequence< Sequence<beans::PropertyValue> > pv( nStyles );
1268 for( i=0; i<pv.getLength(); i++ ) {
1269 pv[i] = Sequence<beans::PropertyValue>( nAttributes );
1272 sal_Unicode const *** pStyle = p0;
1273 for( i=0; i<nStyles; i++ ) {
1274 sal_Unicode const ** pAttribute = pStyle[i];
1275 for( int j=0; j<nAttributes; j++ ) { // prefix, numberingtype, ...
1276 sal_Unicode const * pString = pAttribute[j];
1277 beans::PropertyValue& rVal = pv[i][j];
1278 OUString sVal;
1279 if( pString ) {
1280 if( 0 != j && 2 != j )
1281 sVal = pString;
1282 else if( *pString )
1283 sVal = OUString( pString, 1 );
1286 switch( j )
1288 case 0:
1289 rVal.Name = "Prefix";
1290 rVal.Value <<= sVal;
1291 break;
1292 case 1:
1293 rVal.Name = "NumberingType";
1294 rVal.Value <<= static_cast<sal_Int16>(sVal.toInt32());
1295 break;
1296 case 2:
1297 rVal.Name = "Suffix";
1298 rVal.Value <<= sVal;
1299 break;
1300 case 3:
1301 rVal.Name = "Transliteration";
1302 rVal.Value <<= sVal;
1303 break;
1304 case 4:
1305 rVal.Name = "NatNum";
1306 rVal.Value <<= static_cast<sal_Int16>(sVal.toInt32());
1307 break;
1308 default:
1309 OSL_ASSERT(false);
1313 return pv;
1316 return Sequence< Sequence<beans::PropertyValue> >();
1319 // OutlineNumbering helper class
1321 struct OutlineNumberingLevel_Impl
1323 OUString sPrefix;
1324 sal_Int16 nNumType; //css::style::NumberingType
1325 OUString sSuffix;
1326 sal_Unicode cBulletChar;
1327 OUString sBulletFontName;
1328 sal_Int16 nParentNumbering;
1329 sal_Int32 nLeftMargin;
1330 sal_Int32 nSymbolTextDistance;
1331 sal_Int32 nFirstLineOffset;
1332 OUString sTransliteration;
1333 sal_Int32 nNatNum;
1336 class OutlineNumbering : public cppu::WeakImplHelper < container::XIndexAccess >
1338 // OutlineNumbering helper class
1340 std::unique_ptr<const OutlineNumberingLevel_Impl[]> m_pOutlineLevels;
1341 sal_Int16 m_nCount;
1342 public:
1343 OutlineNumbering(std::unique_ptr<const OutlineNumberingLevel_Impl[]> pOutlineLevels, int nLevels);
1345 //XIndexAccess
1346 virtual sal_Int32 SAL_CALL getCount( ) override;
1347 virtual Any SAL_CALL getByIndex( sal_Int32 Index ) override;
1349 //XElementAccess
1350 virtual Type SAL_CALL getElementType( ) override;
1351 virtual sal_Bool SAL_CALL hasElements( ) override;
1354 Sequence< Reference<container::XIndexAccess> >
1355 LocaleDataImpl::getOutlineNumberingLevels( const lang::Locale& rLocale )
1357 // load symbol
1358 MyFunc_Type3 func = reinterpret_cast<MyFunc_Type3>(getFunctionSymbol( rLocale, "getOutlineNumberingLevels" ));
1360 if ( func )
1362 int i;
1363 // invoke function
1364 sal_Int16 nStyles;
1365 sal_Int16 nLevels;
1366 sal_Int16 nAttributes;
1367 sal_Unicode const **** p0 = func( nStyles, nLevels, nAttributes );
1369 Sequence< Reference<container::XIndexAccess> > aRet( nStyles );
1371 sal_Unicode const **** pStyle = p0;
1372 for( i=0; i<nStyles; i++ )
1374 int j;
1376 std::unique_ptr<OutlineNumberingLevel_Impl[]> level(new OutlineNumberingLevel_Impl[ nLevels+1 ]);
1377 sal_Unicode const *** pLevel = pStyle[i];
1378 for( j = 0; j < nLevels; j++ )
1380 sal_Unicode const ** pAttribute = pLevel[j];
1381 for( int k=0; k<nAttributes; k++ )
1383 OUString tmp( pAttribute[k] );
1384 switch( k )
1386 case 0: level[j].sPrefix = tmp; break;
1387 case 1: level[j].nNumType = sal::static_int_cast<sal_Int16>(tmp.toInt32()); break;
1388 case 2: level[j].sSuffix = tmp; break;
1389 case 3: level[j].cBulletChar = sal::static_int_cast<sal_Unicode>(tmp.toUInt32(16)); break; // base 16
1390 case 4: level[j].sBulletFontName = tmp; break;
1391 case 5: level[j].nParentNumbering = sal::static_int_cast<sal_Int16>(tmp.toInt32()); break;
1392 case 6: level[j].nLeftMargin = tmp.toInt32(); break;
1393 case 7: level[j].nSymbolTextDistance = tmp.toInt32(); break;
1394 case 8: level[j].nFirstLineOffset = tmp.toInt32(); break;
1395 case 9: break;
1396 case 10: level[j].sTransliteration = tmp; break;
1397 case 11: level[j].nNatNum = tmp.toInt32(); break;
1398 default:
1399 OSL_ASSERT(false);
1403 level[j].sPrefix.clear();
1404 level[j].nNumType = 0;
1405 level[j].sSuffix.clear();
1406 level[j].cBulletChar = 0;
1407 level[j].sBulletFontName.clear();
1408 level[j].nParentNumbering = 0;
1409 level[j].nLeftMargin = 0;
1410 level[j].nSymbolTextDistance = 0;
1411 level[j].nFirstLineOffset = 0;
1412 level[j].sTransliteration.clear();
1413 level[j].nNatNum = 0;
1414 aRet[i] = new OutlineNumbering( std::move(level), nLevels );
1416 return aRet;
1418 else {
1419 Sequence< Reference<container::XIndexAccess> > seq1(0);
1420 return seq1;
1424 // helper functions
1426 oslGenericFunction LocaleDataImpl::getFunctionSymbol( const Locale& rLocale, const sal_Char* pFunction )
1428 lcl_LookupTableHelper & rLookupTable = lcl_LookupTableStatic::get();
1430 if (cachedItem.get() && cachedItem->equals(rLocale))
1432 OString sSymbolName = rtl::OStringView(pFunction) + "_" +
1433 cachedItem->localeName;
1434 return cachedItem->module->getFunctionSymbol(sSymbolName.getStr());
1437 oslGenericFunction pSymbol = nullptr;
1438 std::unique_ptr<LocaleDataLookupTableItem> pCachedItem;
1440 // Load function with name <func>_<lang>_<country> or <func>_<bcp47> and
1441 // fallbacks.
1442 pSymbol = rLookupTable.getFunctionSymbolByName( LocaleDataImpl::getFirstLocaleServiceName( rLocale),
1443 pFunction, &pCachedItem);
1444 if (!pSymbol)
1446 ::std::vector< OUString > aFallbacks( LocaleDataImpl::getFallbackLocaleServiceNames( rLocale));
1447 for (const auto& rFallback : aFallbacks)
1449 pSymbol = rLookupTable.getFunctionSymbolByName(rFallback, pFunction, &pCachedItem);
1450 if (pSymbol)
1451 break;
1454 if (!pSymbol)
1456 // load default function with name <func>_en_US
1457 pSymbol = rLookupTable.getFunctionSymbolByName("en_US", pFunction, &pCachedItem);
1460 if (!pSymbol)
1461 // Appropriate symbol could not be found. Give up.
1462 throw RuntimeException();
1464 if (pCachedItem)
1465 cachedItem = std::move(pCachedItem);
1466 if (cachedItem)
1467 cachedItem->aLocale = rLocale;
1469 return pSymbol;
1472 Sequence< Locale > SAL_CALL
1473 LocaleDataImpl::getAllInstalledLocaleNames()
1475 Sequence< lang::Locale > seq( nbOfLocales );
1476 sal_Int16 nInstalled = 0;
1478 for(const auto & i : aLibTable) {
1479 OUString name = OUString::createFromAscii( i.pLocale );
1481 // Check if the locale is really available and not just in the table,
1482 // don't allow fall backs.
1483 std::unique_ptr<LocaleDataLookupTableItem> pCachedItem;
1484 if (lcl_LookupTableStatic::get().getFunctionSymbolByName( name, "getLocaleItem", &pCachedItem )) {
1485 if( pCachedItem )
1486 cachedItem = std::move( pCachedItem );
1487 seq[nInstalled++] = LanguageTag::convertToLocale( name.replace( cUnder, cHyphen), false);
1490 if ( nInstalled < nbOfLocales )
1491 seq.realloc( nInstalled ); // reflect reality
1493 return seq;
1496 using namespace ::com::sun::star::container;
1497 using namespace ::com::sun::star::beans;
1498 using namespace ::com::sun::star::text;
1500 OutlineNumbering::OutlineNumbering(std::unique_ptr<const OutlineNumberingLevel_Impl[]> pOutlnLevels, int nLevels) :
1501 m_pOutlineLevels(std::move(pOutlnLevels)),
1502 m_nCount(sal::static_int_cast<sal_Int16>(nLevels))
1506 sal_Int32 OutlineNumbering::getCount( )
1508 return m_nCount;
1511 Any OutlineNumbering::getByIndex( sal_Int32 nIndex )
1513 if(nIndex < 0 || nIndex >= m_nCount)
1514 throw IndexOutOfBoundsException();
1515 const OutlineNumberingLevel_Impl* pTemp = m_pOutlineLevels.get();
1516 pTemp += nIndex;
1517 Any aRet;
1519 Sequence<PropertyValue> aOutlineNumbering(12);
1520 PropertyValue* pValues = aOutlineNumbering.getArray();
1521 pValues[0].Name = "Prefix";
1522 pValues[0].Value <<= pTemp->sPrefix;
1523 pValues[1].Name = "NumberingType";
1524 pValues[1].Value <<= pTemp->nNumType;
1525 pValues[2].Name = "Suffix";
1526 pValues[2].Value <<= pTemp->sSuffix;
1527 pValues[3].Name = "BulletChar";
1528 pValues[3].Value <<= OUString(&pTemp->cBulletChar, 1);
1529 pValues[4].Name = "BulletFontName";
1530 pValues[4].Value <<= pTemp->sBulletFontName;
1531 pValues[5].Name = "ParentNumbering";
1532 pValues[5].Value <<= pTemp->nParentNumbering;
1533 pValues[6].Name = "LeftMargin";
1534 pValues[6].Value <<= pTemp->nLeftMargin;
1535 pValues[7].Name = "SymbolTextDistance";
1536 pValues[7].Value <<= pTemp->nSymbolTextDistance;
1537 pValues[8].Name = "FirstLineOffset";
1538 pValues[8].Value <<= pTemp->nFirstLineOffset;
1539 pValues[9].Name = "Adjust";
1540 pValues[9].Value <<= sal_Int16(HoriOrientation::LEFT);
1541 pValues[10].Name = "Transliteration";
1542 pValues[10].Value <<= pTemp->sTransliteration;
1543 pValues[11].Name = "NatNum";
1544 pValues[11].Value <<= pTemp->nNatNum;
1545 aRet <<= aOutlineNumbering;
1546 return aRet;
1549 Type OutlineNumbering::getElementType( )
1551 return cppu::UnoType<Sequence<PropertyValue>>::get();
1554 sal_Bool OutlineNumbering::hasElements( )
1556 return m_nCount > 0;
1559 OUString SAL_CALL
1560 LocaleDataImpl::getImplementationName()
1562 return "com.sun.star.i18n.LocaleDataImpl";
1565 sal_Bool SAL_CALL LocaleDataImpl::supportsService(const OUString& rServiceName)
1567 return cppu::supportsService(this, rServiceName);
1570 Sequence< OUString > SAL_CALL
1571 LocaleDataImpl::getSupportedServiceNames()
1573 Sequence< OUString > aRet {
1574 "com.sun.star.i18n.LocaleData",
1575 "com.sun.star.i18n.LocaleData2"
1577 return aRet;
1580 // static
1581 OUString LocaleDataImpl::getFirstLocaleServiceName( const css::lang::Locale & rLocale )
1583 if (rLocale.Language == I18NLANGTAG_QLT)
1584 return rLocale.Variant.replace( cHyphen, cUnder);
1585 else if (!rLocale.Country.isEmpty())
1586 return rLocale.Language + "_" + rLocale.Country;
1587 else
1588 return rLocale.Language;
1591 // static
1592 ::std::vector< OUString > LocaleDataImpl::getFallbackLocaleServiceNames( const css::lang::Locale & rLocale )
1594 ::std::vector< OUString > aVec;
1595 if (rLocale.Language == I18NLANGTAG_QLT)
1597 aVec = LanguageTag( rLocale).getFallbackStrings( false);
1598 for (auto& rItem : aVec)
1600 rItem = rItem.replace(cHyphen, cUnder);
1603 else if (!rLocale.Country.isEmpty())
1605 aVec.push_back( rLocale.Language);
1607 // else nothing, language-only was the first
1608 return aVec;
1613 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
1614 com_sun_star_i18n_LocaleDataImpl_get_implementation(
1615 css::uno::XComponentContext *,
1616 css::uno::Sequence<css::uno::Any> const &)
1618 return cppu::acquire(new i18npool::LocaleDataImpl());
1621 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */