2 Copyright © 1995-2013, The AROS Development Team. All rights reserved.
6 /*********************************************************************************************/
8 #include <aros/debug.h>
10 #include <proto/exec.h>
11 #include <proto/dos.h>
12 #include <proto/locale.h>
13 #include <proto/utility.h>
14 #include <proto/alib.h>
15 #include <proto/iffparse.h>
17 #include <aros/macros.h>
19 #include <prefs/prefhdr.h>
28 /*********************************************************************************************/
30 #define PREFS_PATH_ENVARC "ENVARC:SYS/locale.prefs"
31 #define PREFS_PATH_ENV "ENV:SYS/locale.prefs"
33 /*********************************************************************************************/
42 /*********************************************************************************************/
44 struct LocalePrefs localeprefs
;
45 char character_set
[CHARACTER_SET_LEN
];
46 char restore_charset
[CHARACTER_SET_LEN
];
47 struct List region_list
;
48 struct List language_list
;
49 struct List pref_language_list
;
51 /*********************************************************************************************/
55 const char *flagpathstr
= "\033I[5:Locale:Flags/";
57 /*********************************************************************************************/
59 STATIC VOID
SortInNode(struct List
*list
, struct Node
*node
)
61 struct Node
*sort
, *prev
= NULL
;
64 loc
= OpenLocale(NULL
);
66 ForeachNode(list
, sort
)
69 node
->ln_Name
, sort
->ln_Name
,
70 strlen(node
->ln_Name
), SC_COLLATE2
)
78 Insert(list
, node
, prev
);
82 /*********************************************************************************************/
84 char *GetAROSRegionAttribs(struct AnchorPath
*ap
, char **regionNamePtr
)
86 char *lockFlag
= NULL
;
87 struct IFFHandle
*iff
;
88 struct ContextNode
*cn
;
89 LONG parse_mode
= IFFPARSE_SCAN
, error
;
91 if ((iff
= AllocIFF()))
93 if ((iff
->iff_Stream
= (IPTR
)Open(ap
->ap_Info
.fib_FileName
, MODE_OLDFILE
)))
97 if (!OpenIFF(iff
, IFFF_READ
))
99 if (!StopChunk(iff
, ID_PREF
, ID_PRHD
))
103 if ((error
= ParseIFF(iff
, parse_mode
)) == 0)
105 parse_mode
= IFFPARSE_STEP
;
107 cn
= CurrentChunk(iff
);
108 D(bug("[LocalePrefs] GetAROSRegionAttribs: Chunk ID %08x. %d bytes\n", cn
->cn_ID
, cn
->cn_Size
));
110 if (cn
->cn_ID
== MAKE_ID('N','N','A','M'))
112 FreeVecPooled(mempool
, *regionNamePtr
);
113 *regionNamePtr
= AllocVecPooled(mempool
, cn
->cn_Size
);
114 ReadChunkBytes(iff
, *regionNamePtr
, cn
->cn_Size
);
115 D(bug("[LocalePrefs] GetAROSRegionAttribs: NativeNames '%s'\n", *regionNamePtr
));
118 if (cn
->cn_ID
== MAKE_ID('F','L','A','G'))
120 lockFlag
= AllocVecPooled(mempool
, cn
->cn_Size
+ 18 + 1);
121 sprintf(lockFlag
, flagpathstr
);
122 ReadChunkBytes(iff
, lockFlag
+ 18, cn
->cn_Size
);
123 lockFlag
[cn
->cn_Size
+ 17] = ']';
124 D(bug("[LocalePrefs] GetAROSRegionAttribs: Flag '%s'\n", lockFlag
));
127 } while ((error
!= IFFERR_EOF
) && (error
!= IFFERR_NOTIFF
));
131 Close(iff
->iff_Stream
);
139 /*********************************************************************************************/
141 STATIC VOID
ScanDirectory(char *pattern
, struct List
*list
, LONG entrysize
)
143 struct AnchorPath ap
;
144 struct ListviewEntry
*entry
;
149 memset(&ap
, 0, sizeof(ap
));
151 if ((error
= MatchFirst(pattern
, &ap
)) == 0)
152 curdir
= CurrentDir(ap
.ap_Current
->an_Lock
);
156 if (ap
.ap_Info
.fib_DirEntryType
< 0)
158 entry
= (struct ListviewEntry
*)AllocPooled(mempool
, entrysize
);
161 entry
->node
.ln_Name
= AllocVecPooled(mempool
, strlen(ap
.ap_Info
.fib_FileName
));
162 strcpy(entry
->node
.ln_Name
, ap
.ap_Info
.fib_FileName
);
164 entry
->node
.ln_Name
[0] = ToUpper(entry
->node
.ln_Name
[0]);
165 if ((sp
= strchr(entry
->node
.ln_Name
, '.')) != NULL
)
168 strcpy(entry
->realname
, entry
->node
.ln_Name
);
170 if (entrysize
== sizeof(struct RegionEntry
))
172 D(bug("[LocalePrefs] ScanDir: Checking for FLAG chunk\n"));
173 if (!(entry
->displayflag
= GetAROSRegionAttribs(&ap
, &entry
->node
.ln_Name
)))
175 entry
->displayflag
= AllocVec(strlen(entry
->realname
) + strlen(flagpathstr
) + 12, MEMF_CLEAR
);
176 sprintf(entry
->displayflag
, "%sCountries/%s]", flagpathstr
, entry
->realname
);
179 else if (entrysize
== sizeof(struct LanguageEntry
))
181 // TODO: handle translating english language name -> native name.
184 sp
= entry
->node
.ln_Name
;
185 while((sp
= strchr(sp
, '_')))
190 /* Make char after underscore uppercase only if no
191 more underscores follow */
192 if (strchr(sp
, '_') == 0)
194 sp
[1] = ToUpper(sp
[1]);
198 SortInNode(list
, &entry
->node
);
201 error
= MatchNext(&ap
);
208 /*********************************************************************************************/
211 STATIC VOID
FixCountryEndianess(struct CountryPrefs
*region
)
213 region
->cp_Reserved
[0] = AROS_BE2LONG(region
->cp_Reserved
[0]);
214 region
->cp_Reserved
[1] = AROS_BE2LONG(region
->cp_Reserved
[1]);
215 region
->cp_Reserved
[2] = AROS_BE2LONG(region
->cp_Reserved
[2]);
216 region
->cp_Reserved
[3] = AROS_BE2LONG(region
->cp_Reserved
[3]);
217 region
->cp_CountryCode
= AROS_BE2LONG(region
->cp_CountryCode
);
221 /*********************************************************************************************/
224 STATIC VOID
FixLocaleEndianess(struct LocalePrefs
*localeprefs
)
226 localeprefs
->lp_Reserved
[0] = AROS_BE2LONG(localeprefs
->lp_Reserved
[0]);
227 localeprefs
->lp_Reserved
[1] = AROS_BE2LONG(localeprefs
->lp_Reserved
[1]);
228 localeprefs
->lp_Reserved
[2] = AROS_BE2LONG(localeprefs
->lp_Reserved
[2]);
229 localeprefs
->lp_Reserved
[3] = AROS_BE2LONG(localeprefs
->lp_Reserved
[3]);
230 localeprefs
->lp_GMTOffset
= AROS_BE2LONG(localeprefs
->lp_GMTOffset
);
231 localeprefs
->lp_Flags
= AROS_BE2LONG(localeprefs
->lp_Flags
);
235 /*********************************************************************************************/
237 BOOL
Prefs_LoadRegion(STRPTR name
, struct CountryPrefs
*region
)
239 static struct CountryPrefs loadregion
;
240 struct IFFHandle
*iff
;
241 struct ContextNode
*cn
;
242 LONG parse_mode
= IFFPARSE_SCAN
, error
;
246 strcpy(fullname
, "LOCALE:Countries");
247 AddPart(fullname
, name
, 100);
248 strcat(fullname
, ".country");
250 D(bug("[LocalePrefs] LoadRegion: Trying to open \"%s\"\n", fullname
));
252 if ((iff
= AllocIFF()))
254 if ((iff
->iff_Stream
= (IPTR
)Open(fullname
, MODE_OLDFILE
)))
256 D(bug("[LocalePrefs] LoadRegion: stream opened.\n"));
260 if (!OpenIFF(iff
, IFFF_READ
))
262 D(bug("[LocalePrefs] LoadRegion: OpenIFF okay.\n"));
264 if (!StopChunk(iff
, ID_PREF
, ID_PRHD
))
266 D(bug("[LocalePrefs] LoadRegion: StopChunk okay.\n"));
270 if ((error
= ParseIFF(iff
, parse_mode
)) == 0)
272 parse_mode
= IFFPARSE_STEP
;
274 D(bug("[LocalePrefs] LoadRegion: ParseIFF okay.\n"));
276 cn
= CurrentChunk(iff
);
278 D(bug("[LocalePrefs] LoadRegion: Chunk ID %08x.\n", cn
->cn_ID
));
280 if ((cn
->cn_ID
== ID_CTRY
) && (cn
->cn_Size
== sizeof(struct CountryPrefs
)))
282 D(bug("[LocalePrefs] LoadRegion: Chunk ID_CTRY (size okay).\n"));
284 if (ReadChunkBytes(iff
, &loadregion
, sizeof(struct CountryPrefs
)) == sizeof(struct CountryPrefs
))
286 D(bug("[LocalePrefs] LoadRegion: Reading chunk successful.\n"));
288 *region
= loadregion
;
291 FixCountryEndianess(region
);
294 D(bug("[LocalePrefs] LoadRegion: Everything okay :-)\n"));
300 } /* if (!ParseIFF(iff, IFFPARSE_SCAN)) */
301 } while ((error
!= IFFERR_EOF
) && (error
!= IFFERR_NOTIFF
));
302 } /* if (!StopChunk(iff, ID_PREF, ID_CTRY)) */
304 } /* if (!OpenIFF(iff, IFFF_READ)) */
305 Close((BPTR
)iff
->iff_Stream
);
306 } /* if ((iff->iff_Stream = (IPTR)Open(fullname, MODE_OLDFILE))) */
308 } /* if ((iff = AllocIFF())) */
313 /*********************************************************************************************/
315 BOOL
Prefs_ImportFH(BPTR fh
)
317 static struct LocalePrefs loadprefs
;
318 struct IFFHandle
*iff
;
321 D(bug("[LocalePrefs] LoadPrefsFH\n"));
323 if ((iff
= AllocIFF()))
325 if ((iff
->iff_Stream
= (IPTR
) fh
))
327 D(bug("[LocalePrefs] LoadPrefsFH: stream is ok.\n"));
331 if (!OpenIFF(iff
, IFFF_READ
))
333 D(bug("[LocalePrefs] LoadPrefsFH: OpenIFF okay.\n"));
335 if (!StopChunk(iff
, ID_PREF
, ID_LCLE
))
337 D(bug("[LocalePrefs] LoadPrefsFH: StopChunk okay.\n"));
339 if (!ParseIFF(iff
, IFFPARSE_SCAN
))
341 struct ContextNode
*cn
;
343 D(bug("[LocalePrefs] LoadPrefsFH: ParseIFF okay.\n"));
345 cn
= CurrentChunk(iff
);
347 if (cn
->cn_Size
== sizeof(struct LocalePrefs
))
349 D(bug("[LocalePrefs] LoadPrefsFH: ID_LCLE chunk size okay.\n"));
351 if (ReadChunkBytes(iff
, &loadprefs
, sizeof(struct LocalePrefs
)) == sizeof(struct LocalePrefs
))
353 D(bug("[LocalePrefs] LoadPrefsFH: Reading chunk successful.\n"));
355 localeprefs
= loadprefs
;
358 FixLocaleEndianess(&localeprefs
);
359 FixCountryEndianess(&localeprefs
.lp_CountryData
);
362 D(bug("[LocalePrefs] LoadPrefsFH: Everything okay :-)\n"));
367 } /* if (!ParseIFF(iff, IFFPARSE_SCAN)) */
368 } /* if (!StopChunk(iff, ID_PREF, ID_CTRY)) */
370 } /* if (!OpenIFF(iff, IFFF_READ)) */
371 } /* if ((iff->iff_Stream = (IPTR)Open(filename, MODE_OLDFILE))) */
373 } /* if ((iff = AllocIFF())) */
375 D(bug("[LocalePrefs] CountryName: %s\n",localeprefs
.lp_CountryName
));
377 while(i
<10 && localeprefs
.lp_PreferredLanguages
[i
])
379 D(bug("[LocalePrefs] preferred %ld: %s\n",i
,localeprefs
.lp_PreferredLanguages
[i
]));
382 D(bug("[LocalePrefs] lp_GMTOffset: %ld\n",localeprefs
.lp_GMTOffset
));
387 /*********************************************************************************************/
389 BOOL
Prefs_ExportFH(BPTR fh
)
391 struct LocalePrefs saveprefs
;
392 struct IFFHandle
*iff
;
395 BOOL delete_if_error
= FALSE
;
398 D(bug("[LocalePrefs] SavePrefsFH: fh: %lx\n", fh
));
400 saveprefs
= localeprefs
;
403 FixLocaleEndianess(&saveprefs
);
404 FixCountryEndianess(&saveprefs
.lp_CountryData
);
407 if ((iff
= AllocIFF()))
409 iff
->iff_Stream
= (IPTR
) fh
;
410 D(bug("[LocalePrefs] SavePrefsFH: stream opened.\n"));
413 delete_if_error
= TRUE
;
418 if (!OpenIFF(iff
, IFFF_WRITE
))
420 D(bug("[LocalePrefs] SavePrefsFH: OpenIFF okay.\n"));
422 if (!PushChunk(iff
, ID_PREF
, ID_FORM
, IFFSIZE_UNKNOWN
))
424 D(bug("[LocalePrefs] SavePrefsFH: PushChunk(FORM) okay.\n"));
426 if (!PushChunk(iff
, ID_PREF
, ID_PRHD
, sizeof(struct FilePrefHeader
)))
428 struct FilePrefHeader head
;
430 D(bug("[LocalePrefs] SavePrefsFH: PushChunk(PRHD) okay.\n"));
432 head
.ph_Version
= PHV_CURRENT
;
437 head
.ph_Flags
[3] = 0;
439 if (WriteChunkBytes(iff
, &head
, sizeof(head
)) == sizeof(head
))
441 D(bug("[LocalePrefs] SavePrefsFH: WriteChunkBytes(PRHD) okay.\n"));
445 if (!PushChunk(iff
, ID_PREF
, ID_LCLE
, sizeof(struct LocalePrefs
)))
447 D(bug("[LocalePrefs] SavePrefsFH: PushChunk(LCLE) okay.\n"));
449 if (WriteChunkBytes(iff
, &saveprefs
, sizeof(saveprefs
)) == sizeof(saveprefs
))
451 D(bug("[LocalePrefs] SavePrefsFH: WriteChunkBytes(SERL) okay.\n"));
452 D(bug("[LocalePrefs] SavePrefsFH: Everything okay :-)\n"));
457 } /* if (!PushChunk(iff, ID_PREF, ID_SERL, sizeof(struct LocalePrefs))) */
459 } /* if (WriteChunkBytes(iff, &head, sizeof(head)) == sizeof(head)) */
464 } /* if (!PushChunk(iff, ID_PREF, ID_PRHD, sizeof(struct PrefHeader))) */
466 } /* if (!PushChunk(iff, ID_PREF, ID_FORM, IFFSIZE_UNKNOWN)) */
468 } /* if (!OpenIFF(iff, IFFFWRITE)) */
470 } /* if ((iff = AllocIFF())) */
473 if (!retval
&& delete_if_error
)
475 DeleteFile(filename
);
482 /*********************************************************************************************/
484 BOOL
Prefs_SaveCharset(BOOL envarc
)
486 LONG flags
= GVF_GLOBAL_ONLY
;
488 D(bug("[LocalePrefs] SaveCharset(%ld)\n", envarc
));
491 flags
|= GVF_SAVE_VAR
;
492 /* We don't check results of the following actions because they may fail if ENVARC: is read-only (CD-ROM) */
493 if (character_set
[0])
494 SetVar("CHARSET", character_set
, -1, flags
);
496 DeleteVar("CHARSET", flags
);
501 /*********************************************************************************************/
503 static BOOL
Prefs_Load(STRPTR from
)
507 BPTR fh
= Open(from
, MODE_OLDFILE
);
510 retval
= Prefs_ImportFH(fh
);
517 /*********************************************************************************************/
519 BOOL
Prefs_HandleArgs(STRPTR from
, BOOL use
, BOOL save
)
525 if (!Prefs_Load(from
))
527 ShowMessage("Can't read from input file");
533 if (!Prefs_Load(PREFS_PATH_ENV
))
535 if (!Prefs_Load(PREFS_PATH_ENVARC
))
539 "Can't read from file " PREFS_PATH_ENVARC
540 ".\nUsing default values."
549 Prefs_LoadRegion(localeprefs
.lp_CountryName
, &localeprefs
.lp_CountryData
);
550 fh
= Open(PREFS_PATH_ENV
, MODE_NEWFILE
);
558 ShowMessage("Cant' open " PREFS_PATH_ENV
" for writing.");
563 fh
= Open(PREFS_PATH_ENVARC
, MODE_NEWFILE
);
571 ShowMessage("Cant' open " PREFS_PATH_ENVARC
" for writing.");
578 /*********************************************************************************************/
580 BOOL
Prefs_Initialize(VOID
)
582 D(bug("[LocalePrefs] InitPrefs\n"));
584 struct LanguageEntry
*entry
;
586 mempool
= CreatePool(MEMF_PUBLIC
| MEMF_CLEAR
, 2048, 2048);
589 ShowMessage("Out of memory!");
593 NewList(®ion_list
);
594 NewList(&language_list
);
595 NewList(&pref_language_list
);
597 ScanDirectory("LOCALE:Countries/~(#?.info)", ®ion_list
, sizeof(struct RegionEntry
));
598 ScanDirectory("LOCALE:Languages/#?.language", &language_list
, sizeof(struct LanguageEntry
));
600 /* English language is always available */
602 if ((entry
= AllocPooled(mempool
, sizeof(struct LanguageEntry
))))
604 entry
->lve
.node
.ln_Name
= AllocVecPooled(mempool
, 8);
605 strcpy( entry
->lve
.node
.ln_Name
, "English");
606 strcpy( entry
->lve
.realname
, "English");
608 SortInNode(&language_list
, &entry
->lve
.node
);
611 character_set
[0] = 0;
612 GetVar("CHARSET", character_set
, sizeof(character_set
), 0);
613 D(bug("[LocalePrefs] System character set: %s\n", character_set
));
618 /*********************************************************************************************/
620 VOID
Prefs_Deinitialize(VOID
)
622 D(bug("[LocalePrefs] CleanupPrefs\n"));
630 /*********************************************************************************************/
632 BOOL
Prefs_Default(VOID
)
637 localeprefs
.lp_Reserved
[0] = 0;
638 localeprefs
.lp_Reserved
[1] = 0;
639 localeprefs
.lp_Reserved
[2] = 0;
640 localeprefs
.lp_Reserved
[3] = 0;
642 strcpy(localeprefs
.lp_CountryName
, "united_states");
644 for(i
= 0; i
< 10; i
++)
646 memset(localeprefs
.lp_PreferredLanguages
[i
], 0, sizeof(localeprefs
.lp_PreferredLanguages
[i
]));
648 localeprefs
.lp_GMTOffset
= 5 * 60;
649 localeprefs
.lp_Flags
= 0;
651 if (Prefs_LoadRegion((STRPTR
) "united_states", &localeprefs
.lp_CountryData
))
656 character_set
[0] = 0;