Fixed issue 923: Code spelling fix: function ReadTreeRecurive should be ReadTreeRecursive
[TortoiseGit.git] / src / ResText / ResModule.cpp
blob1a14fe1bc82f12c466bb2aa2aea245cda58e798a
1 // TortoiseSVN - a Windows shell extension for easy version control
3 // Copyright (C) 2003-2008 - 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"
22 #define MYERROR {CUtils::Error(); return FALSE;}
24 CResModule::CResModule(void)
25 : m_bTranslatedStrings(0)
26 , m_bDefaultStrings(0)
27 , m_bTranslatedDialogStrings(0)
28 , m_bDefaultDialogStrings(0)
29 , m_bTranslatedMenuStrings(0)
30 , m_bDefaultMenuStrings(0)
31 , m_bTranslatedAcceleratorStrings(0)
32 , m_bDefaultAcceleratorStrings(0)
33 , m_wTargetLang(0)
34 , m_hResDll(NULL)
35 , m_hUpdateRes(NULL)
36 , m_bQuiet(false)
37 , m_bRTL(false)
41 CResModule::~CResModule(void)
45 BOOL CResModule::ExtractResources(std::vector<std::wstring> filelist, LPCTSTR lpszPOFilePath, BOOL bNoUpdate)
47 BOOL bRet = TRUE;
48 for (std::vector<std::wstring>::iterator I = filelist.begin(); I != filelist.end(); ++I)
50 m_hResDll = LoadLibrary(I->c_str());
51 if (m_hResDll == NULL)
52 MYERROR;
54 size_t nEntries = m_StringEntries.size();
55 // fill in the std::map with all translatable entries
57 if (!m_bQuiet)
58 _ftprintf(stdout, _T("Extracting StringTable...."));
59 EnumResourceNames(m_hResDll, RT_STRING, EnumResNameCallback, (long)this);
60 if (!m_bQuiet)
61 _ftprintf(stdout, _T("%4d Strings\n"), m_StringEntries.size()-nEntries);
62 nEntries = m_StringEntries.size();
64 if (!m_bQuiet)
65 _ftprintf(stdout, _T("Extracting Dialogs........"));
66 EnumResourceNames(m_hResDll, RT_DIALOG, EnumResNameCallback, (long)this);
67 if (!m_bQuiet)
68 _ftprintf(stdout, _T("%4d Strings\n"), m_StringEntries.size()-nEntries);
69 nEntries = m_StringEntries.size();
71 if (!m_bQuiet)
72 _ftprintf(stdout, _T("Extracting Menus.........."));
73 EnumResourceNames(m_hResDll, RT_MENU, EnumResNameCallback, (long)this);
74 if (!m_bQuiet)
75 _ftprintf(stdout, _T("%4d Strings\n"), m_StringEntries.size()-nEntries);
76 nEntries = m_StringEntries.size();
77 if (!m_bQuiet)
78 _ftprintf(stdout, _T("Extracting Accelerators..."));
79 EnumResourceNames(m_hResDll, RT_ACCELERATOR, EnumResNameCallback, (long)this);
80 if (!m_bQuiet)
81 _ftprintf(stdout, _T("%4d Accelerators\n"), m_StringEntries.size()-nEntries);
82 nEntries = m_StringEntries.size();
84 // parse a probably existing file and update the translations which are
85 // already done
86 m_StringEntries.ParseFile(lpszPOFilePath, !bNoUpdate);
88 FreeLibrary(m_hResDll);
89 continue;
92 // at last, save the new file
93 if (bRet)
94 return m_StringEntries.SaveFile(lpszPOFilePath);
95 return FALSE;
98 BOOL CResModule::ExtractResources(LPCTSTR lpszSrcLangDllPath, LPCTSTR lpszPoFilePath, BOOL bNoUpdate)
100 m_hResDll = LoadLibrary(lpszSrcLangDllPath);
101 if (m_hResDll == NULL)
102 MYERROR;
104 size_t nEntries = 0;
105 // fill in the std::map with all translatable entries
107 if (!m_bQuiet)
108 _ftprintf(stdout, _T("Extracting StringTable...."));
109 EnumResourceNames(m_hResDll, RT_STRING, EnumResNameCallback, (long)this);
110 if (!m_bQuiet)
111 _ftprintf(stdout, _T("%4d Strings\n"), m_StringEntries.size());
112 nEntries = m_StringEntries.size();
114 if (!m_bQuiet)
115 _ftprintf(stdout, _T("Extracting Dialogs........"));
116 EnumResourceNames(m_hResDll, RT_DIALOG, EnumResNameCallback, (long)this);
117 if (!m_bQuiet)
118 _ftprintf(stdout, _T("%4d Strings\n"), m_StringEntries.size()-nEntries);
119 nEntries = m_StringEntries.size();
121 if (!m_bQuiet)
122 _ftprintf(stdout, _T("Extracting Menus.........."));
123 EnumResourceNames(m_hResDll, RT_MENU, EnumResNameCallback, (long)this);
124 if (!m_bQuiet)
125 _ftprintf(stdout, _T("%4d Strings\n"), m_StringEntries.size()-nEntries);
126 nEntries = m_StringEntries.size();
128 if (!m_bQuiet)
129 _ftprintf(stdout, _T("Extracting Accelerators..."));
130 EnumResourceNames(m_hResDll, RT_ACCELERATOR, EnumResNameCallback, (long)this);
131 if (!m_bQuiet)
132 _ftprintf(stdout, _T("%4d Accelerators\n"), m_StringEntries.size()-nEntries);
133 nEntries = m_StringEntries.size();
135 // parse a probably existing file and update the translations which are
136 // already done
137 m_StringEntries.ParseFile(lpszPoFilePath, !bNoUpdate);
139 // at last, save the new file
140 if (!m_StringEntries.SaveFile(lpszPoFilePath))
141 goto DONE_ERROR;
143 FreeLibrary(m_hResDll);
144 return TRUE;
146 DONE_ERROR:
147 if (m_hResDll)
148 FreeLibrary(m_hResDll);
149 return FALSE;
152 BOOL CResModule::CreateTranslatedResources(LPCTSTR lpszSrcLangDllPath, LPCTSTR lpszDestLangDllPath, LPCTSTR lpszPOFilePath)
154 if (!CopyFile(lpszSrcLangDllPath, lpszDestLangDllPath, FALSE))
155 MYERROR;
157 int count = 0;
160 m_hResDll = LoadLibraryEx (lpszSrcLangDllPath, NULL, LOAD_LIBRARY_AS_DATAFILE|LOAD_IGNORE_CODE_AUTHZ_LEVEL);
161 if (m_hResDll == NULL)
162 Sleep(100);
163 count++;
164 } while ((m_hResDll == NULL)&&(count < 5));
166 if (m_hResDll == NULL)
167 MYERROR;
169 sDestFile = std::wstring(lpszDestLangDllPath);
171 // get all translated strings
172 if (!m_StringEntries.ParseFile(lpszPOFilePath, FALSE))
173 goto DONE_ERROR;
174 m_bTranslatedStrings = 0;
175 m_bDefaultStrings = 0;
176 m_bTranslatedDialogStrings = 0;
177 m_bDefaultDialogStrings = 0;
178 m_bTranslatedMenuStrings = 0;
179 m_bDefaultMenuStrings = 0;
180 m_bTranslatedAcceleratorStrings = 0;
181 m_bDefaultAcceleratorStrings = 0;
183 if (!m_bQuiet)
184 _ftprintf(stdout, _T("Translating StringTable..."));
185 EnumResourceNames(m_hResDll, RT_STRING, EnumResNameWriteCallback, (long)this);
186 if (!m_bQuiet)
187 _ftprintf(stdout, _T("%4d translated, %4d not translated\n"), m_bTranslatedStrings, m_bDefaultStrings);
189 if (!m_bQuiet)
190 _ftprintf(stdout, _T("Translating Dialogs......."));
191 EnumResourceNames(m_hResDll, RT_DIALOG, EnumResNameWriteCallback, (long)this);
192 if (!m_bQuiet)
193 _ftprintf(stdout, _T("%4d translated, %4d not translated\n"), m_bTranslatedDialogStrings, m_bDefaultDialogStrings);
195 if (!m_bQuiet)
196 _ftprintf(stdout, _T("Translating Menus........."));
197 EnumResourceNames(m_hResDll, RT_MENU, EnumResNameWriteCallback, (long)this);
198 if (!m_bQuiet)
199 _ftprintf(stdout, _T("%4d translated, %4d not translated\n"), m_bTranslatedMenuStrings, m_bDefaultMenuStrings);
201 if (!m_bQuiet)
202 _ftprintf(stdout, _T("Translating Accelerators.."));
203 EnumResourceNames(m_hResDll, RT_ACCELERATOR, EnumResNameWriteCallback, (long)this);
204 if (!m_bQuiet)
205 _ftprintf(stdout, _T("%4d translated, %4d not translated\n"), m_bTranslatedAcceleratorStrings, m_bDefaultAcceleratorStrings);
207 FreeLibrary(m_hResDll);
208 return TRUE;
209 DONE_ERROR:
210 if (m_hResDll)
211 FreeLibrary(m_hResDll);
212 return FALSE;
215 BOOL CResModule::ExtractString(UINT nID)
217 HRSRC hrsrc = FindResource(m_hResDll, MAKEINTRESOURCE(nID), RT_STRING);
218 HGLOBAL hglStringTable;
219 LPWSTR p;
221 if (!hrsrc)
222 MYERROR;
223 hglStringTable = LoadResource(m_hResDll, hrsrc);
225 if (!hglStringTable)
226 goto DONE_ERROR;
227 p = (LPWSTR)LockResource(hglStringTable);
229 if (p == NULL)
230 goto DONE_ERROR;
231 /* [Block of 16 strings. The strings are Pascal style with a WORD
232 length preceding the string. 16 strings are always written, even
233 if not all slots are full. Any slots in the block with no string
234 have a zero WORD for the length.]
237 //first check how much memory we need
238 LPWSTR pp = p;
239 for (int i=0; i<16; ++i)
241 int len = GET_WORD(pp);
242 pp++;
243 std::wstring msgid = std::wstring(pp, len);
244 WCHAR * pBuf = new WCHAR[MAX_STRING_LENGTH*2];
245 SecureZeroMemory(pBuf, MAX_STRING_LENGTH*2*sizeof(WCHAR));
246 wcscpy(pBuf, msgid.c_str());
247 CUtils::StringExtend(pBuf);
249 if (wcslen(pBuf))
251 std::wstring str = std::wstring(pBuf);
252 RESOURCEENTRY entry = m_StringEntries[str];
253 entry.resourceIDs.insert(nID);
254 if (wcschr(str.c_str(), '%'))
255 entry.flag = _T("#, c-format");
256 m_StringEntries[str] = entry;
258 delete [] pBuf;
259 pp += len;
261 UnlockResource(hglStringTable);
262 FreeResource(hglStringTable);
263 return TRUE;
264 DONE_ERROR:
265 UnlockResource(hglStringTable);
266 FreeResource(hglStringTable);
267 MYERROR;
270 BOOL CResModule::ReplaceString(UINT nID, WORD wLanguage)
272 HRSRC hrsrc = FindResourceEx(m_hResDll, RT_STRING, MAKEINTRESOURCE(nID), wLanguage);
273 HGLOBAL hglStringTable;
274 LPWSTR p;
276 if (!hrsrc)
277 MYERROR;
278 hglStringTable = LoadResource(m_hResDll, hrsrc);
280 if (!hglStringTable)
281 goto DONE_ERROR;
282 p = (LPWSTR)LockResource(hglStringTable);
284 if (p == NULL)
285 goto DONE_ERROR;
286 /* [Block of 16 strings. The strings are Pascal style with a WORD
287 length preceding the string. 16 strings are always written, even
288 if not all slots are full. Any slots in the block with no string
289 have a zero WORD for the length.]
292 //first check how much memory we need
293 size_t nMem = 0;
294 LPWSTR pp = p;
295 for (int i=0; i<16; ++i)
297 nMem++;
298 size_t len = GET_WORD(pp);
299 pp++;
300 std::wstring msgid = std::wstring(pp, len);
301 WCHAR * pBuf = new WCHAR[MAX_STRING_LENGTH*2];
302 SecureZeroMemory(pBuf, MAX_STRING_LENGTH*2*sizeof(WCHAR));
303 wcscpy(pBuf, msgid.c_str());
304 CUtils::StringExtend(pBuf);
305 msgid = std::wstring(pBuf);
307 RESOURCEENTRY resEntry;
308 resEntry = m_StringEntries[msgid];
309 wcscpy(pBuf, resEntry.msgstr.c_str());
310 CUtils::StringCollapse(pBuf);
311 size_t newlen = wcslen(pBuf);
312 if (newlen)
313 nMem += newlen;
314 else
315 nMem += len;
316 pp += len;
317 delete [] pBuf;
320 WORD * newTable = new WORD[nMem + (nMem % 2)];
321 SecureZeroMemory(newTable, (nMem + (nMem % 2))*2);
323 size_t index = 0;
324 for (int i=0; i<16; ++i)
326 int len = GET_WORD(p);
327 p++;
328 std::wstring msgid = std::wstring(p, len);
329 WCHAR * pBuf = new WCHAR[MAX_STRING_LENGTH*2];
330 SecureZeroMemory(pBuf, MAX_STRING_LENGTH*2*sizeof(WCHAR));
331 wcscpy(pBuf, msgid.c_str());
332 CUtils::StringExtend(pBuf);
333 msgid = std::wstring(pBuf);
335 RESOURCEENTRY resEntry;
336 resEntry = m_StringEntries[msgid];
337 wcscpy(pBuf, resEntry.msgstr.c_str());
338 CUtils::StringCollapse(pBuf);
339 size_t newlen = wcslen(pBuf);
340 if (newlen)
342 newTable[index++] = (WORD)newlen;
343 wcsncpy((wchar_t *)&newTable[index], pBuf, newlen);
344 index += newlen;
345 m_bTranslatedStrings++;
347 else
349 newTable[index++] = (WORD)len;
350 if (len)
351 wcsncpy((wchar_t *)&newTable[index], p, len);
352 index += len;
353 if (len)
354 m_bDefaultStrings++;
356 p += len;
357 delete [] pBuf;
360 if (!UpdateResource(m_hUpdateRes, RT_STRING, MAKEINTRESOURCE(nID), (m_wTargetLang ? m_wTargetLang : wLanguage), newTable, (DWORD)(nMem + (nMem % 2))*2))
362 delete [] newTable;
363 goto DONE_ERROR;
366 if ((m_wTargetLang)&&(!UpdateResource(m_hUpdateRes, RT_STRING, MAKEINTRESOURCE(nID), wLanguage, NULL, 0)))
368 delete [] newTable;
369 goto DONE_ERROR;
371 delete [] newTable;
372 UnlockResource(hglStringTable);
373 FreeResource(hglStringTable);
374 return TRUE;
375 DONE_ERROR:
376 UnlockResource(hglStringTable);
377 FreeResource(hglStringTable);
378 MYERROR;
381 BOOL CResModule::ExtractMenu(UINT nID)
383 HRSRC hrsrc = FindResource(m_hResDll, MAKEINTRESOURCE(nID), RT_MENU);
384 HGLOBAL hglMenuTemplate;
385 WORD version, offset;
386 DWORD dwHelpId;
387 const WORD *p, *p0;
389 if (!hrsrc)
390 MYERROR;
392 hglMenuTemplate = LoadResource(m_hResDll, hrsrc);
394 if (!hglMenuTemplate)
395 MYERROR;
397 p = (const WORD*)LockResource(hglMenuTemplate);
399 if (p == NULL)
400 MYERROR;
402 // Standard MENU resource
403 //struct MenuHeader {
404 // WORD wVersion; // Currently zero
405 // WORD cbHeaderSize; // Also zero
406 //};
408 // MENUEX resource
409 //struct MenuExHeader {
410 // WORD wVersion; // One
411 // WORD wOffset;
412 // DWORD dwHelpId;
413 //};
414 p0 = p;
415 version = GET_WORD(p);
417 p++;
419 switch (version)
421 case 0:
423 offset = GET_WORD(p);
424 p += offset;
425 p++;
426 if (!ParseMenuResource(p))
427 goto DONE_ERROR;
429 break;
430 case 1:
432 offset = GET_WORD(p);
433 p++;
434 dwHelpId = GET_DWORD(p);
435 if (!ParseMenuExResource(p0 + offset))
436 goto DONE_ERROR;
438 break;
439 default:
440 goto DONE_ERROR;
443 UnlockResource(hglMenuTemplate);
444 FreeResource(hglMenuTemplate);
445 return TRUE;
447 DONE_ERROR:
448 UnlockResource(hglMenuTemplate);
449 FreeResource(hglMenuTemplate);
450 MYERROR;
453 BOOL CResModule::ReplaceMenu(UINT nID, WORD wLanguage)
455 HRSRC hrsrc = FindResourceEx(m_hResDll, RT_MENU, MAKEINTRESOURCE(nID), wLanguage);
456 HGLOBAL hglMenuTemplate;
457 WORD version, offset;
458 LPWSTR p;
459 WORD *p0;
460 DWORD dwHelpId;
462 if (!hrsrc)
463 MYERROR; //just the language wasn't found
465 hglMenuTemplate = LoadResource(m_hResDll, hrsrc);
467 if (!hglMenuTemplate)
468 MYERROR;
470 p = (LPWSTR)LockResource(hglMenuTemplate);
472 if (p == NULL)
473 MYERROR;
475 //struct MenuHeader {
476 // WORD wVersion; // Currently zero
477 // WORD cbHeaderSize; // Also zero
478 //};
480 // MENUEX resource
481 //struct MenuExHeader {
482 // WORD wVersion; // One
483 // WORD wOffset;
484 // DWORD dwHelpId;
485 //};
486 p0 = (WORD *)p;
487 version = GET_WORD(p);
489 p++;
491 switch (version)
493 case 0:
495 offset = GET_WORD(p);
496 p += offset;
497 p++;
498 size_t nMem = 0;
499 if (!CountMemReplaceMenuResource((WORD *)p, &nMem, NULL))
500 goto DONE_ERROR;
501 WORD * newMenu = new WORD[nMem + (nMem % 2)+2];
502 SecureZeroMemory(newMenu, (nMem + (nMem % 2)+2)*2);
503 size_t index = 2; // MenuHeader has 2 WORDs zero
504 if (!CountMemReplaceMenuResource((WORD *)p, &index, newMenu))
506 delete [] newMenu;
507 goto DONE_ERROR;
510 if (!UpdateResource(m_hUpdateRes, RT_MENU, MAKEINTRESOURCE(nID), (m_wTargetLang ? m_wTargetLang : wLanguage), newMenu, (DWORD)(nMem + (nMem % 2)+2)*2))
512 delete [] newMenu;
513 goto DONE_ERROR;
516 if ((m_wTargetLang)&&(!UpdateResource(m_hUpdateRes, RT_MENU, MAKEINTRESOURCE(nID), wLanguage, NULL, 0)))
518 delete [] newMenu;
519 goto DONE_ERROR;
521 delete [] newMenu;
523 break;
524 case 1:
526 offset = GET_WORD(p);
527 p++;
528 dwHelpId = GET_DWORD(p);
529 size_t nMem = 0;
530 if (!CountMemReplaceMenuExResource((WORD *)(p0 + offset), &nMem, NULL))
531 goto DONE_ERROR;
532 WORD * newMenu = new WORD[nMem + (nMem % 2) + 4];
533 SecureZeroMemory(newMenu, (nMem + (nMem % 2) + 4) * 2);
534 CopyMemory(newMenu, p0, 2 * sizeof(WORD) + sizeof(DWORD));
535 size_t index = 4; // MenuExHeader has 2 x WORD + 1 x DWORD
536 if (!CountMemReplaceMenuExResource((WORD *)(p0 + offset), &index, newMenu))
538 delete [] newMenu;
539 goto DONE_ERROR;
542 if (!UpdateResource(m_hUpdateRes, RT_MENU, MAKEINTRESOURCE(nID), (m_wTargetLang ? m_wTargetLang : wLanguage), newMenu, (DWORD)(nMem + (nMem % 2) + 4) * 2))
544 delete [] newMenu;
545 goto DONE_ERROR;
548 if ((m_wTargetLang)&&(!UpdateResource(m_hUpdateRes, RT_MENU, MAKEINTRESOURCE(nID), wLanguage, NULL, 0)))
550 delete [] newMenu;
551 goto DONE_ERROR;
553 delete [] newMenu;
555 break;
556 default:
557 goto DONE_ERROR;
560 UnlockResource(hglMenuTemplate);
561 FreeResource(hglMenuTemplate);
562 return TRUE;
564 DONE_ERROR:
565 UnlockResource(hglMenuTemplate);
566 FreeResource(hglMenuTemplate);
567 MYERROR;
570 const WORD* CResModule::ParseMenuResource(const WORD * res)
572 WORD flags;
573 WORD id = 0;
574 LPCWSTR str;
575 WORD *p0;
577 //struct PopupMenuItem {
578 // WORD fItemFlags;
579 // WCHAR szItemText[];
580 //};
581 //struct NormalMenuItem {
582 // WORD fItemFlags;
583 // WORD wMenuID;
584 // WCHAR szItemText[];
585 //};
589 p0 = (WORD *)res;
590 flags = GET_WORD(res);
591 res++;
592 if (!(flags & MF_POPUP))
594 id = GET_WORD(res); //normal menu item
595 res++;
597 else
598 id = (WORD)-1; //popup menu item
600 str = (LPCWSTR)res;
601 size_t l = wcslen(str)+1;
602 res += l;
604 if (flags & MF_POPUP)
606 TCHAR * pBuf = new TCHAR[MAX_STRING_LENGTH];
607 SecureZeroMemory(pBuf, MAX_STRING_LENGTH * sizeof(TCHAR));
608 _tcscpy(pBuf, str);
609 CUtils::StringExtend(pBuf);
611 std::wstring wstr = std::wstring(pBuf);
612 RESOURCEENTRY entry = m_StringEntries[wstr];
613 if (id)
614 entry.resourceIDs.insert(id);
616 m_StringEntries[wstr] = entry;
617 delete [] pBuf;
619 if ((res = ParseMenuResource(res))==0)
620 return NULL;
622 else if (id != 0)
624 TCHAR * pBuf = new TCHAR[MAX_STRING_LENGTH];
625 SecureZeroMemory(pBuf, MAX_STRING_LENGTH * sizeof(TCHAR));
626 _tcscpy(pBuf, str);
627 CUtils::StringExtend(pBuf);
629 std::wstring wstr = std::wstring(pBuf);
630 RESOURCEENTRY entry = m_StringEntries[wstr];
631 entry.resourceIDs.insert(id);
633 TCHAR szTempBuf[1024];
634 _stprintf(szTempBuf, _T("#: MenuEntry; ID:%d"), id);
635 MENUENTRY menu_entry;
636 menu_entry.wID = id;
637 menu_entry.reference = szTempBuf;
638 menu_entry.msgstr = wstr;
640 m_StringEntries[wstr] = entry;
641 m_MenuEntries[id] = menu_entry;
642 delete [] pBuf;
644 } while (!(flags & MF_END));
645 return res;
648 const WORD* CResModule::CountMemReplaceMenuResource(const WORD * res, size_t * wordcount, WORD * newMenu)
650 WORD flags;
651 WORD id = 0;
653 //struct PopupMenuItem {
654 // WORD fItemFlags;
655 // WCHAR szItemText[];
656 //};
657 //struct NormalMenuItem {
658 // WORD fItemFlags;
659 // WORD wMenuID;
660 // WCHAR szItemText[];
661 //};
665 flags = GET_WORD(res);
666 res++;
667 if (newMenu == NULL)
668 (*wordcount)++;
669 else
670 newMenu[(*wordcount)++] = flags;
671 if (!(flags & MF_POPUP))
673 id = GET_WORD(res); //normal menu item
674 res++;
675 if (newMenu == NULL)
676 (*wordcount)++;
677 else
678 newMenu[(*wordcount)++] = id;
680 else
681 id = (WORD)-1; //popup menu item
683 if (flags & MF_POPUP)
685 ReplaceStr((LPCWSTR)res, newMenu, wordcount, &m_bTranslatedMenuStrings, &m_bDefaultMenuStrings);
686 res += wcslen((LPCWSTR)res) + 1;
688 if ((res = CountMemReplaceMenuResource(res, wordcount, newMenu))==0)
689 return NULL;
691 else if (id != 0)
693 ReplaceStr((LPCWSTR)res, newMenu, wordcount, &m_bTranslatedMenuStrings, &m_bDefaultMenuStrings);
694 res += wcslen((LPCWSTR)res) + 1;
696 else
698 if (newMenu)
699 wcscpy((wchar_t *)&newMenu[(*wordcount)], (LPCWSTR)res);
700 (*wordcount) += wcslen((LPCWSTR)res) + 1;
701 res += wcslen((LPCWSTR)res) + 1;
703 } while (!(flags & MF_END));
704 return res;
707 const WORD* CResModule::ParseMenuExResource(const WORD * res)
709 DWORD dwType, dwState, menuId;
710 WORD bResInfo;
711 LPCWSTR str;
712 WORD *p0;
714 //struct MenuExItem {
715 // DWORD dwType;
716 // DWORD dwState;
717 // DWORD menuId;
718 // WORD bResInfo;
719 // WCHAR szText[];
720 // DWORD dwHelpId; - Popup menu only
721 //};
725 p0 = (WORD *)res;
726 dwType = GET_DWORD(res);
727 res += 2;
728 dwState = GET_DWORD(res);
729 res += 2;
730 menuId = GET_DWORD(res);
731 res += 2;
732 bResInfo = GET_WORD(res);
733 res++;
735 str = (LPCWSTR)res;
736 size_t l = wcslen(str)+1;
737 res += l;
738 // Align to DWORD boundary
739 res += ((((WORD)res + 3) & ~3) - (WORD)res)/sizeof(WORD);
741 if (dwType & MFT_SEPARATOR)
742 continue;
744 if (bResInfo & 0x01)
746 // Popup menu - note this can also have a non-zero ID
747 if (menuId == 0)
748 menuId = (WORD)-1;
749 TCHAR * pBuf = new TCHAR[MAX_STRING_LENGTH];
750 SecureZeroMemory(pBuf, MAX_STRING_LENGTH * sizeof(TCHAR));
751 _tcscpy(pBuf, str);
752 CUtils::StringExtend(pBuf);
754 std::wstring wstr = std::wstring(pBuf);
755 RESOURCEENTRY entry = m_StringEntries[wstr];
756 // Popup has a DWORD help entry on a DWORD boundary - skip over it
757 res += 2;
759 entry.resourceIDs.insert(menuId);
760 TCHAR szTempBuf[1024];
761 _stprintf(szTempBuf, _T("#: MenuExPopupEntry; ID:%d"), menuId);
762 MENUENTRY menu_entry;
763 menu_entry.wID = (WORD)menuId;
764 menu_entry.reference = szTempBuf;
765 menu_entry.msgstr = wstr;
766 m_StringEntries[wstr] = entry;
767 m_MenuEntries[(WORD)menuId] = menu_entry;
768 delete [] pBuf;
770 if ((res = ParseMenuExResource(res)) == 0)
771 return NULL;
772 } else if (menuId != 0)
774 TCHAR * pBuf = new TCHAR[MAX_STRING_LENGTH];
775 SecureZeroMemory(pBuf, MAX_STRING_LENGTH * sizeof(TCHAR));
776 _tcscpy(pBuf, str);
777 CUtils::StringExtend(pBuf);
779 std::wstring wstr = std::wstring(pBuf);
780 RESOURCEENTRY entry = m_StringEntries[wstr];
781 entry.resourceIDs.insert(menuId);
783 TCHAR szTempBuf[1024];
784 _stprintf(szTempBuf, _T("#: MenuExEntry; ID:%d"), menuId);
785 MENUENTRY menu_entry;
786 menu_entry.wID = (WORD)menuId;
787 menu_entry.reference = szTempBuf;
788 menu_entry.msgstr = wstr;
789 m_StringEntries[wstr] = entry;
790 m_MenuEntries[(WORD)menuId] = menu_entry;
791 delete [] pBuf;
793 } while (!(bResInfo & 0x80));
794 return res;
797 const WORD* CResModule::CountMemReplaceMenuExResource(const WORD * res, size_t * wordcount, WORD * newMenu)
799 DWORD dwType, dwState, menuId;
800 WORD bResInfo;
801 WORD *p0;
803 //struct MenuExItem {
804 // DWORD dwType;
805 // DWORD dwState;
806 // DWORD menuId;
807 // WORD bResInfo;
808 // WCHAR szText[];
809 // DWORD dwHelpId; - Popup menu only
810 //};
814 p0 = (WORD *)res;
815 dwType = GET_DWORD(res);
816 res += 2;
817 dwState = GET_DWORD(res);
818 res += 2;
819 menuId = GET_DWORD(res);
820 res += 2;
821 bResInfo = GET_WORD(res);
822 res++;
824 if (newMenu != NULL) {
825 CopyMemory(&newMenu[*wordcount], p0, 7 * sizeof(WORD));
827 (*wordcount) += 7;
829 if (dwType & MFT_SEPARATOR) {
830 // Align to DWORD
831 (*wordcount)++;
832 res++;
833 continue;
836 if (bResInfo & 0x01)
838 ReplaceStr((LPCWSTR)res, newMenu, wordcount, &m_bTranslatedMenuStrings, &m_bDefaultMenuStrings);
839 res += wcslen((LPCWSTR)res) + 1;
840 // Align to DWORD
841 res += ((((WORD)res + 3) & ~3) - (WORD)res)/sizeof(WORD);
842 if ((*wordcount) & 0x01)
843 (*wordcount)++;
845 if (newMenu != NULL)
846 CopyMemory(&newMenu[*wordcount], res, sizeof(DWORD)); // Copy Help ID
848 res += 2;
849 (*wordcount) += 2;
851 if ((res = CountMemReplaceMenuExResource(res, wordcount, newMenu)) == 0)
852 return NULL;
854 else if (menuId != 0)
856 ReplaceStr((LPCWSTR)res, newMenu, wordcount, &m_bTranslatedMenuStrings, &m_bDefaultMenuStrings);
857 res += wcslen((LPCWSTR)res) + 1;
859 else
861 if (newMenu)
862 wcscpy((wchar_t *)&newMenu[(*wordcount)], (LPCWSTR)res);
863 (*wordcount) += wcslen((LPCWSTR)res) + 1;
864 res += wcslen((LPCWSTR)res) + 1;
866 // Align to DWORD
867 res += ((((WORD)res + 3) & ~3) - (WORD)res)/sizeof(WORD);
868 if ((*wordcount) & 0x01)
869 (*wordcount)++;
870 } while (!(bResInfo & 0x80));
871 return res;
874 BOOL CResModule::ExtractAccelerator(UINT nID)
876 HRSRC hrsrc = FindResource(m_hResDll, MAKEINTRESOURCE(nID), RT_ACCELERATOR);
877 HGLOBAL hglAccTable;
878 WORD fFlags, wAnsi, wID;
879 const WORD* p;
880 bool bEnd(false);
882 if (!hrsrc)
883 MYERROR;
885 hglAccTable = LoadResource(m_hResDll, hrsrc);
887 if (!hglAccTable)
888 goto DONE_ERROR;
890 p = (const WORD*)LockResource(hglAccTable);
892 if (p == NULL)
893 MYERROR;
896 struct ACCELTABLEENTRY
898 WORD fFlags; FVIRTKEY, FSHIFT, FCONTROL, FALT, 0x80 - Last in a table
899 WORD wAnsi; ANSI character
900 WORD wId; Keyboard accelerator passed to windows
901 WORD padding; # bytes added to ensure aligned to DWORD boundary
907 fFlags = GET_WORD(p);
908 p++;
909 wAnsi = GET_WORD(p);
910 p++;
911 wID = GET_WORD(p);
912 p++;
913 p++; // Skip over padding
915 if ((fFlags & 0x80) == 0x80)
916 { // 0x80
917 bEnd = true;
920 if ((wAnsi < 0x30) ||
921 (wAnsi > 0x5A) ||
922 (wAnsi >= 0x3A && wAnsi <= 0x40))
923 continue;
925 TCHAR * pBuf = new TCHAR[1024];
926 SecureZeroMemory(pBuf, 1024 * sizeof(TCHAR));
928 // include the menu ID in the msgid to make sure that 'duplicate'
929 // accelerator keys are listed in the po-file.
930 // without this, we would get entries like this:
931 //#. Accelerator Entry for Menu ID:32809; '&Filter'
932 //#. Accelerator Entry for Menu ID:57636; '&Find'
933 //#: Corresponding Menu ID:32771; '&Find'
934 //msgid "V C +F"
935 //msgstr ""
937 // Since "filter" and "find" are most likely translated to words starting
938 // with different letters, we need to have a separate accelerator entry
939 // for each of those
940 _stprintf(pBuf, _T("ID:%d:"), wID);
942 // EXACTLY 5 characters long "ACS+X"
943 // V = Virtual key (or blank if not used)
944 // A = Alt key (or blank if not used)
945 // C = Ctrl key (or blank if not used)
946 // S = Shift key (or blank if not used)
947 // X = upper case character
948 // e.g. "V CS+Q" == Ctrl + Shift + 'Q'
949 if ((fFlags & FVIRTKEY) == FVIRTKEY) // 0x01
950 _tcscat(pBuf, _T("V"));
951 else
952 _tcscat(pBuf, _T(" "));
954 if ((fFlags & FALT) == FALT) // 0x10
955 _tcscat(pBuf, _T("A"));
956 else
957 _tcscat(pBuf, _T(" "));
959 if ((fFlags & FCONTROL) == FCONTROL) // 0x08
960 _tcscat(pBuf, _T("C"));
961 else
962 _tcscat(pBuf, _T(" "));
964 if ((fFlags & FSHIFT) == FSHIFT) // 0x04
965 _tcscat(pBuf, _T("S"));
966 else
967 _tcscat(pBuf, _T(" "));
969 _stprintf(pBuf, _T("%s+%c"), pBuf, wAnsi);
971 std::wstring wstr = std::wstring(pBuf);
972 RESOURCEENTRY AKey_entry = m_StringEntries[wstr];
974 TCHAR szTempBuf[1024];
975 SecureZeroMemory(szTempBuf, 1024 * sizeof(TCHAR));
976 std::wstring wmenu = _T("");
977 pME_iter = m_MenuEntries.find(wID);
978 if (pME_iter != m_MenuEntries.end())
980 wmenu = pME_iter->second.msgstr;
982 _stprintf(szTempBuf, _T("#. Accelerator Entry for Menu ID:%d; '%s'"), wID, wmenu.c_str());
983 AKey_entry.automaticcomments.push_back(std::wstring(szTempBuf));
985 m_StringEntries[wstr] = AKey_entry;
986 delete [] pBuf;
987 } while (!bEnd);
989 UnlockResource(hglAccTable);
990 FreeResource(hglAccTable);
991 return TRUE;
993 DONE_ERROR:
994 UnlockResource(hglAccTable);
995 FreeResource(hglAccTable);
996 MYERROR;
999 BOOL CResModule::ReplaceAccelerator(UINT nID, WORD wLanguage)
1001 LPACCEL lpaccelNew; // pointer to new accelerator table
1002 HACCEL haccelOld; // handle to old accelerator table
1003 int cAccelerators; // number of accelerators in table
1004 HGLOBAL hglAccTableNew;
1005 const WORD* p;
1006 int i;
1008 haccelOld = LoadAccelerators(m_hResDll, MAKEINTRESOURCE(nID));
1010 if (haccelOld == NULL)
1011 MYERROR;
1013 cAccelerators = CopyAcceleratorTable(haccelOld, NULL, 0);
1015 lpaccelNew = (LPACCEL) LocalAlloc(LPTR, cAccelerators * sizeof(ACCEL));
1017 if (lpaccelNew == NULL)
1018 MYERROR;
1020 CopyAcceleratorTable(haccelOld, lpaccelNew, cAccelerators);
1022 // Find the accelerator that the user modified
1023 // and change its flags and virtual-key code
1024 // as appropriate.
1026 BYTE xfVirt;
1027 WORD xkey;
1028 for (i = 0; i < cAccelerators; i++)
1030 m_bDefaultAcceleratorStrings++;
1031 if ((lpaccelNew[i].key < 0x30) ||
1032 (lpaccelNew[i].key > 0x5A) ||
1033 (lpaccelNew[i].key >= 0x3A && lpaccelNew[i].key <= 0x40))
1034 continue;
1036 TCHAR * pBuf = new TCHAR[1024];
1037 SecureZeroMemory(pBuf, 1024 * sizeof(TCHAR));
1039 _stprintf(pBuf, _T("ID:%d:"), lpaccelNew[i].cmd);
1041 // get original key combination
1042 if ((lpaccelNew[i].fVirt & FVIRTKEY) == FVIRTKEY) // 0x01
1043 _tcscat(pBuf, _T("V"));
1044 else
1045 _tcscat(pBuf, _T(" "));
1047 if ((lpaccelNew[i].fVirt & FALT) == FALT) // 0x10
1048 _tcscat(pBuf, _T("A"));
1049 else
1050 _tcscat(pBuf, _T(" "));
1052 if ((lpaccelNew[i].fVirt & FCONTROL) == FCONTROL) // 0x08
1053 _tcscat(pBuf, _T("C"));
1054 else
1055 _tcscat(pBuf, _T(" "));
1057 if ((lpaccelNew[i].fVirt & FSHIFT) == FSHIFT) // 0x04
1058 _tcscat(pBuf, _T("S"));
1059 else
1060 _tcscat(pBuf, _T(" "));
1062 _stprintf(pBuf, _T("%s+%c"), pBuf, lpaccelNew[i].key);
1064 // Is it there?
1065 std::map<std::wstring, RESOURCEENTRY>::iterator pAK_iter = m_StringEntries.find(pBuf);
1066 if (pAK_iter != m_StringEntries.end())
1068 m_bTranslatedAcceleratorStrings++;
1069 xfVirt = 0;
1070 xkey = 0;
1071 std::wstring wtemp = pAK_iter->second.msgstr;
1072 wtemp = wtemp.substr(wtemp.find_last_of(':')+1);
1073 if (wtemp.size() != 6)
1074 continue;
1075 if (wtemp.compare(0, 1, _T("V")) == 0)
1076 xfVirt |= FVIRTKEY;
1077 else if (wtemp.compare(0, 1, _T(" ")) != 0)
1078 continue; // not a space - user must have made a mistake when translating
1079 if (wtemp.compare(1, 1, _T("A")) == 0)
1080 xfVirt |= FALT;
1081 else if (wtemp.compare(1, 1, _T(" ")) != 0)
1082 continue; // not a space - user must have made a mistake when translating
1083 if (wtemp.compare(2, 1, _T("C")) == 0)
1084 xfVirt |= FCONTROL;
1085 else if (wtemp.compare(2, 1, _T(" ")) != 0)
1086 continue; // not a space - user must have made a mistake when translating
1087 if (wtemp.compare(3, 1, _T("S")) == 0)
1088 xfVirt |= FSHIFT;
1089 else if (wtemp.compare(3, 1, _T(" ")) != 0)
1090 continue; // not a space - user must have made a mistake when translating
1091 if (wtemp.compare(4, 1, _T("+")) == 0)
1093 _stscanf(wtemp.substr(5, 1).c_str(), _T("%c"), &xkey);
1094 lpaccelNew[i].fVirt = xfVirt;
1095 lpaccelNew[i].key = xkey;
1100 // Create the new accelerator table
1101 hglAccTableNew = LocalAlloc(LPTR, cAccelerators * 4 * sizeof(WORD));
1102 p = (WORD *)hglAccTableNew;
1103 lpaccelNew[cAccelerators-1].fVirt |= 0x80;
1104 for (i = 0; i < cAccelerators; i++)
1106 memcpy((void *)p, &lpaccelNew[i].fVirt, 1);
1107 p++;
1108 memcpy((void *)p, &lpaccelNew[i].key, sizeof(WORD));
1109 p++;
1110 memcpy((void *)p, &lpaccelNew[i].cmd, sizeof(WORD));
1111 p++;
1112 p++;
1115 if (!UpdateResource(m_hUpdateRes, RT_ACCELERATOR, MAKEINTRESOURCE(nID),
1116 (m_wTargetLang ? m_wTargetLang : wLanguage), hglAccTableNew /* haccelNew*/, cAccelerators * 4 * sizeof(WORD)))
1118 goto DONE_ERROR;
1121 if ((m_wTargetLang)&&(!UpdateResource(m_hUpdateRes, RT_ACCELERATOR, MAKEINTRESOURCE(nID), wLanguage, NULL, 0)))
1123 goto DONE_ERROR;
1126 LocalFree(lpaccelNew);
1127 return TRUE;
1129 DONE_ERROR:
1130 LocalFree(lpaccelNew);
1131 MYERROR;
1134 BOOL CResModule::ExtractDialog(UINT nID)
1136 const WORD* lpDlg;
1137 const WORD* lpDlgItem;
1138 DIALOGINFO dlg;
1139 DLGITEMINFO dlgItem;
1140 WORD bNumControls;
1141 HRSRC hrsrc;
1142 HGLOBAL hGlblDlgTemplate;
1144 hrsrc = FindResource(m_hResDll, MAKEINTRESOURCE(nID), RT_DIALOG);
1146 if (hrsrc == NULL)
1147 MYERROR;
1149 hGlblDlgTemplate = LoadResource(m_hResDll, hrsrc);
1150 if (hGlblDlgTemplate == NULL)
1151 MYERROR;
1153 lpDlg = (const WORD*) LockResource(hGlblDlgTemplate);
1155 if (lpDlg == NULL)
1156 MYERROR;
1158 lpDlgItem = (const WORD*) GetDialogInfo(lpDlg, &dlg);
1159 bNumControls = dlg.nbItems;
1161 if (dlg.caption)
1163 TCHAR * pBuf = new TCHAR[MAX_STRING_LENGTH];
1164 SecureZeroMemory(pBuf, MAX_STRING_LENGTH * sizeof(TCHAR));
1165 _tcscpy(pBuf, dlg.caption);
1166 CUtils::StringExtend(pBuf);
1168 std::wstring wstr = std::wstring(pBuf);
1169 RESOURCEENTRY entry = m_StringEntries[wstr];
1170 entry.resourceIDs.insert(nID);
1172 m_StringEntries[wstr] = entry;
1173 delete [] pBuf;
1176 while (bNumControls-- != 0)
1178 TCHAR szTitle[500];
1179 SecureZeroMemory(szTitle, sizeof(szTitle));
1180 BOOL bCode;
1182 lpDlgItem = GetControlInfo((WORD *) lpDlgItem, &dlgItem, dlg.dialogEx, &bCode);
1184 if (bCode == FALSE)
1185 _tcscpy(szTitle, dlgItem.windowName);
1187 if (_tcslen(szTitle) > 0)
1189 CUtils::StringExtend(szTitle);
1191 std::wstring wstr = std::wstring(szTitle);
1192 RESOURCEENTRY entry = m_StringEntries[wstr];
1193 entry.resourceIDs.insert(dlgItem.id);
1195 m_StringEntries[wstr] = entry;
1199 UnlockResource(hGlblDlgTemplate);
1200 FreeResource(hGlblDlgTemplate);
1201 return (TRUE);
1204 BOOL CResModule::ReplaceDialog(UINT nID, WORD wLanguage)
1206 const WORD* lpDlg;
1207 HRSRC hrsrc;
1208 HGLOBAL hGlblDlgTemplate;
1210 hrsrc = FindResourceEx(m_hResDll, RT_DIALOG, MAKEINTRESOURCE(nID), wLanguage);
1212 if (hrsrc == NULL)
1213 MYERROR;
1215 hGlblDlgTemplate = LoadResource(m_hResDll, hrsrc);
1217 if (hGlblDlgTemplate == NULL)
1218 MYERROR;
1220 lpDlg = (WORD *) LockResource(hGlblDlgTemplate);
1222 if (lpDlg == NULL)
1223 MYERROR;
1225 size_t nMem = 0;
1226 const WORD * p = lpDlg;
1227 if (!CountMemReplaceDialogResource(p, &nMem, NULL))
1228 goto DONE_ERROR;
1229 WORD * newDialog = new WORD[nMem + (nMem % 2)];
1230 SecureZeroMemory(newDialog, (nMem + (nMem % 2))*2);
1232 size_t index = 0;
1233 if (!CountMemReplaceDialogResource(lpDlg, &index, newDialog))
1235 delete [] newDialog;
1236 goto DONE_ERROR;
1239 if (!UpdateResource(m_hUpdateRes, RT_DIALOG, MAKEINTRESOURCE(nID), (m_wTargetLang ? m_wTargetLang : wLanguage), newDialog, (DWORD)(nMem + (nMem % 2))*2))
1241 delete [] newDialog;
1242 goto DONE_ERROR;
1245 if ((m_wTargetLang)&&(!UpdateResource(m_hUpdateRes, RT_DIALOG, MAKEINTRESOURCE(nID), wLanguage, NULL, 0)))
1247 delete [] newDialog;
1248 goto DONE_ERROR;
1251 delete [] newDialog;
1252 UnlockResource(hGlblDlgTemplate);
1253 FreeResource(hGlblDlgTemplate);
1254 return TRUE;
1256 DONE_ERROR:
1257 UnlockResource(hGlblDlgTemplate);
1258 FreeResource(hGlblDlgTemplate);
1259 MYERROR;
1262 const WORD* CResModule::GetDialogInfo(const WORD * pTemplate, LPDIALOGINFO lpDlgInfo)
1264 const WORD* p = (const WORD *)pTemplate;
1266 lpDlgInfo->style = GET_DWORD(p);
1267 p += 2;
1269 if (lpDlgInfo->style == 0xffff0001) // DIALOGEX resource
1271 lpDlgInfo->dialogEx = TRUE;
1272 lpDlgInfo->helpId = GET_DWORD(p);
1273 p += 2;
1274 lpDlgInfo->exStyle = GET_DWORD(p);
1275 p += 2;
1276 lpDlgInfo->style = GET_DWORD(p);
1277 p += 2;
1279 else
1281 lpDlgInfo->dialogEx = FALSE;
1282 lpDlgInfo->helpId = 0;
1283 lpDlgInfo->exStyle = GET_DWORD(p);
1284 p += 2;
1287 lpDlgInfo->nbItems = GET_WORD(p);
1288 p++;
1290 lpDlgInfo->x = GET_WORD(p);
1291 p++;
1293 lpDlgInfo->y = GET_WORD(p);
1294 p++;
1296 lpDlgInfo->cx = GET_WORD(p);
1297 p++;
1299 lpDlgInfo->cy = GET_WORD(p);
1300 p++;
1302 // Get the menu name
1304 switch (GET_WORD(p))
1306 case 0x0000:
1307 lpDlgInfo->menuName = NULL;
1308 p++;
1309 break;
1310 case 0xffff:
1311 lpDlgInfo->menuName = (LPCTSTR) (WORD) GET_WORD(p + 1);
1312 p += 2;
1313 break;
1314 default:
1315 lpDlgInfo->menuName = (LPCTSTR) p;
1316 p += wcslen((LPCWSTR) p) + 1;
1317 break;
1320 // Get the class name
1322 switch (GET_WORD(p))
1324 case 0x0000:
1325 lpDlgInfo->className = (LPCTSTR)MAKEINTATOM(32770);
1326 p++;
1327 break;
1328 case 0xffff:
1329 lpDlgInfo->className = (LPCTSTR) (WORD) GET_WORD(p + 1);
1330 p += 2;
1331 break;
1332 default:
1333 lpDlgInfo->className = (LPCTSTR) p;
1334 p += wcslen((LPCTSTR)p) + 1;
1335 break;
1338 // Get the window caption
1340 lpDlgInfo->caption = (LPCTSTR)p;
1341 p += wcslen((LPCWSTR) p) + 1;
1343 // Get the font name
1345 if (lpDlgInfo->style & DS_SETFONT)
1347 lpDlgInfo->pointSize = GET_WORD(p);
1348 p++;
1350 if (lpDlgInfo->dialogEx)
1352 lpDlgInfo->weight = GET_WORD(p);
1353 p++;
1354 lpDlgInfo->italic = LOBYTE(GET_WORD(p));
1355 p++;
1357 else
1359 lpDlgInfo->weight = FW_DONTCARE;
1360 lpDlgInfo->italic = FALSE;
1363 lpDlgInfo->faceName = (LPCTSTR)p;
1364 p += wcslen((LPCWSTR) p) + 1;
1366 // First control is on DWORD boundary
1367 return (const WORD *) ((((long)p) + 3) & ~3);
1370 const WORD* CResModule::GetControlInfo(const WORD* p, LPDLGITEMINFO lpDlgItemInfo, BOOL dialogEx, LPBOOL bIsID)
1372 if (dialogEx)
1374 lpDlgItemInfo->helpId = GET_DWORD(p);
1375 p += 2;
1376 lpDlgItemInfo->exStyle = GET_DWORD(p);
1377 p += 2;
1378 lpDlgItemInfo->style = GET_DWORD(p);
1379 p += 2;
1381 else
1383 lpDlgItemInfo->helpId = 0;
1384 lpDlgItemInfo->style = GET_DWORD(p);
1385 p += 2;
1386 lpDlgItemInfo->exStyle = GET_DWORD(p);
1387 p += 2;
1390 lpDlgItemInfo->x = GET_WORD(p);
1391 p++;
1393 lpDlgItemInfo->y = GET_WORD(p);
1394 p++;
1396 lpDlgItemInfo->cx = GET_WORD(p);
1397 p++;
1399 lpDlgItemInfo->cy = GET_WORD(p);
1400 p++;
1402 if (dialogEx)
1404 // ID is a DWORD for DIALOGEX
1405 lpDlgItemInfo->id = (WORD) GET_DWORD(p);
1406 p += 2;
1408 else
1410 lpDlgItemInfo->id = GET_WORD(p);
1411 p++;
1414 if (GET_WORD(p) == 0xffff)
1416 GET_WORD(p + 1);
1418 p += 2;
1420 else
1422 lpDlgItemInfo->className = (LPCTSTR) p;
1423 p += wcslen((LPCWSTR) p) + 1;
1426 if (GET_WORD(p) == 0xffff) // an integer ID?
1428 *bIsID = TRUE;
1429 lpDlgItemInfo->windowName = (LPCTSTR) (DWORD) GET_WORD(p + 1);
1430 p += 2;
1432 else
1434 *bIsID = FALSE;
1435 lpDlgItemInfo->windowName = (LPCTSTR) p;
1436 p += wcslen((LPCWSTR) p) + 1;
1439 if (GET_WORD(p))
1441 lpDlgItemInfo->data = (LPVOID) (p + 1);
1442 p += GET_WORD(p) / sizeof(WORD);
1444 else
1445 lpDlgItemInfo->data = NULL;
1447 p++;
1448 // Next control is on DWORD boundary
1449 return (const WORD *)((((long)p) + 3) & ~3);
1452 const WORD * CResModule::CountMemReplaceDialogResource(const WORD * res, size_t * wordcount, WORD * newDialog)
1454 BOOL bEx = FALSE;
1455 DWORD style = GET_DWORD(res);
1456 if (newDialog)
1458 newDialog[(*wordcount)++] = GET_WORD(res++);
1459 newDialog[(*wordcount)++] = GET_WORD(res++);
1461 else
1463 res += 2;
1464 (*wordcount) += 2;
1467 if (style == 0xffff0001) // DIALOGEX resource
1469 bEx = TRUE;
1470 if (newDialog)
1472 newDialog[(*wordcount)++] = GET_WORD(res++); //help id
1473 newDialog[(*wordcount)++] = GET_WORD(res++); //help id
1474 newDialog[(*wordcount)++] = GET_WORD(res++); //exStyle
1475 newDialog[(*wordcount)++] = GET_WORD(res++); //exStyle
1476 style = GET_DWORD(res);
1477 newDialog[(*wordcount)++] = GET_WORD(res++); //style
1478 newDialog[(*wordcount)++] = GET_WORD(res++); //style
1480 else
1482 res += 4;
1483 style = GET_DWORD(res);
1484 res += 2;
1485 (*wordcount) += 6;
1488 else
1490 bEx = FALSE;
1491 if (newDialog)
1493 newDialog[(*wordcount)++] = GET_WORD(res++); //exStyle
1494 newDialog[(*wordcount)++] = GET_WORD(res++); //exStyle
1495 //style = GET_DWORD(res);
1496 //newDialog[(*wordcount)++] = GET_WORD(res++); //style
1497 //newDialog[(*wordcount)++] = GET_WORD(res++); //style
1499 else
1501 res += 2;
1502 (*wordcount) += 2;
1506 if (newDialog)
1507 newDialog[(*wordcount)] = GET_WORD(res);
1508 WORD nbItems = GET_WORD(res);
1509 (*wordcount)++;
1510 res++;
1512 if (newDialog)
1513 newDialog[(*wordcount)] = GET_WORD(res); //x
1514 (*wordcount)++;
1515 res++;
1517 if (newDialog)
1518 newDialog[(*wordcount)] = GET_WORD(res); //y
1519 (*wordcount)++;
1520 res++;
1522 if (newDialog)
1523 newDialog[(*wordcount)] = GET_WORD(res); //cx
1524 (*wordcount)++;
1525 res++;
1527 if (newDialog)
1528 newDialog[(*wordcount)] = GET_WORD(res); //cy
1529 (*wordcount)++;
1530 res++;
1532 // Get the menu name
1534 switch (GET_WORD(res))
1536 case 0x0000:
1537 if (newDialog)
1538 newDialog[(*wordcount)] = GET_WORD(res);
1539 (*wordcount)++;
1540 res++;
1541 break;
1542 case 0xffff:
1543 if (newDialog)
1545 newDialog[(*wordcount)++] = GET_WORD(res++);
1546 newDialog[(*wordcount)++] = GET_WORD(res++);
1548 else
1550 (*wordcount) += 2;
1551 res += 2;
1553 break;
1554 default:
1555 if (newDialog)
1557 wcscpy((LPWSTR)&newDialog[(*wordcount)], (LPCWSTR)res);
1559 (*wordcount) += wcslen((LPCWSTR) res) + 1;
1560 res += wcslen((LPCWSTR) res) + 1;
1561 break;
1564 // Get the class name
1566 switch (GET_WORD(res))
1568 case 0x0000:
1569 if (newDialog)
1570 newDialog[(*wordcount)] = GET_WORD(res);
1571 (*wordcount)++;
1572 res++;
1573 break;
1574 case 0xffff:
1575 if (newDialog)
1577 newDialog[(*wordcount)++] = GET_WORD(res++);
1578 newDialog[(*wordcount)++] = GET_WORD(res++);
1580 else
1582 (*wordcount) += 2;
1583 res += 2;
1585 break;
1586 default:
1587 if (newDialog)
1589 wcscpy((LPWSTR)&newDialog[(*wordcount)], (LPCWSTR)res);
1591 (*wordcount) += wcslen((LPCWSTR) res) + 1;
1592 res += wcslen((LPCWSTR) res) + 1;
1593 break;
1596 // Get the window caption
1598 ReplaceStr((LPCWSTR)res, newDialog, wordcount, &m_bTranslatedDialogStrings, &m_bDefaultDialogStrings);
1599 res += wcslen((LPCWSTR)res) + 1;
1601 // Get the font name
1603 if (style & DS_SETFONT)
1605 if (newDialog)
1606 newDialog[(*wordcount)] = GET_WORD(res);
1607 res++;
1608 (*wordcount)++;
1610 if (bEx)
1612 if (newDialog)
1614 newDialog[(*wordcount)++] = GET_WORD(res++);
1615 newDialog[(*wordcount)++] = GET_WORD(res++);
1617 else
1619 res += 2;
1620 (*wordcount) += 2;
1624 if (newDialog)
1625 wcscpy((LPWSTR)&newDialog[(*wordcount)], (LPCWSTR)res);
1626 (*wordcount) += wcslen((LPCWSTR)res) + 1;
1627 res += wcslen((LPCWSTR)res) + 1;
1629 // First control is on DWORD boundary
1630 while ((*wordcount)%2)
1631 (*wordcount)++;
1632 while ((ULONG)res % 4)
1633 res++;
1635 while (nbItems--)
1637 res = ReplaceControlInfo(res, wordcount, newDialog, bEx);
1639 return res;
1642 const WORD* CResModule::ReplaceControlInfo(const WORD * res, size_t * wordcount, WORD * newDialog, BOOL bEx)
1644 if (bEx)
1646 if (newDialog)
1648 newDialog[(*wordcount)++] = GET_WORD(res++); //helpid
1649 newDialog[(*wordcount)++] = GET_WORD(res++); //helpid
1651 else
1653 res += 2;
1654 (*wordcount) += 2;
1657 if (newDialog)
1659 LONG * exStyle = (LONG*)&newDialog[(*wordcount)];
1660 newDialog[(*wordcount)++] = GET_WORD(res++); //exStyle
1661 newDialog[(*wordcount)++] = GET_WORD(res++); //exStyle
1662 if (m_bRTL)
1663 *exStyle |= WS_EX_RTLREADING;
1665 else
1667 res += 2;
1668 (*wordcount) += 2;
1671 if (newDialog)
1673 newDialog[(*wordcount)++] = GET_WORD(res++); //style
1674 newDialog[(*wordcount)++] = GET_WORD(res++); //style
1676 else
1678 res += 2;
1679 (*wordcount) += 2;
1682 if (newDialog)
1683 newDialog[(*wordcount)] = GET_WORD(res); //x
1684 res++;
1685 (*wordcount)++;
1687 if (newDialog)
1688 newDialog[(*wordcount)] = GET_WORD(res); //y
1689 res++;
1690 (*wordcount)++;
1692 if (newDialog)
1693 newDialog[(*wordcount)] = GET_WORD(res); //cx
1694 res++;
1695 (*wordcount)++;
1697 if (newDialog)
1698 newDialog[(*wordcount)] = GET_WORD(res); //cy
1699 res++;
1700 (*wordcount)++;
1702 if (bEx)
1704 // ID is a DWORD for DIALOGEX
1705 if (newDialog)
1707 newDialog[(*wordcount)++] = GET_WORD(res++);
1708 newDialog[(*wordcount)++] = GET_WORD(res++);
1710 else
1712 res += 2;
1713 (*wordcount) += 2;
1716 else
1718 if (newDialog)
1719 newDialog[(*wordcount)] = GET_WORD(res);
1720 res++;
1721 (*wordcount)++;
1724 if (GET_WORD(res) == 0xffff) //classID
1726 if (newDialog)
1728 newDialog[(*wordcount)++] = GET_WORD(res++);
1729 newDialog[(*wordcount)++] = GET_WORD(res++);
1731 else
1733 res += 2;
1734 (*wordcount) += 2;
1737 else
1739 if (newDialog)
1740 wcscpy((LPWSTR)&newDialog[(*wordcount)], (LPCWSTR)res);
1741 (*wordcount) += wcslen((LPCWSTR) res) + 1;
1742 res += wcslen((LPCWSTR) res) + 1;
1745 if (GET_WORD(res) == 0xffff) // an integer ID?
1747 if (newDialog)
1749 newDialog[(*wordcount)++] = GET_WORD(res++);
1750 newDialog[(*wordcount)++] = GET_WORD(res++);
1752 else
1754 res += 2;
1755 (*wordcount) += 2;
1758 else
1760 ReplaceStr((LPCWSTR)res, newDialog, wordcount, &m_bTranslatedDialogStrings, &m_bDefaultDialogStrings);
1761 res += wcslen((LPCWSTR)res) + 1;
1764 if (newDialog)
1765 memcpy(&newDialog[(*wordcount)], res, (GET_WORD(res)+1)*sizeof(WORD));
1766 (*wordcount) += (GET_WORD(res)+1);
1767 res += (GET_WORD(res)+1);
1768 // Next control is on DWORD boundary
1769 while ((*wordcount) % 2)
1770 (*wordcount)++;
1771 return (const WORD *)((((long)res) + 3) & ~3);
1774 BOOL CALLBACK CResModule::EnumResNameCallback(HMODULE /*hModule*/, LPCTSTR lpszType, LPTSTR lpszName, LONG_PTR lParam)
1776 CResModule* lpResModule = (CResModule*)lParam;
1778 if (lpszType == RT_STRING)
1780 if (IS_INTRESOURCE(lpszName))
1782 if (!lpResModule->ExtractString(LOWORD(lpszName)))
1783 return FALSE;
1786 else if (lpszType == RT_MENU)
1788 if (IS_INTRESOURCE(lpszName))
1790 if (!lpResModule->ExtractMenu(LOWORD(lpszName)))
1791 return FALSE;
1794 else if (lpszType == RT_DIALOG)
1796 if (IS_INTRESOURCE(lpszName))
1798 if (!lpResModule->ExtractDialog(LOWORD(lpszName)))
1799 return FALSE;
1802 else if (lpszType == RT_ACCELERATOR)
1804 if (IS_INTRESOURCE(lpszName))
1806 if (!lpResModule->ExtractAccelerator(LOWORD(lpszName)))
1807 return FALSE;
1811 return TRUE;
1814 #pragma warning(push)
1815 #pragma warning(disable: 4189)
1816 BOOL CALLBACK CResModule::EnumResNameWriteCallback(HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG_PTR lParam)
1818 CResModule* lpResModule = (CResModule*)lParam;
1819 return EnumResourceLanguages(hModule, lpszType, lpszName, (ENUMRESLANGPROC)&lpResModule->EnumResWriteLangCallback, lParam);
1821 #pragma warning(pop)
1823 BOOL CALLBACK CResModule::EnumResWriteLangCallback(HMODULE /*hModule*/, LPCTSTR lpszType, LPTSTR lpszName, WORD wLanguage, LONG_PTR lParam)
1825 BOOL bRes = FALSE;
1826 CResModule* lpResModule = (CResModule*)lParam;
1829 int count = 0;
1832 lpResModule->m_hUpdateRes = BeginUpdateResource(lpResModule->sDestFile.c_str(), FALSE);
1833 if (lpResModule->m_hUpdateRes == NULL)
1834 Sleep(100);
1835 count++;
1836 } while ((lpResModule->m_hUpdateRes == NULL)&&(count < 5));
1838 if (lpszType == RT_STRING)
1840 if (IS_INTRESOURCE(lpszName))
1842 bRes = lpResModule->ReplaceString(LOWORD(lpszName), wLanguage);
1845 else if (lpszType == RT_MENU)
1847 if (IS_INTRESOURCE(lpszName))
1849 bRes = lpResModule->ReplaceMenu(LOWORD(lpszName), wLanguage);
1852 else if (lpszType == RT_DIALOG)
1854 if (IS_INTRESOURCE(lpszName))
1856 bRes = lpResModule->ReplaceDialog(LOWORD(lpszName), wLanguage);
1859 else if (lpszType == RT_ACCELERATOR)
1861 if (IS_INTRESOURCE(lpszName))
1863 bRes = lpResModule->ReplaceAccelerator(LOWORD(lpszName), wLanguage);
1867 if (!EndUpdateResource(lpResModule->m_hUpdateRes, !bRes))
1868 MYERROR;
1869 return bRes;
1873 void CResModule::ReplaceStr(LPCWSTR src, WORD * dest, size_t * count, int * translated, int * def)
1875 TCHAR * pBuf = new TCHAR[MAX_STRING_LENGTH];
1876 SecureZeroMemory(pBuf, MAX_STRING_LENGTH * sizeof(TCHAR));
1877 wcscpy(pBuf, src);
1878 CUtils::StringExtend(pBuf);
1880 std::wstring wstr = std::wstring(pBuf);
1881 RESOURCEENTRY entry = m_StringEntries[wstr];
1882 if (entry.msgstr.size())
1884 wcscpy(pBuf, entry.msgstr.c_str());
1885 CUtils::StringCollapse(pBuf);
1886 if (dest)
1887 wcscpy((wchar_t *)&dest[(*count)], pBuf);
1888 (*count) += wcslen(pBuf)+1;
1889 (*translated)++;
1891 else
1893 if (dest)
1894 wcscpy((wchar_t *)&dest[(*count)], src);
1895 (*count) += wcslen(src) + 1;
1896 if (wcslen(src))
1897 (*def)++;
1899 delete [] pBuf;