fix localeprefs language display after behaviour changes in the code for native name...
[AROS.git] / workbench / prefs / locale / prefs.c
blobc62cf8de1e619ee931cfeca84df3307ffc742883
1 /*
2 Copyright © 1995-2013, The AROS Development Team. All rights reserved.
3 $Id$
4 */
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>
21 #include <stdio.h>
22 #include <string.h>
23 #include <stdlib.h>
25 #include "prefs.h"
26 #include "misc.h"
28 /*********************************************************************************************/
30 #define PREFS_PATH_ENVARC "ENVARC:SYS/locale.prefs"
31 #define PREFS_PATH_ENV "ENV:SYS/locale.prefs"
33 /*********************************************************************************************/
35 struct FilePrefHeader
37 UBYTE ph_Version;
38 UBYTE ph_Type;
39 UBYTE ph_Flags[4];
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 /*********************************************************************************************/
53 static APTR mempool;
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;
62 struct Locale *loc;
64 loc = OpenLocale(NULL);
66 ForeachNode(list, sort)
68 if (StrnCmp(loc,
69 node->ln_Name, sort->ln_Name,
70 strlen(node->ln_Name), SC_COLLATE2)
71 < 0)
73 break;
75 prev = sort;
78 Insert(list, node, prev);
79 CloseLocale(loc);
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)))
95 InitIFFasDOS(iff);
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));
129 CloseIFF(iff);
131 Close(iff->iff_Stream);
133 FreeIFF(iff);
136 return lockFlag;
139 /*********************************************************************************************/
141 STATIC VOID ScanDirectory(char *pattern, struct List *list, LONG entrysize)
143 struct AnchorPath ap;
144 struct ListviewEntry *entry;
145 BPTR curdir = BNULL;
146 char *sp;
147 LONG error;
149 memset(&ap, 0, sizeof(ap));
151 if ((error = MatchFirst(pattern, &ap)) == 0)
152 curdir = CurrentDir(ap.ap_Current->an_Lock);
154 while((error == 0))
156 if (ap.ap_Info.fib_DirEntryType < 0)
158 entry = (struct ListviewEntry *)AllocPooled(mempool, entrysize);
159 if (entry)
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)
166 sp[0] = '\0';
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, '_')))
187 sp[0] = ' ';
188 if (sp[1])
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);
203 if (curdir != BNULL)
204 CurrentDir(curdir);
205 MatchEnd(&ap);
208 /*********************************************************************************************/
210 #if !AROS_BIG_ENDIAN
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);
219 #endif
221 /*********************************************************************************************/
223 #if !AROS_BIG_ENDIAN
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);
233 #endif
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;
243 char fullname[100];
244 BOOL retval = FALSE;
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"));
258 InitIFFasDOS(iff);
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;
290 #if !AROS_BIG_ENDIAN
291 FixCountryEndianess(region);
292 #endif
294 D(bug("[LocalePrefs] LoadRegion: Everything okay :-)\n"));
296 retval = TRUE;
297 error = IFFERR_EOF;
300 } /* if (!ParseIFF(iff, IFFPARSE_SCAN)) */
301 } while ((error != IFFERR_EOF) && (error != IFFERR_NOTIFF));
302 } /* if (!StopChunk(iff, ID_PREF, ID_CTRY)) */
303 CloseIFF(iff);
304 } /* if (!OpenIFF(iff, IFFF_READ)) */
305 Close((BPTR)iff->iff_Stream);
306 } /* if ((iff->iff_Stream = (IPTR)Open(fullname, MODE_OLDFILE))) */
307 FreeIFF(iff);
308 } /* if ((iff = AllocIFF())) */
310 return retval;
313 /*********************************************************************************************/
315 BOOL Prefs_ImportFH(BPTR fh)
317 static struct LocalePrefs loadprefs;
318 struct IFFHandle *iff;
319 BOOL retval = FALSE;
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"));
329 InitIFFasDOS(iff);
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;
357 #if !AROS_BIG_ENDIAN
358 FixLocaleEndianess(&localeprefs);
359 FixCountryEndianess(&localeprefs.lp_CountryData);
360 #endif
362 D(bug("[LocalePrefs] LoadPrefsFH: Everything okay :-)\n"));
364 retval = TRUE;
367 } /* if (!ParseIFF(iff, IFFPARSE_SCAN)) */
368 } /* if (!StopChunk(iff, ID_PREF, ID_CTRY)) */
369 CloseIFF(iff);
370 } /* if (!OpenIFF(iff, IFFF_READ)) */
371 } /* if ((iff->iff_Stream = (IPTR)Open(filename, MODE_OLDFILE))) */
372 FreeIFF(iff);
373 } /* if ((iff = AllocIFF())) */
375 D(bug("[LocalePrefs] CountryName: %s\n",localeprefs.lp_CountryName));
376 int i=0;
377 while(i<10 && localeprefs.lp_PreferredLanguages[i])
379 D(bug("[LocalePrefs] preferred %ld: %s\n",i,localeprefs.lp_PreferredLanguages[i]));
380 i++;
382 D(bug("[LocalePrefs] lp_GMTOffset: %ld\n",localeprefs.lp_GMTOffset));
383 return retval;
387 /*********************************************************************************************/
389 BOOL Prefs_ExportFH(BPTR fh)
391 struct LocalePrefs saveprefs;
392 struct IFFHandle *iff;
393 BOOL retval = FALSE;
394 #if 0 /* unused */
395 BOOL delete_if_error = FALSE;
396 #endif
398 D(bug("[LocalePrefs] SavePrefsFH: fh: %lx\n", fh));
400 saveprefs = localeprefs;
402 #if !AROS_BIG_ENDIAN
403 FixLocaleEndianess(&saveprefs);
404 FixCountryEndianess(&saveprefs.lp_CountryData);
405 #endif
407 if ((iff = AllocIFF()))
409 iff->iff_Stream = (IPTR) fh;
410 D(bug("[LocalePrefs] SavePrefsFH: stream opened.\n"));
412 #if 0 /* unused */
413 delete_if_error = TRUE;
414 #endif
416 InitIFFasDOS(iff);
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;
433 head.ph_Type = 0;
434 head.ph_Flags[0] =
435 head.ph_Flags[1] =
436 head.ph_Flags[2] =
437 head.ph_Flags[3] = 0;
439 if (WriteChunkBytes(iff, &head, sizeof(head)) == sizeof(head))
441 D(bug("[LocalePrefs] SavePrefsFH: WriteChunkBytes(PRHD) okay.\n"));
443 PopChunk(iff);
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"));
454 retval = TRUE;
456 PopChunk(iff);
457 } /* if (!PushChunk(iff, ID_PREF, ID_SERL, sizeof(struct LocalePrefs))) */
459 } /* if (WriteChunkBytes(iff, &head, sizeof(head)) == sizeof(head)) */
460 else
462 PopChunk(iff);
464 } /* if (!PushChunk(iff, ID_PREF, ID_PRHD, sizeof(struct PrefHeader))) */
465 PopChunk(iff);
466 } /* if (!PushChunk(iff, ID_PREF, ID_FORM, IFFSIZE_UNKNOWN)) */
467 CloseIFF(iff);
468 } /* if (!OpenIFF(iff, IFFFWRITE)) */
469 FreeIFF(iff);
470 } /* if ((iff = AllocIFF())) */
472 #if 0 /* unused */
473 if (!retval && delete_if_error)
475 DeleteFile(filename);
477 #endif
479 return retval;
482 /*********************************************************************************************/
484 BOOL Prefs_SaveCharset(BOOL envarc)
486 LONG flags = GVF_GLOBAL_ONLY;
488 D(bug("[LocalePrefs] SaveCharset(%ld)\n", envarc));
490 if (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);
495 else
496 DeleteVar("CHARSET", flags);
498 return TRUE;
501 /*********************************************************************************************/
503 static BOOL Prefs_Load(STRPTR from)
505 BOOL retval = FALSE;
507 BPTR fh = Open(from, MODE_OLDFILE);
508 if (fh)
510 retval = Prefs_ImportFH(fh);
511 Close(fh);
514 return retval;
517 /*********************************************************************************************/
519 BOOL Prefs_HandleArgs(STRPTR from, BOOL use, BOOL save)
521 BPTR fh;
523 if (from)
525 if (!Prefs_Load(from))
527 ShowMessage("Can't read from input file");
528 return FALSE;
531 else
533 if (!Prefs_Load(PREFS_PATH_ENV))
535 if (!Prefs_Load(PREFS_PATH_ENVARC))
537 ShowMessage
539 "Can't read from file " PREFS_PATH_ENVARC
540 ".\nUsing default values."
542 Prefs_Default();
547 if (use || save)
549 Prefs_LoadRegion(localeprefs.lp_CountryName, &localeprefs.lp_CountryData);
550 fh = Open(PREFS_PATH_ENV, MODE_NEWFILE);
551 if (fh)
553 Prefs_ExportFH(fh);
554 Close(fh);
556 else
558 ShowMessage("Cant' open " PREFS_PATH_ENV " for writing.");
561 if (save)
563 fh = Open(PREFS_PATH_ENVARC, MODE_NEWFILE);
564 if (fh)
566 Prefs_ExportFH(fh);
567 Close(fh);
569 else
571 ShowMessage("Cant' open " PREFS_PATH_ENVARC " for writing.");
575 return TRUE;
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);
587 if (!mempool)
589 ShowMessage("Out of memory!");
590 return FALSE;
593 NewList(&region_list);
594 NewList(&language_list);
595 NewList(&pref_language_list);
597 ScanDirectory("LOCALE:Countries/~(#?.info)", &region_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));
615 return TRUE;
618 /*********************************************************************************************/
620 VOID Prefs_Deinitialize(VOID)
622 D(bug("[LocalePrefs] CleanupPrefs\n"));
623 if (mempool)
625 DeletePool(mempool);
626 mempool = NULL;
630 /*********************************************************************************************/
632 BOOL Prefs_Default(VOID)
634 BOOL retval = FALSE;
635 WORD i;
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))
653 retval = TRUE;
656 character_set[0] = 0;
658 return retval;