Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : #include "nscore.h"
7 : #include "nsString.h"
8 : #include "nsPosixLocale.h"
9 : #include "mozilla/Sprintf.h"
10 : #include "plstr.h"
11 : #include "nsReadableUtils.h"
12 :
13 : static bool
14 : ParseLocaleString(const char* locale_string, char* language, char* country, char* extra, char separator);
15 :
16 : nsresult
17 0 : nsPosixLocale::GetPlatformLocale(const nsAString& locale, nsACString& posixLocale)
18 : {
19 : char country_code[MAX_COUNTRY_CODE_LEN+1];
20 : char lang_code[MAX_LANGUAGE_CODE_LEN+1];
21 : char extra[MAX_EXTRA_LEN+1];
22 : char posix_locale[MAX_LOCALE_LEN+1];
23 0 : NS_LossyConvertUTF16toASCII xp_locale(locale);
24 :
25 0 : if (!xp_locale.IsEmpty()) {
26 0 : if (!ParseLocaleString(xp_locale.get(),lang_code,country_code,extra,'-')) {
27 : // strncpy(posixLocale,"C",length);
28 0 : posixLocale = xp_locale; // use xp locale if parse failed
29 0 : return NS_OK;
30 : }
31 :
32 0 : if (*country_code) {
33 0 : if (*extra) {
34 0 : SprintfLiteral(posix_locale,"%s_%s.%s",lang_code,country_code,extra);
35 : }
36 : else {
37 0 : SprintfLiteral(posix_locale,"%s_%s",lang_code,country_code);
38 : }
39 : }
40 : else {
41 0 : if (*extra) {
42 0 : SprintfLiteral(posix_locale,"%s.%s",lang_code,extra);
43 : }
44 : else {
45 0 : SprintfLiteral(posix_locale,"%s",lang_code);
46 : }
47 : }
48 :
49 0 : posixLocale = posix_locale;
50 0 : return NS_OK;
51 : }
52 :
53 0 : return NS_ERROR_FAILURE;
54 : }
55 :
56 : nsresult
57 0 : nsPosixLocale::GetXPLocale(const char* posixLocale, nsAString& locale)
58 : {
59 : char country_code[MAX_COUNTRY_CODE_LEN+1];
60 : char lang_code[MAX_LANGUAGE_CODE_LEN+1];
61 : char extra[MAX_EXTRA_LEN+1];
62 : char posix_locale[MAX_LOCALE_LEN+1];
63 :
64 0 : if (posixLocale!=nullptr) {
65 0 : if (strcmp(posixLocale,"C")==0 || strcmp(posixLocale,"POSIX")==0) {
66 0 : locale.AssignLiteral("en-US");
67 0 : return NS_OK;
68 : }
69 0 : if (strcmp(posixLocale,"C.UTF-8")==0) {
70 0 : locale.AssignLiteral("en-US.UTF-8");
71 0 : return NS_OK;
72 : }
73 0 : if (!ParseLocaleString(posixLocale,lang_code,country_code,extra,'_')) {
74 : // * locale = "x-user-defined";
75 : // use posix if parse failed
76 0 : CopyASCIItoUTF16(nsDependentCString(posixLocale), locale);
77 0 : return NS_OK;
78 : }
79 :
80 : // Special case: substitute "nb" (Norwegian Bokmal) for macrolanguage
81 : // code "no" (Norwegian)
82 0 : if (nsDependentCString(lang_code).LowerCaseEqualsLiteral("no")) {
83 0 : lang_code[1] = 'b';
84 : }
85 :
86 0 : if (*country_code) {
87 0 : SprintfLiteral(posix_locale,"%s-%s",lang_code,country_code);
88 : }
89 : else {
90 0 : SprintfLiteral(posix_locale,"%s",lang_code);
91 : }
92 :
93 0 : CopyASCIItoUTF16(nsDependentCString(posix_locale), locale);
94 0 : return NS_OK;
95 :
96 : }
97 :
98 0 : return NS_ERROR_FAILURE;
99 :
100 : }
101 :
102 : //
103 : // returns false/true depending on if it was of the form LL-CC.Extra
104 : static bool
105 0 : ParseLocaleString(const char* locale_string, char* language, char* country, char* extra, char separator)
106 : {
107 0 : const char *src = locale_string;
108 : char modifier[MAX_EXTRA_LEN+1];
109 : char *dest;
110 : int dest_space, len;
111 :
112 0 : *language = '\0';
113 0 : *country = '\0';
114 0 : *extra = '\0';
115 0 : if (strlen(locale_string) < 2) {
116 0 : return(false);
117 : }
118 :
119 : //
120 : // parse the language part
121 : //
122 0 : dest = language;
123 0 : dest_space = MAX_LANGUAGE_CODE_LEN;
124 0 : while ((*src) && (isalpha(*src)) && (dest_space--)) {
125 0 : *dest++ = tolower(*src++);
126 : }
127 0 : *dest = '\0';
128 0 : len = dest - language;
129 0 : if ((len != 2) && (len != 3)) {
130 0 : NS_ASSERTION((len == 2) || (len == 3), "language code too short");
131 0 : NS_ASSERTION(len < 3, "reminder: verify we can handle 3+ character language code in all parts of the system; eg: language packs");
132 0 : *language = '\0';
133 0 : return(false);
134 : }
135 :
136 : // check if all done
137 0 : if (*src == '\0') {
138 0 : return(true);
139 : }
140 :
141 0 : if ((*src != '_') && (*src != '-') && (*src != '.') && (*src != '@')) {
142 0 : NS_ASSERTION(isalpha(*src), "language code too long");
143 0 : NS_ASSERTION(!isalpha(*src), "unexpected language/country separator");
144 0 : *language = '\0';
145 0 : return(false);
146 : }
147 :
148 : //
149 : // parse the country part
150 : //
151 0 : if ((*src == '_') || (*src == '-')) {
152 0 : src++;
153 0 : dest = country;
154 0 : dest_space = MAX_COUNTRY_CODE_LEN;
155 0 : while ((*src) && (isalpha(*src)) && (dest_space--)) {
156 0 : *dest++ = toupper(*src++);
157 : }
158 0 : *dest = '\0';
159 0 : len = dest - country;
160 0 : if (len != 2) {
161 0 : NS_ASSERTION(len == 2, "unexpected country code length");
162 0 : *language = '\0';
163 0 : *country = '\0';
164 0 : return(false);
165 : }
166 : }
167 :
168 : // check if all done
169 0 : if (*src == '\0') {
170 0 : return(true);
171 : }
172 :
173 0 : if ((*src != '.') && (*src != '@')) {
174 0 : NS_ASSERTION(isalpha(*src), "country code too long");
175 0 : NS_ASSERTION(!isalpha(*src), "unexpected country/extra separator");
176 0 : *language = '\0';
177 0 : *country = '\0';
178 0 : return(false);
179 : }
180 :
181 : //
182 : // handle the extra part
183 : //
184 0 : if (*src == '.') {
185 0 : src++; // move past the extra part separator
186 0 : dest = extra;
187 0 : dest_space = MAX_EXTRA_LEN;
188 0 : while ((*src) && (*src != '@') && (dest_space--)) {
189 0 : *dest++ = *src++;
190 : }
191 0 : *dest = '\0';
192 0 : len = dest - extra;
193 0 : if (len < 1) {
194 0 : NS_ASSERTION(len > 0, "found country/extra separator but no extra code");
195 0 : *language = '\0';
196 0 : *country = '\0';
197 0 : *extra = '\0';
198 0 : return(false);
199 : }
200 : }
201 :
202 : // check if all done
203 0 : if (*src == '\0') {
204 0 : return(true);
205 : }
206 :
207 : //
208 : // handle the modifier part
209 : //
210 :
211 0 : if (*src == '@') {
212 0 : src++; // move past the modifier separator
213 0 : NS_ASSERTION(strcmp("euro",src) == 0, "found non euro modifier");
214 0 : dest = modifier;
215 0 : dest_space = MAX_EXTRA_LEN;
216 0 : while ((*src) && (dest_space--)) {
217 0 : *dest++ = *src++;
218 : }
219 0 : *dest = '\0';
220 0 : len = dest - modifier;
221 0 : if (len < 1) {
222 0 : NS_ASSERTION(len > 0, "found modifier separator but no modifier code");
223 0 : *language = '\0';
224 0 : *country = '\0';
225 0 : *extra = '\0';
226 0 : *modifier = '\0';
227 0 : return(false);
228 : }
229 : }
230 :
231 : // check if all done
232 0 : if (*src == '\0') {
233 0 : return(true);
234 : }
235 :
236 0 : NS_ASSERTION(*src == '\0', "extra/modifier code too long");
237 0 : *language = '\0';
238 0 : *country = '\0';
239 0 : *extra = '\0';
240 :
241 0 : return(false);
242 : }
243 :
|