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