1 // LangPage.cpp
2
3 #include "StdAfx.h"
4
5 #include "../../../Common/Lang.h"
6
7 #include "../../../Windows/FileFind.h"
8 #include "../../../Windows/ResourceString.h"
9
10 #include "HelpUtils.h"
11 #include "LangPage.h"
12 #include "LangPageRes.h"
13 #include "LangUtils.h"
14 #include "RegistryUtils.h"
15
16 using namespace NWindows;
17
18
19 static const unsigned k_NumLangLines_EN = 443;
20
21 #ifdef Z7_LANG
22 static const UInt32 kLangIDs[] =
23 {
24 IDT_LANG_LANG
25 };
26 #endif
27
28 #define kLangTopic "fm/options.htm#language"
29
30
31 struct CLangListRecord
32 {
33 int Order;
34 unsigned LangInfoIndex;
35 bool IsSelected;
36 UString Mark;
37 UString Name;
38
CLangListRecordCLangListRecord39 CLangListRecord(): Order (10), IsSelected(false) {}
CompareCLangListRecord40 int Compare(const CLangListRecord &a) const
41 {
42 if (Order < a.Order) return -1;
43 if (Order > a.Order) return 1;
44 return MyStringCompareNoCase(Name, a.Name);
45 }
46 };
47
48
NativeLangString(UString & dest,const wchar_t * s)49 static void NativeLangString(UString &dest, const wchar_t *s)
50 {
51 dest += " (";
52 dest += s;
53 dest.Add_Char(')');
54 }
55
56 bool LangOpen(CLang &lang, CFSTR fileName);
57
OnInit()58 bool CLangPage::OnInit()
59 {
60 #ifdef Z7_LANG
61 LangSetDlgItems(*this, kLangIDs, Z7_ARRAY_SIZE(kLangIDs));
62 #endif
63 _langCombo.Attach(GetItem(IDC_LANG_LANG));
64
65
66 unsigned listRecords_SelectedIndex = 0;
67
68 CObjectVector<CLangListRecord> listRecords;
69 {
70 CLangListRecord listRecord;
71 listRecord.Order = 0;
72 listRecord.Mark = "---";
73 listRecord.Name = MyLoadString(IDS_LANG_ENGLISH);
74 NativeLangString(listRecord.Name, MyLoadString(IDS_LANG_NATIVE));
75 listRecord.LangInfoIndex = _langs.Size();
76 listRecords.Add(listRecord);
77 }
78
79 AStringVector names;
80 unsigned subLangIndex = 0;
81 Lang_GetShortNames_for_DefaultLang(names, subLangIndex);
82
83 const FString dirPrefix = GetLangDirPrefix();
84 NFile::NFind::CEnumerator enumerator;
85 enumerator.SetDirPrefix(dirPrefix);
86 NFile::NFind::CFileInfo fi;
87
88 CLang lang_en;
89 {
90 CLangInfo &langInfo = _langs.AddNew();
91 langInfo.Name = "-";
92 if (LangOpen(lang_en, dirPrefix + FTEXT("en.ttt")))
93 {
94 langInfo.NumLines = lang_en._ids.Size();
95 // langInfo.Comments = lang_en.Comments;
96 }
97 else
98 langInfo.NumLines = k_NumLangLines_EN;
99 NumLangLines_EN = langInfo.NumLines;
100 }
101
102 CLang lang;
103 UString error;
104 UString n;
105
106 while (enumerator.Next(fi))
107 {
108 if (fi.IsDir())
109 continue;
110 const unsigned kExtSize = 4;
111 if (fi.Name.Len() < kExtSize)
112 continue;
113 const unsigned pos = fi.Name.Len() - kExtSize;
114 if (!StringsAreEqualNoCase_Ascii(fi.Name.Ptr(pos), ".txt"))
115 {
116 // if (!StringsAreEqualNoCase_Ascii(fi.Name.Ptr(pos), ".ttt"))
117 continue;
118 }
119
120 if (!LangOpen(lang, dirPrefix + fi.Name))
121 {
122 error.Add_Space_if_NotEmpty();
123 error += fs2us(fi.Name);
124 continue;
125 }
126
127 const UString shortName = fs2us(fi.Name.Left(pos));
128
129 CLangListRecord listRecord;
130 if (!names.IsEmpty())
131 {
132 for (unsigned i = 0; i < names.Size(); i++)
133 if (shortName.IsEqualTo_Ascii_NoCase(names[i]))
134 {
135 if (subLangIndex == i || names.Size() == 1)
136 {
137 listRecord.Mark = "***";
138 // listRecord.Order = 1;
139 }
140 else
141 {
142 listRecord.Mark = "+++";
143 // listRecord.Order = 2;
144 }
145 break;
146 }
147 if (listRecord.Mark.IsEmpty())
148 {
149 const int minusPos = shortName.Find(L'-');
150 if (minusPos >= 0)
151 {
152 const UString shortName2 = shortName.Left(minusPos);
153 if (shortName2.IsEqualTo_Ascii_NoCase(names[0]))
154 {
155 listRecord.Mark = "+++";
156 // listRecord.Order = 3;
157 }
158 }
159 }
160 }
161 UString s = shortName;
162 const wchar_t *eng = lang.Get(IDS_LANG_ENGLISH);
163 if (eng)
164 s = eng;
165 const wchar_t *native = lang.Get(IDS_LANG_NATIVE);
166 if (native)
167 NativeLangString(s, native);
168
169 listRecord.Name = s;
170 listRecord.LangInfoIndex = _langs.Size();
171 listRecords.Add(listRecord);
172 if (g_LangID.IsEqualTo_NoCase(shortName))
173 listRecords_SelectedIndex = listRecords.Size() - 1;
174
175 CLangInfo &langInfo = _langs.AddNew();
176 langInfo.Comments = lang.Comments;
177 langInfo.Name = shortName;
178 unsigned numLines = lang._ids.Size();
179 if (!lang_en.IsEmpty())
180 {
181 numLines = 0;
182 unsigned i1 = 0;
183 unsigned i2 = 0;
184 for (;;)
185 {
186 UInt32 id1 = (UInt32)0 - 1;
187 UInt32 id2 = (UInt32)0 - 1;
188 bool id1_defined = false;
189 bool id2_defined = false;
190 if (i1 < lang_en._ids.Size())
191 {
192 id1 = lang_en._ids[i1];
193 id1_defined = true;
194 }
195 if (i2 < lang._ids.Size())
196 {
197 id2 = lang._ids[i2];
198 id2_defined = true;
199 }
200
201 bool id1_is_smaller = true;
202 if (id1_defined)
203 {
204 if (id2_defined)
205 {
206 if (id1 == id2)
207 {
208 i1++;
209 i2++;
210 numLines++;
211 continue;
212 }
213 if (id1 > id2)
214 id1_is_smaller = false;
215 }
216 }
217 else if (!id2_defined)
218 break;
219 else
220 id1_is_smaller = false;
221
222 n.Empty();
223 if (id1_is_smaller)
224 {
225 n.Add_UInt32(id1);
226 n += " : ";
227 n += lang_en.Get_by_index(i1);
228 langInfo.MissingLines.Add(n);
229 i1++;
230 }
231 else
232 {
233 n.Add_UInt32(id2);
234 n += " : ";
235 n += lang.Get_by_index(i2);
236 langInfo.ExtraLines.Add(n);
237 i2++;
238 }
239 }
240 }
241 langInfo.NumLines = numLines + langInfo.ExtraLines.Size();
242 }
243
244 listRecords[listRecords_SelectedIndex].IsSelected = true;
245
246 listRecords.Sort();
247 FOR_VECTOR (i, listRecords)
248 {
249 const CLangListRecord &rec= listRecords[i];
250 UString temp = rec.Name;
251 if (!rec.Mark.IsEmpty())
252 {
253 temp += " ";
254 temp += rec.Mark;
255 }
256 const int index = (int)_langCombo.AddString(temp);
257 _langCombo.SetItemData(index, (LPARAM)rec.LangInfoIndex);
258 if (rec.IsSelected)
259 _langCombo.SetCurSel(index);
260 }
261
262 ShowLangInfo();
263
264 if (!error.IsEmpty())
265 MessageBoxW(NULL, error, L"Error in Lang file", MB_ICONERROR);
266 return CPropertyPage::OnInit();
267 }
268
OnApply()269 LONG CLangPage::OnApply()
270 {
271 if (_needSave)
272 {
273 const int pathIndex = (int)_langCombo.GetItemData_of_CurSel();
274 if ((unsigned)pathIndex < _langs.Size())
275 SaveRegLang(_langs[pathIndex].Name);
276 }
277 _needSave = false;
278 #ifdef Z7_LANG
279 ReloadLang();
280 #endif
281 LangWasChanged = true;
282 return PSNRET_NOERROR;
283 }
284
OnNotifyHelp()285 void CLangPage::OnNotifyHelp()
286 {
287 ShowHelpWindow(kLangTopic);
288 }
289
OnCommand(unsigned code,unsigned itemID,LPARAM param)290 bool CLangPage::OnCommand(unsigned code, unsigned itemID, LPARAM param)
291 {
292 if (code == CBN_SELCHANGE && itemID == IDC_LANG_LANG)
293 {
294 _needSave = true;
295 Changed();
296 ShowLangInfo();
297 return true;
298 }
299 return CPropertyPage::OnCommand(code, itemID, param);
300 }
301
AddVectorToString(UString & s,const UStringVector & v)302 static void AddVectorToString(UString &s, const UStringVector &v)
303 {
304 UString a;
305 FOR_VECTOR (i, v)
306 {
307 if (i >= 50)
308 break;
309 a = v[i];
310 if (a.Len() > 1500)
311 continue;
312 if (a[0] == ';')
313 {
314 a.DeleteFrontal(1);
315 a.Trim();
316 }
317 s += a;
318 s.Add_LF();
319 }
320 }
321
AddVectorToString2(UString & s,const char * name,const UStringVector & v)322 static void AddVectorToString2(UString &s, const char *name, const UStringVector &v)
323 {
324 if (v.IsEmpty())
325 return;
326 s.Add_LF();
327 s += "------ ";
328 s += name;
329 s += ": ";
330 s.Add_UInt32(v.Size());
331 s += " :";
332 s.Add_LF();
333 AddVectorToString(s, v);
334 }
335
ShowLangInfo()336 void CLangPage::ShowLangInfo()
337 {
338 UString s;
339 const int pathIndex = (int)_langCombo.GetItemData_of_CurSel();
340 if ((unsigned)pathIndex < _langs.Size())
341 {
342 const CLangInfo &langInfo = _langs[pathIndex];
343 const unsigned numLines = langInfo.NumLines;
344 s += langInfo.Name;
345 s += " : ";
346 s.Add_UInt32(numLines);
347 if (NumLangLines_EN != 0)
348 {
349 s += " / ";
350 s.Add_UInt32(NumLangLines_EN);
351 s += " = ";
352 s.Add_UInt32(numLines * 100 / NumLangLines_EN);
353 s += "%";
354 }
355 s.Add_LF();
356 AddVectorToString(s, langInfo.Comments);
357 AddVectorToString2(s, "Missing lines", langInfo.MissingLines);
358 AddVectorToString2(s, "Extra lines", langInfo.ExtraLines);
359 }
360 SetItemText(IDT_LANG_INFO, s);
361 }
362