2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
5 Desc: InitLocale() load locale preferences from a file.
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>
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
[];
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);
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;
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
;
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);
96 && ((((struct Process
*)FindTask(NULL
))->pr_HomeDir
) !=
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);
113 static void BuildPreferredLanguages(struct IntLocale
* locale
)
116 struct Library
* lang
= NULL
;
120 STRPTR lName
= locale
->LanguagesOnDiskNames
[i
];
122 if (lName
&& lName
[0] != '\0')
124 lang
= OpenOnDiskLanguage(lName
);
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);
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
;
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
];
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
);
176 lang
= OpenOnDiskLanguage(il
->LanguagesOnDiskNames
[i
]);
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 */
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
205 If we could open any of the libraries, replace its function,
206 otherwise replace none of them.
209 il
->il_CurrentLanguage
= lang
;
213 mask
= AROS_LC0(ULONG
, mask
, struct Library
*, lang
, 5, Language
);
218 DEBUG_INITLOCALE(dprintf("SetLocaleLanguage: Language Mask 0x%lx\n",
220 /* CONST: If we add any more functions we need to increase this number */
221 for (i
= 0; i
< 17; i
++)
226 il
->il_LanguageFunctions
[i
] =
227 (APTR
) (((ULONG
) lang
) - ((i
+ 6) * 6));
229 il
->il_LanguageFunctions
[i
] = __AROS_GETVECADDR(lang
, (i
+ 6));
231 DEBUG_INITLOCALE(dprintf
232 ("SetLocaleLanguage: use Lanugage Entry %ld Func 0x%lx\n",
233 i
, il
->il_LanguageFunctions
[i
]));
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) */
246 OpenCatalogA((struct Locale
*)il
, "System/Libs/dos.catalog", NULL
);
248 DEBUG_INITLOCALE(dprintf("SetLocaleLanguage: DosCatalog 0x%lx\n",
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
;
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
];
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
);
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"));