xref: /trunk/main/sal/osl/unx/nlsupport.c (revision 6de71850)
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 #include <osl/nlsupport.h>
25 #include <osl/diagnose.h>
26 #include <osl/process.h>
27 #include <rtl/memory.h>
28 
29 #if defined(LINUX) || defined(SOLARIS) || defined(NETBSD) || defined(FREEBSD) || defined(MACOSX)
30 #include <pthread.h>
31 #ifndef MACOSX
32  #include <locale.h>
33  #include <langinfo.h>
34 #else
35 #include <osl/module.h>
36 #include <osl/thread.h>
37 #endif	/* !MACOSX */
38 #endif	/* LINUX || SOLARIS || NETBSD || MACOSX */
39 
40 #include <string.h>
41 
42 /*****************************************************************************
43  typedefs
44  *****************************************************************************/
45 
46 
47 typedef struct {
48     const char              *key;
49     const rtl_TextEncoding   value;
50 } _pair;
51 
52 
53 /*****************************************************************************
54  compare function for binary search
55  *****************************************************************************/
56 
57 static int
58 _pair_compare (const char *key, const _pair *pair)
59 {
60     int result = rtl_str_compareIgnoreAsciiCase( key, pair->key );
61     return result;
62 }
63 
64 /*****************************************************************************
65  binary search on encoding tables
66  *****************************************************************************/
67 
68 static const _pair*
69 _pair_search (const char *key, const _pair *base, unsigned int member )
70 {
71     unsigned int lower = 0;
72     unsigned int upper = member;
73     unsigned int current;
74     int comparison;
75 
76     /* check for validity of input */
77     if ( (key == NULL) || (base == NULL) || (member == 0) )
78         return NULL;
79 
80     /* binary search */
81     while ( lower < upper )
82     {
83         current = (lower + upper) / 2;
84         comparison = _pair_compare( key, base + current );
85         if (comparison < 0)
86             upper = current;
87         else if (comparison > 0)
88             lower = current + 1;
89         else
90             return base + current;
91     }
92 
93     return NULL;
94 }
95 
96 
97 /*****************************************************************************
98  convert rtl_Locale to locale string
99  *****************************************************************************/
100 
101 static char * _compose_locale( rtl_Locale * pLocale, char * buffer, size_t n )
102 {
103     /* check if a valid locale is specified */
104     if( pLocale && pLocale->Language &&
105             (pLocale->Language->length == 2 || pLocale->Language->length == 3) )
106     {
107         size_t offset = 0;
108 
109         /* convert language code to ascii */
110         {
111             rtl_String *pLanguage = NULL;
112 
113             rtl_uString2String( &pLanguage,
114                 pLocale->Language->buffer, pLocale->Language->length,
115                 RTL_TEXTENCODING_ASCII_US, OUSTRING_TO_OSTRING_CVTFLAGS );
116 
117             if( SAL_INT_CAST(sal_uInt32, pLanguage->length) < n )
118             {
119                 strcpy( buffer, pLanguage->buffer );
120                 offset = pLanguage->length;
121             }
122 
123             rtl_string_release( pLanguage );
124         }
125 
126         /* convert country code to ascii */
127         if( pLocale->Country && (pLocale->Country->length == 2) )
128         {
129             rtl_String *pCountry = NULL;
130 
131             rtl_uString2String( &pCountry,
132                 pLocale->Country->buffer, pLocale->Country->length,
133                 RTL_TEXTENCODING_ASCII_US, OUSTRING_TO_OSTRING_CVTFLAGS );
134 
135             if( offset + pCountry->length + 1 < n )
136             {
137                 strcpy( buffer + offset++, "_" );
138                 strcpy( buffer + offset, pCountry->buffer );
139                 offset += pCountry->length;
140             }
141 
142             rtl_string_release( pCountry );
143         }
144 
145         /* convert variant to ascii - check if there is enough space for the variant string */
146         if( pLocale->Variant && pLocale->Variant->length &&
147             ( SAL_INT_CAST(sal_uInt32, pLocale->Variant->length) < n - 6 ) )
148         {
149             rtl_String *pVariant = NULL;
150 
151             rtl_uString2String( &pVariant,
152                 pLocale->Variant->buffer, pLocale->Variant->length,
153                 RTL_TEXTENCODING_ASCII_US, OUSTRING_TO_OSTRING_CVTFLAGS );
154 
155             if( offset + pVariant->length + 1 < n )
156             {
157                 strcpy( buffer + offset, pVariant->buffer );
158                 offset += pVariant->length;
159             }
160 
161             rtl_string_release( pVariant );
162         }
163 
164         return buffer;
165     }
166 
167     return NULL;
168 }
169 
170 /*****************************************************************************
171  convert locale string to rtl_Locale
172  *****************************************************************************/
173 
174 static rtl_Locale * _parse_locale( const char * locale )
175 {
176     static sal_Unicode c_locale[2] = { (sal_Unicode) 'C', 0 };
177 
178     /* check if locale contains a valid string */
179     if( locale )
180     {
181         size_t len = strlen( locale );
182 
183         if( len >= 2 )
184         {
185             rtl_uString * pLanguage = NULL;
186             rtl_uString * pCountry  = NULL;
187             rtl_uString * pVariant  = NULL;
188 
189             size_t offset = 2;
190 
191             rtl_Locale * ret;
192 
193             /* language is a two or three letter code */
194             if( (len > 3 && '_' == locale[3]) || (len == 3 && '_' != locale[2]) )
195                 offset = 3;
196 
197             /* convert language code to unicode */
198             rtl_string2UString( &pLanguage, locale, offset, RTL_TEXTENCODING_ASCII_US, OSTRING_TO_OUSTRING_CVTFLAGS );
199             OSL_ASSERT(pLanguage != NULL);
200 
201             /* convert country code to unicode */
202             if( len >= offset+3 && '_' == locale[offset] )
203             {
204                 rtl_string2UString( &pCountry, locale + offset + 1, 2, RTL_TEXTENCODING_ASCII_US, OSTRING_TO_OUSTRING_CVTFLAGS );
205                 OSL_ASSERT(pCountry != NULL);
206                 offset += 3;
207             }
208 
209             /* convert variant code to unicode - do not rely on "." as delimiter */
210             if( len > offset ) {
211                 rtl_string2UString( &pVariant, locale + offset, len - offset, RTL_TEXTENCODING_ASCII_US, OSTRING_TO_OUSTRING_CVTFLAGS );
212                 OSL_ASSERT(pVariant != NULL);
213             }
214 
215             ret =  rtl_locale_register( pLanguage->buffer, pCountry ? pCountry->buffer : c_locale + 1, pVariant ? pVariant->buffer : c_locale + 1 );
216 
217             if (pVariant) rtl_uString_release(pVariant);
218             if (pCountry) rtl_uString_release(pCountry);
219             if (pLanguage) rtl_uString_release(pLanguage);
220 
221 			return ret;
222         }
223         else
224             return rtl_locale_register( c_locale, c_locale + 1, c_locale + 1 );
225     }
226 
227     return NULL;
228 }
229 
230 #if defined(LINUX) || defined(SOLARIS) || defined(NETBSD) || defined(FREEBSD)
231 
232 /*
233  * This implementation of osl_getTextEncodingFromLocale maps
234  * from nl_langinfo(CODESET) to rtl_textencoding defines.
235  * nl_langinfo() is supported only on Linux, Solaris,
236  * >= NetBSD 1.6 and >= FreeBSD 4.4
237  *
238  * This routine is SLOW because of the setlocale call, so
239  * grab the result and cache it.
240  *
241  * XXX this code has the usual mt problems aligned with setlocale() XXX
242  */
243 
244 #ifdef LINUX
245 #if !defined(CODESET)
246 #define CODESET _NL_CTYPE_CODESET_NAME
247 #endif
248 #endif
249 
250 /*
251  * _nl_language_list[] is an array list of supported encodings. Because
252  * we are using a binary search, the list has to be in ascending order.
253  * We are comparing the encodings case insensitiv, so the list has
254  * to be completly upper- , or lowercase.
255  */
256 
257 #if defined(SOLARIS)
258 
259 /* The values in the below list can be obtained with a script like
260  *  #!/bin/sh
261  *  for i in `locale -a`; do
262  *    LC_ALL=$i locale -k code_set_name
263  *  done
264  */
265 const _pair _nl_language_list[] = {
266     { "5601",           RTL_TEXTENCODING_EUC_KR         }, /* ko_KR.EUC */
267     { "646",            RTL_TEXTENCODING_ISO_8859_1     }, /* fake: ASCII_US */
268     { "ANSI-1251",      RTL_TEXTENCODING_MS_1251        }, /* ru_RU.ANSI1251 */
269     { "BIG5",           RTL_TEXTENCODING_BIG5           }, /* zh_CN.BIG5 */
270     { "BIG5-HKSCS",     RTL_TEXTENCODING_BIG5_HKSCS     }, /* zh_CN.BIG5HK */
271     { "CNS11643",       RTL_TEXTENCODING_EUC_TW         }, /* zh_TW.EUC */
272     { "EUCJP",          RTL_TEXTENCODING_EUC_JP         }, /* ja_JP.eucjp */
273     { "GB18030",        RTL_TEXTENCODING_GB_18030       }, /* zh_CN.GB18030 */
274     { "GB2312",         RTL_TEXTENCODING_GB_2312        }, /* zh_CN */
275     { "GBK",            RTL_TEXTENCODING_GBK            }, /* zh_CN.GBK */
276     { "ISO8859-1",      RTL_TEXTENCODING_ISO_8859_1     },
277     { "ISO8859-10",     RTL_TEXTENCODING_ISO_8859_10    },
278     { "ISO8859-13",     RTL_TEXTENCODING_ISO_8859_13    }, /* lt_LT lv_LV */
279     { "ISO8859-14",     RTL_TEXTENCODING_ISO_8859_14    },
280     { "ISO8859-15",     RTL_TEXTENCODING_ISO_8859_15    },
281     { "ISO8859-2",      RTL_TEXTENCODING_ISO_8859_2     },
282     { "ISO8859-3",      RTL_TEXTENCODING_ISO_8859_3     },
283     { "ISO8859-4",      RTL_TEXTENCODING_ISO_8859_4     },
284     { "ISO8859-5",      RTL_TEXTENCODING_ISO_8859_5     },
285     { "ISO8859-6",      RTL_TEXTENCODING_ISO_8859_6     },
286     { "ISO8859-7",      RTL_TEXTENCODING_ISO_8859_7     },
287     { "ISO8859-8",      RTL_TEXTENCODING_ISO_8859_8     },
288     { "ISO8859-9",      RTL_TEXTENCODING_ISO_8859_9     },
289     { "KOI8-R",         RTL_TEXTENCODING_KOI8_R         },
290     { "KOI8-U",         RTL_TEXTENCODING_KOI8_U         },
291     { "PCK",            RTL_TEXTENCODING_MS_932         },
292     { "SUN_EU_GREEK",   RTL_TEXTENCODING_ISO_8859_7     }, /* 8859-7 + Euro */
293     { "TIS620.2533",    RTL_TEXTENCODING_MS_874         }, /* th_TH.TIS620 */
294     { "UTF-8",          RTL_TEXTENCODING_UTF8           }
295 };
296 
297 /* XXX MS-874 is an extension to tis620, so this is not
298  * really equivalent */
299 
300 #elif defined(LINUX) || defined(NETBSD)
301 
302 const _pair _nl_language_list[] = {
303     { "ANSI_X3.110-1983",           RTL_TEXTENCODING_DONTKNOW   },  /* ISO-IR-99 NAPLPS */
304     { "ANSI_X3.4-1968",             RTL_TEXTENCODING_ISO_8859_1 },  /* fake: ASCII_US */
305     { "ASMO_449",                   RTL_TEXTENCODING_DONTKNOW },    /* ISO_9036 ARABIC7 */
306     { "BALTIC",                     RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-179 */
307     { "BIG5",                       RTL_TEXTENCODING_BIG5 },        /* locale: zh_TW */
308     { "BIG5-HKSCS",                 RTL_TEXTENCODING_BIG5_HKSCS },  /* locale: zh_CN.BIG5HK */
309     { "BIG5HKSCS",                  RTL_TEXTENCODING_BIG5_HKSCS },  /* depricated */
310     { "BS_4730",                    RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-4 ISO646-GB */
311     { "BS_VIEWDATA",                RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-47 */
312     { "CP1250",                     RTL_TEXTENCODING_MS_1250 },     /* MS-EE */
313     { "CP1251",                     RTL_TEXTENCODING_MS_1251 },     /* MS-CYRL */
314     { "CP1252",                     RTL_TEXTENCODING_MS_1252 },     /* MS-ANSI */
315     { "CP1253",                     RTL_TEXTENCODING_MS_1253 },     /* MS-GREEK */
316     { "CP1254",                     RTL_TEXTENCODING_MS_1254 },     /* MS-TURK */
317     { "CP1255",                     RTL_TEXTENCODING_MS_1255 },     /* MS-HEBR */
318     { "CP1256",                     RTL_TEXTENCODING_MS_1256 },     /* MS-ARAB */
319     { "CP1257",                     RTL_TEXTENCODING_MS_1257 },     /* WINBALTRIM */
320     { "CSA_Z243.4-1985-1",          RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-121 */
321     { "CSA_Z243.4-1985-2",          RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-122 CSA7-2 */
322     { "CSA_Z243.4-1985-GR",         RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-123 */
323     { "CSN_369103",                 RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-139 */
324     { "CWI",                        RTL_TEXTENCODING_DONTKNOW },    /* CWI-2 CP-HU */
325     { "DEC-MCS",                    RTL_TEXTENCODING_DONTKNOW },    /* DEC */
326     { "DIN_66003",                  RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-21 */
327     { "DS_2089",                    RTL_TEXTENCODING_DONTKNOW },    /* DS2089 ISO646-DK */
328     { "EBCDIC-AT-DE",               RTL_TEXTENCODING_DONTKNOW },
329     { "EBCDIC-AT-DE-A",             RTL_TEXTENCODING_DONTKNOW },
330     { "EBCDIC-CA-FR",               RTL_TEXTENCODING_DONTKNOW },
331     { "EBCDIC-DK-NO",               RTL_TEXTENCODING_DONTKNOW },
332     { "EBCDIC-DK-NO-A",             RTL_TEXTENCODING_DONTKNOW },
333     { "EBCDIC-ES",                  RTL_TEXTENCODING_DONTKNOW },
334     { "EBCDIC-ES-A",                RTL_TEXTENCODING_DONTKNOW },
335     { "EBCDIC-ES-S",                RTL_TEXTENCODING_DONTKNOW },
336     { "EBCDIC-FI-SE",               RTL_TEXTENCODING_DONTKNOW },
337     { "EBCDIC-FI-SE-A",             RTL_TEXTENCODING_DONTKNOW },
338     { "EBCDIC-FR",                  RTL_TEXTENCODING_DONTKNOW },
339     { "EBCDIC-IS-FRISS",            RTL_TEXTENCODING_DONTKNOW },    /*  FRISS */
340     { "EBCDIC-IT",                  RTL_TEXTENCODING_DONTKNOW },
341     { "EBCDIC-PT",                  RTL_TEXTENCODING_DONTKNOW },
342     { "EBCDIC-UK",                  RTL_TEXTENCODING_DONTKNOW },
343     { "EBCDIC-US",                  RTL_TEXTENCODING_DONTKNOW },
344     { "ECMA-CYRILLIC",              RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-111 */
345     { "ES",                         RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-17 */
346     { "ES2",                        RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-85 */
347     { "EUC-JP",                     RTL_TEXTENCODING_EUC_JP },      /* locale: ja_JP.eucjp */
348     { "EUC-KR",                     RTL_TEXTENCODING_EUC_KR },      /* locale: ko_KR.euckr */
349     { "EUC-TW",                     RTL_TEXTENCODING_EUC_TW },      /* locale: zh_TW.euctw */
350     { "GB18030",                    RTL_TEXTENCODING_GB_18030 },    /* locale: zh_CN.gb18030 */
351     { "GB2312",                     RTL_TEXTENCODING_GB_2312 },     /* locale: zh_CN */
352     { "GB_1988-80",                 RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-57 */
353     { "GBK",                        RTL_TEXTENCODING_GBK },         /* locale: zh_CN.GBK */
354     { "GOST_19768-74",              RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-153 */
355     { "GREEK-CCITT",                RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-150 */
356     { "GREEK7",                     RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-88 */
357     { "GREEK7-OLD",                 RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-18 */
358     { "HP-ROMAN8",                  RTL_TEXTENCODING_DONTKNOW },    /* ROMAN8 R8 */
359     { "IBM037",                     RTL_TEXTENCODING_DONTKNOW },    /* EBCDIC-[US|CA|WT] */
360     { "IBM038",                     RTL_TEXTENCODING_DONTKNOW },    /* EBCDIC-INT CP038 */
361     { "IBM1004",                    RTL_TEXTENCODING_DONTKNOW },    /* CP1004 OS2LATIN1 */
362     { "IBM1026",                    RTL_TEXTENCODING_DONTKNOW },    /* CP1026 1026 */
363     { "IBM1047",                    RTL_TEXTENCODING_DONTKNOW },    /* CP1047 1047 */
364     { "IBM256",                     RTL_TEXTENCODING_DONTKNOW },    /* EBCDIC-INT1 */
365     { "IBM273",                     RTL_TEXTENCODING_DONTKNOW },    /* CP273 */
366     { "IBM274",                     RTL_TEXTENCODING_DONTKNOW },    /* EBCDIC-BE CP274 */
367     { "IBM275",                     RTL_TEXTENCODING_DONTKNOW },    /* EBCDIC-BR CP275 */
368     { "IBM277",                     RTL_TEXTENCODING_DONTKNOW },    /* EBCDIC-CP-[DK|NO] */
369     { "IBM278",                     RTL_TEXTENCODING_DONTKNOW },    /* EBCDIC-CP-[FISE]*/
370     { "IBM280",                     RTL_TEXTENCODING_DONTKNOW },    /* CP280 EBCDIC-CP-IT*/
371     { "IBM281",                     RTL_TEXTENCODING_DONTKNOW },    /* EBCDIC-JP-E CP281 */
372     { "IBM284",                     RTL_TEXTENCODING_DONTKNOW },    /* CP284 EBCDIC-CP-ES */
373     { "IBM285",                     RTL_TEXTENCODING_DONTKNOW },    /* CP285 EBCDIC-CP-GB */
374     { "IBM290",                     RTL_TEXTENCODING_DONTKNOW },    /* EBCDIC-JP-KANA */
375     { "IBM297",                     RTL_TEXTENCODING_DONTKNOW },    /* EBCDIC-CP-FR */
376     { "IBM420",                     RTL_TEXTENCODING_DONTKNOW },    /* EBCDIC-CP-AR1 */
377     { "IBM423",                     RTL_TEXTENCODING_DONTKNOW },    /* CP423 EBCDIC-CP-GR */
378     { "IBM424",                     RTL_TEXTENCODING_DONTKNOW },    /* CP424 EBCDIC-CP-HE */
379     { "IBM437",                     RTL_TEXTENCODING_IBM_437 },     /* CP437 437 */
380     { "IBM500",                     RTL_TEXTENCODING_DONTKNOW },    /* EBCDIC-CP-[BE|CH] */
381     { "IBM850",                     RTL_TEXTENCODING_IBM_850 },     /* CP850 850 */
382     { "IBM851",                     RTL_TEXTENCODING_DONTKNOW },    /* CP851 851 */
383     { "IBM852",                     RTL_TEXTENCODING_IBM_852 },     /* CP852 852 */
384     { "IBM855",                     RTL_TEXTENCODING_IBM_855 },     /* CP855 855 */
385     { "IBM857",                     RTL_TEXTENCODING_IBM_857 },     /* CP857 857 */
386     { "IBM860",                     RTL_TEXTENCODING_IBM_860 },     /* CP860 860 */
387     { "IBM861",                     RTL_TEXTENCODING_IBM_861 },     /* CP861 861 CP-IS */
388     { "IBM862",                     RTL_TEXTENCODING_IBM_862 },     /* CP862 862 */
389     { "IBM863",                     RTL_TEXTENCODING_IBM_863 },     /* CP863 863 */
390     { "IBM864",                     RTL_TEXTENCODING_IBM_864 },     /* CP864 */
391     { "IBM865",                     RTL_TEXTENCODING_IBM_865 },     /* CP865 865 */
392     { "IBM866",                     RTL_TEXTENCODING_IBM_866 },     /* CP866 866 */
393     { "IBM868",                     RTL_TEXTENCODING_DONTKNOW },    /* CP868 CP-AR */
394     { "IBM869",                     RTL_TEXTENCODING_IBM_869 },     /* CP869 869 CP-GR */
395     { "IBM870",                     RTL_TEXTENCODING_DONTKNOW },    /* EBCDIC-[ROECE|YU] */
396     { "IBM871",                     RTL_TEXTENCODING_DONTKNOW },    /* CP871 EBCDIC-CP-IS */
397     { "IBM875",                     RTL_TEXTENCODING_DONTKNOW },    /* CP875 EBCDIC-GREEK */
398     { "IBM880",                     RTL_TEXTENCODING_DONTKNOW },    /* EBCDIC-CYRILLIC */
399     { "IBM891",                     RTL_TEXTENCODING_DONTKNOW },    /* CP891 */
400     { "IBM903",                     RTL_TEXTENCODING_DONTKNOW },    /* CP903 */
401     { "IBM904",                     RTL_TEXTENCODING_DONTKNOW },    /* CP904 904 */
402     { "IBM905",                     RTL_TEXTENCODING_DONTKNOW },    /* CP905 EBCDIC-CP-TR */
403     { "IBM918",                     RTL_TEXTENCODING_DONTKNOW },    /* CP918 EBCDIC-AR2 */
404     { "IEC_P27-1",                  RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-143 */
405     { "INIS",                       RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-49 */
406     { "INIS-8",                     RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-50 */
407     { "INIS-CYRILLIC",              RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-51 */
408     { "INVARIANT",                  RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-170 */
409     { "ISO-8859-1",                 RTL_TEXTENCODING_ISO_8859_1 },  /* ISO-IR-100 CP819 */
410     { "ISO-8859-10",                RTL_TEXTENCODING_ISO_8859_10 }, /* ISO-IR-157 LATIN6 */
411     { "ISO-8859-13",                RTL_TEXTENCODING_ISO_8859_13 }, /* ISO-IR-179 LATIN7 */
412     { "ISO-8859-14",                RTL_TEXTENCODING_ISO_8859_14 }, /* LATIN8 L8 */
413     { "ISO-8859-15",                RTL_TEXTENCODING_ISO_8859_15 },
414     { "ISO-8859-2",                 RTL_TEXTENCODING_ISO_8859_2 },  /* LATIN2 L2 */
415     { "ISO-8859-3",                 RTL_TEXTENCODING_ISO_8859_3 },  /* LATIN3 L3 */
416     { "ISO-8859-4",                 RTL_TEXTENCODING_ISO_8859_4 },  /* LATIN4 L4 */
417     { "ISO-8859-5",                 RTL_TEXTENCODING_ISO_8859_5 },  /* CYRILLIC */
418     { "ISO-8859-6",                 RTL_TEXTENCODING_ISO_8859_6 },  /* ECMA-114 ARABIC */
419     { "ISO-8859-7",                 RTL_TEXTENCODING_ISO_8859_7 },  /* ECMA-118 GREEK8 */
420     { "ISO-8859-8",                 RTL_TEXTENCODING_ISO_8859_8 },  /* ISO_8859-8 HEBREW */
421     { "ISO-8859-9",                 RTL_TEXTENCODING_ISO_8859_9 },  /* ISO_8859-9 LATIN5 */
422     { "ISO-IR-90",                  RTL_TEXTENCODING_DONTKNOW },    /* ISO_6937-2:1983 */
423     { "ISO_10367-BOX",              RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-155 */
424     { "ISO_2033-1983",              RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-98 E13B */
425     { "ISO_5427",                   RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-37 KOI-7 */
426     { "ISO_5427-EXT",               RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-54  */
427     { "ISO_5428",                   RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-55 */
428     { "ISO_646.BASIC",              RTL_TEXTENCODING_ASCII_US },    /* REF */
429     { "ISO_646.IRV",                RTL_TEXTENCODING_ASCII_US },    /* ISO-IR-2 IRV */
430     { "ISO_646.IRV:1983",           RTL_TEXTENCODING_ISO_8859_1 },  /* fake: ASCII_US, used for "C" locale*/
431     { "ISO_6937",                   RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-156 ISO6937*/
432     { "ISO_6937-2-25",              RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-152 */
433     { "ISO_6937-2-ADD",             RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-142 */
434     { "ISO_8859-SUPP",              RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-154 */
435     { "IT",                         RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-15  */
436     { "JIS_C6220-1969-JP",          RTL_TEXTENCODING_DONTKNOW },    /* KATAKANA X0201-7 */
437     { "JIS_C6220-1969-RO",          RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-14 */
438     { "JIS_C6229-1984-A",           RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-91 */
439     { "JIS_C6229-1984-B",           RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-92 */
440     { "JIS_C6229-1984-B-ADD",       RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-93 */
441     { "JIS_C6229-1984-HAND",        RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-94 */
442     { "JIS_C6229-1984-HAND-ADD",    RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-95 */
443     { "JIS_C6229-1984-KANA",        RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-96 */
444     { "JIS_X0201",                  RTL_TEXTENCODING_DONTKNOW },    /* X0201 */
445     { "JUS_I.B1.002",               RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-141 */
446     { "JUS_I.B1.003-MAC",           RTL_TEXTENCODING_DONTKNOW },    /* MACEDONIAN */
447     { "JUS_I.B1.003-SERB",          RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-146 SERBIAN */
448     { "KOI-8",                      RTL_TEXTENCODING_DONTKNOW },
449     { "KOI8-R",                     RTL_TEXTENCODING_KOI8_R },
450     { "KOI8-U",                     RTL_TEXTENCODING_KOI8_U },
451     { "KSC5636",                    RTL_TEXTENCODING_DONTKNOW },    /* ISO646-KR */
452     { "LATIN-GREEK",                RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-19 */
453     { "LATIN-GREEK-1",              RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-27 */
454     { "MAC-IS",                     RTL_TEXTENCODING_APPLE_ROMAN },
455     { "MAC-UK",                     RTL_TEXTENCODING_APPLE_ROMAN },
456     { "MACINTOSH",                  RTL_TEXTENCODING_APPLE_ROMAN }, /* MAC */
457     { "MSZ_7795.3",                 RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-86 */
458     { "NATS-DANO",                  RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-9-1 */
459     { "NATS-DANO-ADD",              RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-9-2 */
460     { "NATS-SEFI",                  RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-8-1 */
461     { "NATS-SEFI-ADD",              RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-8-2 */
462     { "NC_NC00-10",                 RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-151 */
463     { "NEXTSTEP",                   RTL_TEXTENCODING_DONTKNOW },    /* NEXT */
464     { "NF_Z_62-010",                RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-69 */
465     { "NF_Z_62-010_(1973)",         RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-25 */
466     { "NS_4551-1",                  RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-60 */
467     { "NS_4551-2",                  RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-61 */
468     { "PT",                         RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-16 */
469     { "PT2",                        RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-84 */
470     { "SAMI",                       RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-158 */
471     { "SEN_850200_B",               RTL_TEXTENCODING_DONTKNOW },    /* ISO646-[FI|SE] */
472     { "SEN_850200_C",               RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-11 */
473     { "T.101-G2",                   RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-128 */
474     { "T.61-7BIT",                  RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-102 */
475     { "T.61-8BIT",                  RTL_TEXTENCODING_DONTKNOW },    /* T.61 ISO-IR-103 */
476     { "TIS-620",                    RTL_TEXTENCODING_MS_874 },     /* locale: th_TH */
477     { "UTF-8",                      RTL_TEXTENCODING_UTF8 },        /* ISO-10646/UTF-8 */
478     { "VIDEOTEX-SUPPL",             RTL_TEXTENCODING_DONTKNOW },    /* ISO-IR-70 */
479     { "WIN-SAMI-2",                 RTL_TEXTENCODING_DONTKNOW }     /* WS2 */
480 };
481 
482 #elif defined(FREEBSD)
483 
484 const _pair _nl_language_list[] = {
485     { "ASCII",         RTL_TEXTENCODING_ASCII_US       }, /* US-ASCII */
486     { "BIG5",          RTL_TEXTENCODING_BIG5           }, /* China - Traditional Chinese */
487     { "CP1251",        RTL_TEXTENCODING_MS_1251        }, /* MS-CYRL */
488     { "CP866",         RTL_TEXTENCODING_IBM_866        }, /* CP866 866 */
489     { "EUCCN",         RTL_TEXTENCODING_EUC_CN         }, /* China - Simplified Chinese */
490     { "EUCJP",         RTL_TEXTENCODING_EUC_JP         }, /* Japan */
491     { "EUCKR",         RTL_TEXTENCODING_EUC_KR         }, /* Korea */
492     { "ISO8859-1",     RTL_TEXTENCODING_ISO_8859_1     }, /* Western */
493     { "ISO8859-15",    RTL_TEXTENCODING_ISO_8859_15    }, /* Western Updated (w/Euro sign) */
494     { "ISO8859-2",     RTL_TEXTENCODING_ISO_8859_2     }, /* Central European */
495     { "ISO8859-4",     RTL_TEXTENCODING_ISO_8859_4     }, /* LATIN4 L4 */
496     { "ISO8859-5",     RTL_TEXTENCODING_ISO_8859_5     }, /* Cyrillic */
497     { "ISO8859-7",     RTL_TEXTENCODING_ISO_8859_7     }, /* Greek */
498     { "ISO8859-9",     RTL_TEXTENCODING_ISO_8859_9     }, /* Turkish */
499     { "KOI8-R",        RTL_TEXTENCODING_KOI8_R         }, /* KOI8-R */
500     { "KOI8-U",        RTL_TEXTENCODING_KOI8_U         }, /* KOI8-U */
501     { "SJIS",          RTL_TEXTENCODING_SHIFT_JIS      }, /* Japan */
502     { "US-ASCII",      RTL_TEXTENCODING_ASCII_US       }, /* US-ASCII */
503     { "UTF-8",         RTL_TEXTENCODING_UTF8           }  /* ISO-10646/UTF-8 */
504 };
505 
506 #elif defined(NETBSD)
507 
508 const _pair _nl_language_list[] = {
509     { "ASCII",         RTL_TEXTENCODING_ASCII_US       }, /* US-ASCII */
510     { "BIG5",          RTL_TEXTENCODING_BIG5           }, /* China - Traditional Chinese */
511     { "CP1251",        RTL_TEXTENCODING_MS_1251        }, /* MS-CYRL */
512     { "CP866",         RTL_TEXTENCODING_IBM_866        }, /* CP866 866 */
513     { "CTEXT",         RTL_TEXTENCODING_ASCII_US       }, /* US-ASCII */
514     { "EUCCN",         RTL_TEXTENCODING_EUC_CN         }, /* China - Simplified Chinese */
515     { "EUCJP",         RTL_TEXTENCODING_EUC_JP         }, /* Japan */
516     { "EUCKR",         RTL_TEXTENCODING_EUC_KR         }, /* Korea */
517     { "EUCTW",         RTL_TEXTENCODING_EUC_TW         }, /* China - Traditional Chinese */
518     { "ISO-2022-JP",   RTL_TEXTENCODING_DONTKNOW       }, /* */
519     { "ISO-2022-JP-2", RTL_TEXTENCODING_DONTKNOW       }, /* */
520     { "ISO8859-1",     RTL_TEXTENCODING_ISO_8859_1     }, /* Western */
521     { "ISO8859-15",    RTL_TEXTENCODING_ISO_8859_15    }, /* Western Updated (w/Euro sign) */
522     { "ISO8859-2",     RTL_TEXTENCODING_ISO_8859_2     }, /* Central European */
523     { "ISO8859-4",     RTL_TEXTENCODING_ISO_8859_4     }, /* LATIN4 L4 */
524     { "ISO8859-5",     RTL_TEXTENCODING_ISO_8859_5     }, /* Cyrillic */
525     { "ISO8859-7",     RTL_TEXTENCODING_ISO_8859_7     }, /* Greek */
526     { "ISO8859-9",     RTL_TEXTENCODING_ISO_8859_9     }, /* Turkish */
527     { "KOI8-R",        RTL_TEXTENCODING_KOI8_R         }, /* KOI8-R */
528     { "KOI8-U",        RTL_TEXTENCODING_KOI8_U         }, /* KOI8-U */
529     { "SJIS",          RTL_TEXTENCODING_SHIFT_JIS      }, /* Japan */
530     { "US-ASCII",      RTL_TEXTENCODING_ASCII_US       }, /* US-ASCII */
531     { "UTF-8",         RTL_TEXTENCODING_UTF8           }  /* ISO-10646/UTF-8 */
532 };
533 
534 #endif /* ifdef SOLARIS LINUX FREEBSD NETBSD */
535 
536 static pthread_mutex_t aLocalMutex = PTHREAD_MUTEX_INITIALIZER;
537 
538 /*****************************************************************************
539  return the text encoding corresponding to the given locale
540  *****************************************************************************/
541 
542 rtl_TextEncoding osl_getTextEncodingFromLocale( rtl_Locale * pLocale )
543 {
544     const _pair *language=NULL;
545 
546     char  locale_buf[64] = "";
547     char  codeset_buf[64];
548 
549     char *ctype_locale = NULL;
550     char *codeset      = NULL;
551 
552     /* default to process locale if pLocale == NULL */
553     if( NULL == pLocale )
554         osl_getProcessLocale( &pLocale );
555 
556     /* convert rtl_Locale to locale string */
557     _compose_locale( pLocale, locale_buf, 64 );
558 
559     /* basic thread safeness */
560     pthread_mutex_lock( &aLocalMutex );
561 
562     /* remember the charset as indicated by the LC_CTYPE locale */
563     ctype_locale = setlocale( LC_CTYPE, NULL );
564 
565     /* set the desired LC_CTYPE locale */
566     if( NULL == setlocale( LC_CTYPE, locale_buf ) )
567     {
568         pthread_mutex_unlock(&aLocalMutex);
569         return RTL_TEXTENCODING_DONTKNOW;
570     }
571 
572     /* get the charset as indicated by the LC_CTYPE locale */
573 #if defined(NETBSD) && !defined(CODESET)
574     codeset = NULL;
575 #else
576     codeset = nl_langinfo( CODESET );
577 #endif
578 
579     if ( codeset != NULL )
580     {
581         /* get codeset into mt save memory */
582         strncpy( codeset_buf, codeset, sizeof(codeset_buf) );
583         codeset_buf[sizeof(codeset_buf) - 1] = 0;
584         codeset = codeset_buf;
585     }
586 
587     /* restore the original value of locale */
588     if ( ctype_locale != NULL )
589         setlocale( LC_CTYPE, ctype_locale );
590 
591     pthread_mutex_unlock( &aLocalMutex );
592 
593     /* search the codeset in our language list */
594     if ( codeset != NULL )
595     {
596         const unsigned int members = sizeof(_nl_language_list) / sizeof(_pair);
597         language = _pair_search (codeset, _nl_language_list, members);
598     }
599 
600     OSL_ASSERT( language && ( RTL_TEXTENCODING_DONTKNOW != language->value ) );
601 
602     /* a matching item in our list provides a mapping from codeset to
603      * rtl-codeset */
604     if ( language != NULL )
605         return language->value;
606 
607     return RTL_TEXTENCODING_DONTKNOW;
608 }
609 
610 /*****************************************************************************
611  return the current process locale
612  *****************************************************************************/
613 
614 void _imp_getProcessLocale( rtl_Locale ** ppLocale )
615 {
616     char * locale;
617 
618     /* basic thread safeness */
619     pthread_mutex_lock( &aLocalMutex );
620 
621     /* set the locale defined by the env vars */
622     locale = setlocale( LC_CTYPE, "" );
623 
624     /* fallback to the current locale */
625     if( NULL == locale )
626         locale = setlocale( LC_CTYPE, NULL );
627 
628     /* return the LC_CTYPE locale */
629     *ppLocale = _parse_locale( locale );
630 
631     pthread_mutex_unlock( &aLocalMutex );
632 }
633 
634 /*****************************************************************************
635  set the current process locale
636  *****************************************************************************/
637 
638 int _imp_setProcessLocale( rtl_Locale * pLocale )
639 {
640     char  locale_buf[64] = "";
641     int   ret = 0;
642 
643     /* convert rtl_Locale to locale string */
644     _compose_locale( pLocale, locale_buf, 64 );
645 
646     /* basic thread safeness */
647     pthread_mutex_lock( &aLocalMutex );
648 
649     /* try to set LC_ALL locale */
650     if( NULL == setlocale( LC_ALL, locale_buf ) )
651         ret = -1;
652 
653     pthread_mutex_unlock( &aLocalMutex );
654     return ret;
655 }
656 
657 #else /* ifdef LINUX || SOLARIS || MACOSX || NETBSD */
658 
659 /*
660  * This implementation of osl_getTextEncodingFromLocale maps
661  * from the ISO language codes.
662  */
663 
664 const _pair _full_locale_list[] = {
665     { "ja_JP.eucJP",  RTL_TEXTENCODING_EUC_JP      },
666     { "ja_JP.EUC",    RTL_TEXTENCODING_EUC_JP      },
667     { "ko_KR.EUC",    RTL_TEXTENCODING_EUC_KR      },
668     { "zh_CN.EUC",    RTL_TEXTENCODING_EUC_CN      },
669     { "zh_TW.EUC",    RTL_TEXTENCODING_EUC_TW      }
670 };
671 
672 const _pair _locale_extension_list[] = {
673     { "big5",         RTL_TEXTENCODING_BIG5        },
674     { "big5hk",       RTL_TEXTENCODING_BIG5_HKSCS  },
675     { "gb18030",      RTL_TEXTENCODING_GB_18030    },
676     { "euc",          RTL_TEXTENCODING_EUC_JP      },
677     { "iso8859-1",    RTL_TEXTENCODING_ISO_8859_1  },
678     { "iso8859-10",   RTL_TEXTENCODING_ISO_8859_10 },
679     { "iso8859-13",   RTL_TEXTENCODING_ISO_8859_13 },
680     { "iso8859-14",   RTL_TEXTENCODING_ISO_8859_14 },
681     { "iso8859-15",   RTL_TEXTENCODING_ISO_8859_15 },
682     { "iso8859-2",    RTL_TEXTENCODING_ISO_8859_2  },
683     { "iso8859-3",    RTL_TEXTENCODING_ISO_8859_3  },
684     { "iso8859-4",    RTL_TEXTENCODING_ISO_8859_4  },
685     { "iso8859-5",    RTL_TEXTENCODING_ISO_8859_5  },
686     { "iso8859-6",    RTL_TEXTENCODING_ISO_8859_6  },
687     { "iso8859-7",    RTL_TEXTENCODING_ISO_8859_7  },
688     { "iso8859-8",    RTL_TEXTENCODING_ISO_8859_8  },
689     { "iso8859-9",    RTL_TEXTENCODING_ISO_8859_9  },
690     { "koi8-r",       RTL_TEXTENCODING_KOI8_R      },
691     { "koi8-u",       RTL_TEXTENCODING_KOI8_U      },
692     { "pck",          RTL_TEXTENCODING_MS_932      },
693 #if (0)
694     { "sun_eu_greek", RTL_TEXTENCODING_DONTKNOW    },
695 #endif
696     { "utf-16",       RTL_TEXTENCODING_UNICODE     },
697     { "utf-7",        RTL_TEXTENCODING_UTF7        },
698     { "utf-8",        RTL_TEXTENCODING_UTF8        }
699 };
700 
701 const _pair _iso_language_list[] = {
702     { "af",  RTL_TEXTENCODING_ISO_8859_1 },
703     { "ar",  RTL_TEXTENCODING_ISO_8859_6 },
704     { "az",  RTL_TEXTENCODING_ISO_8859_9 },
705     { "be",  RTL_TEXTENCODING_ISO_8859_5 },
706     { "bg",  RTL_TEXTENCODING_ISO_8859_5 },
707     { "ca",  RTL_TEXTENCODING_ISO_8859_1 },
708     { "cs",  RTL_TEXTENCODING_ISO_8859_2 },
709     { "da",  RTL_TEXTENCODING_ISO_8859_1 },
710     { "de",  RTL_TEXTENCODING_ISO_8859_1 },
711     { "el",  RTL_TEXTENCODING_ISO_8859_7 },
712     { "en",  RTL_TEXTENCODING_ISO_8859_1 },
713     { "es",  RTL_TEXTENCODING_ISO_8859_1 },
714     { "et",  RTL_TEXTENCODING_ISO_8859_4 },
715     { "eu",  RTL_TEXTENCODING_ISO_8859_1 },
716     { "fa",  RTL_TEXTENCODING_ISO_8859_6 },
717     { "fi",  RTL_TEXTENCODING_ISO_8859_1 },
718     { "fo",  RTL_TEXTENCODING_ISO_8859_1 },
719     { "fr",  RTL_TEXTENCODING_ISO_8859_1 },
720     { "gr",  RTL_TEXTENCODING_ISO_8859_7 },
721     { "he",  RTL_TEXTENCODING_ISO_8859_8 },
722     { "hi",  RTL_TEXTENCODING_DONTKNOW },
723     { "hr",  RTL_TEXTENCODING_ISO_8859_2 },
724     { "hu",  RTL_TEXTENCODING_ISO_8859_2 },
725     { "hy",  RTL_TEXTENCODING_DONTKNOW },
726     { "id",  RTL_TEXTENCODING_ISO_8859_1 },
727     { "is",  RTL_TEXTENCODING_ISO_8859_1 },
728     { "it",  RTL_TEXTENCODING_ISO_8859_1 },
729     { "iw",  RTL_TEXTENCODING_ISO_8859_8 },
730     { "ja",  RTL_TEXTENCODING_EUC_JP },
731     { "ka",  RTL_TEXTENCODING_DONTKNOW },
732     { "kk",  RTL_TEXTENCODING_ISO_8859_5 },
733     { "ko",  RTL_TEXTENCODING_EUC_KR },
734     { "lt",  RTL_TEXTENCODING_ISO_8859_4 },
735     { "lv",  RTL_TEXTENCODING_ISO_8859_4 },
736     { "mk",  RTL_TEXTENCODING_ISO_8859_5 },
737     { "mr",  RTL_TEXTENCODING_DONTKNOW },
738     { "ms",  RTL_TEXTENCODING_ISO_8859_1 },
739     { "nl",  RTL_TEXTENCODING_ISO_8859_1 },
740     { "no",  RTL_TEXTENCODING_ISO_8859_1 },
741     { "pl",  RTL_TEXTENCODING_ISO_8859_2 },
742     { "pt",  RTL_TEXTENCODING_ISO_8859_1 },
743     { "ro",  RTL_TEXTENCODING_ISO_8859_2 },
744     { "ru",  RTL_TEXTENCODING_ISO_8859_5 },
745     { "sa",  RTL_TEXTENCODING_DONTKNOW },
746     { "sk",  RTL_TEXTENCODING_ISO_8859_2 },
747     { "sl",  RTL_TEXTENCODING_ISO_8859_2 },
748     { "sq",  RTL_TEXTENCODING_ISO_8859_2 },
749     { "sv",  RTL_TEXTENCODING_ISO_8859_1 },
750     { "sw",  RTL_TEXTENCODING_ISO_8859_1 },
751     { "ta",  RTL_TEXTENCODING_DONTKNOW },
752     { "th",  RTL_TEXTENCODING_DONTKNOW },
753     { "tr",  RTL_TEXTENCODING_ISO_8859_9 },
754     { "tt",  RTL_TEXTENCODING_ISO_8859_5 },
755     { "uk",  RTL_TEXTENCODING_ISO_8859_5 },
756     { "ur",  RTL_TEXTENCODING_ISO_8859_6 },
757     { "uz",  RTL_TEXTENCODING_ISO_8859_9 },
758     { "vi",  RTL_TEXTENCODING_DONTKNOW },
759     { "zh",  RTL_TEXTENCODING_BIG5 }
760 };
761 
762 /*****************************************************************************
763  return the text encoding corresponding to the given locale
764  *****************************************************************************/
765 
766 rtl_TextEncoding osl_getTextEncodingFromLocale( rtl_Locale * pLocale )
767 {
768     const _pair *language = NULL;
769     char locale_buf[64] = "";
770     char *cp;
771 
772     /* default to process locale if pLocale == NULL */
773     if( NULL == pLocale )
774         osl_getProcessLocale( &pLocale );
775 
776     /* convert rtl_Locale to locale string */
777     if( _compose_locale( pLocale, locale_buf, 64 ) )
778     {
779         /* check special handling list (EUC) first */
780         const unsigned int members = sizeof( _full_locale_list ) / sizeof( _pair );
781         language = _pair_search( locale_buf, _full_locale_list, members);
782 
783         if( NULL == language )
784         {
785             /*
786              *  check if there is a charset qualifier at the end of the given locale string
787              *  e.g. de.ISO8859-15 or de.ISO8859-15@euro which strongly indicates what
788              *  charset to use
789              */
790 		    cp = strrchr( locale_buf, '.' );
791 
792             if( NULL != cp )
793             {
794                 const unsigned int members = sizeof( _locale_extension_list ) / sizeof( _pair );
795                 language = _pair_search( cp + 1, _locale_extension_list, members);
796             }
797         }
798 
799         /* use iso language code to determine the charset */
800         if( NULL == language )
801         {
802             const unsigned int members = sizeof( _iso_language_list ) / sizeof( _pair );
803 
804             /* iso lang codes have 2 charaters */
805             locale_buf[2] = '\0';
806 
807             language = _pair_search( locale_buf, _iso_language_list, members);
808         }
809     }
810 
811     /* a matching item in our list provides a mapping from codeset to
812      * rtl-codeset */
813     if ( language != NULL )
814         return language->value;
815 
816     return RTL_TEXTENCODING_DONTKNOW;
817 }
818 
819 #ifdef MACOSX
820 #include "system.h"
821 
822 /* OS X locale discovery function */
823 int (*pGetOSXLocale)( char *, sal_uInt32 );
824 
825 oslModule SAL_CALL osl_psz_loadModule(const sal_Char *pszModuleName, sal_Int32 nRtldMode);
826 /*****************************************************************************
827  return the current process locale
828  *****************************************************************************/
829 
830 int macosx_getLocale(char *locale, sal_uInt32 bufferLen);
831 
832 void _imp_getProcessLocale( rtl_Locale ** ppLocale )
833 {
834     static char *locale = NULL;
835     char *npath, *opath;
836     int slen;
837 
838     /* basic thread safeness */
839 //    pthread_mutex_lock( &aLocalMutex );
840 
841     /* Only fetch the locale once and cache it */
842     if ( NULL == locale )
843     {
844 
845         locale = (char *)malloc( 128 );
846         if ( locale )
847             macosx_getLocale( locale, 128 );
848         else
849             fprintf( stderr, "nlsupport.c:  locale allocation returned NULL!\n" );
850     }
851 
852     /* handle the case where OS specific method of finding locale fails */
853     if ( NULL == locale )
854     {
855         /* simulate behavior of setlocale */
856         locale = getenv( "LC_ALL" );
857 
858         if( NULL == locale )
859             locale = getenv( "LC_CTYPE" );
860 
861         if( NULL == locale )
862             locale = getenv( "LANG" );
863 
864         if( NULL == locale )
865             locale = "C";
866     }
867 
868     /* return the locale */
869     *ppLocale = _parse_locale( locale );
870 
871     setenv( "LC_ALL", locale, 1);
872     setenv("LC_CTYPE", locale, 1 );
873     setenv("LANG", locale, 1 );
874 
875     /*
876      * This is a hack. We know that we are setting some envvars here
877      * and due to https://bz.apache.org/ooo/show_bug.cgi?id=127965
878      * we need to update PATH on macOS. Doing it here ensures
879      * that it's done but it's not the right location to be doing
880      * this.
881      *
882      * Also address https://bz.apache.org/ooo/show_bug.cgi?id=127966
883      * here as well :/
884      */
885     opath = getenv ( "PATH" );
886     slen = strlen( "/usr/local/bin" ) + 1;
887     if ( opath != NULL )
888         slen += strlen( ":" ) + strlen( opath );
889     npath = malloc( slen );
890     *npath = '\0';
891     if ( opath != NULL ) {
892         strcat( npath, opath );
893         strcat( npath, ":" );
894     }
895     strcat( npath, "/usr/local/bin" ); /* We are adding at the end */
896     setenv("PATH", npath, 1 );
897     free(npath);
898 
899 /* https://bz.apache.org/ooo/show_bug.cgi?id=127966 */
900     opath = getenv ( "HOME" );
901     if ( opath && *opath ) {
902         chdir ( opath );
903     } else {
904         chdir ( "/tmp" );
905     }
906 
907 #ifdef DEBUG
908     fprintf( stderr, "nlsupport.c:  _imp_getProcessLocale() returning %s as current locale.\n", locale );
909 #endif
910 
911 //    pthread_mutex_unlock( &aLocalMutex );
912 
913 }
914 #else
915 /*****************************************************************************
916  return the current process locale
917  *****************************************************************************/
918 
919 void _imp_getProcessLocale( rtl_Locale ** ppLocale )
920 {
921     /* simulate behavior off setlocale */
922     char * locale = getenv( "LC_ALL" );
923 
924     if( NULL == locale )
925         locale = getenv( "LC_CTYPE" );
926 
927     if( NULL == locale )
928         locale = getenv( "LANG" );
929 
930     if( NULL == locale )
931         locale = "C";
932 
933     *ppLocale = _parse_locale( locale );
934 }
935 #endif
936 
937 /*****************************************************************************
938  set the current process locale
939  *****************************************************************************/
940 
941 int _imp_setProcessLocale( rtl_Locale * pLocale )
942 {
943     char locale_buf[64];
944 
945     /* convert rtl_Locale to locale string */
946     if( NULL != _compose_locale( pLocale, locale_buf, 64 ) )
947     {
948         /* only change env vars that exist already */
949         if( getenv( "LC_ALL" ) ) {
950 #if defined( FREEBSD ) || defined( NETBSD ) || defined( MACOSX )
951             setenv( "LC_ALL", locale_buf, 1);
952 #else
953             setenv( "LC_ALL", locale_buf );
954 #endif
955         }
956 
957         if( getenv( "LC_CTYPE" ) ) {
958 #if defined( FREEBSD ) || defined( NETBSD ) || defined( MACOSX )
959             setenv("LC_CTYPE", locale_buf, 1 );
960 #else
961             setenv( "LC_CTYPE", locale_buf );
962 #endif
963         }
964 
965         if( getenv( "LANG" ) ) {
966 #if defined( FREEBSD ) || defined( NETBSD ) || defined( MACOSX )
967             setenv("LC_CTYPE", locale_buf, 1 );
968 #else
969             setenv( "LANG", locale_buf );
970 #endif
971         }
972     }
973 
974     return 0;
975 }
976 
977 #endif /* ifdef LINUX || SOLARIS || MACOSX || NETBSD */
978 
979 
980