revert between 56095 -> 55830 in arch
[AROS.git] / workbench / prefs / locale / prefs.c
blob8505587117cfb8a6f089caa2fc39097ff92a994a
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((BPTR)iff->iff_Stream);
133 FreeIFF(iff);
136 return lockFlag;
139 char *GetAROSLanguageAttribs(struct AnchorPath *ap, char **languageNamePtr)
141 BPTR fileHandle;
142 char tmpbuff[32];
143 int read, len = 0, pos, i;
144 BOOL match = FALSE;
146 if ((fileHandle = Open(ap->ap_Info.fib_FileName, MODE_OLDFILE)) != BNULL)
148 while ((read = Read(fileHandle, &tmpbuff[len], sizeof(tmpbuff) - len)) > 0)
150 len = len + read;
152 if (match)
154 for (i = 0; i < len; i++)
156 if (tmpbuff[i] == '\0')
158 FreeVecPooled(mempool, *languageNamePtr);
159 *languageNamePtr = AllocVecPooled(mempool, i + 2);
160 CopyMem(tmpbuff, *languageNamePtr, i + 1);
161 Close(fileHandle);
162 D(bug("[LocalePrefs] GetAROSLanguageAttribs: NativeName (A) '%s'\n", *languageNamePtr));
163 return *languageNamePtr;
165 /* we shouldnt really ever reach here .. */
168 else
170 pos = 0;
172 while ((len - pos) >= 7)
174 if (strncmp(&tmpbuff[pos], "$NLANG:", 7) == 0)
176 match = TRUE;
177 pos += 7;
179 if ((len - pos) > 0)
181 CopyMem(&tmpbuff[pos], tmpbuff, (len - pos));
182 len = len - pos;
183 for (i = 0; i < len; i++)
185 if (tmpbuff[i] == '\0')
187 FreeVecPooled(mempool, *languageNamePtr);
188 *languageNamePtr = AllocVecPooled(mempool, i + 2);
189 CopyMem(tmpbuff, *languageNamePtr, i + 1);
190 Close(fileHandle);
191 D(bug("[LocalePrefs] GetAROSLanguageAttribs: NativeName (B) '%s'\n", *languageNamePtr));
192 return *languageNamePtr;
196 else
197 len = 0;
199 else
200 pos++;
202 if (!match && (pos < len))
204 CopyMem(&tmpbuff[pos], tmpbuff, (len - pos));
205 len = len - pos;
209 Close(fileHandle);
211 return NULL;
214 /*********************************************************************************************/
216 STATIC VOID ScanDirectory(char *pattern, struct List *list, LONG entrysize)
218 struct AnchorPath ap;
219 struct ListviewEntry *entry;
220 BPTR curdir = BNULL;
221 char *sp;
222 LONG error;
224 memset(&ap, 0, sizeof(ap));
226 if ((error = MatchFirst(pattern, &ap)) == 0)
227 curdir = CurrentDir(ap.ap_Current->an_Lock);
229 while((error == 0))
231 if (ap.ap_Info.fib_DirEntryType < 0)
233 entry = (struct ListviewEntry *)AllocPooled(mempool, entrysize);
234 if (entry)
236 entry->node.ln_Name = AllocVecPooled(mempool, strlen(ap.ap_Info.fib_FileName) + 1);
237 strcpy(entry->node.ln_Name, ap.ap_Info.fib_FileName);
239 if ((sp = strchr(entry->node.ln_Name, '.')) != NULL)
240 sp[0] = '\0';
242 strcpy(entry->realname, entry->node.ln_Name);
243 entry->node.ln_Name[0] = ToUpper(entry->node.ln_Name[0]);
245 if (entrysize == sizeof(struct RegionEntry))
247 D(bug("[LocalePrefs] ScanDir: Checking for FLAG chunk\n"));
248 if (!(entry->displayflag = GetAROSRegionAttribs(&ap, &entry->node.ln_Name)))
250 entry->displayflag = AllocVecPooled(mempool, strlen(entry->realname) + strlen(flagpathstr) + 12);
251 sprintf(entry->displayflag, "%sCountries/%s]", flagpathstr, entry->realname);
254 else if (entrysize == sizeof(struct LanguageEntry))
256 D(bug("[LocalePrefs] ScanDir: Checking for native Language name\n"));
257 GetAROSLanguageAttribs(&ap, &entry->node.ln_Name);
258 entry->node.ln_Name[0] = ToUpper(entry->node.ln_Name[0]);
261 sp = entry->node.ln_Name;
262 while((sp = strchr(sp, '_')))
264 sp[0] = ' ';
265 if (sp[1])
267 /* Make char after underscore uppercase only if no
268 more underscores follow */
269 if (strchr(sp, '_') == 0)
271 sp[1] = ToUpper(sp[1]);
275 SortInNode(list, &entry->node);
278 error = MatchNext(&ap);
280 if (curdir != BNULL)
281 CurrentDir(curdir);
282 MatchEnd(&ap);
285 /*********************************************************************************************/
287 #if !AROS_BIG_ENDIAN
288 STATIC VOID FixCountryEndianess(struct CountryPrefs *region)
290 region->cp_Reserved[0] = AROS_BE2LONG(region->cp_Reserved[0]);
291 region->cp_Reserved[1] = AROS_BE2LONG(region->cp_Reserved[1]);
292 region->cp_Reserved[2] = AROS_BE2LONG(region->cp_Reserved[2]);
293 region->cp_Reserved[3] = AROS_BE2LONG(region->cp_Reserved[3]);
294 region->cp_CountryCode = AROS_BE2LONG(region->cp_CountryCode);
296 #endif
298 /*********************************************************************************************/
300 #if !AROS_BIG_ENDIAN
301 STATIC VOID FixLocaleEndianess(struct LocalePrefs *localeprefs)
303 localeprefs->lp_Reserved[0] = AROS_BE2LONG(localeprefs->lp_Reserved[0]);
304 localeprefs->lp_Reserved[1] = AROS_BE2LONG(localeprefs->lp_Reserved[1]);
305 localeprefs->lp_Reserved[2] = AROS_BE2LONG(localeprefs->lp_Reserved[2]);
306 localeprefs->lp_Reserved[3] = AROS_BE2LONG(localeprefs->lp_Reserved[3]);
307 localeprefs->lp_GMTOffset = AROS_BE2LONG(localeprefs->lp_GMTOffset);
308 localeprefs->lp_Flags = AROS_BE2LONG(localeprefs->lp_Flags);
310 #endif
312 /*********************************************************************************************/
314 BOOL Prefs_LoadRegion(STRPTR name, struct CountryPrefs *region)
316 static struct CountryPrefs loadregion;
317 struct IFFHandle *iff;
318 struct ContextNode *cn;
319 LONG parse_mode = IFFPARSE_SCAN, error;
320 char fullname[100];
321 BOOL retval = FALSE;
323 strcpy(fullname, "LOCALE:Countries");
324 AddPart(fullname, name, 100);
325 strcat(fullname, ".country");
327 D(bug("[LocalePrefs] LoadRegion: Trying to open \"%s\"\n", fullname));
329 if ((iff = AllocIFF()))
331 if ((iff->iff_Stream = (IPTR)Open(fullname, MODE_OLDFILE)))
333 D(bug("[LocalePrefs] LoadRegion: stream opened.\n"));
335 InitIFFasDOS(iff);
337 if (!OpenIFF(iff, IFFF_READ))
339 D(bug("[LocalePrefs] LoadRegion: OpenIFF okay.\n"));
341 if (!StopChunk(iff, ID_PREF, ID_PRHD))
343 D(bug("[LocalePrefs] LoadRegion: StopChunk okay.\n"));
347 if ((error = ParseIFF(iff, parse_mode)) == 0)
349 parse_mode = IFFPARSE_STEP;
351 D(bug("[LocalePrefs] LoadRegion: ParseIFF okay.\n"));
353 cn = CurrentChunk(iff);
355 D(bug("[LocalePrefs] LoadRegion: Chunk ID %08x.\n", cn->cn_ID));
357 if ((cn->cn_ID == ID_CTRY) && (cn->cn_Size == sizeof(struct CountryPrefs)))
359 D(bug("[LocalePrefs] LoadRegion: Chunk ID_CTRY (size okay).\n"));
361 if (ReadChunkBytes(iff, &loadregion, sizeof(struct CountryPrefs)) == sizeof(struct CountryPrefs))
363 D(bug("[LocalePrefs] LoadRegion: Reading chunk successful.\n"));
365 *region = loadregion;
367 #if !AROS_BIG_ENDIAN
368 FixCountryEndianess(region);
369 #endif
371 D(bug("[LocalePrefs] LoadRegion: Everything okay :-)\n"));
373 retval = TRUE;
374 error = IFFERR_EOF;
377 } /* if (!ParseIFF(iff, IFFPARSE_SCAN)) */
378 } while ((error != IFFERR_EOF) && (error != IFFERR_NOTIFF));
379 } /* if (!StopChunk(iff, ID_PREF, ID_CTRY)) */
380 CloseIFF(iff);
381 } /* if (!OpenIFF(iff, IFFF_READ)) */
382 Close((BPTR)iff->iff_Stream);
383 } /* if ((iff->iff_Stream = (IPTR)Open(fullname, MODE_OLDFILE))) */
384 FreeIFF(iff);
385 } /* if ((iff = AllocIFF())) */
387 return retval;
390 /*********************************************************************************************/
392 BOOL Prefs_ImportFH(BPTR fh)
394 static struct LocalePrefs loadprefs;
395 struct IFFHandle *iff;
396 BOOL retval = FALSE;
398 D(bug("[LocalePrefs] LoadPrefsFH\n"));
400 if ((iff = AllocIFF()))
402 if ((iff->iff_Stream = (IPTR) fh))
404 D(bug("[LocalePrefs] LoadPrefsFH: stream is ok.\n"));
406 InitIFFasDOS(iff);
408 if (!OpenIFF(iff, IFFF_READ))
410 D(bug("[LocalePrefs] LoadPrefsFH: OpenIFF okay.\n"));
412 if (!StopChunk(iff, ID_PREF, ID_LCLE))
414 D(bug("[LocalePrefs] LoadPrefsFH: StopChunk okay.\n"));
416 if (!ParseIFF(iff, IFFPARSE_SCAN))
418 struct ContextNode *cn;
420 D(bug("[LocalePrefs] LoadPrefsFH: ParseIFF okay.\n"));
422 cn = CurrentChunk(iff);
424 if (cn->cn_Size == sizeof(struct LocalePrefs))
426 D(bug("[LocalePrefs] LoadPrefsFH: ID_LCLE chunk size okay.\n"));
428 if (ReadChunkBytes(iff, &loadprefs, sizeof(struct LocalePrefs)) == sizeof(struct LocalePrefs))
430 D(bug("[LocalePrefs] LoadPrefsFH: Reading chunk successful.\n"));
432 localeprefs = loadprefs;
434 #if !AROS_BIG_ENDIAN
435 FixLocaleEndianess(&localeprefs);
436 FixCountryEndianess(&localeprefs.lp_CountryData);
437 #endif
439 D(bug("[LocalePrefs] LoadPrefsFH: Everything okay :-)\n"));
441 retval = TRUE;
444 } /* if (!ParseIFF(iff, IFFPARSE_SCAN)) */
445 } /* if (!StopChunk(iff, ID_PREF, ID_CTRY)) */
446 CloseIFF(iff);
447 } /* if (!OpenIFF(iff, IFFF_READ)) */
448 } /* if ((iff->iff_Stream = (IPTR)Open(filename, MODE_OLDFILE))) */
449 FreeIFF(iff);
450 } /* if ((iff = AllocIFF())) */
452 D(bug("[LocalePrefs] LoadPrefsFH: CountryName = '%s'\n", localeprefs.lp_CountryName));
455 int i;
456 for(i = 0; i < 10 && localeprefs.lp_PreferredLanguages[i]; i++)
458 bug("[LocalePrefs] LoadPrefsFH: preferred %02d = '%s'\n", i, localeprefs.lp_PreferredLanguages[i]);
461 D(bug("[LocalePrefs] LoadPrefsFH: lp_GMTOffset = %ld\n", localeprefs.lp_GMTOffset));
462 return retval;
466 /*********************************************************************************************/
468 BOOL Prefs_ExportFH(BPTR fh)
470 struct LocalePrefs saveprefs;
471 struct IFFHandle *iff;
472 BOOL retval = FALSE;
473 #if 0 /* unused */
474 BOOL delete_if_error = FALSE;
475 #endif
477 D(bug("[LocalePrefs] SavePrefsFH: fh: %lx\n", fh));
479 CopyMem(&localeprefs, &saveprefs, sizeof(struct LocalePrefs));
481 #if !AROS_BIG_ENDIAN
482 FixLocaleEndianess(&saveprefs);
483 FixCountryEndianess(&saveprefs.lp_CountryData);
484 #endif
486 if ((iff = AllocIFF()))
488 iff->iff_Stream = (IPTR) fh;
489 D(bug("[LocalePrefs] SavePrefsFH: stream opened.\n"));
491 #if 0 /* unused */
492 delete_if_error = TRUE;
493 #endif
495 InitIFFasDOS(iff);
497 if (!OpenIFF(iff, IFFF_WRITE))
499 D(bug("[LocalePrefs] SavePrefsFH: OpenIFF okay.\n"));
501 if (!PushChunk(iff, ID_PREF, ID_FORM, IFFSIZE_UNKNOWN))
503 D(bug("[LocalePrefs] SavePrefsFH: PushChunk(FORM) okay.\n"));
505 if (!PushChunk(iff, ID_PREF, ID_PRHD, sizeof(struct FilePrefHeader)))
507 struct FilePrefHeader head;
509 D(bug("[LocalePrefs] SavePrefsFH: PushChunk(PRHD) okay.\n"));
511 head.ph_Version = PHV_CURRENT;
512 head.ph_Type = 0;
513 head.ph_Flags[0] =
514 head.ph_Flags[1] =
515 head.ph_Flags[2] =
516 head.ph_Flags[3] = 0;
518 if (WriteChunkBytes(iff, &head, sizeof(head)) == sizeof(head))
520 D(bug("[LocalePrefs] SavePrefsFH: WriteChunkBytes(PRHD) okay.\n"));
522 PopChunk(iff);
524 if (!PushChunk(iff, ID_PREF, ID_LCLE, sizeof(struct LocalePrefs)))
526 D(bug("[LocalePrefs] SavePrefsFH: PushChunk(LCLE) okay.\n"));
528 if (WriteChunkBytes(iff, &saveprefs, sizeof(saveprefs)) == sizeof(saveprefs))
530 D(bug("[LocalePrefs] SavePrefsFH: WriteChunkBytes(SERL) okay.\n"));
531 D(bug("[LocalePrefs] SavePrefsFH: Everything okay :-)\n"));
533 retval = TRUE;
535 PopChunk(iff);
536 } /* if (!PushChunk(iff, ID_PREF, ID_SERL, sizeof(struct LocalePrefs))) */
538 } /* if (WriteChunkBytes(iff, &head, sizeof(head)) == sizeof(head)) */
539 else
541 PopChunk(iff);
543 } /* if (!PushChunk(iff, ID_PREF, ID_PRHD, sizeof(struct PrefHeader))) */
544 PopChunk(iff);
545 } /* if (!PushChunk(iff, ID_PREF, ID_FORM, IFFSIZE_UNKNOWN)) */
546 CloseIFF(iff);
547 } /* if (!OpenIFF(iff, IFFFWRITE)) */
548 FreeIFF(iff);
549 } /* if ((iff = AllocIFF())) */
551 #if 0 /* unused */
552 if (!retval && delete_if_error)
554 DeleteFile(filename);
556 #endif
558 return retval;
561 /*********************************************************************************************/
563 BOOL Prefs_SaveCharset(BOOL envarc)
565 LONG flags = GVF_GLOBAL_ONLY;
567 D(bug("[LocalePrefs] SaveCharset(%ld)\n", envarc));
569 if (envarc)
570 flags |= GVF_SAVE_VAR;
571 /* We don't check results of the following actions because they may fail if ENVARC: is read-only (CD-ROM) */
572 if (character_set[0])
573 SetVar("CHARSET", character_set, -1, flags);
574 else
575 DeleteVar("CHARSET", flags);
577 return TRUE;
580 /*********************************************************************************************/
582 static BOOL Prefs_Load(STRPTR from)
584 BOOL retval = FALSE;
586 BPTR fh = Open(from, MODE_OLDFILE);
587 if (fh)
589 retval = Prefs_ImportFH(fh);
590 Close(fh);
593 return retval;
596 /*********************************************************************************************/
598 BOOL Prefs_HandleArgs(STRPTR from, BOOL use, BOOL save)
600 BPTR fh;
602 if (from)
604 if (!Prefs_Load(from))
606 ShowMessage("Can't read from input file");
607 return FALSE;
610 else
612 if (!Prefs_Load(PREFS_PATH_ENV))
614 if (!Prefs_Load(PREFS_PATH_ENVARC))
616 ShowMessage
618 "Can't read from file " PREFS_PATH_ENVARC
619 ".\nUsing default values."
621 Prefs_Default();
626 if (use || save)
628 Prefs_LoadRegion(localeprefs.lp_CountryName, &localeprefs.lp_CountryData);
629 fh = Open(PREFS_PATH_ENV, MODE_NEWFILE);
630 if (fh)
632 Prefs_ExportFH(fh);
633 Close(fh);
635 else
637 ShowMessage("Cant' open " PREFS_PATH_ENV " for writing.");
640 if (save)
642 fh = Open(PREFS_PATH_ENVARC, MODE_NEWFILE);
643 if (fh)
645 Prefs_ExportFH(fh);
646 Close(fh);
648 else
650 ShowMessage("Cant' open " PREFS_PATH_ENVARC " for writing.");
654 return TRUE;
657 /*********************************************************************************************/
659 BOOL Prefs_Initialize(VOID)
661 D(bug("[LocalePrefs] InitPrefs\n"));
663 struct LanguageEntry *entry;
665 mempool = CreatePool(MEMF_PUBLIC | MEMF_CLEAR, 2048, 2048);
666 if (!mempool)
668 ShowMessage("Out of memory!");
669 return FALSE;
672 NewList(&region_list);
673 NewList(&language_list);
674 NewList(&pref_language_list);
676 ScanDirectory("LOCALE:Countries/~(#?.info)", &region_list, sizeof(struct RegionEntry));
677 ScanDirectory("LOCALE:Languages/#?.language", &language_list, sizeof(struct LanguageEntry));
679 /* English language is always available */
681 if ((entry = AllocPooled(mempool, sizeof(struct LanguageEntry))))
683 entry->lve.node.ln_Name = AllocVecPooled(mempool, 8);
684 strcpy( entry->lve.node.ln_Name, "English");
685 strcpy( entry->lve.realname, "english");
687 SortInNode(&language_list, &entry->lve.node);
690 character_set[0] = 0;
691 GetVar("CHARSET", character_set, sizeof(character_set), 0);
692 D(bug("[LocalePrefs] System character set: %s\n", character_set));
694 return TRUE;
697 /*********************************************************************************************/
699 VOID Prefs_Deinitialize(VOID)
701 D(bug("[LocalePrefs] CleanupPrefs\n"));
702 if (mempool)
704 DeletePool(mempool);
705 mempool = NULL;
709 /*********************************************************************************************/
711 BOOL Prefs_Default(VOID)
713 BOOL retval = FALSE;
714 WORD i;
716 localeprefs.lp_Reserved[0] = 0;
717 localeprefs.lp_Reserved[1] = 0;
718 localeprefs.lp_Reserved[2] = 0;
719 localeprefs.lp_Reserved[3] = 0;
721 strcpy(localeprefs.lp_CountryName, "united_states");
723 for(i = 0; i < 10; i++)
725 memset(localeprefs.lp_PreferredLanguages[i], 0, sizeof(localeprefs.lp_PreferredLanguages[i]));
727 localeprefs.lp_GMTOffset = 5 * 60;
728 localeprefs.lp_Flags = 0;
730 if (Prefs_LoadRegion((STRPTR) "united_states", &localeprefs.lp_CountryData))
732 retval = TRUE;
735 character_set[0] = 0;
737 return retval;