revert between 56095 -> 55830 in arch
[AROS.git] / workbench / libs / locale / initlocale.c
blob9ad0b2f4ab4c259637fdbfc257241e19345dcc8a
1 /*
2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: InitLocale() load locale preferences from a file.
6 Lang: english
7 */
9 #include <exec/types.h>
10 #include <proto/dos.h>
11 #include <proto/iffparse.h>
12 #include "locale_intern.h"
13 #include <libraries/iffparse.h>
14 #include <prefs/prefhdr.h>
15 #include <prefs/locale.h>
16 #include <proto/exec.h>
17 #include <proto/locale.h>
18 #include <aros/asmcall.h>
19 #include <aros/libcall.h>
21 #include <aros/debug.h>
23 #include <string.h>
24 #include <stdio.h> /* For snprintf */
25 #include <limits.h> /* For PATH_MAX */
27 #define DEBUG_INITLOCALE(x) ;
29 AROS_LD4(ULONG, strcompare,
30 AROS_UFPA(STRPTR, string1, A1),
31 AROS_UFPA(STRPTR, string2, A2),
32 AROS_UFPA(ULONG, length, D0),
33 AROS_UFPA(ULONG, how, D1),
34 struct LocaleBase *, LocaleBase, 22, english);
36 extern void *__eng_functable[];
38 #define EC(x)\
40 (x) = (((x) & 0xFF000000) >> 24)\
41 | (((x) & 0x00FF0000) >> 8)\
42 | (((x) & 0x0000FF00) << 8)\
43 | (((x) & 0x000000FF) << 24);\
46 static struct Library * OpenOnDiskLanguage(STRPTR lName)
48 struct Library * lang = NULL;
49 TEXT fileBuf[PATH_MAX];
51 snprintf(fileBuf, PATH_MAX, "%s.language", lName);
52 fileBuf[PATH_MAX - 1] = 0;
54 /* Try and open the specified language */
55 lang = OpenLibrary(fileBuf, 0);
57 #ifdef __MORPHOS
58 if (lang == NULL)
61 Ok, so the language didn't open, lets try for
62 MOSSYS:LOCALE/Languages/xxx.language
65 snprintf(fileBuf, PATH_MAX,
66 "MOSSYS:LOCALE/Languages/%s.language", lName);
67 fileBuf[PATH_MAX - 1] = 0;
70 APTR oldwinptr;
71 struct Process *me =
72 (struct Process *)FindTask(NULL);
73 oldwinptr = me->pr_WindowPtr;
74 me->pr_WindowPtr = (APTR) - 1;
75 lang = OpenLibrary(fileBuf, 0);
76 me->pr_WindowPtr = oldwinptr;
79 #endif
81 if (lang == NULL)
84 Ok, so the language didn't open, lets try for
85 LOCALE:Languages/xxx.language
88 snprintf(fileBuf, PATH_MAX,
89 "LOCALE:Languages/%s.language", lName);
90 fileBuf[PATH_MAX - 1] = 0;
92 lang = OpenLibrary(fileBuf, 0);
95 if ((lang == NULL)
96 && ((((struct Process *)FindTask(NULL))->pr_HomeDir) !=
97 BNULL))
100 Ok, so we are still NULL, lets then try for
101 PROGDIR:Languages/xxx.language
103 snprintf(fileBuf, PATH_MAX,
104 "PROGDIR:Languages/%s.language", lName);
105 fileBuf[PATH_MAX - 1] = 0;
107 lang = OpenLibrary(fileBuf, 0);
110 return lang;
113 static void BuildPreferredLanguages(struct IntLocale * locale)
115 LONG i = 0;
116 struct Library * lang = NULL;
118 while(i < 10)
120 STRPTR lName = locale->LanguagesOnDiskNames[i];
122 if (lName && lName[0] != '\0')
124 lang = OpenOnDiskLanguage(lName);
126 if (lang)
128 CONST_STRPTR nlang = NULL;
130 nlang = AROS_CALL1(CONST_STRPTR, __AROS_GETVECADDR(lang, (3 + 6)),
131 AROS_LCA(ULONG, LANG_NAME, D0), struct LocaleBase *, LocaleBase);
133 strncpy(locale->PreferredLanguages[i], nlang, 30);
135 CloseLibrary(lang);
138 i++;
142 void SetLocaleLanguage(struct IntLocale *, struct LocaleBase *)
144 Try and set up the language of a Locale structure.
147 void SetLocaleLanguage(struct IntLocale *il, struct LocaleBase *LocaleBase)
149 struct Library *lang = NULL;
150 ULONG mask = 0;
151 LONG i = 0;
154 DEBUG_INITLOCALE(dprintf("SetLocaleLanguage: Locale 0x%lx\n", il));
156 while (lang == NULL && i < 10)
158 STRPTR lName = il->il_Locale.loc_PrefLanguages[i];
159 ULONG ret;
161 if (lName != NULL)
164 /* Is this english? If not try and load the language */
165 void *fn = AROS_SLIB_ENTRY(strcompare, english, 22);
167 ret = AROS_CALL4(ULONG, fn,
168 AROS_LCA(STRPTR, defLocale.loc_PrefLanguages[0], A1),
169 AROS_LCA(STRPTR, lName, A2),
170 AROS_LCA(ULONG, 7, D0),
171 AROS_LCA(ULONG, SC_ASCII, D1),
172 struct LocaleBase *, LocaleBase);
174 if (ret != 0)
176 lang = OpenOnDiskLanguage(il->LanguagesOnDiskNames[i]);
178 if (lang)
180 /* Native name is expected in loc_LanguageName */
181 sprintf(il->LanguageName, "%s.language", lName);
184 /* If it is still no good, then we have no hope */
187 i++;
190 if (lang == NULL)
192 strcpy(il->LanguageName, defLocale.loc_LanguageName);
195 il->il_Locale.loc_LanguageName = &il->LanguageName[0];
198 Ok so we now should have a language, or nothing. Either way
199 we now fill in the locale functions in the structure.
200 I remember there was a VERY big bug in here once, which I
201 finally managed to fix, only to blow away the only copy
202 of the file (and the rest of the locale.library) from all
203 existance. Sigh.
205 If we could open any of the libraries, replace its function,
206 otherwise replace none of them.
209 il->il_CurrentLanguage = lang;
211 if (lang != NULL)
213 mask = AROS_LC0(ULONG, mask, struct Library *, lang, 5, Language);
215 else
216 mask = 0;
218 DEBUG_INITLOCALE(dprintf("SetLocaleLanguage: Language Mask 0x%lx\n",
219 mask));
220 /* CONST: If we add any more functions we need to increase this number */
221 for (i = 0; i < 17; i++)
223 if (mask & (1 << i))
225 #ifdef __MORPHOS__
226 il->il_LanguageFunctions[i] =
227 (APTR) (((ULONG) lang) - ((i + 6) * 6));
228 #else
229 il->il_LanguageFunctions[i] = __AROS_GETVECADDR(lang, (i + 6));
230 #endif
231 DEBUG_INITLOCALE(dprintf
232 ("SetLocaleLanguage: use Lanugage Entry %ld Func 0x%lx\n",
233 i, il->il_LanguageFunctions[i]));
235 else
237 il->il_LanguageFunctions[i] = __eng_functable[i];
238 DEBUG_INITLOCALE(dprintf
239 ("SetLocaleLanguage: use Default Entry %ld Func 0x%lx\n", i,
240 il->il_LanguageFunctions[i]));
244 /* Open dos.catalog (needed for DosGetLocalizedString patch) */
245 il->il_DosCatalog =
246 OpenCatalogA((struct Locale *)il, "System/Libs/dos.catalog", NULL);
248 DEBUG_INITLOCALE(dprintf("SetLocaleLanguage: DosCatalog 0x%lx\n",
249 il->il_DosCatalog));
252 /* InitLocale(IntLocale *, LocalePrefs *)
253 This procedure will extract all the relevant information out of
254 a LocalePrefs structure, and stuff it into a IntLocale structure.
256 This is really a silly way of doing things, but unfortunately it
257 is the only way that doesn't keep the entire chunk in memory,
258 (by duplicating the LocalePrefs chunk), or by doing extra loops
259 on things (counting string sizes, then allocating).
261 This puts it smack bang in the centre of speed/memory use.
262 This is mainly a separate procedure to get rid of the indentation.
265 void InitLocale(STRPTR filename, struct IntLocale *locale,
266 struct LocalePrefs *lp, struct LocaleBase *LocaleBase)
268 struct CountryPrefs *cp;
269 int i, i2;
271 DEBUG_INITLOCALE(dprintf
272 ("InitLocale: filename <%s> Locale 0x%lx LocalePrefs 0x%lx\n",
273 filename, locale, lp));
275 cp = &lp->lp_CountryData;
277 strncpy(locale->LocaleName, FilePart(filename), sizeof(locale->LocaleName) - 1);
278 locale->il_Locale.loc_LocaleName = &locale->LocaleName[0];
280 /* Configuration contains on-disk language names */
281 CopyMem(lp->lp_PreferredLanguages[0],
282 locale->LanguagesOnDiskNames[0], 300);
284 /* Build PreferredLanguages array containing native names */
285 BuildPreferredLanguages(locale);
287 for (i = 0, i2 = 0; i < 10; i++)
289 if (locale->PreferredLanguages[i][0])
291 locale->il_Locale.loc_PrefLanguages[i2++] =
292 locale->PreferredLanguages[i];
296 if (i2 == 0)
298 /* The user did not set any preferred Language. So we automatically
299 poke "english" into the array (Tested on the Amiga where this
300 does seem to happen, too!) */
302 DEBUG_INITLOCALE(dprintf
303 ("InitLocale: user set no preferred lang\n"));
304 strcpy(locale->PreferredLanguages[0],
305 defLocale.loc_PrefLanguages[0]);
306 locale->il_Locale.loc_PrefLanguages[0] =
307 locale->PreferredLanguages[0];
311 If we cannot open ANY of the languages, then all the language
312 function vectors would have the default language data.
314 SetLocaleLanguage(locale, LocaleBase);
316 locale->il_Locale.loc_Flags = lp->lp_Flags;
317 locale->il_Locale.loc_CodeSet = 0;
318 locale->il_Locale.loc_CountryCode = cp->cp_CountryCode;
319 locale->il_Locale.loc_TelephoneCode = cp->cp_TelephoneCode;
320 locale->il_Locale.loc_GMTOffset = lp->lp_GMTOffset;
321 locale->il_Locale.loc_MeasuringSystem = cp->cp_MeasuringSystem;
322 locale->il_Locale.loc_CalendarType = cp->cp_CalendarType;
324 #if (AROS_BIG_ENDIAN == 0)
325 EC(locale->il_Locale.loc_Flags);
326 EC(locale->il_Locale.loc_CountryCode);
327 EC(locale->il_Locale.loc_TelephoneCode);
328 EC(locale->il_Locale.loc_GMTOffset);
329 #endif
331 /* Another really large section to copy,
332 from cp_DateTimeFormat[] to cp_MonFracGrouping[] incl
333 80 + 40 + 40 + 80 + 40 + 40 + (10 * 10)
336 CopyMem(&cp->cp_DateTimeFormat[0], &locale->DateTimeFormat[0], 420);
338 locale->il_Locale.loc_DateTimeFormat = &locale->DateTimeFormat[0];
339 locale->il_Locale.loc_DateFormat = &locale->DateFormat[0];
340 locale->il_Locale.loc_TimeFormat = &locale->TimeFormat[0];
341 locale->il_Locale.loc_ShortDateTimeFormat =
342 &locale->ShortDateTimeFormat[0];
343 locale->il_Locale.loc_ShortDateFormat = &locale->ShortDateFormat[0];
344 locale->il_Locale.loc_ShortTimeFormat = &locale->ShortTimeFormat[0];
346 locale->il_Locale.loc_DecimalPoint = &locale->DecimalPoint[0];
347 locale->il_Locale.loc_GroupSeparator = &locale->GroupSeparator[0];
348 locale->il_Locale.loc_FracGroupSeparator =
349 &locale->FracGroupSeparator[0];
350 locale->il_Locale.loc_Grouping = &locale->Grouping[0];
351 locale->il_Locale.loc_FracGrouping = &locale->FracGrouping[0];
353 locale->il_Locale.loc_MonDecimalPoint = &locale->MonDecimalPoint[0];
354 locale->il_Locale.loc_MonGroupSeparator = &locale->MonGroupSeparator[0];
355 locale->il_Locale.loc_MonFracGroupSeparator =
356 &locale->MonFracGroupSeparator[0];
357 locale->il_Locale.loc_MonGrouping = &locale->MonGrouping[0];
358 locale->il_Locale.loc_MonFracGrouping = &locale->MonFracGrouping[0];
360 locale->il_Locale.loc_MonFracDigits = cp->cp_MonFracDigits;
361 locale->il_Locale.loc_MonIntFracDigits = cp->cp_MonIntFracDigits;
363 /* The three currency symbols, and +ve sign */
364 CopyMem(&cp->cp_MonCS, &locale->MonCS[0], 40);
366 locale->il_Locale.loc_MonCS = &locale->MonCS[0];
367 locale->il_Locale.loc_MonSmallCS = &locale->MonSmallCS[0];
368 locale->il_Locale.loc_MonIntCS = &locale->MonIntCS[0];
369 locale->il_Locale.loc_MonPositiveSign = &locale->MonPositiveSign[0];
371 locale->il_Locale.loc_MonPositiveSpaceSep = cp->cp_MonPositiveSpaceSep;
372 locale->il_Locale.loc_MonPositiveSignPos = cp->cp_MonPositiveSignPos;
373 locale->il_Locale.loc_MonPositiveCSPos = cp->cp_MonPositiveCSPos;
375 CopyMem(&cp->cp_MonNegativeSign[0], &locale->MonNegativeSign[0], 10);
376 locale->il_Locale.loc_MonNegativeSign = &locale->MonNegativeSign[0];
377 locale->il_Locale.loc_MonNegativeSpaceSep = cp->cp_MonNegativeSpaceSep;
378 locale->il_Locale.loc_MonNegativeSignPos = cp->cp_MonNegativeSignPos;
379 locale->il_Locale.loc_MonNegativeCSPos = cp->cp_MonNegativeCSPos;
380 locale->il_Locale.loc_CalendarType = cp->cp_CalendarType;
382 DEBUG_INITLOCALE(dprintf("InitLocale: done\n"));