1 // LangUtils.cpp
2
3 #include "StdAfx.h"
4
5 #include "../../../Common/Lang.h"
6
7 #include "../../../Windows/DLL.h"
8 #include "../../../Windows/Synchronization.h"
9 #include "../../../Windows/Window.h"
10
11 #include "LangUtils.h"
12 #include "RegistryUtils.h"
13
14 using namespace NWindows;
15
16 #ifndef _UNICODE
17 extern bool g_IsNT;
18 #endif
19
20 UString g_LangID;
21
22 // static
23 CLang g_Lang;
24 static bool g_Loaded = false;
25 static NSynchronization::CCriticalSection g_CriticalSection;
26
27 bool LangOpen(CLang &lang, CFSTR fileName);
LangOpen(CLang & lang,CFSTR fileName)28 bool LangOpen(CLang &lang, CFSTR fileName)
29 {
30 return lang.Open(fileName, "7-Zip");
31 }
32
GetLangDirPrefix()33 FString GetLangDirPrefix()
34 {
35 return NDLL::GetModuleDirPrefix() + FTEXT("Lang") FSTRING_PATH_SEPARATOR;
36 }
37
38 #ifdef Z7_LANG
39
LoadLangOneTime()40 void LoadLangOneTime()
41 {
42 NSynchronization::CCriticalSectionLock lock(g_CriticalSection);
43 if (g_Loaded)
44 return;
45 g_Loaded = true;
46 ReloadLang();
47 }
48
LangSetDlgItemText(HWND dialog,UInt32 controlID,UInt32 langID)49 void LangSetDlgItemText(HWND dialog, UInt32 controlID, UInt32 langID)
50 {
51 const wchar_t *s = g_Lang.Get(langID);
52 if (s)
53 {
54 CWindow window(GetDlgItem(dialog, (int)controlID));
55 window.SetText(s);
56 }
57 }
58
59 #ifndef IDCONTINUE
60 #define IDCONTINUE 11
61 #endif
62
63 static const CIDLangPair kLangPairs[] =
64 {
65 { IDOK, 401 },
66 { IDCANCEL, 402 },
67 { IDYES, 406 },
68 { IDNO, 407 },
69 { IDCLOSE, 408 },
70 { IDHELP, 409 },
71 { IDCONTINUE, 411 }
72 };
73
74
LangSetDlgItems(HWND dialog,const UInt32 * ids,unsigned numItems)75 void LangSetDlgItems(HWND dialog, const UInt32 *ids, unsigned numItems)
76 {
77 unsigned i;
78 for (i = 0; i < Z7_ARRAY_SIZE(kLangPairs); i++)
79 {
80 const CIDLangPair &pair = kLangPairs[i];
81 CWindow window(GetDlgItem(dialog, (int)pair.ControlID));
82 if (window)
83 {
84 const wchar_t *s = g_Lang.Get(pair.LangID);
85 if (s)
86 window.SetText(s);
87 }
88 }
89
90 for (i = 0; i < numItems; i++)
91 {
92 const UInt32 id = ids[i];
93 LangSetDlgItemText(dialog, id, id);
94 }
95 }
96
LangSetDlgItems_Colon(HWND dialog,const UInt32 * ids,unsigned numItems)97 void LangSetDlgItems_Colon(HWND dialog, const UInt32 *ids, unsigned numItems)
98 {
99 for (unsigned i = 0; i < numItems; i++)
100 {
101 const UInt32 id = ids[i];
102 const wchar_t *s = g_Lang.Get(id);
103 if (s)
104 {
105 CWindow window(GetDlgItem(dialog, (int)id));
106 UString s2 = s;
107 s2.Add_Colon();
108 window.SetText(s2);
109 }
110 }
111 }
112
LangSetDlgItems_RemoveColon(HWND dialog,const UInt32 * ids,unsigned numItems)113 void LangSetDlgItems_RemoveColon(HWND dialog, const UInt32 *ids, unsigned numItems)
114 {
115 for (unsigned i = 0; i < numItems; i++)
116 {
117 const UInt32 id = ids[i];
118 const wchar_t *s = g_Lang.Get(id);
119 if (s)
120 {
121 CWindow window(GetDlgItem(dialog, (int)id));
122 UString s2 = s;
123 if (!s2.IsEmpty() && s2.Back() == ':')
124 s2.DeleteBack();
125 window.SetText(s2);
126 }
127 }
128 }
129
LangSetWindowText(HWND window,UInt32 langID)130 void LangSetWindowText(HWND window, UInt32 langID)
131 {
132 const wchar_t *s = g_Lang.Get(langID);
133 if (s)
134 MySetWindowText(window, s);
135 }
136
LangString(UInt32 langID)137 UString LangString(UInt32 langID)
138 {
139 const wchar_t *s = g_Lang.Get(langID);
140 if (s)
141 return s;
142 return MyLoadString(langID);
143 }
144
AddLangString(UString & s,UInt32 langID)145 void AddLangString(UString &s, UInt32 langID)
146 {
147 s += LangString(langID);
148 }
149
LangString(UInt32 langID,UString & dest)150 void LangString(UInt32 langID, UString &dest)
151 {
152 const wchar_t *s = g_Lang.Get(langID);
153 if (s)
154 {
155 dest = s;
156 return;
157 }
158 MyLoadString(langID, dest);
159 }
160
LangString_OnlyFromLangFile(UInt32 langID,UString & dest)161 void LangString_OnlyFromLangFile(UInt32 langID, UString &dest)
162 {
163 dest.Empty();
164 const wchar_t *s = g_Lang.Get(langID);
165 if (s)
166 dest = s;
167 }
168
169 static const char * const kLangs =
170 "ar.bg.ca.zh.-tw.-cn.cs.da.de.el.en.es.fi.fr.he.hu.is."
171 "it.ja.ko.nl.no.=nb.=nn.pl.pt.-br.rm.ro.ru.sr.=hr.-spl.-spc.=hr.=bs.sk.sq.sv.th.tr."
172 "ur.id.uk.be.sl.et.lv.lt.tg.fa.vi.hy.az.eu.hsb.mk."
173 "st.ts.tn.ve.xh.zu.af.ka.fo.hi.mt.se.ga.yi.ms.kk."
174 "ky.sw.tk.uz.-latn.-cyrl.tt.bn.pa.-in.gu.or.ta.te.kn.ml.as.mr.sa."
175 "mn.=mn.=mng.bo.cy.kh.lo.my.gl.kok..sd.syr.si..iu.am.tzm."
176 "ks.ne.fy.ps.tl.dv..ff.ha..yo.qu.st.ba.lb.kl."
177 "ig.kr.om.ti.gn..la.so.ii..arn..moh..br.."
178 "ug.mi.oc.co."
179 // "gsw.sah.qut.rw.wo....prs...."
180 // ".gd."
181 ;
182
FindShortNames(UInt32 primeLang,AStringVector & names)183 static void FindShortNames(UInt32 primeLang, AStringVector &names)
184 {
185 UInt32 index = 0;
186 for (const char *p = kLangs; *p != 0;)
187 {
188 const char *p2 = p;
189 for (; *p2 != '.'; p2++);
190 bool isSub = (p[0] == '-' || p[0] == '=');
191 if (!isSub)
192 index++;
193 if (index >= primeLang)
194 {
195 if (index > primeLang)
196 break;
197 AString s;
198 if (isSub)
199 {
200 if (p[0] == '-')
201 s = names[0];
202 else
203 p++;
204 }
205 while (p != p2)
206 s.Add_Char((char)(Byte)*p++);
207 names.Add(s);
208 }
209 p = p2 + 1;
210 }
211 }
212
213 /*
214 #include "../../../Common/IntToString.h"
215
216 static struct CC1Lang
217 {
218 CC1Lang()
219 {
220 for (int i = 1; i < 150; i++)
221 {
222 UString s;
223 char ttt[32];
224 ConvertUInt32ToHex(i, ttt);
225 s += ttt;
226 UStringVector names;
227 FindShortNames(i, names);
228
229 FOR_VECTOR (k, names)
230 {
231 s.Add_Space();
232 s += names[k];
233 }
234 OutputDebugStringW(s);
235 }
236 }
237 } g_cc1;
238 */
239
240 // typedef LANGID (WINAPI *GetUserDefaultUILanguageP)();
241
Lang_GetShortNames_for_DefaultLang(AStringVector & names,unsigned & subLang)242 void Lang_GetShortNames_for_DefaultLang(AStringVector &names, unsigned &subLang)
243 {
244 names.Clear();
245 subLang = 0;
246 // Region / Administative / Language for non-Unicode programs:
247 const LANGID sysLang = GetSystemDefaultLangID();
248
249 // Region / Formats / Format:
250 const LANGID userLang = GetUserDefaultLangID();
251
252 if (PRIMARYLANGID(sysLang) !=
253 PRIMARYLANGID(userLang))
254 return;
255 const LANGID langID = userLang;
256
257 // const LANGID langID = MAKELANGID(0x1a, 1); // for debug
258
259 /*
260 LANGID sysUILang; // english in XP64
261 LANGID userUILang; // english in XP64
262
263 GetUserDefaultUILanguageP fn = (GetUserDefaultUILanguageP)GetProcAddress(
264 GetModuleHandle("kernel32"), "GetUserDefaultUILanguage");
265 if (fn)
266 userUILang = fn();
267 fn = (GetUserDefaultUILanguageP)GetProcAddress(
268 GetModuleHandle("kernel32"), "GetSystemDefaultUILanguage");
269 if (fn)
270 sysUILang = fn();
271 */
272
273 const WORD primLang = (WORD)(PRIMARYLANGID(langID));
274 subLang = SUBLANGID(langID);
275 FindShortNames(primLang, names);
276 }
277
278
OpenDefaultLang()279 static void OpenDefaultLang()
280 {
281 AStringVector names;
282 unsigned subLang;
283 Lang_GetShortNames_for_DefaultLang(names, subLang);
284 {
285 const FString dirPrefix (GetLangDirPrefix());
286 for (unsigned i = 0; i < 2; i++)
287 {
288 const unsigned index = (i == 0 ? subLang : 0);
289 if (index < names.Size())
290 {
291 const AString &name = names[index];
292 if (!name.IsEmpty())
293 {
294 FString path (dirPrefix);
295 path += name;
296 path += ".txt";
297 if (LangOpen(g_Lang, path))
298 {
299 g_LangID = name;
300 return;
301 }
302 }
303 }
304 }
305 }
306 }
307
ReloadLang()308 void ReloadLang()
309 {
310 g_Lang.Clear();
311 ReadRegLang(g_LangID);
312 #ifndef _UNICODE
313 if (g_IsNT)
314 #endif
315 {
316 if (g_LangID.IsEmpty())
317 {
318 OpenDefaultLang();
319 return;
320 }
321 }
322 if (g_LangID.Len() > 1 || g_LangID[0] != L'-')
323 {
324 FString s = us2fs(g_LangID);
325 if (s.ReverseFind_PathSepar() < 0)
326 {
327 if (s.ReverseFind_Dot() < 0)
328 s += ".txt";
329 s.Insert(0, GetLangDirPrefix());
330 LangOpen(g_Lang, s);
331 }
332 }
333 }
334
335 #endif
336