1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_i18npool.hxx"
26 
27 #include <localedata.hxx>
28 #include <i18npool/mslangid.hxx>
29 #include <rtl/ustrbuf.hxx>
30 #include <string.h>
31 #include <stdio.h>
32 #include "rtl/instance.hxx"
33 
34 using namespace com::sun::star::i18n;
35 using namespace com::sun::star::uno;
36 using namespace com::sun::star::lang;
37 using namespace com::sun::star;
38 using namespace rtl;
39 
40 static const sal_Char clocaledata[] = "com.sun.star.i18n.LocaleData";
41 
42 typedef sal_Unicode**   (SAL_CALL * MyFunc_Type)( sal_Int16&);
43 typedef sal_Unicode***  (SAL_CALL * MyFunc_Type2)( sal_Int16&, sal_Int16& );
44 typedef sal_Unicode**** (SAL_CALL * MyFunc_Type3)( sal_Int16&, sal_Int16&, sal_Int16& );
45 typedef sal_Unicode const * const * (SAL_CALL * MyFunc_FormatCode)( sal_Int16&, sal_Unicode const *&, sal_Unicode const *& );
46 
47 #ifdef OS2 // YD 8.3!!
48 static const char *lcl_DATA_EN = "ld_en";
49 static const char *lcl_DATA_ES = "ld_es";
50 static const char *lcl_DATA_EURO = "ld_eur";
51 static const char *lcl_DATA_OTHERS = "ld_oth";
52 #else
53 static const char *lcl_DATA_EN = "localedata_en";
54 static const char *lcl_DATA_ES = "localedata_es";
55 static const char *lcl_DATA_EURO = "localedata_euro";
56 static const char *lcl_DATA_OTHERS = "localedata_others";
57 #endif
58 
59 static const struct {
60     const char* pLocale;
61     const char* pLib;
62 } aLibTable[] = {
63     { "en_US",  lcl_DATA_EN },
64     { "en_AU",  lcl_DATA_EN },
65     { "en_BZ",  lcl_DATA_EN },
66     { "en_CA",  lcl_DATA_EN },
67     { "en_GB",  lcl_DATA_EN },
68     { "en_IE",  lcl_DATA_EN },
69     { "en_JM",  lcl_DATA_EN },
70     { "en_NZ",  lcl_DATA_EN },
71     { "en_PH",  lcl_DATA_EN },
72     { "en_TT",  lcl_DATA_EN },
73     { "en_ZA",  lcl_DATA_EN },
74     { "en_ZW",  lcl_DATA_EN },
75     { "en_NA",  lcl_DATA_EN },
76     { "en_GH",  lcl_DATA_EN },
77 
78     { "es_ES",  lcl_DATA_ES },
79     { "es_AR",  lcl_DATA_ES },
80     { "es_BO",  lcl_DATA_ES },
81     { "es_CL",  lcl_DATA_ES },
82     { "es_CO",  lcl_DATA_ES },
83     { "es_CR",  lcl_DATA_ES },
84     { "es_DO",  lcl_DATA_ES },
85     { "es_EC",  lcl_DATA_ES },
86     { "es_GT",  lcl_DATA_ES },
87     { "es_HN",  lcl_DATA_ES },
88     { "es_MX",  lcl_DATA_ES },
89     { "es_NI",  lcl_DATA_ES },
90     { "es_PA",  lcl_DATA_ES },
91     { "es_PE",  lcl_DATA_ES },
92     { "es_PR",  lcl_DATA_ES },
93     { "es_PY",  lcl_DATA_ES },
94     { "es_SV",  lcl_DATA_ES },
95     { "es_UY",  lcl_DATA_ES },
96     { "es_VE",  lcl_DATA_ES },
97     { "gl_ES",  lcl_DATA_ES },
98 
99     { "de_DE",  lcl_DATA_EURO },
100     { "de_AT",  lcl_DATA_EURO },
101     { "de_CH",  lcl_DATA_EURO },
102     { "de_LI",  lcl_DATA_EURO },
103     { "de_LU",  lcl_DATA_EURO },
104     { "fr_FR",  lcl_DATA_EURO },
105     { "fr_BE",  lcl_DATA_EURO },
106     { "fr_CA",  lcl_DATA_EURO },
107     { "fr_CH",  lcl_DATA_EURO },
108     { "fr_LU",  lcl_DATA_EURO },
109     { "fr_MC",  lcl_DATA_EURO },
110     { "it_IT",  lcl_DATA_EURO },
111     { "it_CH",  lcl_DATA_EURO },
112     { "sl_SI",  lcl_DATA_EURO },
113     { "sv_SE",  lcl_DATA_EURO },
114     { "sv_FI",  lcl_DATA_EURO },
115     { "ca_ES",  lcl_DATA_EURO },
116     { "cs_CZ",  lcl_DATA_EURO },
117     { "sk_SK",  lcl_DATA_EURO },
118     { "da_DK",  lcl_DATA_EURO },
119     { "el_GR",  lcl_DATA_EURO },
120     { "fi_FI",  lcl_DATA_EURO },
121     { "is_IS",  lcl_DATA_EURO },
122     { "nl_BE",  lcl_DATA_EURO },
123     { "nl_NL",  lcl_DATA_EURO },
124     { "no_NO",  lcl_DATA_EURO },
125     { "nn_NO",  lcl_DATA_EURO },
126     { "nb_NO",  lcl_DATA_EURO },
127     { "nds_DE", lcl_DATA_EURO },
128     { "pl_PL",  lcl_DATA_EURO },
129     { "pt_BR",  lcl_DATA_EURO },
130     { "pt_PT",  lcl_DATA_EURO },
131     { "ru_RU",  lcl_DATA_EURO },
132     { "tr_TR",  lcl_DATA_EURO },
133     { "tt_RU",  lcl_DATA_EURO },
134     { "et_EE",  lcl_DATA_EURO },
135     { "lb_LU",  lcl_DATA_EURO },
136     { "lt_LT",  lcl_DATA_EURO },
137     { "lv_LV",  lcl_DATA_EURO },
138     { "uk_UA",  lcl_DATA_EURO },
139     { "ro_RO",  lcl_DATA_EURO },
140     { "cy_GB",  lcl_DATA_EURO },
141     { "bg_BG",  lcl_DATA_EURO },
142     { "sh_ME",  lcl_DATA_EURO },
143     { "sh_RS",  lcl_DATA_EURO },
144     { "sh_YU",  lcl_DATA_EURO },
145     { "sr_ME",  lcl_DATA_EURO },
146     { "sr_RS",  lcl_DATA_EURO },
147     { "sr_YU",  lcl_DATA_EURO },
148     { "hr_HR",  lcl_DATA_EURO },
149     { "bs_BA",  lcl_DATA_EURO },
150     { "eu",     lcl_DATA_EURO },
151     { "fo_FO",  lcl_DATA_EURO },
152     { "ga_IE",  lcl_DATA_EURO },
153     { "gd_GB",  lcl_DATA_EURO },
154     { "ka_GE",  lcl_DATA_EURO },
155     { "be_BY",  lcl_DATA_EURO },
156     { "kl_GL",  lcl_DATA_EURO },
157     { "mk_MK",  lcl_DATA_EURO },
158     { "br_FR",  lcl_DATA_EURO },
159     { "la_VA",  lcl_DATA_EURO },
160     { "cv_RU",  lcl_DATA_EURO },
161     { "wa_BE",  lcl_DATA_EURO },
162     { "fur_IT", lcl_DATA_EURO },
163     { "gsc_FR", lcl_DATA_EURO },
164     { "fy_NL",  lcl_DATA_EURO },
165     { "oc_FR",  lcl_DATA_EURO },
166     { "mt_MT",  lcl_DATA_EURO },
167     { "sc_IT",  lcl_DATA_EURO },
168     { "ast_ES", lcl_DATA_EURO },
169     { "ltg_LV", lcl_DATA_EURO },
170     { "hsb_DE", lcl_DATA_EURO },
171     { "dsb_DE", lcl_DATA_EURO },
172     { "rue_SK", lcl_DATA_EURO },
173 
174     { "ja_JP",  lcl_DATA_OTHERS },
175     { "ko_KR",  lcl_DATA_OTHERS },
176     { "zh_CN",  lcl_DATA_OTHERS },
177     { "zh_HK",  lcl_DATA_OTHERS },
178     { "zh_SG",  lcl_DATA_OTHERS },
179     { "zh_TW",  lcl_DATA_OTHERS },
180     { "zh_MO",  lcl_DATA_OTHERS },
181 
182     { "ar_EG",  lcl_DATA_OTHERS },
183     { "ar_DZ",  lcl_DATA_OTHERS },
184     { "ar_LB",  lcl_DATA_OTHERS },
185     { "ar_SA",  lcl_DATA_OTHERS },
186     { "ar_TN",  lcl_DATA_OTHERS },
187     { "he_IL",  lcl_DATA_OTHERS },
188     { "hi_IN",  lcl_DATA_OTHERS },
189     { "kn_IN",  lcl_DATA_OTHERS },
190     { "ta_IN",  lcl_DATA_OTHERS },
191     { "te_IN",  lcl_DATA_OTHERS },
192     { "gu_IN",  lcl_DATA_OTHERS },
193     { "mr_IN",  lcl_DATA_OTHERS },
194     { "pa_IN",  lcl_DATA_OTHERS },
195     { "bn_IN",  lcl_DATA_OTHERS },
196     { "or_IN",  lcl_DATA_OTHERS },
197     { "en_IN",  lcl_DATA_OTHERS },
198     { "ml_IN",  lcl_DATA_OTHERS },
199     { "bn_BD",  lcl_DATA_OTHERS },
200     { "th_TH",  lcl_DATA_OTHERS },
201 
202     { "af_ZA",  lcl_DATA_OTHERS },
203     { "hu_HU",  lcl_DATA_OTHERS },
204     { "id_ID",  lcl_DATA_OTHERS },
205     { "ms_MY",  lcl_DATA_OTHERS },
206     { "ia",     lcl_DATA_OTHERS },
207     { "mn_MN",  lcl_DATA_OTHERS },
208     { "az_AZ",  lcl_DATA_OTHERS },
209     { "sw_TZ",  lcl_DATA_OTHERS },
210     { "km_KH",  lcl_DATA_OTHERS },
211     { "lo_LA",  lcl_DATA_OTHERS },
212     { "rw_RW",  lcl_DATA_OTHERS },
213     { "eo",     lcl_DATA_OTHERS },
214     { "dz_BT",  lcl_DATA_OTHERS },
215     { "ne_NP",  lcl_DATA_OTHERS },
216     { "zu_ZA",  lcl_DATA_OTHERS },
217     { "nso_ZA", lcl_DATA_OTHERS },
218     { "vi_VN",  lcl_DATA_OTHERS },
219     { "tn_ZA",  lcl_DATA_OTHERS },
220     { "xh_ZA",  lcl_DATA_OTHERS },
221     { "st_ZA",  lcl_DATA_OTHERS },
222     { "ss_ZA",  lcl_DATA_OTHERS },
223     { "ve_ZA",  lcl_DATA_OTHERS },
224     { "nr_ZA",  lcl_DATA_OTHERS },
225     { "ts_ZA",  lcl_DATA_OTHERS },
226     { "ku_TR",  lcl_DATA_OTHERS },
227     { "ak_GH",  lcl_DATA_OTHERS },
228     { "af_NA",  lcl_DATA_OTHERS },
229     { "am_ET",  lcl_DATA_OTHERS },
230     { "ti_ER",  lcl_DATA_OTHERS },
231     { "tg_TJ",  lcl_DATA_OTHERS },
232     { "ky_KG",  lcl_DATA_OTHERS },
233     { "kk_KZ",  lcl_DATA_OTHERS },
234     { "fa_IR",  lcl_DATA_OTHERS },
235     { "ha_GH",  lcl_DATA_OTHERS },
236     { "ee_GH",  lcl_DATA_OTHERS },
237     { "sg_CF",  lcl_DATA_OTHERS },
238     { "lg_UG",  lcl_DATA_OTHERS },
239     { "uz_UZ",  lcl_DATA_OTHERS },
240     { "ln_CD",  lcl_DATA_OTHERS },
241     { "hy_AM",  lcl_DATA_OTHERS },
242     { "hil_PH", lcl_DATA_OTHERS },
243     { "so_SO",  lcl_DATA_OTHERS },
244     { "gug_PY", lcl_DATA_OTHERS },
245     { "tk_TM",  lcl_DATA_OTHERS },
246     { "my_MM",  lcl_DATA_OTHERS },
247     { "shs_CA", lcl_DATA_OTHERS },
248     { "tpi_PG", lcl_DATA_OTHERS },
249     { "ar_OM",  lcl_DATA_OTHERS },
250     { "ug_CN",  lcl_DATA_OTHERS },
251     { "om_ET",  lcl_DATA_OTHERS },
252     { "plt_MG", lcl_DATA_OTHERS },
253     { "mai_IN", lcl_DATA_OTHERS },
254     { "yi_US",  lcl_DATA_OTHERS },
255     { "haw_US", lcl_DATA_OTHERS },
256     { "lif_NP", lcl_DATA_OTHERS },
257     { "ur_PK",  lcl_DATA_OTHERS },
258     { "ht_HT",  lcl_DATA_OTHERS },
259     { "jbo",    lcl_DATA_OTHERS }
260 };
261 
262 static const sal_Unicode under = sal_Unicode('_');
263 
264 static const sal_Int16 nbOfLocales = sizeof(aLibTable) / sizeof(aLibTable[0]);
265 
266 struct LocaleDataLookupTableItem
267 {
268         LocaleDataLookupTableItem(const sal_Char *name, osl::Module* m, const sal_Char* lname) : dllName(name), module(m), localeName(lname)
269         {
270         }
271         const sal_Char* dllName;
272         osl::Module *module;
273         const sal_Char* localeName;
274 
275         com::sun::star::lang::Locale aLocale;
276         sal_Bool equals(const com::sun::star::lang::Locale& rLocale)
277         {
278             return (rLocale == aLocale);
279         }
280 };
281 
282 LocaleData::LocaleData()
283 {
284 }
285 LocaleData::~LocaleData()
286 {
287 }
288 
289 
290 LocaleDataItem SAL_CALL
291 LocaleData::getLocaleItem( const Locale& rLocale ) throw(RuntimeException)
292 {
293         sal_Int16 dataItemCount = 0;
294         sal_Unicode **dataItem = NULL;
295 
296         MyFunc_Type func = (MyFunc_Type) getFunctionSymbol( rLocale, "getLocaleItem" );
297 
298         if ( func ) {
299             dataItem = func(dataItemCount);
300 
301             LocaleDataItem item(
302                     dataItem[0],
303                     dataItem[1],
304                     dataItem[2],
305                     dataItem[3],
306                     dataItem[4],
307                     dataItem[5],
308                     dataItem[6],
309                     dataItem[7],
310                     dataItem[8],
311                     dataItem[9],
312                     dataItem[10],
313                     dataItem[11],
314                     dataItem[12],
315                     dataItem[13],
316                     dataItem[14],
317                     dataItem[15],
318                     dataItem[16],
319                     dataItem[17]
320                     );
321             return item;
322         }
323         else {
324             LocaleDataItem item1;
325             return item1;
326         }
327 }
328 
329 extern "C" { static void SAL_CALL thisModule() {} }
330 
331 namespace
332 {
333 
334 // implement the lookup table as a safe static object
335 class lcl_LookupTableHelper
336 {
337 public:
338     lcl_LookupTableHelper();
339     ~lcl_LookupTableHelper();
340 
341     oslGenericFunction SAL_CALL getFunctionSymbolByName(
342         const OUString& localeName, const sal_Char* pFunction,
343         LocaleDataLookupTableItem** pOutCachedItem );
344 
345 private:
346     ::osl::Mutex maMutex;
347     ::std::vector< LocaleDataLookupTableItem* >  maLookupTable;
348 };
349 
350 // from instance.hxx: Helper base class for a late-initialized
351 // (default-constructed) static variable, implementing the double-checked
352 // locking pattern correctly.
353 // usage:  lcl_LookupTableHelper & rLookupTable = lcl_LookupTableStatic::get();
354 // retrieves the singleton lookup table instance
355 struct lcl_LookupTableStatic : public ::rtl::Static< lcl_LookupTableHelper, lcl_LookupTableStatic >
356 {};
357 
358 lcl_LookupTableHelper::lcl_LookupTableHelper()
359 {
360 }
361 
362 lcl_LookupTableHelper::~lcl_LookupTableHelper()
363 {
364     LocaleDataLookupTableItem* pItem = 0;
365 
366     std::vector<LocaleDataLookupTableItem*>::const_iterator aEnd(maLookupTable.end());
367     std::vector<LocaleDataLookupTableItem*>::iterator aIter(maLookupTable.begin());
368 
369     for ( ; aIter != aEnd; ++aIter ) {
370         pItem = *aIter;
371         delete pItem->module;
372         delete pItem;
373     }
374     maLookupTable.clear();
375 }
376 
377 oslGenericFunction SAL_CALL lcl_LookupTableHelper::getFunctionSymbolByName(
378     const OUString& localeName, const sal_Char* pFunction,
379     LocaleDataLookupTableItem** pOutCachedItem )
380 {
381     OUString aFallback;
382     bool bFallback = (localeName.indexOf( under) < 0);
383     if (bFallback)
384     {
385         Locale aLocale;
386         aLocale.Language = localeName;
387         Locale aFbLocale = MsLangId::getFallbackLocale( aLocale);
388         if (aFbLocale == aLocale)
389             bFallback = false;  // may be a "language-only-locale" like Interlingua (ia)
390         else if (aFbLocale.Country.getLength()) {
391             OUStringBuffer aBuf(5);
392             aFallback = aBuf.append(aFbLocale.Language).append( under).append(aFbLocale.Country).makeStringAndClear();
393         }
394         else
395             aFallback = aFbLocale.Language;
396     }
397 
398     for ( sal_Int16 i = 0; i < nbOfLocales; i++)
399     {
400         if (localeName.equalsAscii(aLibTable[i].pLocale) ||
401                 (bFallback && localeName == aFallback))
402         {
403             LocaleDataLookupTableItem* pCurrent = 0;
404             OUStringBuffer aBuf(strlen(aLibTable[i].pLocale) + 1 + strlen(pFunction));
405             {
406                 ::osl::MutexGuard aGuard( maMutex );
407                 for (size_t l = 0; l < maLookupTable.size(); l++)
408                 {
409                     pCurrent = maLookupTable[l];
410                     if (pCurrent->dllName == aLibTable[i].pLib)
411                     {
412                         OSL_ASSERT( pOutCachedItem );
413                         if( pOutCachedItem )
414                         {
415                             (*pOutCachedItem) = new LocaleDataLookupTableItem( *pCurrent );
416                             (*pOutCachedItem)->localeName = aLibTable[i].pLocale;
417                             return (*pOutCachedItem)->module->getFunctionSymbol(
418                                 aBuf.appendAscii( pFunction).append( under).
419                                 appendAscii( (*pOutCachedItem)->localeName).makeStringAndClear());
420                         }
421                         else
422                             return NULL;
423                     }
424                 }
425             }
426             // Library not loaded, load it and add it to the list.
427 #ifdef SAL_DLLPREFIX
428             aBuf.ensureCapacity(strlen(aLibTable[i].pLib) + 6);    // mostly "lib*.so"
429             aBuf.appendAscii( SAL_DLLPREFIX ).appendAscii(aLibTable[i].pLib).appendAscii( SAL_DLLEXTENSION );
430 #else
431             aBuf.ensureCapacity(strlen(aLibTable[i].pLib) + 4);    // mostly "*.dll"
432             aBuf.appendAscii(aLibTable[i].pLib).appendAscii( SAL_DLLEXTENSION );
433 #endif
434             osl::Module *module = new osl::Module();
435             if ( module->loadRelative(&thisModule, aBuf.makeStringAndClear()) )
436             {
437                 ::osl::MutexGuard aGuard( maMutex );
438                 LocaleDataLookupTableItem* pNewItem = 0;
439                 maLookupTable.push_back(pNewItem = new LocaleDataLookupTableItem(aLibTable[i].pLib, module, aLibTable[i].pLocale ));
440                 OSL_ASSERT( pOutCachedItem );
441                 if( pOutCachedItem )
442                 {
443                     (*pOutCachedItem) = new LocaleDataLookupTableItem( *pNewItem );
444                     return module->getFunctionSymbol(
445                         aBuf.appendAscii(pFunction).append(under).
446                         appendAscii((*pOutCachedItem)->localeName).makeStringAndClear());
447                 }
448                 else
449                     return NULL;
450             }
451             else
452                 delete module;
453         }
454     }
455     return NULL;
456 }
457 
458 } // anonymous namespace
459 
460 #define REF_DAYS 0
461 #define REF_MONTHS 1
462 #define REF_ERAS 2
463 
464 Sequence< CalendarItem > &LocaleData::getCalendarItemByName(const OUString& name,
465         const Locale& rLocale, const Sequence< Calendar >& calendarsSeq, sal_Int16 len, sal_Int16 item)
466         throw(RuntimeException)
467 {
468         if (!ref_name.equals(name)) {
469             sal_Int32 index = 0;
470             OUString language = name.getToken(0, under, index);
471             OUString country = name.getToken(0, under, index);
472             Locale loc(language, country, OUString());
473             Sequence < Calendar > cals;
474             if (loc == rLocale) {
475                 cals = calendarsSeq;
476             } else {
477                 cals = getAllCalendars(loc);
478                 len = sal::static_int_cast<sal_Int16>( cals.getLength() );
479             }
480             const OUString& id = name.getToken(0, under, index);
481             for (index = 0; index < cals.getLength(); index++) {
482                 if (id.equals(cals[index].Name)) {
483                     ref_cal = cals[index];
484                     break;
485                 }
486             }
487             // Referred locale does not found, return name for en_US locale.
488             if (index == cals.getLength()) {
489                 cals = getAllCalendars(
490                         Locale(OUString::createFromAscii("en"), OUString::createFromAscii("US"), OUString()));
491                 if (cals.getLength() > 0)
492                     ref_cal = cals[0];
493                 else
494                     throw RuntimeException();
495             }
496             ref_name = name;
497         }
498         return item == REF_DAYS ? ref_cal.Days : item == REF_MONTHS ? ref_cal.Months : ref_cal.Eras;
499 }
500 
501 
502 Sequence< Calendar > SAL_CALL
503 LocaleData::getAllCalendars( const Locale& rLocale ) throw(RuntimeException)
504 {
505 
506         sal_Int16 calendarsCount = 0;
507         sal_Unicode **allCalendars = NULL;
508 
509         MyFunc_Type func = (MyFunc_Type) getFunctionSymbol( rLocale, "getAllCalendars" );
510 
511         if ( func ) {
512             allCalendars = func(calendarsCount);
513 
514             Sequence< Calendar > calendarsSeq(calendarsCount);
515             sal_Int16 offset = 3;
516             sal_Int16 i, j;
517             for(i = 0; i < calendarsCount; i++) {
518                 Sequence< CalendarItem > days(allCalendars[0][i]);
519                 Sequence< CalendarItem > months(allCalendars[1][i]);
520                 Sequence< CalendarItem > eras(allCalendars[2][i]);
521                 OUString calendarID(allCalendars[offset]);
522                 offset++;
523                 sal_Bool defaultCalendar = sal::static_int_cast<sal_Bool>( allCalendars[offset][0] );
524                 offset++;
525                 if (OUString(allCalendars[offset]).equalsAscii("ref")) {
526                     days = getCalendarItemByName(OUString(allCalendars[offset+1]), rLocale, calendarsSeq, i, REF_DAYS);
527                     offset += 2;
528                 } else {
529                     for(j = 0; j < allCalendars[0][i]; j++) {
530                         CalendarItem day(allCalendars[offset],
531                             allCalendars[offset+1], allCalendars[offset+2]);
532                         days[j] = day;
533                         offset += 3;
534                     }
535                 }
536                 if (OUString(allCalendars[offset]).equalsAscii("ref")) {
537                     months = getCalendarItemByName(OUString(allCalendars[offset+1]), rLocale, calendarsSeq, i, REF_MONTHS);
538                     offset += 2;
539                 } else {
540                     for(j = 0; j < allCalendars[1][i]; j++) {
541                         CalendarItem month(allCalendars[offset],
542                             allCalendars[offset+1], allCalendars[offset+2]);
543                         months[j] = month;
544                         offset += 3;
545                     }
546                 }
547                 if (OUString(allCalendars[offset]).equalsAscii("ref")) {
548                     eras = getCalendarItemByName(OUString(allCalendars[offset+1]), rLocale, calendarsSeq, i, REF_ERAS);
549                     offset += 2;
550                 } else {
551                     for(j = 0; j < allCalendars[2][i]; j++) {
552                         CalendarItem era(allCalendars[offset],
553                             allCalendars[offset+1], allCalendars[offset+2]);
554                         eras[j] = era;
555                         offset += 3;
556                     }
557                 }
558                 OUString startOfWeekDay(allCalendars[offset]);
559                 offset++;
560                 sal_Int16 minimalDaysInFirstWeek = allCalendars[offset][0];
561                 offset++;
562                 Calendar aCalendar(days, months, eras, startOfWeekDay,
563                         minimalDaysInFirstWeek, defaultCalendar, calendarID);
564                 calendarsSeq[i] = aCalendar;
565             }
566             return calendarsSeq;
567         }
568         else {
569             Sequence< Calendar > seq1(0);
570             return seq1;
571         }
572 }
573 
574 
575 Sequence< Currency2 > SAL_CALL
576 LocaleData::getAllCurrencies2( const Locale& rLocale ) throw(RuntimeException)
577 {
578 
579         sal_Int16 currencyCount = 0;
580         sal_Unicode **allCurrencies = NULL;
581 
582         MyFunc_Type func = (MyFunc_Type) getFunctionSymbol( rLocale, "getAllCurrencies" );
583 
584         if ( func ) {
585             allCurrencies = func(currencyCount);
586 
587             Sequence< Currency2 > seq(currencyCount);
588             for(int i = 0, nOff = 0; i < currencyCount; i++, nOff += 8 ) {
589                 Currency2 cur(
590                     allCurrencies[nOff],        // string ID
591                     allCurrencies[nOff+1],      // string Symbol
592                     allCurrencies[nOff+2],      // string BankSymbol
593                     allCurrencies[nOff+3],      // string Name
594                     allCurrencies[nOff+4][0] != 0, // boolean Default
595                     allCurrencies[nOff+5][0] != 0, // boolean UsedInCompatibleFormatCodes
596                     allCurrencies[nOff+6][0],   // short DecimalPlaces
597                     allCurrencies[nOff+7][0] != 0 // boolean LegacyOnly
598                     );
599                     seq[i] = cur;
600             }
601             return seq;
602         }
603         else {
604             Sequence< Currency2 > seq1(0);
605             return seq1;
606         }
607 }
608 
609 
610 Sequence< Currency > SAL_CALL
611 LocaleData::getAllCurrencies( const Locale& rLocale ) throw(RuntimeException)
612 {
613     Sequence< Currency2 > aCur2( getAllCurrencies2( rLocale));
614     sal_Int32 nLen = aCur2.getLength();
615     Sequence< Currency > aCur1( nLen);
616     const Currency2* p2 = aCur2.getArray();
617     Currency* p1 = aCur1.getArray();
618     for (sal_Int32 i=0; i < nLen; ++i, ++p1, ++p2)
619     {
620         *p1 = *p2;
621     }
622     return aCur1;
623 }
624 
625 
626 // return a static (!) string resulting from replacing all occurrences of
627 // 'oldStr' string in 'formatCode' string with 'newStr' string
628 static const sal_Unicode * replace( sal_Unicode const * const formatCode, sal_Unicode const * const oldStr, sal_Unicode const * const newStr)
629 {
630 // make reasonable assumption of maximum length of formatCode.
631 #define MAX_FORMATCODE_LENTH 512
632     static sal_Unicode str[MAX_FORMATCODE_LENTH];
633 
634     if (oldStr[0] == 0) // no replacement requires
635         return formatCode;
636 
637     sal_Int32 i = 0, k = 0;
638     while (formatCode[i] > 0 && k < MAX_FORMATCODE_LENTH) {
639         sal_Int32 j = 0, last = k;
640         // search oldStr in formatCode
641         while (formatCode[i] > 0 && oldStr[j] > 0 && k < MAX_FORMATCODE_LENTH) {
642             str[k++] = formatCode[i];
643             if (formatCode[i++] != oldStr[j++])
644                 break;
645         }
646         if (oldStr[j] == 0) {
647             // matched string found, do replacement
648             k = last; j = 0;
649             while (newStr[j] > 0 && k < MAX_FORMATCODE_LENTH)
650                 str[k++] = newStr[j++];
651         }
652     }
653     if (k >= MAX_FORMATCODE_LENTH) // could not complete replacement, return original formatCode
654         return formatCode;
655 
656     str[k] = 0;
657     return str;
658 }
659 
660 Sequence< FormatElement > SAL_CALL
661 LocaleData::getAllFormats( const Locale& rLocale ) throw(RuntimeException)
662 {
663     const int SECTIONS = 2;
664     struct FormatSection
665     {
666         MyFunc_FormatCode         func;
667         sal_Unicode const        *from;
668         sal_Unicode const        *to;
669         sal_Unicode const *const *formatArray;
670         sal_Int16                 formatCount;
671 
672         FormatSection() : func(0), from(0), to(0), formatArray(0), formatCount(0) {}
673         sal_Int16 getFunc( LocaleData& rLocaleData, const Locale& rL, const char* pName )
674         {
675             func = reinterpret_cast<MyFunc_FormatCode>( rLocaleData.getFunctionSymbol( rL, pName));
676             if (func)
677                 formatArray = func( formatCount, from, to);
678             return formatCount;
679         }
680     } section[SECTIONS];
681 
682 #if 0
683 // #i79398# wntmsci10 MSVC doesn't get this right with optimization.
684     const sal_Int32 formatCount = section[0].getFunc( *this, rLocale, "getAllFormats0")
685                                 + section[1].getFunc( *this, rLocale, "getAllFormats1");
686 #else
687     sal_Int32 formatCount  = section[0].getFunc( *this, rLocale, "getAllFormats0");
688               formatCount += section[1].getFunc( *this, rLocale, "getAllFormats1");
689 #endif
690     Sequence< FormatElement > seq(formatCount);
691     sal_Int32 f = 0;
692     for (int s = 0; s < SECTIONS; ++s)
693     {
694         sal_Unicode const * const * const formatArray = section[s].formatArray;
695         if ( formatArray )
696         {
697             for (int i = 0, nOff = 0; i < section[s].formatCount; ++i, nOff += 7, ++f)
698             {
699                 FormatElement elem(
700                         replace( formatArray[nOff], section[s].from, section[s].to),
701                         formatArray[nOff + 1],
702                         formatArray[nOff + 2],
703                         formatArray[nOff + 3],
704                         formatArray[nOff + 4],
705                         formatArray[nOff + 5][0],
706                         sal::static_int_cast<sal_Bool>(formatArray[nOff + 6][0]));
707                 seq[f] = elem;
708             }
709         }
710     }
711     return seq;
712 }
713 
714 #define COLLATOR_OFFSET_ALGO    0
715 #define COLLATOR_OFFSET_DEFAULT 1
716 #define COLLATOR_OFFSET_RULE    2
717 #define COLLATOR_ELEMENTS       3
718 
719 OUString SAL_CALL
720 LocaleData::getCollatorRuleByAlgorithm( const Locale& rLocale, const OUString& algorithm ) throw(RuntimeException)
721 {
722         MyFunc_Type func = (MyFunc_Type) getFunctionSymbol( rLocale, "getCollatorImplementation" );
723         if ( func ) {
724             sal_Int16 collatorCount = 0;
725             sal_Unicode **collatorArray = func(collatorCount);
726             for(sal_Int16 i = 0; i < collatorCount; i++)
727                 if (algorithm.equals(collatorArray[i * COLLATOR_ELEMENTS + COLLATOR_OFFSET_ALGO]))
728                     return OUString(collatorArray[i * COLLATOR_ELEMENTS + COLLATOR_OFFSET_RULE]);
729         }
730         return OUString();
731 }
732 
733 
734 Sequence< Implementation > SAL_CALL
735 LocaleData::getCollatorImplementations( const Locale& rLocale ) throw(RuntimeException)
736 {
737         sal_Int16 collatorCount = 0;
738         sal_Unicode **collatorArray = NULL;
739 
740         MyFunc_Type func = (MyFunc_Type) getFunctionSymbol( rLocale, "getCollatorImplementation" );
741 
742         if ( func ) {
743             collatorArray = func(collatorCount);
744             Sequence< Implementation > seq(collatorCount);
745             for(sal_Int16 i = 0; i < collatorCount; i++) {
746               Implementation impl(collatorArray[i * COLLATOR_ELEMENTS + COLLATOR_OFFSET_ALGO],
747                       sal::static_int_cast<sal_Bool>(
748                           collatorArray[i * COLLATOR_ELEMENTS + COLLATOR_OFFSET_DEFAULT][0]));
749               seq[i] = impl;
750             }
751             return seq;
752         }
753         else {
754             Sequence< Implementation > seq1(0);
755             return seq1;
756         }
757 }
758 
759 Sequence< OUString > SAL_CALL
760 LocaleData::getCollationOptions( const Locale& rLocale ) throw(RuntimeException)
761 {
762         sal_Int16 optionsCount = 0;
763         sal_Unicode **optionsArray = NULL;
764 
765         MyFunc_Type func = (MyFunc_Type) getFunctionSymbol( rLocale, "getCollationOptions" );
766 
767         if ( func ) {
768             optionsArray = func(optionsCount);
769             Sequence< OUString > seq(optionsCount);
770             for(sal_Int16 i = 0; i < optionsCount; i++) {
771                     seq[i] = OUString( optionsArray[i] );
772             }
773             return seq;
774         }
775         else {
776             Sequence< OUString > seq1(0);
777             return seq1;
778         }
779 }
780 
781 Sequence< OUString > SAL_CALL
782 LocaleData::getSearchOptions( const Locale& rLocale ) throw(RuntimeException)
783 {
784         sal_Int16 optionsCount = 0;
785         sal_Unicode **optionsArray = NULL;
786 
787         MyFunc_Type func = (MyFunc_Type) getFunctionSymbol( rLocale, "getSearchOptions" );
788 
789         if ( func ) {
790             optionsArray = func(optionsCount);
791             Sequence< OUString > seq(optionsCount);
792             for(sal_Int16 i = 0; i < optionsCount; i++) {
793                     seq[i] = OUString( optionsArray[i] );
794             }
795             return seq;
796         }
797         else {
798             Sequence< OUString > seq1(0);
799             return seq1;
800         }
801 }
802 
803 sal_Unicode ** SAL_CALL
804 LocaleData::getIndexArray(const Locale& rLocale, sal_Int16& indexCount)
805 {
806         MyFunc_Type func = (MyFunc_Type) getFunctionSymbol( rLocale, "getIndexAlgorithm" );
807 
808         if (func)
809             return func(indexCount);
810         return NULL;
811 }
812 
813 Sequence< OUString > SAL_CALL
814 LocaleData::getIndexAlgorithm( const Locale& rLocale ) throw(RuntimeException)
815 {
816         sal_Int16 indexCount = 0;
817         sal_Unicode **indexArray = getIndexArray(rLocale, indexCount);
818 
819         if ( indexArray ) {
820             Sequence< OUString > seq(indexCount);
821             for(sal_Int16 i = 0; i < indexCount; i++) {
822               seq[i] = indexArray[i*5];
823             }
824             return seq;
825         }
826         else {
827             Sequence< OUString > seq1(0);
828             return seq1;
829         }
830 }
831 
832 OUString SAL_CALL
833 LocaleData::getDefaultIndexAlgorithm( const Locale& rLocale ) throw(RuntimeException)
834 {
835         sal_Int16 indexCount = 0;
836         sal_Unicode **indexArray = getIndexArray(rLocale, indexCount);
837 
838         if ( indexArray ) {
839             for(sal_Int16 i = 0; i < indexCount; i++) {
840               if (indexArray[i*5 + 3][0])
841                   return OUString(indexArray[i*5]);
842             }
843         }
844         return OUString();
845 }
846 
847 sal_Bool SAL_CALL
848 LocaleData::hasPhonetic( const Locale& rLocale ) throw(RuntimeException)
849 {
850         sal_Int16 indexCount = 0;
851         sal_Unicode **indexArray = getIndexArray(rLocale, indexCount);
852 
853         if ( indexArray ) {
854             for(sal_Int16 i = 0; i < indexCount; i++) {
855               if (indexArray[i*5 + 4][0])
856                   return sal_True;
857             }
858         }
859         return sal_False;
860 }
861 
862 sal_Unicode ** SAL_CALL
863 LocaleData::getIndexArrayForAlgorithm(const Locale& rLocale, const OUString& algorithm)
864 {
865         sal_Int16 indexCount = 0;
866         sal_Unicode **indexArray = getIndexArray(rLocale, indexCount);
867         if ( indexArray ) {
868             for(sal_Int16 i = 0; i < indexCount; i++) {
869               if (algorithm.equals(indexArray[i*5]))
870                   return indexArray+i*5;
871             }
872         }
873         return NULL;
874 }
875 
876 sal_Bool SAL_CALL
877 LocaleData::isPhonetic( const Locale& rLocale, const OUString& algorithm ) throw(RuntimeException)
878 {
879         sal_Unicode **indexArray = getIndexArrayForAlgorithm(rLocale, algorithm);
880         return (indexArray && indexArray[4][0]) ? sal_True : sal_False;
881 }
882 
883 OUString SAL_CALL
884 LocaleData::getIndexKeysByAlgorithm( const Locale& rLocale, const OUString& algorithm ) throw(RuntimeException)
885 {
886         sal_Unicode **indexArray = getIndexArrayForAlgorithm(rLocale, algorithm);
887         return indexArray ? OUString::createFromAscii("0-9")+OUString(indexArray[2]) : OUString();
888 }
889 
890 OUString SAL_CALL
891 LocaleData::getIndexModuleByAlgorithm( const Locale& rLocale, const OUString& algorithm ) throw(RuntimeException)
892 {
893         sal_Unicode **indexArray = getIndexArrayForAlgorithm(rLocale, algorithm);
894         return indexArray ? OUString(indexArray[1]) : OUString();
895 }
896 
897 Sequence< UnicodeScript > SAL_CALL
898 LocaleData::getUnicodeScripts( const Locale& rLocale ) throw(RuntimeException)
899 {
900         sal_Int16 scriptCount = 0;
901         sal_Unicode **scriptArray = NULL;
902 
903         MyFunc_Type func = (MyFunc_Type) getFunctionSymbol( rLocale, "getUnicodeScripts" );
904 
905         if ( func ) {
906             scriptArray = func(scriptCount);
907             Sequence< UnicodeScript > seq(scriptCount);
908             for(sal_Int16 i = 0; i < scriptCount; i++) {
909                     seq[i] = UnicodeScript( OUString(scriptArray[i]).toInt32() );
910             }
911             return seq;
912         }
913         else {
914             Sequence< UnicodeScript > seq1(0);
915             return seq1;
916         }
917 }
918 
919 Sequence< OUString > SAL_CALL
920 LocaleData::getFollowPageWords( const Locale& rLocale ) throw(RuntimeException)
921 {
922         sal_Int16 wordCount = 0;
923         sal_Unicode **wordArray = NULL;
924 
925         MyFunc_Type func = (MyFunc_Type) getFunctionSymbol( rLocale, "getFollowPageWords" );
926 
927         if ( func ) {
928             wordArray = func(wordCount);
929             Sequence< OUString > seq(wordCount);
930             for(sal_Int16 i = 0; i < wordCount; i++) {
931                     seq[i] = OUString(wordArray[i]);
932             }
933             return seq;
934         }
935         else {
936             Sequence< OUString > seq1(0);
937             return seq1;
938         }
939 }
940 
941 Sequence< OUString > SAL_CALL
942 LocaleData::getTransliterations( const Locale& rLocale ) throw(RuntimeException)
943 {
944 
945         sal_Int16 transliterationsCount = 0;
946         sal_Unicode **transliterationsArray = NULL;
947 
948         MyFunc_Type func = (MyFunc_Type) getFunctionSymbol( rLocale, "getTransliterations" );
949 
950         if ( func ) {
951             transliterationsArray = func(transliterationsCount);
952 
953             Sequence< OUString > seq(transliterationsCount);
954             for(int i = 0; i < transliterationsCount; i++) {
955                     OUString  elem(transliterationsArray[i]);
956                     seq[i] = elem;
957             }
958             return seq;
959         }
960         else {
961             Sequence< OUString > seq1(0);
962             return seq1;
963         }
964 
965 
966 }
967 
968 
969 LanguageCountryInfo SAL_CALL
970 LocaleData::getLanguageCountryInfo( const Locale& rLocale ) throw(RuntimeException)
971 {
972         sal_Int16 LCInfoCount = 0;
973         sal_Unicode **LCInfoArray = NULL;
974 
975         MyFunc_Type func = (MyFunc_Type) getFunctionSymbol( rLocale, "getLCInfo" );
976 
977         if ( func ) {
978             LCInfoArray = func(LCInfoCount);
979             LanguageCountryInfo info(LCInfoArray[0],
980                                     LCInfoArray[1],
981                                     LCInfoArray[2],
982                                     LCInfoArray[3],
983                                     LCInfoArray[4]);
984             return info;
985         }
986         else {
987             LanguageCountryInfo info1;
988             return info1;
989         }
990 
991 }
992 
993 
994 ForbiddenCharacters SAL_CALL
995 LocaleData::getForbiddenCharacters( const Locale& rLocale ) throw(RuntimeException)
996 {
997         sal_Int16 LCForbiddenCharactersCount = 0;
998         sal_Unicode **LCForbiddenCharactersArray = NULL;
999 
1000         MyFunc_Type func = (MyFunc_Type) getFunctionSymbol( rLocale, "getForbiddenCharacters" );
1001 
1002         if ( func ) {
1003             LCForbiddenCharactersArray = func(LCForbiddenCharactersCount);
1004             ForbiddenCharacters chars(LCForbiddenCharactersArray[0], LCForbiddenCharactersArray[1]);
1005             return chars;
1006         }
1007         else {
1008             ForbiddenCharacters chars1;
1009             return chars1;
1010         }
1011 }
1012 
1013 OUString SAL_CALL
1014 LocaleData::getHangingCharacters( const Locale& rLocale ) throw(RuntimeException)
1015 {
1016         sal_Int16 LCForbiddenCharactersCount = 0;
1017         sal_Unicode **LCForbiddenCharactersArray = NULL;
1018 
1019         MyFunc_Type func = (MyFunc_Type) getFunctionSymbol( rLocale, "getForbiddenCharacters" );
1020 
1021         if ( func ) {
1022             LCForbiddenCharactersArray = func(LCForbiddenCharactersCount);
1023             return OUString(LCForbiddenCharactersArray[2]);
1024         }
1025 
1026         return OUString();
1027 }
1028 
1029 Sequence< OUString > SAL_CALL
1030 LocaleData::getBreakIteratorRules( const Locale& rLocale  ) throw(RuntimeException)
1031 {
1032         sal_Int16 LCBreakIteratorRuleCount = 0;
1033         sal_Unicode **LCBreakIteratorRulesArray = NULL;
1034 
1035         MyFunc_Type func = (MyFunc_Type) getFunctionSymbol( rLocale, "getBreakIteratorRules" );
1036 
1037         if ( func ) {
1038             LCBreakIteratorRulesArray = func(LCBreakIteratorRuleCount);
1039             Sequence< OUString > seq(LCBreakIteratorRuleCount);
1040             for(int i = 0; i < (LCBreakIteratorRuleCount); i++) {
1041                 OUString  elem(LCBreakIteratorRulesArray[i]);
1042                 seq[i] = elem;
1043             }
1044             return seq;
1045         }
1046         else {
1047             Sequence< OUString > seq1(0);
1048             return seq1;
1049         }
1050 }
1051 
1052 
1053 Sequence< OUString > SAL_CALL
1054 LocaleData::getReservedWord( const Locale& rLocale  ) throw(RuntimeException)
1055 {
1056         sal_Int16 LCReservedWordsCount = 0;
1057         sal_Unicode **LCReservedWordsArray = NULL;
1058 
1059         MyFunc_Type func = (MyFunc_Type) getFunctionSymbol( rLocale, "getReservedWords" );
1060 
1061         if ( func ) {
1062             LCReservedWordsArray = func(LCReservedWordsCount);
1063             Sequence< OUString > seq(LCReservedWordsCount);
1064             for(int i = 0; i < (LCReservedWordsCount); i++) {
1065                 OUString  elem(LCReservedWordsArray[i]);
1066                 seq[i] = elem;
1067             }
1068             return seq;
1069         }
1070         else {
1071             Sequence< OUString > seq1(0);
1072             return seq1;
1073         }
1074 }
1075 
1076 
1077 inline
1078 OUString C2U( const char* s )
1079 {
1080         return OUString::createFromAscii( s );
1081 }
1082 
1083 Sequence< Sequence<beans::PropertyValue> > SAL_CALL
1084 LocaleData::getContinuousNumberingLevels( const lang::Locale& rLocale ) throw(RuntimeException)
1085 {
1086          int i;
1087 
1088          // load symbol
1089          MyFunc_Type2 func = (MyFunc_Type2) getFunctionSymbol( rLocale, "getContinuousNumberingLevels" );
1090 
1091          if ( func )
1092          {
1093               // invoke function
1094               sal_Int16 nStyles;
1095               sal_Int16 nAttributes;
1096               sal_Unicode*** p0 = func( nStyles, nAttributes );
1097 
1098               // allocate memory for nAttributes attributes for each of the nStyles styles.
1099               Sequence< Sequence<beans::PropertyValue> > pv( nStyles );
1100               for( i=0; i<pv.getLength(); i++ ) {
1101                    pv[i] = Sequence<beans::PropertyValue>( nAttributes );
1102               }
1103 
1104               sal_Unicode*** pStyle = p0;
1105               for( i=0;  i<nStyles;  i++ ) {
1106                    sal_Unicode** pAttribute = pStyle[i];
1107                    for( int j=0;  j<nAttributes;  j++ ) { // prefix, numberingtype, ...
1108                         sal_Unicode* pString = pAttribute[j];
1109                         beans::PropertyValue& rVal = pv[i][j];
1110                         OUString sVal;
1111                         if( pString ) {
1112                             if( 0 != j && 2 != j )
1113                                 sVal = pString;
1114                             else if( *pString )
1115                                 sVal = OUString( pString, 1 );
1116                         }
1117 
1118                         switch( j )
1119                         {
1120                         case 0:
1121                              rVal.Name = C2U("Prefix");
1122                              rVal.Value <<= sVal;
1123                              break;
1124                         case 1:
1125                              rVal.Name = C2U("NumberingType");
1126                              rVal.Value <<= (sal_Int16) sVal.toInt32();
1127                              break;
1128                         case 2:
1129                              rVal.Name = C2U("Suffix");
1130                              rVal.Value <<= sVal;
1131                              break;
1132                         case 3:
1133                              rVal.Name = C2U("Transliteration");
1134                              rVal.Value <<= sVal;
1135                              break;
1136                         case 4:
1137                              rVal.Name = C2U("NatNum");
1138                              rVal.Value <<= (sal_Int16) sVal.toInt32();
1139                              break;
1140                         default:
1141                              OSL_ASSERT(0);
1142                         }
1143                    }
1144               }
1145               return pv;
1146          }
1147 
1148          Sequence< Sequence<beans::PropertyValue> > seq1(0);
1149          return seq1;
1150 }
1151 
1152 // ============================================================================
1153 // \/ OutlineNumbering helper class \/
1154 //
1155 #include <com/sun/star/container/XIndexAccess.hpp>
1156 #include <cppuhelper/implbase1.hxx>
1157 
1158 namespace com{ namespace sun{ namespace star{ namespace lang {
1159         struct  Locale;
1160 }}}}
1161 //-----------------------------------------------------------------------------
1162 struct OutlineNumberingLevel_Impl
1163 {
1164         OUString        sPrefix;
1165         sal_Int16               nNumType; //com::sun::star::style::NumberingType
1166         OUString        sSuffix;
1167         sal_Unicode     cBulletChar;
1168         const sal_Char* sBulletFontName;
1169         sal_Int16               nParentNumbering;
1170         sal_Int32               nLeftMargin;
1171         sal_Int32               nSymbolTextDistance;
1172         sal_Int32               nFirstLineOffset;
1173         OUString        sTransliteration;
1174         sal_Int32               nNatNum;
1175 };
1176 //-----------------------------------------------------------------------------
1177 class OutlineNumbering : public cppu::WeakImplHelper1 < container::XIndexAccess >
1178 {
1179         const OutlineNumberingLevel_Impl* m_pOutlineLevels;
1180         sal_Int16                         m_nCount;
1181 public:
1182 //      OutlineNumbering(const OutlineNumberingLevel_Impl* pOutlineLevels);
1183         OutlineNumbering(const OutlineNumberingLevel_Impl* pOutlineLevels, int nLevels);
1184         ~OutlineNumbering();
1185 
1186         //XIndexAccess
1187         virtual sal_Int32 SAL_CALL getCount(  ) throw(RuntimeException);
1188         virtual Any SAL_CALL getByIndex( sal_Int32 Index )
1189             throw(IndexOutOfBoundsException, WrappedTargetException, RuntimeException);
1190 
1191         //XElementAccess
1192         virtual Type SAL_CALL getElementType(  ) throw(RuntimeException);
1193         virtual sal_Bool SAL_CALL hasElements(  ) throw(RuntimeException);
1194 };
1195 
1196 //
1197 //     OutlineNumbering helper class
1198 // ============================================================================
1199 
1200 static
1201 sal_Char* U2C( OUString str )
1202 {
1203 	 sal_Char* s = new sal_Char[ str.getLength()+1 ];
1204 	 int i;
1205 	 for( i = 0; i < str.getLength(); i++)
1206 		 s[i] = sal::static_int_cast<sal_Char>( str[i] );
1207 	 s[i]='\0';
1208 	 return s;
1209 }
1210 
1211 
1212 Sequence< Reference<container::XIndexAccess> > SAL_CALL
1213 LocaleData::getOutlineNumberingLevels( const lang::Locale& rLocale ) throw(RuntimeException)
1214 {
1215     int i;
1216 
1217     // load symbol
1218     MyFunc_Type3 func = (MyFunc_Type3) getFunctionSymbol( rLocale, "getOutlineNumberingLevels" );
1219 
1220     if ( func )
1221     {
1222         // invoke function
1223         sal_Int16 nStyles;
1224         sal_Int16 nLevels;
1225         sal_Int16 nAttributes;
1226         sal_Unicode**** p0 = func( nStyles, nLevels, nAttributes );
1227 
1228         Sequence< Reference<container::XIndexAccess> > aRet( nStyles );
1229 
1230         OUString aEmptyStr;
1231 
1232         sal_Unicode**** pStyle = p0;
1233         for( i=0;  i<nStyles;  i++ )
1234         {
1235             int j;
1236 
1237             OutlineNumberingLevel_Impl* level = new OutlineNumberingLevel_Impl[ nLevels+1 ];
1238             sal_Unicode*** pLevel = pStyle[i];
1239             for( j = 0;  j < nLevels;  j++ )
1240             {
1241                 sal_Unicode** pAttribute = pLevel[j];
1242                 for( int k=0; k<nAttributes; k++ )
1243                 {
1244                     OUString tmp( pAttribute[k] );
1245                     switch( k )
1246                     {
1247                         case 0: level[j].sPrefix             = tmp;             break;
1248                         case 1: level[j].nNumType            = sal::static_int_cast<sal_Int16>(tmp.toInt32()); break;
1249                         case 2: level[j].sSuffix             = tmp;             break;
1250                         //case 3: level[j].cBulletChar         = tmp.toChar();    break;
1251                         case 3: level[j].cBulletChar         = sal::static_int_cast<sal_Unicode>(tmp.toInt32(16)); break; // base 16
1252                         case 4: level[j].sBulletFontName     = U2C( tmp );      break;
1253                         case 5: level[j].nParentNumbering    = sal::static_int_cast<sal_Int16>(tmp.toInt32()); break;
1254                         case 6: level[j].nLeftMargin         = tmp.toInt32();   break;
1255                         case 7: level[j].nSymbolTextDistance = tmp.toInt32();   break;
1256                         case 8: level[j].nFirstLineOffset    = tmp.toInt32();   break;
1257                         case 9: // Adjust
1258                         // these values seem to be hard-coded elsewhere:
1259                         // level[j].Value <<= (sal_Int16) text::HoriOrientation::LEFT;
1260                         // level[j].Value <<= (sal_Int16) style::HorizontalAlignment::LEFT;
1261                             break;
1262                         case 10: level[j].sTransliteration = tmp; break;
1263                         case 11: level[j].nNatNum    = tmp.toInt32();   break;
1264                         default:
1265                             OSL_ASSERT(0);
1266                     }
1267                 }
1268             }
1269             level[j].sPrefix             = aEmptyStr;
1270             level[j].nNumType            = 0;
1271             level[j].sSuffix             = aEmptyStr;
1272             level[j].cBulletChar         = 0;
1273             level[j].sBulletFontName     = 0;
1274             level[j].nParentNumbering    = 0;
1275             level[j].nLeftMargin         = 0;
1276             level[j].nSymbolTextDistance = 0;
1277             level[j].nFirstLineOffset    = 0;
1278             level[j].sTransliteration    = aEmptyStr;
1279             level[j].nNatNum             = 0;
1280             aRet[i] = new OutlineNumbering( level, nLevels );
1281         }
1282         return aRet;
1283     }
1284     else {
1285         Sequence< Reference<container::XIndexAccess> > seq1(0);
1286         return seq1;
1287     }
1288 }
1289 
1290 /////////////////////////////////////////////////////////////////////////////////////////////
1291 //////////////////////////////////helper functions///////////////////////////////////////////
1292 /////////////////////////////////////////////////////////////////////////////////////////////
1293 
1294 oslGenericFunction SAL_CALL LocaleData::getFunctionSymbol( const Locale& rLocale, const sal_Char* pFunction )
1295         throw(RuntimeException)
1296 {
1297         lcl_LookupTableHelper & rLookupTable = lcl_LookupTableStatic::get();
1298 
1299         OUStringBuffer aBuf(1);
1300         if (cachedItem.get() && cachedItem->equals(rLocale)) {
1301             aBuf.ensureCapacity(strlen(pFunction) + 1 + strlen(cachedItem->localeName));
1302             return cachedItem->module->getFunctionSymbol(aBuf.appendAscii(pFunction).append(under).
1303                                         appendAscii(cachedItem->localeName).makeStringAndClear());
1304         }
1305 
1306         oslGenericFunction pSymbol = 0;
1307         static OUString tw(OUString::createFromAscii("TW"));
1308         static OUString en_US(OUString::createFromAscii("en_US"));
1309 
1310         sal_Int32 l = rLocale.Language.getLength();
1311         sal_Int32 c = rLocale.Country.getLength();
1312         sal_Int32 v = rLocale.Variant.getLength();
1313         aBuf.ensureCapacity(l+c+v+3);
1314 
1315         LocaleDataLookupTableItem *pCachedItem = 0;
1316 
1317         if ((l > 0 && c > 0 && v > 0 &&
1318                 // load function with name <func>_<lang>_<country>_<varian>
1319                 (pSymbol = rLookupTable.getFunctionSymbolByName(aBuf.append(rLocale.Language).append(under).append(
1320                         rLocale.Country).append(under).append(rLocale.Variant).makeStringAndClear(), pFunction, &pCachedItem)) != 0) ||
1321             (l > 0 && c > 0 &&
1322                 // load function with name <ase>_<lang>_<country>
1323                 (pSymbol = rLookupTable.getFunctionSymbolByName(aBuf.append(rLocale.Language).append(under).append(
1324                         rLocale.Country).makeStringAndClear(), pFunction, &pCachedItem)) != 0) ||
1325             (l > 0 && c > 0 && rLocale.Language.equalsAscii("zh") &&
1326                                 (rLocale.Country.equalsAscii("HK") ||
1327                                 rLocale.Country.equalsAscii("MO")) &&
1328                 // if the country code is HK or MO, one more step to try TW.
1329                 (pSymbol = rLookupTable.getFunctionSymbolByName(aBuf.append(rLocale.Language).append(under).append(tw).makeStringAndClear(),
1330                         pFunction, &pCachedItem)) != 0) ||
1331             (l > 0 &&
1332                 // load function with name <func>_<lang>
1333                 (pSymbol = rLookupTable.getFunctionSymbolByName(rLocale.Language, pFunction, &pCachedItem)) != 0) ||
1334                 // load default function with name <func>_en_US
1335                 (pSymbol = rLookupTable.getFunctionSymbolByName(en_US, pFunction, &pCachedItem)) != 0)
1336         {
1337             if( pCachedItem )
1338                 cachedItem.reset( pCachedItem );
1339             if( cachedItem.get())
1340                 cachedItem->aLocale = rLocale;
1341             return pSymbol;
1342         }
1343         throw RuntimeException();
1344 }
1345 
1346 Sequence< Locale > SAL_CALL
1347 LocaleData::getAllInstalledLocaleNames() throw(RuntimeException)
1348 {
1349         Sequence< lang::Locale > seq( nbOfLocales );
1350         OUString empStr;
1351         sal_Int16 nInstalled = 0;
1352 
1353         for( sal_Int16 i=0; i<nbOfLocales; i++ ) {
1354             OUString name = OUString::createFromAscii( aLibTable[i].pLocale );
1355 
1356             // Check if the locale is really available and not just in the table,
1357             // don't allow fall backs.
1358             LocaleDataLookupTableItem *pCachedItem = 0;
1359             if (lcl_LookupTableStatic::get().getFunctionSymbolByName( name, "getLocaleItem", &pCachedItem )) {
1360                 if( pCachedItem )
1361                     cachedItem.reset( pCachedItem );
1362                 sal_Int32 index = 0;
1363                 lang::Locale tmpLocale(name.getToken(0, under, index), empStr, empStr);
1364                 if (index >= 0) {
1365                     tmpLocale.Country = name.getToken(0, under, index);
1366                     if (index >= 0)
1367                         tmpLocale.Variant = name.getToken(0, under, index);
1368                 }
1369                 seq[nInstalled++] = tmpLocale;
1370             }
1371         }
1372         if ( nInstalled < nbOfLocales )
1373             seq.realloc( nInstalled );          // reflect reality
1374 
1375         return seq;
1376 }
1377 
1378 // ============================================================================
1379 
1380 using namespace ::com::sun::star::container;
1381 using namespace ::com::sun::star::beans;
1382 using namespace ::com::sun::star::style;
1383 using namespace ::com::sun::star::text;
1384 
1385 // // bad: can't have empty prefix ...
1386 // OutlineNumbering::OutlineNumbering(const OutlineNumberingLevel_Impl* pOutlnLevels) :
1387 //         m_pOutlineLevels(pOutlnLevels),
1388 //         m_nCount(0)
1389 // {
1390 //         const OutlineNumberingLevel_Impl* pTemp = m_pOutlineLevels;
1391 //         while((pTemp++)->sPrefix)
1392 //                 m_nCount++;
1393 // }
1394 
1395 OutlineNumbering::OutlineNumbering(const OutlineNumberingLevel_Impl* pOutlnLevels, int nLevels) :
1396         m_pOutlineLevels(pOutlnLevels),
1397         m_nCount(sal::static_int_cast<sal_Int16>(nLevels))
1398 {
1399 }
1400 
1401 OutlineNumbering::~OutlineNumbering()
1402 {
1403         delete [] m_pOutlineLevels;
1404 }
1405 
1406 sal_Int32 OutlineNumbering::getCount(  ) throw(RuntimeException)
1407 {
1408         return m_nCount;
1409 }
1410 
1411 Any OutlineNumbering::getByIndex( sal_Int32 nIndex )
1412         throw(IndexOutOfBoundsException, WrappedTargetException, RuntimeException)
1413 {
1414         if(nIndex < 0 || nIndex >= m_nCount)
1415                 throw IndexOutOfBoundsException();
1416         const OutlineNumberingLevel_Impl* pTemp = m_pOutlineLevels;
1417         pTemp += nIndex;
1418         Any aRet;
1419 
1420         Sequence<PropertyValue> aOutlineNumbering(12);
1421         PropertyValue* pValues = aOutlineNumbering.getArray();
1422         pValues[0].Name = C2U( "Prefix");
1423         pValues[0].Value <<= pTemp->sPrefix;
1424         pValues[1].Name = C2U("NumberingType");
1425         pValues[1].Value <<= pTemp->nNumType;
1426         pValues[2].Name = C2U("Suffix");
1427         pValues[2].Value <<= pTemp->sSuffix;
1428         pValues[3].Name = C2U("BulletChar");
1429         pValues[3].Value <<= OUString(&pTemp->cBulletChar, 1);
1430         pValues[4].Name = C2U("BulletFontName");
1431         pValues[4].Value <<= C2U(pTemp->sBulletFontName);
1432         pValues[5].Name = C2U("ParentNumbering");
1433         pValues[5].Value <<= pTemp->nParentNumbering;
1434         pValues[6].Name = C2U("LeftMargin");
1435         pValues[6].Value <<= pTemp->nLeftMargin;
1436         pValues[7].Name = C2U("SymbolTextDistance");
1437         pValues[7].Value <<= pTemp->nSymbolTextDistance;
1438         pValues[8].Name = C2U("FirstLineOffset");
1439         pValues[8].Value <<= pTemp->nFirstLineOffset;
1440         pValues[9].Name = C2U("Adjust");
1441         pValues[9].Value <<= (sal_Int16)HoriOrientation::LEFT;
1442         pValues[10].Name = C2U("Transliteration");
1443         pValues[10].Value <<= pTemp->sTransliteration;
1444         pValues[11].Name = C2U("NatNum");
1445         pValues[11].Value <<= pTemp->nNatNum;
1446         aRet <<= aOutlineNumbering;
1447         return aRet;
1448 }
1449 
1450 Type OutlineNumbering::getElementType(  ) throw(RuntimeException)
1451 {
1452         return ::getCppuType((Sequence<PropertyValue>*)0);
1453 }
1454 
1455 sal_Bool OutlineNumbering::hasElements(  ) throw(RuntimeException)
1456 {
1457         return m_nCount > 0;
1458 }
1459 
1460 OUString SAL_CALL
1461 LocaleData::getImplementationName() throw( RuntimeException )
1462 {
1463         return OUString::createFromAscii(clocaledata);
1464 }
1465 
1466 sal_Bool SAL_CALL
1467 LocaleData::supportsService(const OUString& rServiceName)
1468                 throw( RuntimeException )
1469 {
1470         return !rServiceName.compareToAscii(clocaledata);
1471 }
1472 
1473 Sequence< OUString > SAL_CALL
1474 LocaleData::getSupportedServiceNames() throw( RuntimeException )
1475 {
1476         Sequence< OUString > aRet(1);
1477         aRet[0] = OUString::createFromAscii(clocaledata);
1478         return aRet;
1479 }
1480