- Tabs to spaces.
[AROS.git] / workbench / libs / locale / initlocale.c
blob17490ffb0973ed7a5b28a8c476c0133012dac48d
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);\
47 void SetLocaleLanguage(struct IntLocale *, struct LocaleBase *)
49 Try and set up the language of a Locale structure.
52 void SetLocaleLanguage(struct IntLocale *il, struct LocaleBase *LocaleBase)
54 struct Library *lang = NULL;
55 ULONG mask = 0;
56 STRPTR fileBuf;
57 int i = 0;
59 DEBUG_INITLOCALE(dprintf("SetLocaleLanguage: Locale 0x%lx\n", il));
61 fileBuf = AllocMem(PATH_MAX, MEMF_ANY);
62 if (!fileBuf)
63 return;
65 while (lang == NULL && i < 10)
67 STRPTR lName = il->il_Locale.loc_PrefLanguages[i];
68 ULONG ret;
70 if (lName != NULL)
73 /* Is this english? If not try and load the language */
74 void *fn = AROS_SLIB_ENTRY(strcompare, english, 22);
76 ret = AROS_CALL4(ULONG, fn,
77 AROS_LCA(STRPTR, defLocale.loc_PrefLanguages[0], A1),
78 AROS_LCA(STRPTR, lName, A2),
79 AROS_LCA(ULONG, 7, D0),
80 AROS_LCA(ULONG, SC_ASCII, D1),
81 struct LocaleBase *, LocaleBase);
83 if (ret != 0)
85 snprintf(fileBuf, PATH_MAX, "%s.language", lName);
86 fileBuf[PATH_MAX - 1] = 0;
88 /* Try and open the specified language */
89 lang = OpenLibrary(fileBuf, 0);
91 #ifdef __MORPHOS
92 if (lang == NULL)
95 Ok, so the language didn't open, lets try for
96 MOSSYS:LOCALE/Languages/xxx.language
99 snprintf(fileBuf, PATH_MAX,
100 "MOSSYS:LOCALE/Languages/%s.language", lName);
101 fileBuf[PATH_MAX - 1] = 0;
104 APTR oldwinptr;
105 struct Process *me =
106 (struct Process *)FindTask(NULL);
107 oldwinptr = me->pr_WindowPtr;
108 me->pr_WindowPtr = (APTR) - 1;
109 lang = OpenLibrary(fileBuf, 0);
110 me->pr_WindowPtr = oldwinptr;
113 #endif
115 if (lang == NULL)
118 Ok, so the language didn't open, lets try for
119 LOCALE:Languages/xxx.language
122 snprintf(fileBuf, PATH_MAX,
123 "LOCALE:Languages/%s.language", lName);
124 fileBuf[PATH_MAX - 1] = 0;
126 lang = OpenLibrary(fileBuf, 0);
129 if ((lang == NULL)
130 && ((((struct Process *)FindTask(NULL))->pr_HomeDir) !=
131 BNULL))
134 Ok, so we are still NULL, lets then try for
135 PROGDIR:Languages/xxx.language
137 snprintf(fileBuf, PATH_MAX,
138 "PROGDIR:Languages/%s.language", lName);
139 fileBuf[PATH_MAX - 1] = 0;
141 lang = OpenLibrary(fileBuf, 0);
144 if (lang)
146 strncpy(il->LanguageName, FilePart(fileBuf), 30);
149 /* If it is still no good, then we have no hope */
152 i++;
155 if (lang == NULL)
157 strcpy(il->LanguageName, defLocale.loc_LanguageName);
160 il->il_Locale.loc_LanguageName = &il->LanguageName[0];
163 Ok so we now should have a language, or nothing. Either way
164 we now fill in the locale functions in the structure.
165 I remember there was a VERY big bug in here once, which I
166 finally managed to fix, only to blow away the only copy
167 of the file (and the rest of the locale.library) from all
168 existance. Sigh.
170 If we could open any of the libraries, replace its function,
171 otherwise replace none of them.
174 il->il_CurrentLanguage = lang;
176 if (lang != NULL)
178 mask = AROS_LC0(ULONG, mask, struct Library *, lang, 5, Language);
180 else
181 mask = 0;
183 DEBUG_INITLOCALE(dprintf("SetLocaleLanguage: Language Mask 0x%lx\n",
184 mask));
185 /* CONST: If we add any more functions we need to increase this number */
186 for (i = 0; i < 17; i++)
188 if (mask & (1 << i))
190 #ifdef __MORPHOS__
191 il->il_LanguageFunctions[i] =
192 (APTR) (((ULONG) lang) - ((i + 6) * 6));
193 #else
194 il->il_LanguageFunctions[i] = __AROS_GETVECADDR(lang, (i + 6));
195 #endif
196 DEBUG_INITLOCALE(dprintf
197 ("SetLocaleLanguage: use Lanugage Entry %ld Func 0x%lx\n",
198 i, il->il_LanguageFunctions[i]));
200 else
202 il->il_LanguageFunctions[i] = __eng_functable[i];
203 DEBUG_INITLOCALE(dprintf
204 ("SetLocaleLanguage: use Default Entry %ld Func 0x%lx\n", i,
205 il->il_LanguageFunctions[i]));
209 /* Open dos.catalog (needed for DosGetLocalizedString patch) */
210 il->il_DosCatalog =
211 OpenCatalogA((struct Locale *)il, "System/Libs/dos.catalog", NULL);
213 DEBUG_INITLOCALE(dprintf("SetLocaleLanguage: DosCatalog 0x%lx\n",
214 il->il_DosCatalog));
216 FreeMem(fileBuf, PATH_MAX);
219 /* InitLocale(IntLocale *, LocalePrefs *)
220 This procedure will extract all the relevant information out of
221 a LocalePrefs structure, and stuff it into a IntLocale structure.
223 This is really a silly way of doing things, but unfortunately it
224 is the only way that doesn't keep the entire chunk in memory,
225 (by duplicating the LocalePrefs chunk), or by doing extra loops
226 on things (counting string sizes, then allocating).
228 This puts it smack bang in the centre of speed/memory use.
229 This is mainly a separate procedure to get rid of the indentation.
232 void InitLocale(STRPTR filename, struct IntLocale *locale,
233 struct LocalePrefs *lp, struct LocaleBase *LocaleBase)
235 struct CountryPrefs *cp;
236 int i, i2;
238 DEBUG_INITLOCALE(dprintf
239 ("InitLocale: filename <%s> Locale 0x%lx LocalePrefs 0x%lx\n",
240 filename, locale, lp));
242 cp = &lp->lp_CountryData;
244 strncpy(locale->LocaleName, FilePart(filename), 30);
245 locale->il_Locale.loc_LocaleName = &locale->LocaleName[0];
248 We can copy 300 bytes straight away since
249 the prefered languages are all in a row.
251 CopyMem(lp->lp_PreferredLanguages[0],
252 locale->PreferredLanguages[0], 300);
254 for (i = 0, i2 = 0; i < 10; i++)
256 if (locale->PreferredLanguages[i][0])
258 locale->il_Locale.loc_PrefLanguages[i2++] =
259 locale->PreferredLanguages[i];
263 if (i2 == 0)
265 /* The user did not set any preferred Language. So we automatically
266 poke "english" into the array (Tested on the Amiga where this
267 does seem to happen, too!) */
269 DEBUG_INITLOCALE(dprintf
270 ("InitLocale: user set no preferred lang\n"));
271 strcpy(locale->PreferredLanguages[0],
272 defLocale.loc_PrefLanguages[0]);
273 locale->il_Locale.loc_PrefLanguages[0] =
274 locale->PreferredLanguages[0];
278 If we cannot open ANY of the languages, then all the language
279 function vectors would have the default language data.
281 SetLocaleLanguage(locale, LocaleBase);
283 locale->il_Locale.loc_Flags = lp->lp_Flags;
284 locale->il_Locale.loc_CodeSet = 0;
285 locale->il_Locale.loc_CountryCode = cp->cp_CountryCode;
286 locale->il_Locale.loc_TelephoneCode = cp->cp_TelephoneCode;
287 locale->il_Locale.loc_GMTOffset = lp->lp_GMTOffset;
288 locale->il_Locale.loc_CalendarType = cp->cp_CalendarType;
290 #if (AROS_BIG_ENDIAN == 0)
291 EC(locale->il_Locale.loc_Flags);
292 EC(locale->il_Locale.loc_CountryCode);
293 EC(locale->il_Locale.loc_TelephoneCode);
294 EC(locale->il_Locale.loc_GMTOffset);
295 #endif
297 /* Another really large section to copy,
298 from cp_DateTimeFormat[] to cp_MonFracGrouping[] incl
299 80 + 40 + 40 + 80 + 40 + 40 + (10 * 10)
302 CopyMem(&cp->cp_DateTimeFormat[0], &locale->DateTimeFormat[0], 420);
304 locale->il_Locale.loc_DateTimeFormat = &locale->DateTimeFormat[0];
305 locale->il_Locale.loc_DateFormat = &locale->DateFormat[0];
306 locale->il_Locale.loc_TimeFormat = &locale->TimeFormat[0];
307 locale->il_Locale.loc_ShortDateTimeFormat =
308 &locale->ShortDateTimeFormat[0];
309 locale->il_Locale.loc_ShortDateFormat = &locale->ShortDateFormat[0];
310 locale->il_Locale.loc_ShortTimeFormat = &locale->ShortTimeFormat[0];
312 locale->il_Locale.loc_DecimalPoint = &locale->DecimalPoint[0];
313 locale->il_Locale.loc_GroupSeparator = &locale->GroupSeparator[0];
314 locale->il_Locale.loc_FracGroupSeparator =
315 &locale->FracGroupSeparator[0];
316 locale->il_Locale.loc_Grouping = &locale->Grouping[0];
317 locale->il_Locale.loc_FracGrouping = &locale->FracGrouping[0];
319 locale->il_Locale.loc_MonDecimalPoint = &locale->MonDecimalPoint[0];
320 locale->il_Locale.loc_MonGroupSeparator = &locale->MonGroupSeparator[0];
321 locale->il_Locale.loc_MonFracGroupSeparator =
322 &locale->MonFracGroupSeparator[0];
323 locale->il_Locale.loc_MonGrouping = &locale->MonGrouping[0];
324 locale->il_Locale.loc_MonFracGrouping = &locale->MonFracGrouping[0];
326 locale->il_Locale.loc_MonFracDigits = cp->cp_MonFracDigits;
327 locale->il_Locale.loc_MonIntFracDigits = cp->cp_MonIntFracDigits;
329 /* The three currency symbols, and +ve sign */
330 CopyMem(&cp->cp_MonCS, &locale->MonCS[0], 40);
332 locale->il_Locale.loc_MonCS = &locale->MonCS[0];
333 locale->il_Locale.loc_MonSmallCS = &locale->MonSmallCS[0];
334 locale->il_Locale.loc_MonIntCS = &locale->MonIntCS[0];
335 locale->il_Locale.loc_MonPositiveSign = &locale->MonPositiveSign[0];
337 locale->il_Locale.loc_MonPositiveSpaceSep = cp->cp_MonPositiveSpaceSep;
338 locale->il_Locale.loc_MonPositiveSignPos = cp->cp_MonPositiveSignPos;
339 locale->il_Locale.loc_MonPositiveCSPos = cp->cp_MonPositiveCSPos;
341 CopyMem(&cp->cp_MonNegativeSign[0], &locale->MonNegativeSign[0], 10);
342 locale->il_Locale.loc_MonNegativeSign = &locale->MonNegativeSign[0];
343 locale->il_Locale.loc_MonNegativeSpaceSep = cp->cp_MonNegativeSpaceSep;
344 locale->il_Locale.loc_MonNegativeSignPos = cp->cp_MonNegativeSignPos;
345 locale->il_Locale.loc_MonNegativeCSPos = cp->cp_MonNegativeCSPos;
346 locale->il_Locale.loc_CalendarType = cp->cp_CalendarType;
348 DEBUG_INITLOCALE(dprintf("InitLocale: done\n"));