Synced ResText with TortoiseSVN
[TortoiseGit.git] / src / ResText / ResModule.cpp
blobe35b69f3bc89c86c61d7f57e8bf22b767a5ba7e1
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2003-2008, 2010-2012 - TortoiseSVN
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software Foundation,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 #include "stdafx.h"
19 #include "Utils.h"
20 #include "resmodule.h"
21 #include "..\Utils\SysInfo.h"
22 #include <regex>
23 #include <memory>
25 #ifndef RT_RIBBON
26 #define RT_RIBBON MAKEINTRESOURCE(28)
27 #endif
30 #define MYERROR {CUtils::Error(); return FALSE;}
32 CResModule::CResModule(void)
33 : m_bTranslatedStrings(0)
34 , m_bDefaultStrings(0)
35 , m_bTranslatedDialogStrings(0)
36 , m_bDefaultDialogStrings(0)
37 , m_bTranslatedMenuStrings(0)
38 , m_bDefaultMenuStrings(0)
39 , m_bTranslatedAcceleratorStrings(0)
40 , m_bDefaultAcceleratorStrings(0)
41 , m_bTranslatedRibbonTexts(0)
42 , m_bDefaultRibbonTexts(0)
43 , m_wTargetLang(0)
44 , m_hResDll(NULL)
45 , m_hUpdateRes(NULL)
46 , m_bQuiet(false)
47 , m_bRTL(false)
48 , m_bAdjustEOLs(false)
52 CResModule::~CResModule(void)
56 BOOL CResModule::ExtractResources(std::vector<std::wstring> filelist, LPCTSTR lpszPOFilePath, BOOL bNoUpdate, LPCTSTR lpszHeaderFile)
58 for (std::vector<std::wstring>::iterator I = filelist.begin(); I != filelist.end(); ++I)
60 m_hResDll = LoadLibraryEx(I->c_str(), NULL, LOAD_LIBRARY_AS_IMAGE_RESOURCE|LOAD_LIBRARY_AS_DATAFILE);
61 if (m_hResDll == NULL)
62 MYERROR;
64 size_t nEntries = m_StringEntries.size();
65 // fill in the std::map with all translatable entries
67 if (!m_bQuiet)
68 _ftprintf(stdout, _T("Extracting StringTable...."));
69 EnumResourceNames(m_hResDll, RT_STRING, EnumResNameCallback, (LONG_PTR)this);
70 if (!m_bQuiet)
71 _ftprintf(stdout, _T("%4d Strings\n"), m_StringEntries.size()-nEntries);
72 nEntries = m_StringEntries.size();
74 if (!m_bQuiet)
75 _ftprintf(stdout, _T("Extracting Dialogs........"));
76 EnumResourceNames(m_hResDll, RT_DIALOG, EnumResNameCallback, (LONG_PTR)this);
77 if (!m_bQuiet)
78 _ftprintf(stdout, _T("%4d Strings\n"), m_StringEntries.size()-nEntries);
79 nEntries = m_StringEntries.size();
81 if (!m_bQuiet)
82 _ftprintf(stdout, _T("Extracting Menus.........."));
83 EnumResourceNames(m_hResDll, RT_MENU, EnumResNameCallback, (LONG_PTR)this);
84 if (!m_bQuiet)
85 _ftprintf(stdout, _T("%4d Strings\n"), m_StringEntries.size()-nEntries);
86 nEntries = m_StringEntries.size();
87 if (!m_bQuiet)
88 _ftprintf(stdout, _T("Extracting Accelerators..."));
89 EnumResourceNames(m_hResDll, RT_ACCELERATOR, EnumResNameCallback, (LONG_PTR)this);
90 if (!m_bQuiet)
91 _ftprintf(stdout, _T("%4d Accelerators\n"), m_StringEntries.size()-nEntries);
92 nEntries = m_StringEntries.size();
93 if (!m_bQuiet)
94 _ftprintf(stdout, _T("Extracting Ribbons........"));
95 EnumResourceNames(m_hResDll, RT_RIBBON, EnumResNameCallback, (LONG_PTR)this);
96 if (!m_bQuiet)
97 _ftprintf(stdout, _T("%4d Strings\n"), m_StringEntries.size()-nEntries);
98 nEntries = m_StringEntries.size();
100 // parse a probably existing file and update the translations which are
101 // already done
102 m_StringEntries.ParseFile(lpszPOFilePath, !bNoUpdate, m_bAdjustEOLs);
104 FreeLibrary(m_hResDll);
107 // at last, save the new file
108 return m_StringEntries.SaveFile(lpszPOFilePath, lpszHeaderFile);
111 BOOL CResModule::ExtractResources(LPCTSTR lpszSrcLangDllPath, LPCTSTR lpszPoFilePath, BOOL bNoUpdate, LPCTSTR lpszHeaderFile)
113 m_hResDll = LoadLibraryEx(lpszSrcLangDllPath, NULL, LOAD_LIBRARY_AS_IMAGE_RESOURCE|LOAD_LIBRARY_AS_DATAFILE);
114 if (m_hResDll == NULL)
115 MYERROR;
117 size_t nEntries = 0;
118 // fill in the std::map with all translatable entries
120 if (!m_bQuiet)
121 _ftprintf(stdout, _T("Extracting StringTable...."));
122 EnumResourceNames(m_hResDll, RT_STRING, EnumResNameCallback, (LONG_PTR)this);
123 if (!m_bQuiet)
124 _ftprintf(stdout, _T("%4d Strings\n"), m_StringEntries.size());
125 nEntries = m_StringEntries.size();
127 if (!m_bQuiet)
128 _ftprintf(stdout, _T("Extracting Dialogs........"));
129 EnumResourceNames(m_hResDll, RT_DIALOG, EnumResNameCallback, (LONG_PTR)this);
130 if (!m_bQuiet)
131 _ftprintf(stdout, _T("%4d Strings\n"), m_StringEntries.size()-nEntries);
132 nEntries = m_StringEntries.size();
134 if (!m_bQuiet)
135 _ftprintf(stdout, _T("Extracting Menus.........."));
136 EnumResourceNames(m_hResDll, RT_MENU, EnumResNameCallback, (LONG_PTR)this);
137 if (!m_bQuiet)
138 _ftprintf(stdout, _T("%4d Strings\n"), m_StringEntries.size()-nEntries);
139 nEntries = m_StringEntries.size();
141 if (!m_bQuiet)
142 _ftprintf(stdout, _T("Extracting Accelerators..."));
143 EnumResourceNames(m_hResDll, RT_ACCELERATOR, EnumResNameCallback, (LONG_PTR)this);
144 if (!m_bQuiet)
145 _ftprintf(stdout, _T("%4d Accelerators\n"), m_StringEntries.size()-nEntries);
146 nEntries = m_StringEntries.size();
148 // parse a probably existing file and update the translations which are
149 // already done
150 m_StringEntries.ParseFile(lpszPoFilePath, !bNoUpdate, m_bAdjustEOLs);
152 // at last, save the new file
153 if (!m_StringEntries.SaveFile(lpszPoFilePath, lpszHeaderFile))
154 goto DONE_ERROR;
156 FreeLibrary(m_hResDll);
157 return TRUE;
159 DONE_ERROR:
160 if (m_hResDll)
161 FreeLibrary(m_hResDll);
162 return FALSE;
165 BOOL CResModule::CreateTranslatedResources(LPCTSTR lpszSrcLangDllPath, LPCTSTR lpszDestLangDllPath, LPCTSTR lpszPOFilePath)
167 if (!CopyFile(lpszSrcLangDllPath, lpszDestLangDllPath, FALSE))
168 MYERROR;
170 int count = 0;
173 if (SysInfo::Instance().IsVistaOrLater())
174 m_hResDll = LoadLibraryEx (lpszSrcLangDllPath, NULL, LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE|LOAD_LIBRARY_AS_IMAGE_RESOURCE|LOAD_IGNORE_CODE_AUTHZ_LEVEL);
175 else
176 m_hResDll = LoadLibraryEx (lpszSrcLangDllPath, NULL, LOAD_LIBRARY_AS_IMAGE_RESOURCE|LOAD_IGNORE_CODE_AUTHZ_LEVEL);
177 if (m_hResDll == NULL)
178 Sleep(100);
179 count++;
180 } while ((m_hResDll == NULL)&&(count < 10));
182 if (m_hResDll == NULL)
183 MYERROR;
185 sDestFile = std::wstring(lpszDestLangDllPath);
187 // get all translated strings
188 if (!m_StringEntries.ParseFile(lpszPOFilePath, FALSE, m_bAdjustEOLs))
189 goto DONE_ERROR;
190 m_bTranslatedStrings = 0;
191 m_bDefaultStrings = 0;
192 m_bTranslatedDialogStrings = 0;
193 m_bDefaultDialogStrings = 0;
194 m_bTranslatedMenuStrings = 0;
195 m_bDefaultMenuStrings = 0;
196 m_bTranslatedAcceleratorStrings = 0;
197 m_bDefaultAcceleratorStrings = 0;
199 BOOL bRes = FALSE;
200 count = 0;
203 m_hUpdateRes = BeginUpdateResource(sDestFile.c_str(), FALSE);
204 if (m_hUpdateRes == NULL)
205 Sleep(100);
206 count++;
207 } while ((m_hUpdateRes == NULL)&&(count < 10));
209 if (m_hUpdateRes == NULL)
210 MYERROR;
213 if (!m_bQuiet)
214 _ftprintf(stdout, _T("Translating StringTable..."));
215 bRes = EnumResourceNames(m_hResDll, RT_STRING, EnumResNameWriteCallback, (LONG_PTR)this);
216 if (!m_bQuiet)
217 _ftprintf(stdout, _T("%4d translated, %4d not translated\n"), m_bTranslatedStrings, m_bDefaultStrings);
219 if (!m_bQuiet)
220 _ftprintf(stdout, _T("Translating Dialogs......."));
221 bRes = EnumResourceNames(m_hResDll, RT_DIALOG, EnumResNameWriteCallback, (LONG_PTR)this);
222 if (!m_bQuiet)
223 _ftprintf(stdout, _T("%4d translated, %4d not translated\n"), m_bTranslatedDialogStrings, m_bDefaultDialogStrings);
225 if (!m_bQuiet)
226 _ftprintf(stdout, _T("Translating Menus........."));
227 bRes = EnumResourceNames(m_hResDll, RT_MENU, EnumResNameWriteCallback, (LONG_PTR)this);
228 if (!m_bQuiet)
229 _ftprintf(stdout, _T("%4d translated, %4d not translated\n"), m_bTranslatedMenuStrings, m_bDefaultMenuStrings);
231 if (!m_bQuiet)
232 _ftprintf(stdout, _T("Translating Accelerators.."));
233 bRes = EnumResourceNames(m_hResDll, RT_ACCELERATOR, EnumResNameWriteCallback, (LONG_PTR)this);
234 if (!m_bQuiet)
235 _ftprintf(stdout, _T("%4d translated, %4d not translated\n"), m_bTranslatedAcceleratorStrings, m_bDefaultAcceleratorStrings);
237 if (!m_bQuiet)
238 _ftprintf(stdout, _T("Translating Ribbons......."));
239 bRes = EnumResourceNames(m_hResDll, RT_RIBBON, EnumResNameWriteCallback, (LONG_PTR)this);
240 if (!m_bQuiet)
241 _ftprintf(stdout, _T("%4d translated, %4d not translated\n"), m_bTranslatedRibbonTexts, m_bDefaultRibbonTexts);
242 bRes = TRUE;
243 if (!EndUpdateResource(m_hUpdateRes, !bRes))
244 MYERROR;
246 FreeLibrary(m_hResDll);
247 return TRUE;
248 DONE_ERROR:
249 if (m_hResDll)
250 FreeLibrary(m_hResDll);
251 return FALSE;
254 BOOL CResModule::ExtractString(LPCTSTR lpszType)
256 HRSRC hrsrc = FindResource(m_hResDll, lpszType, RT_STRING);
257 HGLOBAL hglStringTable;
258 LPWSTR p;
260 if (!hrsrc)
261 MYERROR;
262 hglStringTable = LoadResource(m_hResDll, hrsrc);
264 if (!hglStringTable)
265 goto DONE_ERROR;
266 p = (LPWSTR)LockResource(hglStringTable);
268 if (p == NULL)
269 goto DONE_ERROR;
270 /* [Block of 16 strings. The strings are Pascal style with a WORD
271 length preceding the string. 16 strings are always written, even
272 if not all slots are full. Any slots in the block with no string
273 have a zero WORD for the length.]
276 //first check how much memory we need
277 LPWSTR pp = p;
278 for (int i=0; i<16; ++i)
280 int len = GET_WORD(pp);
281 pp++;
282 std::wstring msgid = std::wstring(pp, len);
283 WCHAR * pBuf = new WCHAR[MAX_STRING_LENGTH*2];
284 SecureZeroMemory(pBuf, MAX_STRING_LENGTH*2*sizeof(WCHAR));
285 wcscpy(pBuf, msgid.c_str());
286 CUtils::StringExtend(pBuf);
288 if (wcslen(pBuf))
290 std::wstring str = std::wstring(pBuf);
291 RESOURCEENTRY entry = m_StringEntries[str];
292 entry.resourceIDs.insert((DWORD)lpszType);
293 if (wcschr(str.c_str(), '%'))
294 entry.flag = _T("#, c-format");
295 m_StringEntries[str] = entry;
297 delete [] pBuf;
298 pp += len;
300 UnlockResource(hglStringTable);
301 FreeResource(hglStringTable);
302 return TRUE;
303 DONE_ERROR:
304 UnlockResource(hglStringTable);
305 FreeResource(hglStringTable);
306 MYERROR;
309 BOOL CResModule::ReplaceString(LPCTSTR lpszType, WORD wLanguage)
311 HRSRC hrsrc = FindResourceEx(m_hResDll, RT_STRING, lpszType, wLanguage);
312 HGLOBAL hglStringTable;
313 LPWSTR p;
315 if (!hrsrc)
316 MYERROR;
317 hglStringTable = LoadResource(m_hResDll, hrsrc);
319 if (!hglStringTable)
320 goto DONE_ERROR;
321 p = (LPWSTR)LockResource(hglStringTable);
323 if (p == NULL)
324 goto DONE_ERROR;
325 /* [Block of 16 strings. The strings are Pascal style with a WORD
326 length preceding the string. 16 strings are always written, even
327 if not all slots are full. Any slots in the block with no string
328 have a zero WORD for the length.]
331 //first check how much memory we need
332 size_t nMem = 0;
333 LPWSTR pp = p;
334 for (int i=0; i<16; ++i)
336 nMem++;
337 size_t len = GET_WORD(pp);
338 pp++;
339 std::wstring msgid = std::wstring(pp, len);
340 WCHAR * pBuf = new WCHAR[MAX_STRING_LENGTH*2];
341 SecureZeroMemory(pBuf, MAX_STRING_LENGTH*2*sizeof(WCHAR));
342 wcscpy(pBuf, msgid.c_str());
343 CUtils::StringExtend(pBuf);
344 msgid = std::wstring(pBuf);
346 RESOURCEENTRY resEntry;
347 resEntry = m_StringEntries[msgid];
348 wcscpy(pBuf, resEntry.msgstr.c_str());
349 CUtils::StringCollapse(pBuf);
350 size_t newlen = wcslen(pBuf);
351 if (newlen)
352 nMem += newlen;
353 else
354 nMem += len;
355 pp += len;
356 delete [] pBuf;
359 WORD * newTable = new WORD[nMem + (nMem % 2)];
360 SecureZeroMemory(newTable, (nMem + (nMem % 2))*2);
362 size_t index = 0;
363 for (int i=0; i<16; ++i)
365 int len = GET_WORD(p);
366 p++;
367 std::wstring msgid = std::wstring(p, len);
368 WCHAR * pBuf = new WCHAR[MAX_STRING_LENGTH*2];
369 SecureZeroMemory(pBuf, MAX_STRING_LENGTH*2*sizeof(WCHAR));
370 wcscpy(pBuf, msgid.c_str());
371 CUtils::StringExtend(pBuf);
372 msgid = std::wstring(pBuf);
374 RESOURCEENTRY resEntry;
375 resEntry = m_StringEntries[msgid];
376 wcscpy(pBuf, resEntry.msgstr.c_str());
377 CUtils::StringCollapse(pBuf);
378 size_t newlen = wcslen(pBuf);
379 if (newlen)
381 newTable[index++] = (WORD)newlen;
382 wcsncpy((wchar_t *)&newTable[index], pBuf, newlen);
383 index += newlen;
384 m_bTranslatedStrings++;
386 else
388 newTable[index++] = (WORD)len;
389 if (len)
390 wcsncpy((wchar_t *)&newTable[index], p, len);
391 index += len;
392 if (len)
393 m_bDefaultStrings++;
395 p += len;
396 delete [] pBuf;
399 if (!UpdateResource(m_hUpdateRes, RT_STRING, lpszType, (m_wTargetLang ? m_wTargetLang : wLanguage), newTable, (DWORD)(nMem + (nMem % 2))*2))
401 delete [] newTable;
402 goto DONE_ERROR;
405 if ((m_wTargetLang)&&(!UpdateResource(m_hUpdateRes, RT_STRING, lpszType, wLanguage, NULL, 0)))
407 delete [] newTable;
408 goto DONE_ERROR;
410 delete [] newTable;
411 UnlockResource(hglStringTable);
412 FreeResource(hglStringTable);
413 return TRUE;
414 DONE_ERROR:
415 UnlockResource(hglStringTable);
416 FreeResource(hglStringTable);
417 MYERROR;
420 BOOL CResModule::ExtractMenu(LPCTSTR lpszType)
422 HRSRC hrsrc = FindResource(m_hResDll, lpszType, RT_MENU);
423 HGLOBAL hglMenuTemplate;
424 WORD version, offset;
425 const WORD *p, *p0;
427 if (!hrsrc)
428 MYERROR;
430 hglMenuTemplate = LoadResource(m_hResDll, hrsrc);
432 if (!hglMenuTemplate)
433 MYERROR;
435 p = (const WORD*)LockResource(hglMenuTemplate);
437 if (p == NULL)
438 MYERROR;
440 // Standard MENU resource
441 //struct MenuHeader {
442 // WORD wVersion; // Currently zero
443 // WORD cbHeaderSize; // Also zero
444 //};
446 // MENUEX resource
447 //struct MenuExHeader {
448 // WORD wVersion; // One
449 // WORD wOffset;
450 // DWORD dwHelpId;
451 //};
452 p0 = p;
453 version = GET_WORD(p);
455 p++;
457 switch (version)
459 case 0:
461 offset = GET_WORD(p);
462 p += offset;
463 p++;
464 if (!ParseMenuResource(p))
465 goto DONE_ERROR;
467 break;
468 case 1:
470 offset = GET_WORD(p);
471 p++;
472 //dwHelpId = GET_DWORD(p);
473 if (!ParseMenuExResource(p0 + offset))
474 goto DONE_ERROR;
476 break;
477 default:
478 goto DONE_ERROR;
481 UnlockResource(hglMenuTemplate);
482 FreeResource(hglMenuTemplate);
483 return TRUE;
485 DONE_ERROR:
486 UnlockResource(hglMenuTemplate);
487 FreeResource(hglMenuTemplate);
488 MYERROR;
491 BOOL CResModule::ReplaceMenu(LPCTSTR lpszType, WORD wLanguage)
493 HRSRC hrsrc = FindResourceEx(m_hResDll, RT_MENU, lpszType, wLanguage);
494 HGLOBAL hglMenuTemplate;
495 WORD version, offset;
496 LPWSTR p;
497 WORD *p0;
499 if (!hrsrc)
500 MYERROR; //just the language wasn't found
502 hglMenuTemplate = LoadResource(m_hResDll, hrsrc);
504 if (!hglMenuTemplate)
505 MYERROR;
507 p = (LPWSTR)LockResource(hglMenuTemplate);
509 if (p == NULL)
510 MYERROR;
512 //struct MenuHeader {
513 // WORD wVersion; // Currently zero
514 // WORD cbHeaderSize; // Also zero
515 //};
517 // MENUEX resource
518 //struct MenuExHeader {
519 // WORD wVersion; // One
520 // WORD wOffset;
521 // DWORD dwHelpId;
522 //};
523 p0 = (WORD *)p;
524 version = GET_WORD(p);
526 p++;
528 switch (version)
530 case 0:
532 offset = GET_WORD(p);
533 p += offset;
534 p++;
535 size_t nMem = 0;
536 if (!CountMemReplaceMenuResource((WORD *)p, &nMem, NULL))
537 goto DONE_ERROR;
538 WORD * newMenu = new WORD[nMem + (nMem % 2)+2];
539 SecureZeroMemory(newMenu, (nMem + (nMem % 2)+2)*2);
540 size_t index = 2; // MenuHeader has 2 WORDs zero
541 if (!CountMemReplaceMenuResource((WORD *)p, &index, newMenu))
543 delete [] newMenu;
544 goto DONE_ERROR;
547 if (!UpdateResource(m_hUpdateRes, RT_MENU, lpszType, (m_wTargetLang ? m_wTargetLang : wLanguage), newMenu, (DWORD)(nMem + (nMem % 2)+2)*2))
549 delete [] newMenu;
550 goto DONE_ERROR;
553 if ((m_wTargetLang)&&(!UpdateResource(m_hUpdateRes, RT_MENU, lpszType, wLanguage, NULL, 0)))
555 delete [] newMenu;
556 goto DONE_ERROR;
558 delete [] newMenu;
560 break;
561 case 1:
563 offset = GET_WORD(p);
564 p++;
565 //dwHelpId = GET_DWORD(p);
566 size_t nMem = 0;
567 if (!CountMemReplaceMenuExResource((WORD *)(p0 + offset), &nMem, NULL))
568 goto DONE_ERROR;
569 WORD * newMenu = new WORD[nMem + (nMem % 2) + 4];
570 SecureZeroMemory(newMenu, (nMem + (nMem % 2) + 4) * 2);
571 CopyMemory(newMenu, p0, 2 * sizeof(WORD) + sizeof(DWORD));
572 size_t index = 4; // MenuExHeader has 2 x WORD + 1 x DWORD
573 if (!CountMemReplaceMenuExResource((WORD *)(p0 + offset), &index, newMenu))
575 delete [] newMenu;
576 goto DONE_ERROR;
579 if (!UpdateResource(m_hUpdateRes, RT_MENU, lpszType, (m_wTargetLang ? m_wTargetLang : wLanguage), newMenu, (DWORD)(nMem + (nMem % 2) + 4) * 2))
581 delete [] newMenu;
582 goto DONE_ERROR;
585 if ((m_wTargetLang)&&(!UpdateResource(m_hUpdateRes, RT_MENU, lpszType, wLanguage, NULL, 0)))
587 delete [] newMenu;
588 goto DONE_ERROR;
590 delete [] newMenu;
592 break;
593 default:
594 goto DONE_ERROR;
597 UnlockResource(hglMenuTemplate);
598 FreeResource(hglMenuTemplate);
599 return TRUE;
601 DONE_ERROR:
602 UnlockResource(hglMenuTemplate);
603 FreeResource(hglMenuTemplate);
604 MYERROR;
607 const WORD* CResModule::ParseMenuResource(const WORD * res)
609 WORD flags;
610 WORD id = 0;
611 LPCWSTR str;
613 //struct PopupMenuItem {
614 // WORD fItemFlags;
615 // WCHAR szItemText[];
616 //};
617 //struct NormalMenuItem {
618 // WORD fItemFlags;
619 // WORD wMenuID;
620 // WCHAR szItemText[];
621 //};
625 flags = GET_WORD(res);
626 res++;
627 if (!(flags & MF_POPUP))
629 id = GET_WORD(res); //normal menu item
630 res++;
632 else
633 id = (WORD)-1; //popup menu item
635 str = (LPCWSTR)res;
636 size_t l = wcslen(str)+1;
637 res += l;
639 if (flags & MF_POPUP)
641 TCHAR * pBuf = new TCHAR[MAX_STRING_LENGTH];
642 SecureZeroMemory(pBuf, MAX_STRING_LENGTH * sizeof(TCHAR));
643 _tcscpy(pBuf, str);
644 CUtils::StringExtend(pBuf);
646 std::wstring wstr = std::wstring(pBuf);
647 RESOURCEENTRY entry = m_StringEntries[wstr];
648 if (id)
649 entry.resourceIDs.insert(id);
651 m_StringEntries[wstr] = entry;
652 delete [] pBuf;
654 if ((res = ParseMenuResource(res))==0)
655 return NULL;
657 else if (id != 0)
659 TCHAR * pBuf = new TCHAR[MAX_STRING_LENGTH];
660 SecureZeroMemory(pBuf, MAX_STRING_LENGTH * sizeof(TCHAR));
661 _tcscpy(pBuf, str);
662 CUtils::StringExtend(pBuf);
664 std::wstring wstr = std::wstring(pBuf);
665 RESOURCEENTRY entry = m_StringEntries[wstr];
666 entry.resourceIDs.insert(id);
668 TCHAR szTempBuf[1024];
669 _stprintf(szTempBuf, _T("#: MenuEntry; ID:%u"), id);
670 MENUENTRY menu_entry;
671 menu_entry.wID = id;
672 menu_entry.reference = szTempBuf;
673 menu_entry.msgstr = wstr;
675 m_StringEntries[wstr] = entry;
676 m_MenuEntries[id] = menu_entry;
677 delete [] pBuf;
679 } while (!(flags & MF_END));
680 return res;
683 const WORD* CResModule::CountMemReplaceMenuResource(const WORD * res, size_t * wordcount, WORD * newMenu)
685 WORD flags;
686 WORD id = 0;
688 //struct PopupMenuItem {
689 // WORD fItemFlags;
690 // WCHAR szItemText[];
691 //};
692 //struct NormalMenuItem {
693 // WORD fItemFlags;
694 // WORD wMenuID;
695 // WCHAR szItemText[];
696 //};
700 flags = GET_WORD(res);
701 res++;
702 if (newMenu == NULL)
703 (*wordcount)++;
704 else
705 newMenu[(*wordcount)++] = flags;
706 if (!(flags & MF_POPUP))
708 id = GET_WORD(res); //normal menu item
709 res++;
710 if (newMenu == NULL)
711 (*wordcount)++;
712 else
713 newMenu[(*wordcount)++] = id;
715 else
716 id = (WORD)-1; //popup menu item
718 if (flags & MF_POPUP)
720 ReplaceStr((LPCWSTR)res, newMenu, wordcount, &m_bTranslatedMenuStrings, &m_bDefaultMenuStrings);
721 res += wcslen((LPCWSTR)res) + 1;
723 if ((res = CountMemReplaceMenuResource(res, wordcount, newMenu))==0)
724 return NULL;
726 else if (id != 0)
728 ReplaceStr((LPCWSTR)res, newMenu, wordcount, &m_bTranslatedMenuStrings, &m_bDefaultMenuStrings);
729 res += wcslen((LPCWSTR)res) + 1;
731 else
733 if (newMenu)
734 wcscpy((wchar_t *)&newMenu[(*wordcount)], (LPCWSTR)res);
735 (*wordcount) += wcslen((LPCWSTR)res) + 1;
736 res += wcslen((LPCWSTR)res) + 1;
738 } while (!(flags & MF_END));
739 return res;
742 const WORD* CResModule::ParseMenuExResource(const WORD * res)
744 DWORD dwType, menuId;
745 WORD bResInfo;
746 LPCWSTR str;
748 //struct MenuExItem {
749 // DWORD dwType;
750 // DWORD dwState;
751 // DWORD menuId;
752 // WORD bResInfo;
753 // WCHAR szText[];
754 // DWORD dwHelpId; - Popup menu only
755 //};
759 dwType = GET_DWORD(res);
760 res += 2;
761 //dwState = GET_DWORD(res);
762 res += 2;
763 menuId = GET_DWORD(res);
764 res += 2;
765 bResInfo = GET_WORD(res);
766 res++;
768 str = (LPCWSTR)res;
769 size_t l = wcslen(str)+1;
770 res += l;
771 // Align to DWORD boundary
772 res += ((((WORD)res + 3) & ~3) - (WORD)res)/sizeof(WORD);
774 if (dwType & MFT_SEPARATOR)
775 continue;
777 if (bResInfo & 0x01)
779 // Popup menu - note this can also have a non-zero ID
780 if (menuId == 0)
781 menuId = (WORD)-1;
782 TCHAR * pBuf = new TCHAR[MAX_STRING_LENGTH];
783 SecureZeroMemory(pBuf, MAX_STRING_LENGTH * sizeof(TCHAR));
784 _tcscpy(pBuf, str);
785 CUtils::StringExtend(pBuf);
787 std::wstring wstr = std::wstring(pBuf);
788 RESOURCEENTRY entry = m_StringEntries[wstr];
789 // Popup has a DWORD help entry on a DWORD boundary - skip over it
790 res += 2;
792 entry.resourceIDs.insert(menuId);
793 TCHAR szTempBuf[1024];
794 _stprintf(szTempBuf, _T("#: MenuExPopupEntry; ID:%u"), menuId);
795 MENUENTRY menu_entry;
796 menu_entry.wID = (WORD)menuId;
797 menu_entry.reference = szTempBuf;
798 menu_entry.msgstr = wstr;
799 m_StringEntries[wstr] = entry;
800 m_MenuEntries[(WORD)menuId] = menu_entry;
801 delete [] pBuf;
803 if ((res = ParseMenuExResource(res)) == 0)
804 return NULL;
805 } else if (menuId != 0)
807 TCHAR * pBuf = new TCHAR[MAX_STRING_LENGTH];
808 SecureZeroMemory(pBuf, MAX_STRING_LENGTH * sizeof(TCHAR));
809 _tcscpy(pBuf, str);
810 CUtils::StringExtend(pBuf);
812 std::wstring wstr = std::wstring(pBuf);
813 RESOURCEENTRY entry = m_StringEntries[wstr];
814 entry.resourceIDs.insert(menuId);
816 TCHAR szTempBuf[1024];
817 _stprintf(szTempBuf, _T("#: MenuExEntry; ID:%u"), menuId);
818 MENUENTRY menu_entry;
819 menu_entry.wID = (WORD)menuId;
820 menu_entry.reference = szTempBuf;
821 menu_entry.msgstr = wstr;
822 m_StringEntries[wstr] = entry;
823 m_MenuEntries[(WORD)menuId] = menu_entry;
824 delete [] pBuf;
826 } while (!(bResInfo & 0x80));
827 return res;
830 const WORD* CResModule::CountMemReplaceMenuExResource(const WORD * res, size_t * wordcount, WORD * newMenu)
832 DWORD dwType, menuId;
833 WORD bResInfo;
834 WORD *p0;
836 //struct MenuExItem {
837 // DWORD dwType;
838 // DWORD dwState;
839 // DWORD menuId;
840 // WORD bResInfo;
841 // WCHAR szText[];
842 // DWORD dwHelpId; - Popup menu only
843 //};
847 p0 = (WORD *)res;
848 dwType = GET_DWORD(res);
849 res += 2;
850 //dwState = GET_DWORD(res);
851 res += 2;
852 menuId = GET_DWORD(res);
853 res += 2;
854 bResInfo = GET_WORD(res);
855 res++;
857 if (newMenu != NULL) {
858 CopyMemory(&newMenu[*wordcount], p0, 7 * sizeof(WORD));
860 (*wordcount) += 7;
862 if (dwType & MFT_SEPARATOR) {
863 // Align to DWORD
864 (*wordcount)++;
865 res++;
866 continue;
869 if (bResInfo & 0x01)
871 ReplaceStr((LPCWSTR)res, newMenu, wordcount, &m_bTranslatedMenuStrings, &m_bDefaultMenuStrings);
872 res += wcslen((LPCWSTR)res) + 1;
873 // Align to DWORD
874 res += ((((WORD)res + 3) & ~3) - (WORD)res)/sizeof(WORD);
875 if ((*wordcount) & 0x01)
876 (*wordcount)++;
878 if (newMenu != NULL)
879 CopyMemory(&newMenu[*wordcount], res, sizeof(DWORD)); // Copy Help ID
881 res += 2;
882 (*wordcount) += 2;
884 if ((res = CountMemReplaceMenuExResource(res, wordcount, newMenu)) == 0)
885 return NULL;
887 else if (menuId != 0)
889 ReplaceStr((LPCWSTR)res, newMenu, wordcount, &m_bTranslatedMenuStrings, &m_bDefaultMenuStrings);
890 res += wcslen((LPCWSTR)res) + 1;
892 else
894 if (newMenu)
895 wcscpy((wchar_t *)&newMenu[(*wordcount)], (LPCWSTR)res);
896 (*wordcount) += wcslen((LPCWSTR)res) + 1;
897 res += wcslen((LPCWSTR)res) + 1;
899 // Align to DWORD
900 res += ((((WORD)res + 3) & ~3) - (WORD)res)/sizeof(WORD);
901 if ((*wordcount) & 0x01)
902 (*wordcount)++;
903 } while (!(bResInfo & 0x80));
904 return res;
907 BOOL CResModule::ExtractAccelerator(LPCTSTR lpszType)
909 HRSRC hrsrc = FindResource(m_hResDll, lpszType, RT_ACCELERATOR);
910 HGLOBAL hglAccTable;
911 WORD fFlags, wAnsi, wID;
912 const WORD* p;
913 bool bEnd(false);
915 if (!hrsrc)
916 MYERROR;
918 hglAccTable = LoadResource(m_hResDll, hrsrc);
920 if (!hglAccTable)
921 goto DONE_ERROR;
923 p = (const WORD*)LockResource(hglAccTable);
925 if (p == NULL)
926 MYERROR;
929 struct ACCELTABLEENTRY
931 WORD fFlags; FVIRTKEY, FSHIFT, FCONTROL, FALT, 0x80 - Last in a table
932 WORD wAnsi; ANSI character
933 WORD wId; Keyboard accelerator passed to windows
934 WORD padding; # bytes added to ensure aligned to DWORD boundary
940 fFlags = GET_WORD(p);
941 p++;
942 wAnsi = GET_WORD(p);
943 p++;
944 wID = GET_WORD(p);
945 p++;
946 p++; // Skip over padding
948 if ((fFlags & 0x80) == 0x80)
949 { // 0x80
950 bEnd = true;
953 if ((wAnsi < 0x30) ||
954 (wAnsi > 0x5A) ||
955 (wAnsi >= 0x3A && wAnsi <= 0x40))
956 continue;
958 std::unique_ptr<WCHAR[]> pBuf(new WCHAR[1024]);
959 std::unique_ptr<WCHAR[]> pBuf2(new WCHAR[1024]);
960 SecureZeroMemory(pBuf.get(), 1024 * sizeof(WCHAR));
961 SecureZeroMemory(pBuf2.get(), 1024 * sizeof(WCHAR));
963 // include the menu ID in the msgid to make sure that 'duplicate'
964 // accelerator keys are listed in the po-file.
965 // without this, we would get entries like this:
966 //#. Accelerator Entry for Menu ID:32809; '&Filter'
967 //#. Accelerator Entry for Menu ID:57636; '&Find'
968 //#: Corresponding Menu ID:32771; '&Find'
969 //msgid "V C +F"
970 //msgstr ""
972 // Since "filter" and "find" are most likely translated to words starting
973 // with different letters, we need to have a separate accelerator entry
974 // for each of those
975 _stprintf(pBuf.get(), _T("ID:%u:"), wID);
977 // EXACTLY 5 characters long "ACS+X"
978 // V = Virtual key (or blank if not used)
979 // A = Alt key (or blank if not used)
980 // C = Ctrl key (or blank if not used)
981 // S = Shift key (or blank if not used)
982 // X = upper case character
983 // e.g. "V CS+Q" == Ctrl + Shift + 'Q'
984 if ((fFlags & FVIRTKEY) == FVIRTKEY) // 0x01
985 _tcscat(pBuf.get(), _T("V"));
986 else
987 _tcscat(pBuf.get(), _T(" "));
989 if ((fFlags & FALT) == FALT) // 0x10
990 _tcscat(pBuf.get(), _T("A"));
991 else
992 _tcscat(pBuf.get(), _T(" "));
994 if ((fFlags & FCONTROL) == FCONTROL) // 0x08
995 _tcscat(pBuf.get(), _T("C"));
996 else
997 _tcscat(pBuf.get(), _T(" "));
999 if ((fFlags & FSHIFT) == FSHIFT) // 0x04
1000 _tcscat(pBuf.get(), _T("S"));
1001 else
1002 _tcscat(pBuf.get(), _T(" "));
1004 _stprintf(pBuf2.get(), _T("%s+%c"), pBuf.get(), wAnsi);
1006 std::wstring wstr = std::wstring(pBuf2.get());
1007 RESOURCEENTRY AKey_entry = m_StringEntries[wstr];
1009 TCHAR szTempBuf[1024];
1010 SecureZeroMemory(szTempBuf, sizeof (szTempBuf));
1011 std::wstring wmenu = _T("");
1012 pME_iter = m_MenuEntries.find(wID);
1013 if (pME_iter != m_MenuEntries.end())
1015 wmenu = pME_iter->second.msgstr;
1017 _stprintf(szTempBuf, _T("#. Accelerator Entry for Menu ID:%u; '%s'"), wID, wmenu.c_str());
1018 AKey_entry.automaticcomments.push_back(std::wstring(szTempBuf));
1020 m_StringEntries[wstr] = AKey_entry;
1021 } while (!bEnd);
1023 UnlockResource(hglAccTable);
1024 FreeResource(hglAccTable);
1025 return TRUE;
1027 DONE_ERROR:
1028 UnlockResource(hglAccTable);
1029 FreeResource(hglAccTable);
1030 MYERROR;
1033 BOOL CResModule::ReplaceAccelerator(LPCTSTR lpszType, WORD wLanguage)
1035 LPACCEL lpaccelNew; // pointer to new accelerator table
1036 HACCEL haccelOld; // handle to old accelerator table
1037 int cAccelerators; // number of accelerators in table
1038 HGLOBAL hglAccTableNew;
1039 const WORD* p;
1040 int i;
1042 haccelOld = LoadAccelerators(m_hResDll, lpszType);
1044 if (haccelOld == NULL)
1045 MYERROR;
1047 cAccelerators = CopyAcceleratorTable(haccelOld, NULL, 0);
1049 lpaccelNew = (LPACCEL) LocalAlloc(LPTR, cAccelerators * sizeof(ACCEL));
1051 if (lpaccelNew == NULL)
1052 MYERROR;
1054 CopyAcceleratorTable(haccelOld, lpaccelNew, cAccelerators);
1056 // Find the accelerator that the user modified
1057 // and change its flags and virtual-key code
1058 // as appropriate.
1060 BYTE xfVirt;
1061 WORD xkey;
1062 static const size_t BufferSize = 1024;
1063 std::unique_ptr<WCHAR[]> pBuf(new WCHAR[BufferSize]);
1064 std::unique_ptr<WCHAR[]> pBuf2(new WCHAR[BufferSize]);
1065 for (i = 0; i < cAccelerators; i++)
1067 if ((lpaccelNew[i].key < 0x30) ||
1068 (lpaccelNew[i].key > 0x5A) ||
1069 (lpaccelNew[i].key >= 0x3A && lpaccelNew[i].key <= 0x40))
1070 continue;
1072 SecureZeroMemory(pBuf.get(), 1024 * sizeof(WCHAR));
1073 SecureZeroMemory(pBuf2.get(), 1024 * sizeof(WCHAR));
1075 _stprintf(pBuf.get(), _T("ID:%d:"), lpaccelNew[i].cmd);
1077 // get original key combination
1078 if ((lpaccelNew[i].fVirt & FVIRTKEY) == FVIRTKEY) // 0x01
1079 _tcscat(pBuf.get(), _T("V"));
1080 else
1081 _tcscat(pBuf.get(), _T(" "));
1083 if ((lpaccelNew[i].fVirt & FALT) == FALT) // 0x10
1084 _tcscat(pBuf.get(), _T("A"));
1085 else
1086 _tcscat(pBuf.get(), _T(" "));
1088 if ((lpaccelNew[i].fVirt & FCONTROL) == FCONTROL) // 0x08
1089 _tcscat(pBuf.get(), _T("C"));
1090 else
1091 _tcscat(pBuf.get(), _T(" "));
1093 if ((lpaccelNew[i].fVirt & FSHIFT) == FSHIFT) // 0x04
1094 _tcscat(pBuf.get(), _T("S"));
1095 else
1096 _tcscat(pBuf.get(), _T(" "));
1098 _stprintf(pBuf2.get(), _T("%s+%c"), pBuf.get(), lpaccelNew[i].key);
1100 // Is it there?
1101 std::map<std::wstring, RESOURCEENTRY>::iterator pAK_iter = m_StringEntries.find(pBuf2.get());
1102 if (pAK_iter != m_StringEntries.end())
1104 m_bTranslatedAcceleratorStrings++;
1105 xfVirt = 0;
1106 xkey = 0;
1107 std::wstring wtemp = pAK_iter->second.msgstr;
1108 wtemp = wtemp.substr(wtemp.find_last_of(':')+1);
1109 if (wtemp.size() != 6)
1110 continue;
1111 if (wtemp.compare(0, 1, _T("V")) == 0)
1112 xfVirt |= FVIRTKEY;
1113 else if (wtemp.compare(0, 1, _T(" ")) != 0)
1114 continue; // not a space - user must have made a mistake when translating
1115 if (wtemp.compare(1, 1, _T("A")) == 0)
1116 xfVirt |= FALT;
1117 else if (wtemp.compare(1, 1, _T(" ")) != 0)
1118 continue; // not a space - user must have made a mistake when translating
1119 if (wtemp.compare(2, 1, _T("C")) == 0)
1120 xfVirt |= FCONTROL;
1121 else if (wtemp.compare(2, 1, _T(" ")) != 0)
1122 continue; // not a space - user must have made a mistake when translating
1123 if (wtemp.compare(3, 1, _T("S")) == 0)
1124 xfVirt |= FSHIFT;
1125 else if (wtemp.compare(3, 1, _T(" ")) != 0)
1126 continue; // not a space - user must have made a mistake when translating
1127 if (wtemp.compare(4, 1, _T("+")) == 0)
1129 _stscanf(wtemp.substr(5, 1).c_str(), _T("%c"), &xkey);
1130 lpaccelNew[i].fVirt = xfVirt;
1131 lpaccelNew[i].key = xkey;
1134 else
1135 m_bDefaultAcceleratorStrings++;
1139 // Create the new accelerator table
1140 hglAccTableNew = LocalAlloc(LPTR, cAccelerators * 4 * sizeof(WORD));
1141 p = (WORD *)hglAccTableNew;
1142 lpaccelNew[cAccelerators-1].fVirt |= 0x80;
1143 for (i = 0; i < cAccelerators; i++)
1145 memcpy((void *)p, &lpaccelNew[i].fVirt, 1);
1146 p++;
1147 memcpy((void *)p, &lpaccelNew[i].key, sizeof(WORD));
1148 p++;
1149 memcpy((void *)p, &lpaccelNew[i].cmd, sizeof(WORD));
1150 p++;
1151 p++;
1154 if (!UpdateResource(m_hUpdateRes, RT_ACCELERATOR, lpszType,
1155 (m_wTargetLang ? m_wTargetLang : wLanguage), hglAccTableNew /* haccelNew*/, cAccelerators * 4 * sizeof(WORD)))
1157 goto DONE_ERROR;
1160 if ((m_wTargetLang)&&(!UpdateResource(m_hUpdateRes, RT_ACCELERATOR, lpszType, wLanguage, NULL, 0)))
1162 goto DONE_ERROR;
1165 LocalFree(hglAccTableNew);
1166 LocalFree(lpaccelNew);
1167 return TRUE;
1169 DONE_ERROR:
1170 LocalFree(hglAccTableNew);
1171 LocalFree(lpaccelNew);
1172 MYERROR;
1175 BOOL CResModule::ExtractDialog(LPCTSTR lpszType)
1177 const WORD* lpDlg;
1178 const WORD* lpDlgItem;
1179 DIALOGINFO dlg;
1180 DLGITEMINFO dlgItem;
1181 WORD bNumControls;
1182 HRSRC hrsrc;
1183 HGLOBAL hGlblDlgTemplate;
1185 hrsrc = FindResource(m_hResDll, lpszType, RT_DIALOG);
1187 if (hrsrc == NULL)
1188 MYERROR;
1190 hGlblDlgTemplate = LoadResource(m_hResDll, hrsrc);
1191 if (hGlblDlgTemplate == NULL)
1192 MYERROR;
1194 lpDlg = (const WORD*) LockResource(hGlblDlgTemplate);
1196 if (lpDlg == NULL)
1197 MYERROR;
1199 lpDlgItem = (const WORD*) GetDialogInfo(lpDlg, &dlg);
1200 bNumControls = dlg.nbItems;
1202 if (dlg.caption)
1204 TCHAR * pBuf = new TCHAR[MAX_STRING_LENGTH];
1205 SecureZeroMemory(pBuf, MAX_STRING_LENGTH * sizeof(TCHAR));
1206 _tcscpy(pBuf, dlg.caption);
1207 CUtils::StringExtend(pBuf);
1209 std::wstring wstr = std::wstring(pBuf);
1210 RESOURCEENTRY entry = m_StringEntries[wstr];
1211 entry.resourceIDs.insert((DWORD)lpszType);
1213 m_StringEntries[wstr] = entry;
1214 delete [] pBuf;
1217 while (bNumControls-- != 0)
1219 TCHAR szTitle[500];
1220 SecureZeroMemory(szTitle, sizeof(szTitle));
1221 BOOL bCode;
1223 lpDlgItem = GetControlInfo((WORD *) lpDlgItem, &dlgItem, dlg.dialogEx, &bCode);
1225 if (bCode == FALSE)
1226 _tcscpy(szTitle, dlgItem.windowName);
1228 if (_tcslen(szTitle) > 0)
1230 CUtils::StringExtend(szTitle);
1232 std::wstring wstr = std::wstring(szTitle);
1233 RESOURCEENTRY entry = m_StringEntries[wstr];
1234 entry.resourceIDs.insert(dlgItem.id);
1236 m_StringEntries[wstr] = entry;
1240 UnlockResource(hGlblDlgTemplate);
1241 FreeResource(hGlblDlgTemplate);
1242 return (TRUE);
1245 BOOL CResModule::ReplaceDialog(LPCTSTR lpszType, WORD wLanguage)
1247 const WORD* lpDlg;
1248 HRSRC hrsrc;
1249 HGLOBAL hGlblDlgTemplate;
1251 hrsrc = FindResourceEx(m_hResDll, RT_DIALOG, lpszType, wLanguage);
1253 if (hrsrc == NULL)
1254 MYERROR;
1256 hGlblDlgTemplate = LoadResource(m_hResDll, hrsrc);
1258 if (hGlblDlgTemplate == NULL)
1259 MYERROR;
1261 lpDlg = (WORD *) LockResource(hGlblDlgTemplate);
1263 if (lpDlg == NULL)
1264 MYERROR;
1266 size_t nMem = 0;
1267 const WORD * p = lpDlg;
1268 if (!CountMemReplaceDialogResource(p, &nMem, NULL))
1269 goto DONE_ERROR;
1270 WORD * newDialog = new WORD[nMem + (nMem % 2)];
1271 SecureZeroMemory(newDialog, (nMem + (nMem % 2))*2);
1273 size_t index = 0;
1274 if (!CountMemReplaceDialogResource(lpDlg, &index, newDialog))
1276 delete [] newDialog;
1277 goto DONE_ERROR;
1280 if (!UpdateResource(m_hUpdateRes, RT_DIALOG, lpszType, (m_wTargetLang ? m_wTargetLang : wLanguage), newDialog, (DWORD)(nMem + (nMem % 2))*2))
1282 delete [] newDialog;
1283 goto DONE_ERROR;
1286 if ((m_wTargetLang)&&(!UpdateResource(m_hUpdateRes, RT_DIALOG, lpszType, wLanguage, NULL, 0)))
1288 delete [] newDialog;
1289 goto DONE_ERROR;
1292 delete [] newDialog;
1293 UnlockResource(hGlblDlgTemplate);
1294 FreeResource(hGlblDlgTemplate);
1295 return TRUE;
1297 DONE_ERROR:
1298 UnlockResource(hGlblDlgTemplate);
1299 FreeResource(hGlblDlgTemplate);
1300 MYERROR;
1303 const WORD* CResModule::GetDialogInfo(const WORD * pTemplate, LPDIALOGINFO lpDlgInfo)
1305 const WORD* p = (const WORD *)pTemplate;
1307 lpDlgInfo->style = GET_DWORD(p);
1308 p += 2;
1310 if (lpDlgInfo->style == 0xffff0001) // DIALOGEX resource
1312 lpDlgInfo->dialogEx = TRUE;
1313 lpDlgInfo->helpId = GET_DWORD(p);
1314 p += 2;
1315 lpDlgInfo->exStyle = GET_DWORD(p);
1316 p += 2;
1317 lpDlgInfo->style = GET_DWORD(p);
1318 p += 2;
1320 else
1322 lpDlgInfo->dialogEx = FALSE;
1323 lpDlgInfo->helpId = 0;
1324 lpDlgInfo->exStyle = GET_DWORD(p);
1325 p += 2;
1328 lpDlgInfo->nbItems = GET_WORD(p);
1329 p++;
1331 lpDlgInfo->x = GET_WORD(p);
1332 p++;
1334 lpDlgInfo->y = GET_WORD(p);
1335 p++;
1337 lpDlgInfo->cx = GET_WORD(p);
1338 p++;
1340 lpDlgInfo->cy = GET_WORD(p);
1341 p++;
1343 // Get the menu name
1345 switch (GET_WORD(p))
1347 case 0x0000:
1348 lpDlgInfo->menuName = NULL;
1349 p++;
1350 break;
1351 case 0xffff:
1352 lpDlgInfo->menuName = (LPCTSTR) (WORD) GET_WORD(p + 1);
1353 p += 2;
1354 break;
1355 default:
1356 lpDlgInfo->menuName = (LPCTSTR) p;
1357 p += wcslen((LPCWSTR) p) + 1;
1358 break;
1361 // Get the class name
1363 switch (GET_WORD(p))
1365 case 0x0000:
1366 lpDlgInfo->className = (LPCTSTR)MAKEINTATOM(32770);
1367 p++;
1368 break;
1369 case 0xffff:
1370 lpDlgInfo->className = (LPCTSTR) (WORD) GET_WORD(p + 1);
1371 p += 2;
1372 break;
1373 default:
1374 lpDlgInfo->className = (LPCTSTR) p;
1375 p += wcslen((LPCTSTR)p) + 1;
1376 break;
1379 // Get the window caption
1381 lpDlgInfo->caption = (LPCTSTR)p;
1382 p += wcslen((LPCWSTR) p) + 1;
1384 // Get the font name
1386 if (lpDlgInfo->style & DS_SETFONT)
1388 lpDlgInfo->pointSize = GET_WORD(p);
1389 p++;
1391 if (lpDlgInfo->dialogEx)
1393 lpDlgInfo->weight = GET_WORD(p);
1394 p++;
1395 lpDlgInfo->italic = LOBYTE(GET_WORD(p));
1396 p++;
1398 else
1400 lpDlgInfo->weight = FW_DONTCARE;
1401 lpDlgInfo->italic = FALSE;
1404 lpDlgInfo->faceName = (LPCTSTR)p;
1405 p += wcslen((LPCWSTR) p) + 1;
1407 // First control is on DWORD boundary
1408 p += ((((WORD)p + 3) & ~3) - (WORD)p)/sizeof(WORD);
1410 return p;
1413 const WORD* CResModule::GetControlInfo(const WORD* p, LPDLGITEMINFO lpDlgItemInfo, BOOL dialogEx, LPBOOL bIsID)
1415 if (dialogEx)
1417 lpDlgItemInfo->helpId = GET_DWORD(p);
1418 p += 2;
1419 lpDlgItemInfo->exStyle = GET_DWORD(p);
1420 p += 2;
1421 lpDlgItemInfo->style = GET_DWORD(p);
1422 p += 2;
1424 else
1426 lpDlgItemInfo->helpId = 0;
1427 lpDlgItemInfo->style = GET_DWORD(p);
1428 p += 2;
1429 lpDlgItemInfo->exStyle = GET_DWORD(p);
1430 p += 2;
1433 lpDlgItemInfo->x = GET_WORD(p);
1434 p++;
1436 lpDlgItemInfo->y = GET_WORD(p);
1437 p++;
1439 lpDlgItemInfo->cx = GET_WORD(p);
1440 p++;
1442 lpDlgItemInfo->cy = GET_WORD(p);
1443 p++;
1445 if (dialogEx)
1447 // ID is a DWORD for DIALOGEX
1448 lpDlgItemInfo->id = (WORD) GET_DWORD(p);
1449 p += 2;
1451 else
1453 lpDlgItemInfo->id = GET_WORD(p);
1454 p++;
1457 if (GET_WORD(p) == 0xffff)
1459 GET_WORD(p + 1);
1461 p += 2;
1463 else
1465 lpDlgItemInfo->className = (LPCTSTR) p;
1466 p += wcslen((LPCWSTR) p) + 1;
1469 if (GET_WORD(p) == 0xffff) // an integer ID?
1471 *bIsID = TRUE;
1472 lpDlgItemInfo->windowName = (LPCTSTR) (DWORD) GET_WORD(p + 1);
1473 p += 2;
1475 else
1477 *bIsID = FALSE;
1478 lpDlgItemInfo->windowName = (LPCTSTR) p;
1479 p += wcslen((LPCWSTR) p) + 1;
1482 if (GET_WORD(p))
1484 lpDlgItemInfo->data = (LPVOID) (p + 1);
1485 p += GET_WORD(p) / sizeof(WORD);
1487 else
1488 lpDlgItemInfo->data = NULL;
1490 p++;
1491 // Next control is on DWORD boundary
1492 p += ((((WORD)p + 3) & ~3) - (WORD)p)/sizeof(WORD);
1493 return p;
1496 const WORD * CResModule::CountMemReplaceDialogResource(const WORD * res, size_t * wordcount, WORD * newDialog)
1498 BOOL bEx = FALSE;
1499 DWORD style = GET_DWORD(res);
1500 if (newDialog)
1502 newDialog[(*wordcount)++] = GET_WORD(res++);
1503 newDialog[(*wordcount)++] = GET_WORD(res++);
1505 else
1507 res += 2;
1508 (*wordcount) += 2;
1511 if (style == 0xffff0001) // DIALOGEX resource
1513 bEx = TRUE;
1514 if (newDialog)
1516 newDialog[(*wordcount)++] = GET_WORD(res++); //help id
1517 newDialog[(*wordcount)++] = GET_WORD(res++); //help id
1518 newDialog[(*wordcount)++] = GET_WORD(res++); //exStyle
1519 newDialog[(*wordcount)++] = GET_WORD(res++); //exStyle
1520 style = GET_DWORD(res);
1521 newDialog[(*wordcount)++] = GET_WORD(res++); //style
1522 newDialog[(*wordcount)++] = GET_WORD(res++); //style
1524 else
1526 res += 4;
1527 style = GET_DWORD(res);
1528 res += 2;
1529 (*wordcount) += 6;
1532 else
1534 bEx = FALSE;
1535 if (newDialog)
1537 newDialog[(*wordcount)++] = GET_WORD(res++); //exStyle
1538 newDialog[(*wordcount)++] = GET_WORD(res++); //exStyle
1539 //style = GET_DWORD(res);
1540 //newDialog[(*wordcount)++] = GET_WORD(res++); //style
1541 //newDialog[(*wordcount)++] = GET_WORD(res++); //style
1543 else
1545 res += 2;
1546 (*wordcount) += 2;
1550 if (newDialog)
1551 newDialog[(*wordcount)] = GET_WORD(res);
1552 WORD nbItems = GET_WORD(res);
1553 (*wordcount)++;
1554 res++;
1556 if (newDialog)
1557 newDialog[(*wordcount)] = GET_WORD(res); //x
1558 (*wordcount)++;
1559 res++;
1561 if (newDialog)
1562 newDialog[(*wordcount)] = GET_WORD(res); //y
1563 (*wordcount)++;
1564 res++;
1566 if (newDialog)
1567 newDialog[(*wordcount)] = GET_WORD(res); //cx
1568 (*wordcount)++;
1569 res++;
1571 if (newDialog)
1572 newDialog[(*wordcount)] = GET_WORD(res); //cy
1573 (*wordcount)++;
1574 res++;
1576 // Get the menu name
1578 switch (GET_WORD(res))
1580 case 0x0000:
1581 if (newDialog)
1582 newDialog[(*wordcount)] = GET_WORD(res);
1583 (*wordcount)++;
1584 res++;
1585 break;
1586 case 0xffff:
1587 if (newDialog)
1589 newDialog[(*wordcount)++] = GET_WORD(res++);
1590 newDialog[(*wordcount)++] = GET_WORD(res++);
1592 else
1594 (*wordcount) += 2;
1595 res += 2;
1597 break;
1598 default:
1599 if (newDialog)
1601 wcscpy((LPWSTR)&newDialog[(*wordcount)], (LPCWSTR)res);
1603 (*wordcount) += wcslen((LPCWSTR) res) + 1;
1604 res += wcslen((LPCWSTR) res) + 1;
1605 break;
1608 // Get the class name
1610 switch (GET_WORD(res))
1612 case 0x0000:
1613 if (newDialog)
1614 newDialog[(*wordcount)] = GET_WORD(res);
1615 (*wordcount)++;
1616 res++;
1617 break;
1618 case 0xffff:
1619 if (newDialog)
1621 newDialog[(*wordcount)++] = GET_WORD(res++);
1622 newDialog[(*wordcount)++] = GET_WORD(res++);
1624 else
1626 (*wordcount) += 2;
1627 res += 2;
1629 break;
1630 default:
1631 if (newDialog)
1633 wcscpy((LPWSTR)&newDialog[(*wordcount)], (LPCWSTR)res);
1635 (*wordcount) += wcslen((LPCWSTR) res) + 1;
1636 res += wcslen((LPCWSTR) res) + 1;
1637 break;
1640 // Get the window caption
1642 ReplaceStr((LPCWSTR)res, newDialog, wordcount, &m_bTranslatedDialogStrings, &m_bDefaultDialogStrings);
1643 res += wcslen((LPCWSTR)res) + 1;
1645 // Get the font name
1647 if (style & DS_SETFONT)
1649 if (newDialog)
1650 newDialog[(*wordcount)] = GET_WORD(res);
1651 res++;
1652 (*wordcount)++;
1654 if (bEx)
1656 if (newDialog)
1658 newDialog[(*wordcount)++] = GET_WORD(res++);
1659 newDialog[(*wordcount)++] = GET_WORD(res++);
1661 else
1663 res += 2;
1664 (*wordcount) += 2;
1668 if (newDialog)
1669 wcscpy((LPWSTR)&newDialog[(*wordcount)], (LPCWSTR)res);
1670 (*wordcount) += wcslen((LPCWSTR)res) + 1;
1671 res += wcslen((LPCWSTR)res) + 1;
1673 // First control is on DWORD boundary
1674 while ((*wordcount)%2)
1675 (*wordcount)++;
1676 while ((ULONG)res % 4)
1677 res++;
1679 while (nbItems--)
1681 res = ReplaceControlInfo(res, wordcount, newDialog, bEx);
1683 return res;
1686 const WORD* CResModule::ReplaceControlInfo(const WORD * res, size_t * wordcount, WORD * newDialog, BOOL bEx)
1688 if (bEx)
1690 if (newDialog)
1692 newDialog[(*wordcount)++] = GET_WORD(res++); //helpid
1693 newDialog[(*wordcount)++] = GET_WORD(res++); //helpid
1695 else
1697 res += 2;
1698 (*wordcount) += 2;
1701 if (newDialog)
1703 LONG * exStyle = (LONG*)&newDialog[(*wordcount)];
1704 newDialog[(*wordcount)++] = GET_WORD(res++); //exStyle
1705 newDialog[(*wordcount)++] = GET_WORD(res++); //exStyle
1706 if (m_bRTL)
1707 *exStyle |= WS_EX_RTLREADING;
1709 else
1711 res += 2;
1712 (*wordcount) += 2;
1715 if (newDialog)
1717 newDialog[(*wordcount)++] = GET_WORD(res++); //style
1718 newDialog[(*wordcount)++] = GET_WORD(res++); //style
1720 else
1722 res += 2;
1723 (*wordcount) += 2;
1726 if (newDialog)
1727 newDialog[(*wordcount)] = GET_WORD(res); //x
1728 res++;
1729 (*wordcount)++;
1731 if (newDialog)
1732 newDialog[(*wordcount)] = GET_WORD(res); //y
1733 res++;
1734 (*wordcount)++;
1736 if (newDialog)
1737 newDialog[(*wordcount)] = GET_WORD(res); //cx
1738 res++;
1739 (*wordcount)++;
1741 if (newDialog)
1742 newDialog[(*wordcount)] = GET_WORD(res); //cy
1743 res++;
1744 (*wordcount)++;
1746 if (bEx)
1748 // ID is a DWORD for DIALOGEX
1749 if (newDialog)
1751 newDialog[(*wordcount)++] = GET_WORD(res++);
1752 newDialog[(*wordcount)++] = GET_WORD(res++);
1754 else
1756 res += 2;
1757 (*wordcount) += 2;
1760 else
1762 if (newDialog)
1763 newDialog[(*wordcount)] = GET_WORD(res);
1764 res++;
1765 (*wordcount)++;
1768 if (GET_WORD(res) == 0xffff) //classID
1770 if (newDialog)
1772 newDialog[(*wordcount)++] = GET_WORD(res++);
1773 newDialog[(*wordcount)++] = GET_WORD(res++);
1775 else
1777 res += 2;
1778 (*wordcount) += 2;
1781 else
1783 if (newDialog)
1784 wcscpy((LPWSTR)&newDialog[(*wordcount)], (LPCWSTR)res);
1785 (*wordcount) += wcslen((LPCWSTR) res) + 1;
1786 res += wcslen((LPCWSTR) res) + 1;
1789 if (GET_WORD(res) == 0xffff) // an integer ID?
1791 if (newDialog)
1793 newDialog[(*wordcount)++] = GET_WORD(res++);
1794 newDialog[(*wordcount)++] = GET_WORD(res++);
1796 else
1798 res += 2;
1799 (*wordcount) += 2;
1802 else
1804 ReplaceStr((LPCWSTR)res, newDialog, wordcount, &m_bTranslatedDialogStrings, &m_bDefaultDialogStrings);
1805 res += wcslen((LPCWSTR)res) + 1;
1808 if (newDialog)
1809 memcpy(&newDialog[(*wordcount)], res, (GET_WORD(res)+1)*sizeof(WORD));
1810 (*wordcount) += (GET_WORD(res)+1);
1811 res += (GET_WORD(res)+1);
1812 // Next control is on DWORD boundary
1813 while ((*wordcount) % 2)
1814 (*wordcount)++;
1815 res += ((((WORD)res + 3) & ~3) - (WORD)res)/sizeof(WORD);
1817 return res;
1820 BOOL CResModule::ExtractRibbon(LPCTSTR lpszType)
1822 HRSRC hrsrc = FindResource(m_hResDll, lpszType, RT_RIBBON);
1823 HGLOBAL hglRibbonTemplate;
1824 const BYTE *p;
1826 if (!hrsrc)
1827 MYERROR;
1829 hglRibbonTemplate = LoadResource(m_hResDll, hrsrc);
1831 DWORD sizeres = SizeofResource(m_hResDll, hrsrc);
1833 if (!hglRibbonTemplate)
1834 MYERROR;
1836 p = (const BYTE*)LockResource(hglRibbonTemplate);
1838 if (p == NULL)
1839 MYERROR;
1841 // Resource consists of one single string
1842 // that is XML.
1844 // extract all <text>blah</text> elements
1846 const std::regex regRevMatch("<TEXT>([^<]+)</TEXT>");
1847 std::string ss = std::string((const char*)p, sizeres);
1848 const std::sregex_iterator end;
1849 for (std::sregex_iterator it(ss.begin(), ss.end(), regRevMatch); it != end; ++it)
1851 std::string str = (*it)[1];
1852 size_t len = str.size();
1853 std::unique_ptr<wchar_t[]> bufw(new wchar_t[len*4 + 1]);
1854 SecureZeroMemory(bufw.get(), (len*4 + 1)*sizeof(wchar_t));
1855 MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, bufw.get(), (int)len*4);
1856 std::wstring ret = bufw.get();
1857 RESOURCEENTRY entry = m_StringEntries[ret];
1858 entry.resourceIDs.insert((DWORD)lpszType);
1859 if (wcschr(ret.c_str(), '%'))
1860 entry.flag = _T("#, c-format");
1861 m_StringEntries[ret] = entry;
1862 m_bDefaultRibbonTexts++;
1865 // extract all </ELEMENT_NAME><NAME>blahblah</NAME> elements
1867 const std::regex regRevMatchName("</ELEMENT_NAME><NAME>([^<]+)</NAME>");
1868 for (std::sregex_iterator it(ss.begin(), ss.end(), regRevMatchName); it != end; ++it)
1870 std::string str = (*it)[1];
1871 size_t len = str.size();
1872 std::unique_ptr<wchar_t[]> bufw(new wchar_t[len*4 + 1]);
1873 SecureZeroMemory(bufw.get(), (len*4 + 1)*sizeof(wchar_t));
1874 MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, bufw.get(), (int)len*4);
1875 std::wstring ret = bufw.get();
1876 RESOURCEENTRY entry = m_StringEntries[ret];
1877 entry.resourceIDs.insert((DWORD)lpszType);
1878 if (wcschr(ret.c_str(), '%'))
1879 entry.flag = _T("#, c-format");
1880 m_StringEntries[ret] = entry;
1881 m_bDefaultRibbonTexts++;
1884 UnlockResource(hglRibbonTemplate);
1885 FreeResource(hglRibbonTemplate);
1886 return TRUE;
1889 BOOL CResModule::ReplaceRibbon(LPCTSTR lpszType, WORD wLanguage)
1891 HRSRC hrsrc = FindResource(m_hResDll, lpszType, RT_RIBBON);
1892 HGLOBAL hglRibbonTemplate;
1893 const BYTE *p;
1895 if (!hrsrc)
1896 MYERROR;
1898 hglRibbonTemplate = LoadResource(m_hResDll, hrsrc);
1900 DWORD sizeres = SizeofResource(m_hResDll, hrsrc);
1902 if (!hglRibbonTemplate)
1903 MYERROR;
1905 p = (const BYTE*)LockResource(hglRibbonTemplate);
1907 if (p == NULL)
1908 MYERROR;
1910 std::string ss = std::string((const char*)p, sizeres);
1911 size_t len = ss.size();
1912 std::unique_ptr<wchar_t[]> bufw(new wchar_t[len*4 + 1]);
1913 SecureZeroMemory(bufw.get(), (len*4 + 1)*sizeof(wchar_t));
1914 MultiByteToWideChar(CP_UTF8, 0, ss.c_str(), -1, bufw.get(), (int)len*4);
1915 std::wstring ssw = bufw.get();
1918 const std::regex regRevMatch("<TEXT>([^<]+)</TEXT>");
1919 const std::sregex_iterator end;
1920 for (std::sregex_iterator it(ss.begin(), ss.end(), regRevMatch); it != end; ++it)
1922 std::string str = (*it)[1];
1923 size_t len = str.size();
1924 std::unique_ptr<wchar_t[]> bufw(new wchar_t[len*4 + 1]);
1925 SecureZeroMemory(bufw.get(), (len*4 + 1)*sizeof(wchar_t));
1926 MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, bufw.get(), (int)len*4);
1927 std::wstring ret = bufw.get();
1929 RESOURCEENTRY entry = m_StringEntries[ret];
1930 ret = L"<TEXT>" + ret + L"</TEXT>";
1932 if (entry.msgstr.size())
1934 CUtils::SearchReplace(ssw, ret, L"<TEXT>" + entry.msgstr + L"</TEXT>");
1935 m_bTranslatedRibbonTexts++;
1937 else
1938 m_bDefaultRibbonTexts++;
1941 const std::regex regRevMatchName("</ELEMENT_NAME><NAME>([^<]+)</NAME>");
1942 for (std::sregex_iterator it(ss.begin(), ss.end(), regRevMatchName); it != end; ++it)
1944 std::string str = (*it)[1];
1945 size_t len = str.size();
1946 std::unique_ptr<wchar_t[]> bufw(new wchar_t[len*4 + 1]);
1947 SecureZeroMemory(bufw.get(), (len*4 + 1)*sizeof(wchar_t));
1948 MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, bufw.get(), (int)len*4);
1949 std::wstring ret = bufw.get();
1951 RESOURCEENTRY entry = m_StringEntries[ret];
1952 ret = L"</ELEMENT_NAME><NAME>" + ret + L"</NAME>";
1954 if (entry.msgstr.size())
1956 CUtils::SearchReplace(ssw, ret, L"</ELEMENT_NAME><NAME>" + entry.msgstr + L"</NAME>");
1957 m_bTranslatedRibbonTexts++;
1959 else
1960 m_bDefaultRibbonTexts++;
1963 std::unique_ptr<char[]> buf(new char[ssw.size()*4 + 1]);
1964 int lengthIncTerminator = WideCharToMultiByte(CP_UTF8, 0, ssw.c_str(), -1, buf.get(), (int)len*4, NULL, NULL);
1967 if (!UpdateResource(m_hUpdateRes, RT_RIBBON, lpszType, (m_wTargetLang ? m_wTargetLang : wLanguage), buf.get(), lengthIncTerminator-1))
1969 goto DONE_ERROR;
1972 if ((m_wTargetLang)&&(!UpdateResource(m_hUpdateRes, RT_RIBBON, lpszType, wLanguage, NULL, 0)))
1974 goto DONE_ERROR;
1978 UnlockResource(hglRibbonTemplate);
1979 FreeResource(hglRibbonTemplate);
1980 return TRUE;
1982 DONE_ERROR:
1983 UnlockResource(hglRibbonTemplate);
1984 FreeResource(hglRibbonTemplate);
1985 MYERROR;
1988 BOOL CALLBACK CResModule::EnumResNameCallback(HMODULE /*hModule*/, LPCTSTR lpszType, LPTSTR lpszName, LONG_PTR lParam)
1990 CResModule* lpResModule = (CResModule*)lParam;
1992 if (lpszType == RT_STRING)
1994 if (IS_INTRESOURCE(lpszName))
1996 if (!lpResModule->ExtractString(lpszName))
1997 return FALSE;
2000 else if (lpszType == RT_MENU)
2002 if (IS_INTRESOURCE(lpszName))
2004 if (!lpResModule->ExtractMenu(lpszName))
2005 return FALSE;
2008 else if (lpszType == RT_DIALOG)
2010 if (IS_INTRESOURCE(lpszName))
2012 if (!lpResModule->ExtractDialog(lpszName))
2013 return FALSE;
2016 else if (lpszType == RT_ACCELERATOR)
2018 if (IS_INTRESOURCE(lpszName))
2020 if (!lpResModule->ExtractAccelerator(lpszName))
2021 return FALSE;
2024 else if (lpszType == RT_RIBBON)
2026 if (IS_INTRESOURCE(lpszName))
2028 if (!lpResModule->ExtractRibbon(lpszName))
2029 return FALSE;
2033 return TRUE;
2036 #pragma warning(push)
2037 #pragma warning(disable: 4189)
2038 BOOL CALLBACK CResModule::EnumResNameWriteCallback(HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG_PTR lParam)
2040 CResModule* lpResModule = (CResModule*)lParam;
2041 return EnumResourceLanguages(hModule, lpszType, lpszName, (ENUMRESLANGPROC)&lpResModule->EnumResWriteLangCallback, lParam);
2043 #pragma warning(pop)
2045 BOOL CALLBACK CResModule::EnumResWriteLangCallback(HMODULE /*hModule*/, LPCTSTR lpszType, LPTSTR lpszName, WORD wLanguage, LONG_PTR lParam)
2047 BOOL bRes = FALSE;
2048 CResModule* lpResModule = (CResModule*)lParam;
2050 if (lpszType == RT_STRING)
2052 bRes = lpResModule->ReplaceString(lpszName, wLanguage);
2054 else if (lpszType == RT_MENU)
2056 bRes = lpResModule->ReplaceMenu(lpszName, wLanguage);
2058 else if (lpszType == RT_DIALOG)
2060 bRes = lpResModule->ReplaceDialog(lpszName, wLanguage);
2062 else if (lpszType == RT_ACCELERATOR)
2064 bRes = lpResModule->ReplaceAccelerator(lpszName, wLanguage);
2066 else if (lpszType == RT_RIBBON)
2068 bRes = lpResModule->ReplaceRibbon(lpszName, wLanguage);
2071 return bRes;
2075 void CResModule::ReplaceStr(LPCWSTR src, WORD * dest, size_t * count, int * translated, int * def)
2077 TCHAR * pBuf = new TCHAR[MAX_STRING_LENGTH];
2078 SecureZeroMemory(pBuf, MAX_STRING_LENGTH * sizeof(TCHAR));
2079 wcscpy(pBuf, src);
2080 CUtils::StringExtend(pBuf);
2082 std::wstring wstr = std::wstring(pBuf);
2083 RESOURCEENTRY entry = m_StringEntries[wstr];
2084 if (!entry.msgstr.empty())
2086 wcscpy(pBuf, entry.msgstr.c_str());
2087 CUtils::StringCollapse(pBuf);
2088 if (dest)
2089 wcscpy((wchar_t *)&dest[(*count)], pBuf);
2090 (*count) += wcslen(pBuf)+1;
2091 (*translated)++;
2093 else
2095 if (dest)
2096 wcscpy((wchar_t *)&dest[(*count)], src);
2097 (*count) += wcslen(src) + 1;
2098 if (wcslen(src))
2099 (*def)++;
2101 delete [] pBuf;