ecere/compiler: Included i18n in bootstrap and updated tarball build Makefiles
[sdk] / ecere / src / sys / i18n.ec
1 import "File"
2 import "Map"
3
4 #ifndef ECERE_BOOTSTRAP
5 #define FileOpen FileOpenBuffered
6 #endif
7
8 Map<String, Map<String, String>> moduleMaps { };
9
10 #define SWAP_DWORD(dword) ((((unsigned int)(dword) & 0x000000ff) << 24) \
11                          | (((unsigned int)(dword) & 0x0000ff00) <<  8) \
12                          | (((unsigned int)(dword) & 0x00ff0000) >>  8) \
13                          | (((unsigned int)(dword) & 0xff000000) >> 24))
14
15 public dllexport void LoadTranslatedStrings(Module module, char * name)
16 {
17    File f;
18    char fileName[MAX_LOCATION];
19
20    char lcAll[256];
21    char language[256];
22    char lang[256];
23    char lcMessages[256];
24    char * locale = null;
25
26    if(GetEnvironment("LANGUAGE", language, sizeof(language)))
27       locale = language;
28    else if(GetEnvironment("LC_ALL", lcAll, sizeof(lcAll)))
29       locale = lcAll;
30    else if(GetEnvironment("LC_MESSAGES", lcMessages, sizeof(lcMessages)))
31       locale = lcMessages;
32    else if(GetEnvironment("LANG", lang, sizeof(lang)))
33       locale = lang;
34
35    if(locale)
36    {
37       char * dot;
38       strcpy(language, locale);
39       dot = strstr(language, ".");
40       if(dot) *dot = 0;
41       locale = language;
42    }
43
44    if(module.name)
45       sprintf(fileName, "<:%s>/locale/%s/LC_MESSAGES/%s.mo", module.name, locale, name);
46    else
47       sprintf(fileName, ":locale/%s/LC_MESSAGES/%s.mo", locale, name);
48    f = FileOpen(fileName, read);
49    if(!f)
50    {
51       sprintf(fileName, "locale/%s/LC_MESSAGES/%s.mo", locale, name);
52       f = FileOpen(fileName, read);
53    }
54    if(!f)
55    {
56       sprintf(fileName, "/usr/share/locale/%s/LC_MESSAGES/%s.mo", locale, name);
57       f = FileOpen(fileName, read);
58    }
59    if(f)
60    {
61       uint magic = 0;
62       f.Read(&magic, sizeof(uint), 1);
63       if(magic == 0x950412de || magic == 0xde120495)
64       {
65          Map<String, String> textMap;
66          bool swap = magic != 0x950412de;
67          uint revision = 0;
68          uint numStrings = 0;
69          uint origStrings = 0, transStrings = 0;
70          uint hashingSize = 0, hashingOffset = 0;
71          int c;
72          f.Read(&revision, sizeof(uint), 1);       if(swap) SWAP_DWORD(revision);
73          f.Read(&numStrings, sizeof(uint), 1);     if(swap) SWAP_DWORD(numStrings);
74          f.Read(&origStrings, sizeof(uint), 1);    if(swap) SWAP_DWORD(origStrings);
75          f.Read(&transStrings, sizeof(uint), 1);   if(swap) SWAP_DWORD(transStrings);
76          f.Read(&hashingSize, sizeof(uint), 1);    if(swap) SWAP_DWORD(hashingSize);
77          f.Read(&hashingOffset, sizeof(uint), 1);  if(swap) SWAP_DWORD(hashingOffset);
78          
79          if(!moduleMaps)
80             moduleMaps = { };
81          {
82             MapIterator<String, Map<String, String>> it { map = moduleMaps };
83             if(it.Index(module.name, false))
84                delete it.data;
85             // TOFIX: delete moduleMaps[module];
86          }
87          moduleMaps[module.name] = textMap = { };
88          for(c = 0; c < numStrings; c++)
89          {
90             uint len = 0, offset = 0;
91             char * original = null, * translated = null;
92
93             f.Seek(origStrings + c*2*sizeof(uint), start);
94             f.Read(&len, sizeof(uint), 1);      if(swap)SWAP_DWORD(len);
95             f.Read(&offset, sizeof(uint), 1);   if(swap)SWAP_DWORD(offset);
96             f.Seek(offset, start);
97
98             original = new byte[len + 1];
99             f.Read(original, 1, len + 1);
100
101             f.Seek(transStrings + c*2*sizeof(uint), start);
102             f.Read(&len, sizeof(uint), 1);      if(swap)SWAP_DWORD(len);
103             f.Read(&offset, sizeof(uint), 1);   if(swap)SWAP_DWORD(offset);
104             f.Seek(offset, start);
105
106             translated = new byte[len + 1];
107             f.Read(translated, 1, len + 1);
108
109             if(len)
110                textMap[original] = translated;
111             else
112                delete translated;
113             delete original;
114          }
115       }
116       else
117       {
118          // Failure
119          printf("Invalid format while loading %s\n", fileName);
120       }
121       delete f;
122    }
123 }
124
125 public dllexport void UnloadTranslatedStrings(Module module)
126 {
127    MapIterator<String, Map<String, String>> it { map = moduleMaps };
128    if(it.Index(module.name, false))
129    {
130       it.data.Free();
131       moduleMaps.Delete(it.pointer);
132    }
133 }
134
135 public dllexport char * GetTranslatedString(Module module, char * string)
136 {
137    Map<String, String> textMap = moduleMaps ? moduleMaps[module.name] : null;
138    return textMap ? textMap[string] : string;
139 }