OSDN Git Service

Add ResText Source code from SVN 14346
authorFrank Li <lznuaa@gmail.com>
Sat, 7 Feb 2009 13:59:21 +0000 (21:59 +0800)
committerFrank Li <lznuaa@gmail.com>
Sat, 7 Feb 2009 13:59:21 +0000 (21:59 +0800)
12 files changed:
src/ResText/POFile.cpp [new file with mode: 0644]
src/ResText/POFile.h [new file with mode: 0644]
src/ResText/ResModule.cpp [new file with mode: 0644]
src/ResText/ResModule.h [new file with mode: 0644]
src/ResText/ResText.cpp [new file with mode: 0644]
src/ResText/ResText.vcproj [new file with mode: 0644]
src/ResText/Utils.cpp [new file with mode: 0644]
src/ResText/Utils.h [new file with mode: 0644]
src/ResText/codecvt.cpp [new file with mode: 0644]
src/ResText/codecvt.h [new file with mode: 0644]
src/ResText/stdafx.cpp [new file with mode: 0644]
src/ResText/stdafx.h [new file with mode: 0644]

diff --git a/src/ResText/POFile.cpp b/src/ResText/POFile.cpp
new file mode 100644 (file)
index 0000000..e4d5fbc
--- /dev/null
@@ -0,0 +1,236 @@
+// TortoiseSVN - a Windows shell extension for easy version control\r
+\r
+// Copyright (C) 2003-2008 - TortoiseSVN\r
+\r
+// This program is free software; you can redistribute it and/or\r
+// modify it under the terms of the GNU General Public License\r
+// as published by the Free Software Foundation; either version 2\r
+// of the License, or (at your option) any later version.\r
+\r
+// This program is distributed in the hope that it will be useful,\r
+// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+// GNU General Public License for more details.\r
+\r
+// You should have received a copy of the GNU General Public License\r
+// along with this program; if not, write to the Free Software Foundation,\r
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
+#include "StdAfx.h"\r
+#include "shlwapi.h"\r
+#include <fstream>\r
+#include "codecvt.h"\r
+#include "Utils.h"\r
+#include "ResModule.h"\r
+#include ".\pofile.h"\r
+\r
+#define MYERROR        {CUtils::Error(); return FALSE;}\r
+\r
+CPOFile::CPOFile()\r
+{\r
+}\r
+\r
+CPOFile::~CPOFile(void)\r
+{\r
+}\r
+\r
+BOOL CPOFile::ParseFile(LPCTSTR szPath, BOOL bUpdateExisting /* = TRUE */)\r
+{\r
+       if (!PathFileExists(szPath))\r
+               return FALSE;\r
+\r
+       if (!m_bQuiet)\r
+               _ftprintf(stdout, _T("parsing file %s...\n"), szPath);\r
+\r
+       int nEntries = 0;\r
+       int nDeleted = 0;\r
+       int nTranslated = 0;\r
+       //since stream classes still expect the filepath in char and not wchar_t\r
+       //we need to convert the filepath to multibyte\r
+       char filepath[MAX_PATH+1];\r
+       SecureZeroMemory(filepath, sizeof(filepath));\r
+       WideCharToMultiByte(CP_ACP, NULL, szPath, -1, filepath, MAX_PATH, NULL, NULL);\r
+\r
+       std::wifstream File;\r
+       File.imbue(std::locale(std::locale(), new utf8_conversion()));\r
+       File.open(filepath);\r
+       if (!File.good())\r
+       {\r
+               _ftprintf(stderr, _T("can't open input file %s\n"), szPath);\r
+               return FALSE;\r
+       }\r
+       TCHAR line[2*MAX_STRING_LENGTH];\r
+       std::vector<std::wstring> entry;\r
+       do\r
+       {\r
+               File.getline(line, sizeof(line)/sizeof(TCHAR));\r
+               if (line[0]==0)\r
+               {\r
+                       //empty line means end of entry!\r
+                       RESOURCEENTRY resEntry;\r
+                       std::wstring msgid;\r
+                       int type = 0;\r
+                       for (std::vector<std::wstring>::iterator I = entry.begin(); I != entry.end(); ++I)\r
+                       {\r
+                               if (_tcsncmp(I->c_str(), _T("# "), 2)==0)\r
+                               {\r
+                                       //user comment\r
+                                       resEntry.translatorcomments.push_back(I->c_str());\r
+                                       type = 0;\r
+                               }\r
+                               if (_tcsncmp(I->c_str(), _T("#."), 2)==0)\r
+                               {\r
+                                       //automatic comments\r
+                                       resEntry.automaticcomments.push_back(I->c_str());\r
+                                       type = 0;\r
+                               }\r
+                               if (_tcsncmp(I->c_str(), _T("#,"), 2)==0)\r
+                               {\r
+                                       //flag\r
+                                       resEntry.flag = I->c_str();\r
+                                       type = 0;\r
+                               }\r
+                               if (_tcsncmp(I->c_str(), _T("msgid"), 5)==0)\r
+                               {\r
+                                       //message id\r
+                                       msgid = I->c_str();\r
+                                       msgid = std::wstring(msgid.substr(7, msgid.size() - 8));\r
+                                       nEntries++;\r
+                                       type = 1;\r
+                               }\r
+                               if (_tcsncmp(I->c_str(), _T("msgstr"), 6)==0)\r
+                               {\r
+                                       //message string\r
+                                       resEntry.msgstr = I->c_str();\r
+                                       resEntry.msgstr = resEntry.msgstr.substr(8, resEntry.msgstr.length() - 9);\r
+                                       if (resEntry.msgstr.size()>0)\r
+                                               nTranslated++;\r
+                                       type = 2;\r
+                               }\r
+                               if (_tcsncmp(I->c_str(), _T("\""), 1)==0)\r
+                               {\r
+                                       if (type == 1)\r
+                                       {\r
+                                               std::wstring temp = I->c_str();\r
+                                               temp = temp.substr(1, temp.length()-2);\r
+                                               msgid += temp;\r
+                                       }\r
+                                       if (type == 2)\r
+                                       {\r
+                                               if (resEntry.msgstr.size() == 0)\r
+                                                       nTranslated++;\r
+                                               std::wstring temp = I->c_str();\r
+                                               temp = temp.substr(1, temp.length()-2);\r
+                                               resEntry.msgstr += temp;\r
+                                       }\r
+                               }\r
+                       }\r
+                       entry.clear();\r
+                       if ((bUpdateExisting)&&(this->count(msgid) == 0))\r
+                               nDeleted++;\r
+                       else\r
+                               (*this)[msgid] = resEntry;\r
+                       msgid.clear();\r
+               }\r
+               else\r
+               {\r
+                       entry.push_back(line);\r
+               }\r
+       } while (File.gcount() > 0);\r
+       printf(File.getloc().name().c_str());\r
+       File.close();\r
+       RESOURCEENTRY emptyentry;\r
+       (*this)[std::wstring(_T(""))] = emptyentry;\r
+       if (!m_bQuiet)\r
+               _ftprintf(stdout, _T("%d Entries found, %d were already translated and %d got deleted\n"), nEntries, nTranslated, nDeleted);\r
+       return TRUE;\r
+}\r
+\r
+BOOL CPOFile::SaveFile(LPCTSTR szPath)\r
+{\r
+       //since stream classes still expect the filepath in char and not wchar_t\r
+       //we need to convert the filepath to multibyte\r
+       char filepath[MAX_PATH+1];\r
+       int nEntries = 0;\r
+       SecureZeroMemory(filepath, sizeof(filepath));\r
+       WideCharToMultiByte(CP_ACP, NULL, szPath, -1, filepath, MAX_PATH, NULL, NULL);\r
+\r
+       std::wofstream File;\r
+//     File.open(filepath, std::ios_base::binary);\r
+//     File << _T("\xEF\xBB\xBF");\r
+//     File.close();\r
+       File.imbue(std::locale(std::locale(), new utf8_conversion()));\r
+       File.open(filepath, std::ios_base::binary);\r
+       File << _T("# SOME DESCRIPTIVE TITLE.\n");\r
+       File << _T("# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER\n");\r
+       File << _T("# This file is distributed under the same license as the PACKAGE package.\n");\r
+       File << _T("# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.\n");\r
+       File << _T("#\n");\r
+       File << _T("#, fuzzy\n");\r
+       File << _T("msgid \"\"\n");\r
+       File << _T("msgstr \"\"\n");\r
+       File << _T("\"Project-Id-Version: PACKAGE VERSION\\n\"\n");\r
+       File << _T("\"Report-Msgid-Bugs-To: \\n\"\n");\r
+       File << _T("\"POT-Creation-Date: 1900-01-01 00:00+0000\\n\"\n");\r
+       File << _T("\"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\\n\"\n");\r
+       File << _T("\"Last-Translator: FULL NAME <EMAIL@ADDRESS>\\n\"\n");\r
+       File << _T("\"Language-Team: LANGUAGE <LL@li.org>\\n\"\n");\r
+       File << _T("\"MIME-Version: 1.0\\n\"\n");\r
+       File << _T("\"Content-Type: text/plain; charset=UTF-8\\n\"\n");\r
+       File << _T("\"Content-Transfer-Encoding: 8bit\\n\"\n\n");\r
+       File << _T("\n");\r
+       File << _T("# msgid/msgstr fields for Accelerator keys\n");\r
+       File << _T("# Format is: \"ID:xxxxxx:VACS+X\" where:\n");\r
+       File << _T("#    ID:xxxxx = the menu ID corresponding to the accelerator\n");\r
+       File << _T("#    V = Virtual key (or blank if not used) - nearly always set!\n");\r
+       File << _T("#    A = Alt key     (or blank if not used)\n");\r
+       File << _T("#    C = Ctrl key    (or blank if not used)\n");\r
+       File << _T("#    S = Shift key   (or blank if not used)\n");\r
+       File << _T("#    X = upper case character\n");\r
+       File << _T("# e.g. \"V CS+Q\" == Ctrl + Shift + 'Q'\n");\r
+       File << _T("\n");\r
+       File << _T("# ONLY Accelerator Keys with corresponding alphanumeric characters can be\n");\r
+       File << _T("# updated i.e. function keys (F2), special keys (Delete, HoMe) etc. will not.\n");\r
+       File << _T("\n");\r
+       File << _T("# ONLY change the msgstr field. Do NOT change any other.\n");\r
+       File << _T("# If you do not want to change an Accelerator Key, copy msgid to msgstr\n");\r
+       File << _T("\n");\r
+\r
+       for (std::map<std::wstring, RESOURCEENTRY>::iterator I = this->begin(); I != this->end(); ++I)\r
+       {\r
+               if (I->first.size() == 0)\r
+                       continue;\r
+               RESOURCEENTRY entry = I->second;\r
+               for (std::vector<std::wstring>::iterator II = entry.automaticcomments.begin(); II != entry.automaticcomments.end(); ++II)\r
+               {\r
+                       File << II->c_str() << _T("\n");\r
+               }\r
+               for (std::vector<std::wstring>::iterator II = entry.translatorcomments.begin(); II != entry.translatorcomments.end(); ++II)\r
+               {\r
+                       File << II->c_str() << _T("\n");\r
+               }\r
+               if (I->second.resourceIDs.size() > 0)\r
+               {\r
+                       File << _T("#. Resource IDs: (");\r
+\r
+                       std::set<DWORD>::const_iterator II = I->second.resourceIDs.begin();\r
+                       File << (*II);\r
+                       ++II;\r
+                       while (II != I->second.resourceIDs.end())\r
+                       {\r
+                               File << _T(", ");\r
+                               File << (*II);\r
+                               ++II;\r
+                       };\r
+                       File << _T(")\n");\r
+               }\r
+               if (I->second.flag.length() > 0)\r
+                       File << (I->second.flag.c_str()) << _T("\n");\r
+               File << (_T("msgid \"")) << (I->first.c_str()) << _T("\"\n");\r
+               File << (_T("msgstr \"")) << (I->second.msgstr.c_str()) << _T("\"\n\n");\r
+               nEntries++;\r
+       }\r
+       File.close();\r
+       if (!m_bQuiet)\r
+               _ftprintf(stdout, _T("File %s saved, containing %d entries\n"), szPath, nEntries);\r
+       return TRUE;\r
+}\r
diff --git a/src/ResText/POFile.h b/src/ResText/POFile.h
new file mode 100644 (file)
index 0000000..3111479
--- /dev/null
@@ -0,0 +1,53 @@
+// TortoiseSVN - a Windows shell extension for easy version control\r
+\r
+// Copyright (C) 2003-2007 - TortoiseSVN\r
+\r
+// This program is free software; you can redistribute it and/or\r
+// modify it under the terms of the GNU General Public License\r
+// as published by the Free Software Foundation; either version 2\r
+// of the License, or (at your option) any later version.\r
+\r
+// This program is distributed in the hope that it will be useful,\r
+// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+// GNU General Public License for more details.\r
+\r
+// You should have received a copy of the GNU General Public License\r
+// along with this program; if not, write to the Free Software Foundation,\r
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
+#pragma once\r
+#include <string>\r
+#include <map>\r
+#include <set>\r
+#include <vector>\r
+\r
+typedef struct tagResourceEntry\r
+{\r
+       WORD                                            menuID;\r
+       std::vector<std::wstring>       translatorcomments;\r
+       std::vector<std::wstring>       automaticcomments;\r
+       std::set<DWORD>                         resourceIDs;\r
+       std::wstring                            flag;\r
+       std::wstring                            msgstr;\r
+} RESOURCEENTRY, * LPRESOURCEENTRY;\r
+\r
+/**\r
+ * \ingroup ResText\r
+ * Class to handle po-files. Inherits from an std::map which assigns\r
+ * string IDs to additional information, including the translated strings.\r
+ *\r
+ * Provides methods to load and save a po-file with the translation information\r
+ * we need for ResText.\r
+ */\r
+class CPOFile : public std::map<std::wstring, RESOURCEENTRY>\r
+{\r
+public:\r
+       CPOFile();\r
+       ~CPOFile(void);\r
+\r
+       BOOL ParseFile(LPCTSTR szPath, BOOL bUpdateExisting = TRUE);\r
+       BOOL SaveFile(LPCTSTR szPath);\r
+       void SetQuiet(BOOL bQuiet = TRUE) {m_bQuiet = bQuiet;}\r
+private:\r
+       BOOL m_bQuiet;\r
+};\r
diff --git a/src/ResText/ResModule.cpp b/src/ResText/ResModule.cpp
new file mode 100644 (file)
index 0000000..1a14fe1
--- /dev/null
@@ -0,0 +1,1900 @@
+// TortoiseSVN - a Windows shell extension for easy version control\r
+\r
+// Copyright (C) 2003-2008 - TortoiseSVN\r
+\r
+// This program is free software; you can redistribute it and/or\r
+// modify it under the terms of the GNU General Public License\r
+// as published by the Free Software Foundation; either version 2\r
+// of the License, or (at your option) any later version.\r
+\r
+// This program is distributed in the hope that it will be useful,\r
+// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+// GNU General Public License for more details.\r
+\r
+// You should have received a copy of the GNU General Public License\r
+// along with this program; if not, write to the Free Software Foundation,\r
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
+#include "StdAfx.h"\r
+#include "Utils.h"\r
+#include ".\resmodule.h"\r
+\r
+#define MYERROR        {CUtils::Error(); return FALSE;}\r
+\r
+CResModule::CResModule(void)\r
+       : m_bTranslatedStrings(0)\r
+       , m_bDefaultStrings(0)\r
+       , m_bTranslatedDialogStrings(0)\r
+       , m_bDefaultDialogStrings(0)\r
+       , m_bTranslatedMenuStrings(0)\r
+       , m_bDefaultMenuStrings(0)\r
+       , m_bTranslatedAcceleratorStrings(0)\r
+       , m_bDefaultAcceleratorStrings(0)\r
+       , m_wTargetLang(0)\r
+       , m_hResDll(NULL)\r
+       , m_hUpdateRes(NULL)\r
+       , m_bQuiet(false)\r
+       , m_bRTL(false)\r
+{\r
+}\r
+\r
+CResModule::~CResModule(void)\r
+{\r
+}\r
+\r
+BOOL CResModule::ExtractResources(std::vector<std::wstring> filelist, LPCTSTR lpszPOFilePath, BOOL bNoUpdate)\r
+{\r
+       BOOL bRet = TRUE;\r
+       for (std::vector<std::wstring>::iterator I = filelist.begin(); I != filelist.end(); ++I)\r
+       {\r
+               m_hResDll = LoadLibrary(I->c_str());\r
+               if (m_hResDll == NULL)\r
+                       MYERROR;\r
+\r
+               size_t nEntries = m_StringEntries.size();\r
+               // fill in the std::map with all translatable entries\r
+\r
+               if (!m_bQuiet)\r
+                       _ftprintf(stdout, _T("Extracting StringTable...."));\r
+               EnumResourceNames(m_hResDll, RT_STRING,  EnumResNameCallback, (long)this);\r
+               if (!m_bQuiet)\r
+                       _ftprintf(stdout, _T("%4d Strings\n"), m_StringEntries.size()-nEntries);\r
+               nEntries = m_StringEntries.size();\r
+\r
+               if (!m_bQuiet)\r
+                       _ftprintf(stdout, _T("Extracting Dialogs........"));\r
+               EnumResourceNames(m_hResDll, RT_DIALOG,  EnumResNameCallback, (long)this);\r
+               if (!m_bQuiet)\r
+                       _ftprintf(stdout, _T("%4d Strings\n"), m_StringEntries.size()-nEntries);\r
+               nEntries = m_StringEntries.size();\r
+\r
+               if (!m_bQuiet)\r
+                       _ftprintf(stdout, _T("Extracting Menus.........."));\r
+               EnumResourceNames(m_hResDll, RT_MENU,    EnumResNameCallback, (long)this);\r
+               if (!m_bQuiet)\r
+                       _ftprintf(stdout, _T("%4d Strings\n"), m_StringEntries.size()-nEntries);\r
+               nEntries = m_StringEntries.size();\r
+               if (!m_bQuiet)\r
+                       _ftprintf(stdout, _T("Extracting Accelerators..."));\r
+               EnumResourceNames(m_hResDll, RT_ACCELERATOR, EnumResNameCallback, (long)this);\r
+               if (!m_bQuiet)\r
+                       _ftprintf(stdout, _T("%4d Accelerators\n"), m_StringEntries.size()-nEntries);\r
+               nEntries = m_StringEntries.size();\r
+\r
+               // parse a probably existing file and update the translations which are\r
+               // already done\r
+               m_StringEntries.ParseFile(lpszPOFilePath, !bNoUpdate);\r
+               \r
+               FreeLibrary(m_hResDll);\r
+               continue;\r
+       }\r
+       \r
+       // at last, save the new file\r
+       if (bRet)\r
+               return m_StringEntries.SaveFile(lpszPOFilePath);\r
+       return FALSE;\r
+}\r
+\r
+BOOL CResModule::ExtractResources(LPCTSTR lpszSrcLangDllPath, LPCTSTR lpszPoFilePath, BOOL bNoUpdate)\r
+{\r
+       m_hResDll = LoadLibrary(lpszSrcLangDllPath);\r
+       if (m_hResDll == NULL)\r
+               MYERROR;\r
+       \r
+       size_t nEntries = 0;\r
+       // fill in the std::map with all translatable entries\r
+\r
+       if (!m_bQuiet)\r
+               _ftprintf(stdout, _T("Extracting StringTable...."));\r
+       EnumResourceNames(m_hResDll, RT_STRING,  EnumResNameCallback, (long)this);\r
+       if (!m_bQuiet)\r
+               _ftprintf(stdout, _T("%4d Strings\n"), m_StringEntries.size());\r
+       nEntries = m_StringEntries.size();\r
+\r
+       if (!m_bQuiet)\r
+               _ftprintf(stdout, _T("Extracting Dialogs........"));\r
+       EnumResourceNames(m_hResDll, RT_DIALOG,  EnumResNameCallback, (long)this);\r
+       if (!m_bQuiet)\r
+               _ftprintf(stdout, _T("%4d Strings\n"), m_StringEntries.size()-nEntries);\r
+       nEntries = m_StringEntries.size();\r
+\r
+       if (!m_bQuiet)\r
+               _ftprintf(stdout, _T("Extracting Menus.........."));\r
+       EnumResourceNames(m_hResDll, RT_MENU,    EnumResNameCallback, (long)this);\r
+       if (!m_bQuiet)\r
+               _ftprintf(stdout, _T("%4d Strings\n"), m_StringEntries.size()-nEntries);\r
+       nEntries = m_StringEntries.size();\r
+\r
+       if (!m_bQuiet)\r
+               _ftprintf(stdout, _T("Extracting Accelerators..."));\r
+       EnumResourceNames(m_hResDll, RT_ACCELERATOR, EnumResNameCallback, (long)this);\r
+       if (!m_bQuiet)\r
+               _ftprintf(stdout, _T("%4d Accelerators\n"), m_StringEntries.size()-nEntries);\r
+       nEntries = m_StringEntries.size();\r
+\r
+       // parse a probably existing file and update the translations which are\r
+       // already done\r
+       m_StringEntries.ParseFile(lpszPoFilePath, !bNoUpdate);\r
+\r
+       // at last, save the new file\r
+       if (!m_StringEntries.SaveFile(lpszPoFilePath))\r
+               goto DONE_ERROR;\r
+\r
+       FreeLibrary(m_hResDll);\r
+       return TRUE;\r
+\r
+DONE_ERROR:\r
+       if (m_hResDll)\r
+               FreeLibrary(m_hResDll);\r
+       return FALSE;\r
+}\r
+\r
+BOOL CResModule::CreateTranslatedResources(LPCTSTR lpszSrcLangDllPath, LPCTSTR lpszDestLangDllPath, LPCTSTR lpszPOFilePath)\r
+{\r
+       if (!CopyFile(lpszSrcLangDllPath, lpszDestLangDllPath, FALSE))\r
+               MYERROR;\r
+\r
+       int count = 0;\r
+       do\r
+       {\r
+               m_hResDll = LoadLibraryEx (lpszSrcLangDllPath, NULL, LOAD_LIBRARY_AS_DATAFILE|LOAD_IGNORE_CODE_AUTHZ_LEVEL);\r
+               if (m_hResDll == NULL)\r
+                       Sleep(100);\r
+               count++;\r
+       } while ((m_hResDll == NULL)&&(count < 5));\r
+\r
+       if (m_hResDll == NULL)\r
+               MYERROR;\r
+\r
+       sDestFile = std::wstring(lpszDestLangDllPath);\r
+\r
+       // get all translated strings\r
+       if (!m_StringEntries.ParseFile(lpszPOFilePath, FALSE))\r
+               goto DONE_ERROR;\r
+       m_bTranslatedStrings = 0;\r
+       m_bDefaultStrings = 0;\r
+       m_bTranslatedDialogStrings = 0;\r
+       m_bDefaultDialogStrings = 0;\r
+       m_bTranslatedMenuStrings = 0;\r
+       m_bDefaultMenuStrings = 0;\r
+       m_bTranslatedAcceleratorStrings = 0;\r
+       m_bDefaultAcceleratorStrings = 0;\r
+\r
+       if (!m_bQuiet)\r
+               _ftprintf(stdout, _T("Translating StringTable..."));\r
+       EnumResourceNames(m_hResDll, RT_STRING, EnumResNameWriteCallback, (long)this);\r
+       if (!m_bQuiet)\r
+               _ftprintf(stdout, _T("%4d translated, %4d not translated\n"), m_bTranslatedStrings, m_bDefaultStrings);\r
+\r
+       if (!m_bQuiet)\r
+               _ftprintf(stdout, _T("Translating Dialogs......."));\r
+       EnumResourceNames(m_hResDll, RT_DIALOG, EnumResNameWriteCallback, (long)this);\r
+       if (!m_bQuiet)\r
+               _ftprintf(stdout, _T("%4d translated, %4d not translated\n"), m_bTranslatedDialogStrings, m_bDefaultDialogStrings);\r
+\r
+       if (!m_bQuiet)\r
+               _ftprintf(stdout, _T("Translating Menus........."));\r
+       EnumResourceNames(m_hResDll, RT_MENU, EnumResNameWriteCallback, (long)this);\r
+       if (!m_bQuiet)\r
+               _ftprintf(stdout, _T("%4d translated, %4d not translated\n"), m_bTranslatedMenuStrings, m_bDefaultMenuStrings);\r
+\r
+       if (!m_bQuiet)\r
+               _ftprintf(stdout, _T("Translating Accelerators.."));\r
+       EnumResourceNames(m_hResDll, RT_ACCELERATOR, EnumResNameWriteCallback, (long)this);\r
+       if (!m_bQuiet)\r
+               _ftprintf(stdout, _T("%4d translated, %4d not translated\n"), m_bTranslatedAcceleratorStrings, m_bDefaultAcceleratorStrings);\r
+\r
+       FreeLibrary(m_hResDll);\r
+       return TRUE;\r
+DONE_ERROR:\r
+       if (m_hResDll)\r
+               FreeLibrary(m_hResDll);\r
+       return FALSE;\r
+}\r
+\r
+BOOL CResModule::ExtractString(UINT nID)\r
+{\r
+       HRSRC           hrsrc = FindResource(m_hResDll, MAKEINTRESOURCE(nID), RT_STRING);\r
+       HGLOBAL         hglStringTable;\r
+       LPWSTR          p;\r
+\r
+       if (!hrsrc)\r
+               MYERROR;\r
+       hglStringTable = LoadResource(m_hResDll, hrsrc);\r
+\r
+       if (!hglStringTable)\r
+               goto DONE_ERROR;\r
+       p = (LPWSTR)LockResource(hglStringTable);\r
+\r
+       if (p == NULL)\r
+               goto DONE_ERROR;\r
+       /*      [Block of 16 strings.  The strings are Pascal style with a WORD \r
+       length preceding the string.  16 strings are always written, even \r
+       if not all slots are full.  Any slots in the block with no string \r
+       have a zero WORD for the length.] \r
+       */\r
+\r
+       //first check how much memory we need\r
+       LPWSTR pp = p;\r
+       for (int i=0; i<16; ++i)\r
+       {\r
+               int len = GET_WORD(pp);\r
+               pp++;\r
+               std::wstring msgid = std::wstring(pp, len);\r
+               WCHAR * pBuf = new WCHAR[MAX_STRING_LENGTH*2];\r
+               SecureZeroMemory(pBuf, MAX_STRING_LENGTH*2*sizeof(WCHAR));\r
+               wcscpy(pBuf, msgid.c_str());\r
+               CUtils::StringExtend(pBuf);\r
+\r
+               if (wcslen(pBuf))\r
+               {\r
+                       std::wstring str = std::wstring(pBuf);\r
+                       RESOURCEENTRY entry = m_StringEntries[str];\r
+                       entry.resourceIDs.insert(nID);\r
+                       if (wcschr(str.c_str(), '%'))\r
+                               entry.flag = _T("#, c-format");\r
+                       m_StringEntries[str] = entry;\r
+               }\r
+               delete [] pBuf;\r
+               pp += len;\r
+       }\r
+       UnlockResource(hglStringTable);\r
+       FreeResource(hglStringTable);\r
+       return TRUE;\r
+DONE_ERROR:\r
+       UnlockResource(hglStringTable);\r
+       FreeResource(hglStringTable);\r
+       MYERROR;\r
+}\r
+\r
+BOOL CResModule::ReplaceString(UINT nID, WORD wLanguage)\r
+{\r
+       HRSRC           hrsrc = FindResourceEx(m_hResDll, RT_STRING, MAKEINTRESOURCE(nID), wLanguage);\r
+       HGLOBAL         hglStringTable;\r
+       LPWSTR          p;\r
+\r
+       if (!hrsrc)\r
+               MYERROR;\r
+       hglStringTable = LoadResource(m_hResDll, hrsrc);\r
+\r
+       if (!hglStringTable)\r
+               goto DONE_ERROR;\r
+       p = (LPWSTR)LockResource(hglStringTable);\r
+\r
+       if (p == NULL)\r
+               goto DONE_ERROR;\r
+/*     [Block of 16 strings.  The strings are Pascal style with a WORD \r
+       length preceding the string.  16 strings are always written, even \r
+       if not all slots are full.  Any slots in the block with no string \r
+       have a zero WORD for the length.] \r
+*/\r
+       \r
+       //first check how much memory we need\r
+       size_t nMem = 0;\r
+       LPWSTR pp = p;\r
+       for (int i=0; i<16; ++i)\r
+       {\r
+               nMem++;\r
+               size_t len = GET_WORD(pp);\r
+               pp++;\r
+               std::wstring msgid = std::wstring(pp, len);\r
+               WCHAR * pBuf = new WCHAR[MAX_STRING_LENGTH*2];\r
+               SecureZeroMemory(pBuf, MAX_STRING_LENGTH*2*sizeof(WCHAR));\r
+               wcscpy(pBuf, msgid.c_str());\r
+               CUtils::StringExtend(pBuf);\r
+               msgid = std::wstring(pBuf);\r
+\r
+               RESOURCEENTRY resEntry;\r
+               resEntry = m_StringEntries[msgid];\r
+               wcscpy(pBuf, resEntry.msgstr.c_str());\r
+               CUtils::StringCollapse(pBuf);\r
+               size_t newlen = wcslen(pBuf);\r
+               if (newlen)\r
+                       nMem += newlen;\r
+               else\r
+                       nMem += len;\r
+               pp += len;\r
+               delete [] pBuf;\r
+       }\r
+\r
+       WORD * newTable = new WORD[nMem + (nMem % 2)];\r
+       SecureZeroMemory(newTable, (nMem + (nMem % 2))*2);\r
+\r
+       size_t index = 0;\r
+       for (int i=0; i<16; ++i)\r
+       {\r
+               int len = GET_WORD(p);\r
+               p++;\r
+               std::wstring msgid = std::wstring(p, len);\r
+               WCHAR * pBuf = new WCHAR[MAX_STRING_LENGTH*2];\r
+               SecureZeroMemory(pBuf, MAX_STRING_LENGTH*2*sizeof(WCHAR));\r
+               wcscpy(pBuf, msgid.c_str());\r
+               CUtils::StringExtend(pBuf);\r
+               msgid = std::wstring(pBuf);\r
+\r
+               RESOURCEENTRY resEntry;\r
+               resEntry = m_StringEntries[msgid];\r
+               wcscpy(pBuf, resEntry.msgstr.c_str());\r
+               CUtils::StringCollapse(pBuf);\r
+               size_t newlen = wcslen(pBuf);\r
+               if (newlen)\r
+               {\r
+                       newTable[index++] = (WORD)newlen;\r
+                       wcsncpy((wchar_t *)&newTable[index], pBuf, newlen);\r
+                       index += newlen;\r
+                       m_bTranslatedStrings++;\r
+               }\r
+               else\r
+               {\r
+                       newTable[index++] = (WORD)len;\r
+                       if (len)\r
+                               wcsncpy((wchar_t *)&newTable[index], p, len);\r
+                       index += len;\r
+                       if (len)\r
+                               m_bDefaultStrings++;\r
+               }\r
+               p += len;\r
+               delete [] pBuf;\r
+       }\r
+\r
+       if (!UpdateResource(m_hUpdateRes, RT_STRING, MAKEINTRESOURCE(nID), (m_wTargetLang ? m_wTargetLang : wLanguage), newTable, (DWORD)(nMem + (nMem % 2))*2))\r
+       {\r
+               delete [] newTable;\r
+               goto DONE_ERROR;\r
+       }\r
+       \r
+       if ((m_wTargetLang)&&(!UpdateResource(m_hUpdateRes, RT_STRING, MAKEINTRESOURCE(nID), wLanguage, NULL, 0)))\r
+       {\r
+               delete [] newTable;\r
+               goto DONE_ERROR;\r
+       }\r
+       delete [] newTable;\r
+       UnlockResource(hglStringTable);\r
+       FreeResource(hglStringTable);\r
+       return TRUE;\r
+DONE_ERROR:\r
+       UnlockResource(hglStringTable);\r
+       FreeResource(hglStringTable);\r
+       MYERROR;\r
+}\r
+\r
+BOOL CResModule::ExtractMenu(UINT nID)\r
+{\r
+       HRSRC           hrsrc = FindResource(m_hResDll, MAKEINTRESOURCE(nID), RT_MENU);\r
+       HGLOBAL         hglMenuTemplate;\r
+       WORD            version, offset;\r
+       DWORD dwHelpId;\r
+       const WORD *p, *p0;\r
+\r
+       if (!hrsrc)\r
+               MYERROR;\r
+\r
+       hglMenuTemplate = LoadResource(m_hResDll, hrsrc);\r
+\r
+       if (!hglMenuTemplate)\r
+               MYERROR;\r
+\r
+       p = (const WORD*)LockResource(hglMenuTemplate);\r
+\r
+       if (p == NULL)\r
+               MYERROR;\r
+\r
+       // Standard MENU resource\r
+       //struct MenuHeader { \r
+       //      WORD   wVersion;           // Currently zero \r
+       //      WORD   cbHeaderSize;       // Also zero \r
+       //}; \r
+\r
+       // MENUEX resource\r
+       //struct MenuExHeader {\r
+       //    WORD wVersion;           // One\r
+       //    WORD wOffset;\r
+       //    DWORD dwHelpId;\r
+       //};\r
+       p0 = p;\r
+       version = GET_WORD(p);\r
+\r
+       p++;\r
+\r
+       switch (version)\r
+       {\r
+       case 0:\r
+               {\r
+                       offset = GET_WORD(p);\r
+                       p += offset;\r
+                       p++;\r
+                       if (!ParseMenuResource(p))\r
+                               goto DONE_ERROR;\r
+               }\r
+               break;\r
+       case 1:\r
+               {\r
+                       offset = GET_WORD(p);\r
+                       p++;\r
+                       dwHelpId = GET_DWORD(p);\r
+                       if (!ParseMenuExResource(p0 + offset))\r
+                               goto DONE_ERROR;\r
+               }\r
+               break;\r
+       default:\r
+               goto DONE_ERROR;\r
+       }\r
+\r
+       UnlockResource(hglMenuTemplate);\r
+       FreeResource(hglMenuTemplate);\r
+       return TRUE;\r
+\r
+DONE_ERROR:\r
+       UnlockResource(hglMenuTemplate);\r
+       FreeResource(hglMenuTemplate);\r
+       MYERROR;\r
+}\r
+\r
+BOOL CResModule::ReplaceMenu(UINT nID, WORD wLanguage)\r
+{\r
+       HRSRC           hrsrc = FindResourceEx(m_hResDll, RT_MENU, MAKEINTRESOURCE(nID), wLanguage);\r
+       HGLOBAL         hglMenuTemplate;\r
+       WORD            version, offset;\r
+       LPWSTR          p;\r
+       WORD *p0;\r
+       DWORD dwHelpId;\r
+\r
+       if (!hrsrc)\r
+               MYERROR;        //just the language wasn't found\r
+\r
+       hglMenuTemplate = LoadResource(m_hResDll, hrsrc);\r
+\r
+       if (!hglMenuTemplate)\r
+               MYERROR;\r
+\r
+       p = (LPWSTR)LockResource(hglMenuTemplate);\r
+\r
+       if (p == NULL)\r
+               MYERROR;\r
+\r
+       //struct MenuHeader { \r
+       //      WORD   wVersion;           // Currently zero \r
+       //      WORD   cbHeaderSize;       // Also zero \r
+       //};\r
+\r
+       // MENUEX resource\r
+       //struct MenuExHeader {\r
+       //    WORD wVersion;           // One\r
+       //    WORD wOffset;\r
+       //    DWORD dwHelpId;\r
+       //};\r
+       p0 = (WORD *)p;\r
+       version = GET_WORD(p);\r
+\r
+       p++;\r
+\r
+       switch (version)\r
+       {\r
+       case 0:\r
+               {\r
+                       offset = GET_WORD(p);\r
+                       p += offset;\r
+                       p++;\r
+                       size_t nMem = 0;\r
+                       if (!CountMemReplaceMenuResource((WORD *)p, &nMem, NULL))\r
+                               goto DONE_ERROR;\r
+                       WORD * newMenu = new WORD[nMem + (nMem % 2)+2];\r
+                       SecureZeroMemory(newMenu, (nMem + (nMem % 2)+2)*2);\r
+                       size_t index = 2;               // MenuHeader has 2 WORDs zero\r
+                       if (!CountMemReplaceMenuResource((WORD *)p, &index, newMenu))\r
+                       {\r
+                               delete [] newMenu;\r
+                               goto DONE_ERROR;\r
+                       } \r
+\r
+                       if (!UpdateResource(m_hUpdateRes, RT_MENU, MAKEINTRESOURCE(nID), (m_wTargetLang ? m_wTargetLang : wLanguage), newMenu, (DWORD)(nMem + (nMem % 2)+2)*2))\r
+                       {\r
+                               delete [] newMenu;\r
+                               goto DONE_ERROR;\r
+                       }\r
+\r
+                       if ((m_wTargetLang)&&(!UpdateResource(m_hUpdateRes, RT_MENU, MAKEINTRESOURCE(nID), wLanguage, NULL, 0)))\r
+                       {\r
+                               delete [] newMenu;\r
+                               goto DONE_ERROR;\r
+                       } \r
+                       delete [] newMenu;\r
+               }\r
+               break;\r
+       case 1:\r
+               {\r
+                       offset = GET_WORD(p);\r
+                       p++;\r
+                       dwHelpId = GET_DWORD(p);\r
+                       size_t nMem = 0;\r
+                       if (!CountMemReplaceMenuExResource((WORD *)(p0 + offset), &nMem, NULL))\r
+                               goto DONE_ERROR;\r
+                       WORD * newMenu = new WORD[nMem + (nMem % 2) + 4];\r
+                       SecureZeroMemory(newMenu, (nMem + (nMem % 2) + 4) * 2);\r
+                       CopyMemory(newMenu, p0, 2 * sizeof(WORD) + sizeof(DWORD));\r
+                       size_t index = 4;               // MenuExHeader has 2 x WORD + 1 x DWORD\r
+                       if (!CountMemReplaceMenuExResource((WORD *)(p0 + offset), &index, newMenu))\r
+                       {\r
+                               delete [] newMenu;\r
+                               goto DONE_ERROR;\r
+                       } \r
+\r
+                       if (!UpdateResource(m_hUpdateRes, RT_MENU, MAKEINTRESOURCE(nID), (m_wTargetLang ? m_wTargetLang : wLanguage), newMenu, (DWORD)(nMem + (nMem % 2) + 4) * 2))\r
+                       {\r
+                               delete [] newMenu;\r
+                               goto DONE_ERROR;\r
+                       }\r
+\r
+                       if ((m_wTargetLang)&&(!UpdateResource(m_hUpdateRes, RT_MENU, MAKEINTRESOURCE(nID), wLanguage, NULL, 0)))\r
+                       {\r
+                               delete [] newMenu;\r
+                               goto DONE_ERROR;\r
+                       } \r
+                       delete [] newMenu;\r
+               }\r
+               break;\r
+       default:\r
+               goto DONE_ERROR;\r
+       }\r
+\r
+       UnlockResource(hglMenuTemplate);\r
+       FreeResource(hglMenuTemplate);\r
+       return TRUE;\r
+\r
+DONE_ERROR:\r
+       UnlockResource(hglMenuTemplate);\r
+       FreeResource(hglMenuTemplate);\r
+       MYERROR;\r
+}\r
+\r
+const WORD* CResModule::ParseMenuResource(const WORD * res)\r
+{\r
+       WORD            flags;\r
+       WORD            id = 0;\r
+       LPCWSTR         str;\r
+       WORD *p0;\r
+\r
+       //struct PopupMenuItem { \r
+       //      WORD   fItemFlags; \r
+       //      WCHAR  szItemText[]; \r
+       //}; \r
+       //struct NormalMenuItem { \r
+       //      WORD   fItemFlags; \r
+       //      WORD   wMenuID; \r
+       //      WCHAR  szItemText[]; \r
+       //}; \r
+\r
+       do\r
+       {\r
+               p0 = (WORD *)res;\r
+               flags = GET_WORD(res);\r
+               res++;\r
+               if (!(flags & MF_POPUP))\r
+               {\r
+                       id = GET_WORD(res);     //normal menu item\r
+                       res++;\r
+               }\r
+               else\r
+                       id = (WORD)-1;                  //popup menu item\r
+\r
+               str = (LPCWSTR)res;\r
+               size_t l = wcslen(str)+1;\r
+               res += l;\r
+\r
+               if (flags & MF_POPUP)\r
+               {\r
+                       TCHAR * pBuf = new TCHAR[MAX_STRING_LENGTH];\r
+                       SecureZeroMemory(pBuf, MAX_STRING_LENGTH * sizeof(TCHAR));\r
+                       _tcscpy(pBuf, str);\r
+                       CUtils::StringExtend(pBuf);\r
+\r
+                       std::wstring wstr = std::wstring(pBuf);\r
+                       RESOURCEENTRY entry = m_StringEntries[wstr];\r
+                       if (id)\r
+                               entry.resourceIDs.insert(id);\r
+\r
+                       m_StringEntries[wstr] = entry;\r
+                       delete [] pBuf;\r
+\r
+                       if ((res = ParseMenuResource(res))==0)\r
+                               return NULL;\r
+               }\r
+               else if (id != 0)\r
+               {\r
+                       TCHAR * pBuf = new TCHAR[MAX_STRING_LENGTH];\r
+                       SecureZeroMemory(pBuf, MAX_STRING_LENGTH * sizeof(TCHAR));\r
+                       _tcscpy(pBuf, str);\r
+                       CUtils::StringExtend(pBuf);\r
+\r
+                       std::wstring wstr = std::wstring(pBuf);\r
+                       RESOURCEENTRY entry = m_StringEntries[wstr];\r
+                       entry.resourceIDs.insert(id);\r
+\r
+                       TCHAR szTempBuf[1024];\r
+                       _stprintf(szTempBuf, _T("#: MenuEntry; ID:%d"), id);\r
+                       MENUENTRY menu_entry;\r
+                       menu_entry.wID = id;\r
+                       menu_entry.reference = szTempBuf;\r
+                       menu_entry.msgstr = wstr;\r
+\r
+                       m_StringEntries[wstr] = entry;\r
+                       m_MenuEntries[id] = menu_entry;\r
+                       delete [] pBuf;\r
+               }\r
+       } while (!(flags & MF_END));\r
+       return res;\r
+}\r
+\r
+const WORD* CResModule::CountMemReplaceMenuResource(const WORD * res, size_t * wordcount, WORD * newMenu)\r
+{\r
+       WORD            flags;\r
+       WORD            id = 0;\r
+\r
+       //struct PopupMenuItem { \r
+       //      WORD   fItemFlags; \r
+       //      WCHAR  szItemText[]; \r
+       //}; \r
+       //struct NormalMenuItem { \r
+       //      WORD   fItemFlags; \r
+       //      WORD   wMenuID; \r
+       //      WCHAR  szItemText[]; \r
+       //}; \r
+\r
+       do\r
+       {\r
+               flags = GET_WORD(res);\r
+               res++;\r
+               if (newMenu == NULL)\r
+                       (*wordcount)++;\r
+               else\r
+                       newMenu[(*wordcount)++] = flags;\r
+               if (!(flags & MF_POPUP))\r
+               {\r
+                       id = GET_WORD(res);     //normal menu item\r
+                       res++;\r
+                       if (newMenu == NULL)\r
+                               (*wordcount)++;\r
+                       else\r
+                               newMenu[(*wordcount)++] = id;\r
+               }\r
+               else\r
+                       id = (WORD)-1;                  //popup menu item\r
+\r
+               if (flags & MF_POPUP)\r
+               {\r
+                       ReplaceStr((LPCWSTR)res, newMenu, wordcount, &m_bTranslatedMenuStrings, &m_bDefaultMenuStrings);\r
+                       res += wcslen((LPCWSTR)res) + 1;\r
+\r
+                       if ((res = CountMemReplaceMenuResource(res, wordcount, newMenu))==0)\r
+                               return NULL;\r
+               }\r
+               else if (id != 0)\r
+               {\r
+                       ReplaceStr((LPCWSTR)res, newMenu, wordcount, &m_bTranslatedMenuStrings, &m_bDefaultMenuStrings);\r
+                       res += wcslen((LPCWSTR)res) + 1;\r
+               }\r
+               else\r
+               {\r
+                       if (newMenu)\r
+                               wcscpy((wchar_t *)&newMenu[(*wordcount)], (LPCWSTR)res);\r
+                       (*wordcount) += wcslen((LPCWSTR)res) + 1;\r
+                       res += wcslen((LPCWSTR)res) + 1;\r
+               }\r
+       } while (!(flags & MF_END));\r
+       return res;\r
+}\r
+\r
+const WORD* CResModule::ParseMenuExResource(const WORD * res)\r
+{\r
+       DWORD dwType, dwState, menuId;\r
+       WORD bResInfo;\r
+       LPCWSTR         str;\r
+       WORD *p0;\r
+\r
+       //struct MenuExItem {\r
+       //    DWORD dwType;\r
+       //    DWORD dwState;\r
+       //    DWORD menuId;\r
+       //    WORD bResInfo;\r
+       //    WCHAR szText[];\r
+       //    DWORD dwHelpId; - Popup menu only\r
+       //};\r
+\r
+       do\r
+       {\r
+               p0 = (WORD *)res;\r
+               dwType = GET_DWORD(res);\r
+               res += 2;\r
+               dwState = GET_DWORD(res);\r
+               res += 2;\r
+               menuId = GET_DWORD(res);\r
+               res += 2;\r
+               bResInfo = GET_WORD(res);\r
+               res++;\r
+\r
+               str = (LPCWSTR)res;\r
+               size_t l = wcslen(str)+1;\r
+               res += l;\r
+               // Align to DWORD boundary\r
+               res += ((((WORD)res + 3) & ~3) - (WORD)res)/sizeof(WORD);\r
+\r
+               if (dwType & MFT_SEPARATOR)\r
+                       continue;\r
+\r
+               if (bResInfo & 0x01)\r
+               {\r
+                       // Popup menu - note this can also have a non-zero ID\r
+                       if (menuId == 0)\r
+                               menuId = (WORD)-1;\r
+                       TCHAR * pBuf = new TCHAR[MAX_STRING_LENGTH];\r
+                       SecureZeroMemory(pBuf, MAX_STRING_LENGTH * sizeof(TCHAR));\r
+                       _tcscpy(pBuf, str);\r
+                       CUtils::StringExtend(pBuf);\r
+\r
+                       std::wstring wstr = std::wstring(pBuf);\r
+                       RESOURCEENTRY entry = m_StringEntries[wstr];\r
+                       // Popup has a DWORD help entry on a DWORD boundary - skip over it\r
+                       res += 2;\r
+\r
+                       entry.resourceIDs.insert(menuId);\r
+                       TCHAR szTempBuf[1024];\r
+                       _stprintf(szTempBuf, _T("#: MenuExPopupEntry; ID:%d"), menuId);\r
+                       MENUENTRY menu_entry;\r
+                       menu_entry.wID = (WORD)menuId;\r
+                       menu_entry.reference = szTempBuf;\r
+                       menu_entry.msgstr = wstr;\r
+                       m_StringEntries[wstr] = entry;\r
+                       m_MenuEntries[(WORD)menuId] = menu_entry;\r
+                       delete [] pBuf;\r
+\r
+                       if ((res = ParseMenuExResource(res)) == 0)\r
+                               return NULL;\r
+               } else if (menuId != 0)\r
+               {\r
+                       TCHAR * pBuf = new TCHAR[MAX_STRING_LENGTH];\r
+                       SecureZeroMemory(pBuf, MAX_STRING_LENGTH * sizeof(TCHAR));\r
+                       _tcscpy(pBuf, str);\r
+                       CUtils::StringExtend(pBuf);\r
+\r
+                       std::wstring wstr = std::wstring(pBuf);\r
+                       RESOURCEENTRY entry = m_StringEntries[wstr];\r
+                       entry.resourceIDs.insert(menuId);\r
+\r
+                       TCHAR szTempBuf[1024];\r
+                       _stprintf(szTempBuf, _T("#: MenuExEntry; ID:%d"), menuId);\r
+                       MENUENTRY menu_entry;\r
+                       menu_entry.wID = (WORD)menuId;\r
+                       menu_entry.reference = szTempBuf;\r
+                       menu_entry.msgstr = wstr;\r
+                       m_StringEntries[wstr] = entry;\r
+                       m_MenuEntries[(WORD)menuId] = menu_entry;\r
+                       delete [] pBuf;\r
+               }\r
+       } while (!(bResInfo & 0x80));\r
+       return res;\r
+}\r
+\r
+const WORD* CResModule::CountMemReplaceMenuExResource(const WORD * res, size_t * wordcount, WORD * newMenu)\r
+{\r
+       DWORD dwType, dwState, menuId;\r
+       WORD bResInfo;\r
+       WORD *p0;\r
+\r
+       //struct MenuExItem {\r
+       //    DWORD dwType;\r
+       //    DWORD dwState;\r
+       //    DWORD menuId;\r
+       //    WORD bResInfo;\r
+       //    WCHAR szText[];\r
+       //    DWORD dwHelpId; - Popup menu only\r
+       //};\r
+\r
+       do\r
+       {\r
+               p0 = (WORD *)res;\r
+               dwType = GET_DWORD(res);\r
+               res += 2;\r
+               dwState = GET_DWORD(res);\r
+               res += 2;\r
+               menuId = GET_DWORD(res);\r
+               res += 2;\r
+               bResInfo = GET_WORD(res);\r
+               res++;\r
+\r
+               if (newMenu != NULL) {\r
+                       CopyMemory(&newMenu[*wordcount], p0, 7 * sizeof(WORD));\r
+               }\r
+               (*wordcount) += 7;\r
+\r
+               if (dwType & MFT_SEPARATOR) {\r
+                       // Align to DWORD\r
+                       (*wordcount)++;\r
+                       res++;\r
+                       continue;\r
+               }\r
+\r
+               if (bResInfo & 0x01)\r
+               {\r
+                       ReplaceStr((LPCWSTR)res, newMenu, wordcount, &m_bTranslatedMenuStrings, &m_bDefaultMenuStrings);\r
+                       res += wcslen((LPCWSTR)res) + 1;\r
+                       // Align to DWORD\r
+                       res += ((((WORD)res + 3) & ~3) - (WORD)res)/sizeof(WORD);\r
+                       if ((*wordcount) & 0x01)\r
+                               (*wordcount)++;\r
+\r
+                       if (newMenu != NULL)\r
+                               CopyMemory(&newMenu[*wordcount], res, sizeof(DWORD));  // Copy Help ID\r
+\r
+                       res += 2;\r
+                       (*wordcount) += 2;\r
+\r
+                       if ((res = CountMemReplaceMenuExResource(res, wordcount, newMenu)) == 0)\r
+                               return NULL;\r
+               }\r
+               else if (menuId != 0)\r
+               {\r
+                       ReplaceStr((LPCWSTR)res, newMenu, wordcount, &m_bTranslatedMenuStrings, &m_bDefaultMenuStrings);\r
+                       res += wcslen((LPCWSTR)res) + 1;\r
+               }\r
+               else\r
+               {\r
+                       if (newMenu)\r
+                               wcscpy((wchar_t *)&newMenu[(*wordcount)], (LPCWSTR)res);\r
+                       (*wordcount) += wcslen((LPCWSTR)res) + 1;\r
+                       res += wcslen((LPCWSTR)res) + 1;\r
+               }\r
+               // Align to DWORD\r
+               res += ((((WORD)res + 3) & ~3) - (WORD)res)/sizeof(WORD);\r
+               if ((*wordcount) & 0x01)\r
+                       (*wordcount)++;\r
+       } while (!(bResInfo & 0x80));\r
+       return res;\r
+}\r
+\r
+BOOL CResModule::ExtractAccelerator(UINT nID)\r
+{\r
+       HRSRC           hrsrc = FindResource(m_hResDll, MAKEINTRESOURCE(nID), RT_ACCELERATOR);\r
+       HGLOBAL         hglAccTable;\r
+       WORD            fFlags, wAnsi, wID;\r
+       const WORD*     p;\r
+       bool            bEnd(false);\r
+\r
+       if (!hrsrc)\r
+               MYERROR;\r
+\r
+       hglAccTable = LoadResource(m_hResDll, hrsrc);\r
+\r
+       if (!hglAccTable)\r
+               goto DONE_ERROR;\r
+\r
+       p = (const WORD*)LockResource(hglAccTable);\r
+\r
+       if (p == NULL)\r
+               MYERROR;\r
+\r
+       /*\r
+       struct ACCELTABLEENTRY \r
+       {\r
+               WORD fFlags;            FVIRTKEY, FSHIFT, FCONTROL, FALT, 0x80 - Last in a table\r
+               WORD wAnsi;                     ANSI character\r
+               WORD wId;                       Keyboard accelerator passed to windows\r
+               WORD padding;           # bytes added to ensure aligned to DWORD boundary\r
+       };\r
+       */\r
+\r
+       do \r
+       {\r
+               fFlags = GET_WORD(p);\r
+               p++;\r
+               wAnsi = GET_WORD(p);\r
+               p++;\r
+               wID = GET_WORD(p);\r
+               p++;\r
+               p++;  // Skip over padding\r
+\r
+               if ((fFlags & 0x80) == 0x80) \r
+               {                               // 0x80\r
+                       bEnd = true;\r
+               }\r
+\r
+               if ((wAnsi < 0x30) ||\r
+                       (wAnsi > 0x5A) ||\r
+                       (wAnsi >= 0x3A && wAnsi <= 0x40))\r
+                       continue;\r
+\r
+               TCHAR * pBuf = new TCHAR[1024];\r
+               SecureZeroMemory(pBuf, 1024 * sizeof(TCHAR));\r
+\r
+               // include the menu ID in the msgid to make sure that 'duplicate'\r
+               // accelerator keys are listed in the po-file.\r
+               // without this, we would get entries like this:\r
+               //#. Accelerator Entry for Menu ID:32809; '&Filter'\r
+               //#. Accelerator Entry for Menu ID:57636; '&Find'\r
+               //#: Corresponding Menu ID:32771; '&Find'\r
+               //msgid "V C +F"\r
+               //msgstr "" \r
+               //\r
+               // Since "filter" and "find" are most likely translated to words starting\r
+               // with different letters, we need to have a separate accelerator entry\r
+               // for each of those\r
+               _stprintf(pBuf, _T("ID:%d:"), wID);\r
+\r
+               // EXACTLY 5 characters long "ACS+X"\r
+               // V = Virtual key (or blank if not used)\r
+               // A = Alt key     (or blank if not used)\r
+               // C = Ctrl key    (or blank if not used)\r
+               // S = Shift key   (or blank if not used)\r
+               // X = upper case character\r
+               // e.g. "V CS+Q" == Ctrl + Shift + 'Q'\r
+               if ((fFlags & FVIRTKEY) == FVIRTKEY)            // 0x01\r
+                       _tcscat(pBuf, _T("V"));\r
+               else\r
+                       _tcscat(pBuf, _T(" "));\r
+\r
+               if ((fFlags & FALT) == FALT)                            // 0x10\r
+                       _tcscat(pBuf, _T("A"));\r
+               else\r
+                       _tcscat(pBuf, _T(" "));\r
+\r
+               if ((fFlags & FCONTROL) == FCONTROL)            // 0x08\r
+                       _tcscat(pBuf, _T("C"));\r
+               else\r
+                       _tcscat(pBuf, _T(" "));\r
+\r
+               if ((fFlags & FSHIFT) == FSHIFT)                        // 0x04\r
+                       _tcscat(pBuf, _T("S"));\r
+               else\r
+                       _tcscat(pBuf, _T(" "));\r
+\r
+               _stprintf(pBuf, _T("%s+%c"), pBuf, wAnsi);\r
+\r
+               std::wstring wstr = std::wstring(pBuf);\r
+               RESOURCEENTRY AKey_entry = m_StringEntries[wstr];\r
+\r
+               TCHAR szTempBuf[1024];\r
+               SecureZeroMemory(szTempBuf, 1024 * sizeof(TCHAR));\r
+               std::wstring wmenu = _T("");\r
+               pME_iter = m_MenuEntries.find(wID);\r
+               if (pME_iter != m_MenuEntries.end()) \r
+               {\r
+                       wmenu = pME_iter->second.msgstr;\r
+               }\r
+               _stprintf(szTempBuf, _T("#. Accelerator Entry for Menu ID:%d; '%s'"), wID, wmenu.c_str());\r
+               AKey_entry.automaticcomments.push_back(std::wstring(szTempBuf));\r
+\r
+               m_StringEntries[wstr] = AKey_entry;\r
+               delete [] pBuf;\r
+       } while (!bEnd);\r
+\r
+       UnlockResource(hglAccTable);\r
+       FreeResource(hglAccTable);\r
+       return TRUE;\r
+\r
+DONE_ERROR:\r
+       UnlockResource(hglAccTable);\r
+       FreeResource(hglAccTable);\r
+       MYERROR;\r
+}\r
+\r
+BOOL CResModule::ReplaceAccelerator(UINT nID, WORD wLanguage)\r
+{\r
+       LPACCEL         lpaccelNew;                     // pointer to new accelerator table\r
+       HACCEL          haccelOld;                      // handle to old accelerator table\r
+       int                     cAccelerators;          // number of accelerators in table\r
+       HGLOBAL         hglAccTableNew;\r
+       const WORD*     p;\r
+       int                     i;\r
+\r
+       haccelOld = LoadAccelerators(m_hResDll, MAKEINTRESOURCE(nID));\r
+\r
+       if (haccelOld == NULL)\r
+               MYERROR;\r
+\r
+       cAccelerators = CopyAcceleratorTable(haccelOld, NULL, 0);\r
+\r
+       lpaccelNew = (LPACCEL) LocalAlloc(LPTR, cAccelerators * sizeof(ACCEL));\r
+\r
+       if (lpaccelNew == NULL)\r
+               MYERROR;\r
+\r
+       CopyAcceleratorTable(haccelOld, lpaccelNew, cAccelerators);\r
+\r
+       // Find the accelerator that the user modified\r
+       // and change its flags and virtual-key code\r
+       // as appropriate.\r
+\r
+       BYTE xfVirt;\r
+       WORD xkey;\r
+       for (i = 0; i < cAccelerators; i++) \r
+       {\r
+               m_bDefaultAcceleratorStrings++;\r
+               if ((lpaccelNew[i].key < 0x30) ||\r
+                       (lpaccelNew[i].key > 0x5A) ||\r
+                       (lpaccelNew[i].key >= 0x3A && lpaccelNew[i].key <= 0x40))\r
+                       continue;\r
+\r
+               TCHAR * pBuf = new TCHAR[1024];\r
+               SecureZeroMemory(pBuf, 1024 * sizeof(TCHAR));\r
+\r
+               _stprintf(pBuf, _T("ID:%d:"), lpaccelNew[i].cmd);\r
+\r
+               // get original key combination\r
+               if ((lpaccelNew[i].fVirt & FVIRTKEY) == FVIRTKEY)               // 0x01\r
+                       _tcscat(pBuf, _T("V"));\r
+               else\r
+                       _tcscat(pBuf, _T(" "));\r
+\r
+               if ((lpaccelNew[i].fVirt & FALT) == FALT)                               // 0x10\r
+                       _tcscat(pBuf, _T("A"));\r
+               else\r
+                       _tcscat(pBuf, _T(" "));\r
+\r
+               if ((lpaccelNew[i].fVirt & FCONTROL) == FCONTROL)               // 0x08\r
+                       _tcscat(pBuf, _T("C"));\r
+               else\r
+                       _tcscat(pBuf, _T(" "));\r
+\r
+               if ((lpaccelNew[i].fVirt & FSHIFT) == FSHIFT)                   // 0x04\r
+                       _tcscat(pBuf, _T("S"));\r
+               else\r
+                       _tcscat(pBuf, _T(" "));\r
+\r
+               _stprintf(pBuf, _T("%s+%c"), pBuf, lpaccelNew[i].key);\r
+\r
+               // Is it there?\r
+               std::map<std::wstring, RESOURCEENTRY>::iterator pAK_iter = m_StringEntries.find(pBuf);\r
+               if (pAK_iter != m_StringEntries.end()) \r
+               {\r
+                       m_bTranslatedAcceleratorStrings++;\r
+                       xfVirt = 0;\r
+                       xkey = 0;\r
+                       std::wstring wtemp = pAK_iter->second.msgstr;\r
+                       wtemp = wtemp.substr(wtemp.find_last_of(':')+1);\r
+                       if (wtemp.size() != 6)\r
+                               continue;\r
+                       if (wtemp.compare(0, 1, _T("V")) == 0)\r
+                               xfVirt |= FVIRTKEY;\r
+                       else if (wtemp.compare(0, 1, _T(" ")) != 0)\r
+                               continue;       // not a space - user must have made a mistake when translating\r
+                       if (wtemp.compare(1, 1, _T("A")) == 0)\r
+                               xfVirt |= FALT;\r
+                       else if (wtemp.compare(1, 1, _T(" ")) != 0)\r
+                               continue;       // not a space - user must have made a mistake when translating\r
+                       if (wtemp.compare(2, 1, _T("C")) == 0)\r
+                               xfVirt |= FCONTROL;\r
+                       else if (wtemp.compare(2, 1, _T(" ")) != 0)\r
+                               continue;       // not a space - user must have made a mistake when translating\r
+                       if (wtemp.compare(3, 1, _T("S")) == 0)\r
+                               xfVirt |= FSHIFT;\r
+                       else if (wtemp.compare(3, 1, _T(" ")) != 0)\r
+                               continue;       // not a space - user must have made a mistake when translating\r
+                       if (wtemp.compare(4, 1, _T("+")) == 0)\r
+                       {\r
+                               _stscanf(wtemp.substr(5, 1).c_str(), _T("%c"), &xkey);\r
+                               lpaccelNew[i].fVirt = xfVirt;\r
+                               lpaccelNew[i].key = xkey;\r
+                       }\r
+               }\r
+       }\r
+\r
+       // Create the new accelerator table\r
+       hglAccTableNew = LocalAlloc(LPTR, cAccelerators * 4 * sizeof(WORD));\r
+       p = (WORD *)hglAccTableNew;\r
+       lpaccelNew[cAccelerators-1].fVirt |= 0x80;\r
+       for (i = 0; i < cAccelerators; i++) \r
+       {\r
+               memcpy((void *)p, &lpaccelNew[i].fVirt, 1);\r
+               p++;\r
+               memcpy((void *)p, &lpaccelNew[i].key, sizeof(WORD));\r
+               p++;\r
+               memcpy((void *)p, &lpaccelNew[i].cmd, sizeof(WORD));\r
+               p++;\r
+               p++;\r
+       }\r
+\r
+       if (!UpdateResource(m_hUpdateRes, RT_ACCELERATOR, MAKEINTRESOURCE(nID),\r
+               (m_wTargetLang ? m_wTargetLang : wLanguage), hglAccTableNew /* haccelNew*/, cAccelerators * 4 * sizeof(WORD)))\r
+       {\r
+               goto DONE_ERROR;\r
+       }\r
+\r
+       if ((m_wTargetLang)&&(!UpdateResource(m_hUpdateRes, RT_ACCELERATOR, MAKEINTRESOURCE(nID), wLanguage, NULL, 0)))\r
+       {\r
+               goto DONE_ERROR;\r
+       }\r
+\r
+       LocalFree(lpaccelNew);\r
+       return TRUE;\r
+\r
+DONE_ERROR:\r
+       LocalFree(lpaccelNew);\r
+       MYERROR;\r
+}\r
+\r
+BOOL CResModule::ExtractDialog(UINT nID)\r
+{\r
+       const WORD*     lpDlg;\r
+       const WORD*     lpDlgItem;\r
+       DIALOGINFO      dlg;\r
+       DLGITEMINFO     dlgItem;\r
+       WORD            bNumControls;\r
+       HRSRC           hrsrc;\r
+       HGLOBAL         hGlblDlgTemplate;\r
+\r
+       hrsrc = FindResource(m_hResDll, MAKEINTRESOURCE(nID), RT_DIALOG);\r
+\r
+       if (hrsrc == NULL)\r
+               MYERROR;\r
+\r
+       hGlblDlgTemplate = LoadResource(m_hResDll, hrsrc);\r
+       if (hGlblDlgTemplate == NULL)\r
+               MYERROR;\r
+\r
+       lpDlg = (const WORD*) LockResource(hGlblDlgTemplate);\r
+\r
+       if (lpDlg == NULL)\r
+               MYERROR;\r
+\r
+       lpDlgItem = (const WORD*) GetDialogInfo(lpDlg, &dlg);\r
+       bNumControls = dlg.nbItems;\r
+\r
+       if (dlg.caption)\r
+       {\r
+               TCHAR * pBuf = new TCHAR[MAX_STRING_LENGTH];\r
+               SecureZeroMemory(pBuf, MAX_STRING_LENGTH * sizeof(TCHAR));\r
+               _tcscpy(pBuf, dlg.caption);\r
+               CUtils::StringExtend(pBuf);\r
+\r
+               std::wstring wstr = std::wstring(pBuf);\r
+               RESOURCEENTRY entry = m_StringEntries[wstr];\r
+               entry.resourceIDs.insert(nID);\r
+\r
+               m_StringEntries[wstr] = entry;\r
+               delete [] pBuf;\r
+       }\r
+\r
+       while (bNumControls-- != 0)\r
+       {\r
+               TCHAR szTitle[500];\r
+               SecureZeroMemory(szTitle, sizeof(szTitle));\r
+               BOOL  bCode;\r
+\r
+               lpDlgItem = GetControlInfo((WORD *) lpDlgItem, &dlgItem, dlg.dialogEx, &bCode);\r
+\r
+               if (bCode == FALSE)\r
+                       _tcscpy(szTitle, dlgItem.windowName);\r
+\r
+               if (_tcslen(szTitle) > 0)\r
+               {\r
+                       CUtils::StringExtend(szTitle);\r
+\r
+                       std::wstring wstr = std::wstring(szTitle);\r
+                       RESOURCEENTRY entry = m_StringEntries[wstr];\r
+                       entry.resourceIDs.insert(dlgItem.id);\r
+\r
+                       m_StringEntries[wstr] = entry;\r
+               }\r
+       }\r
+\r
+       UnlockResource(hGlblDlgTemplate);\r
+       FreeResource(hGlblDlgTemplate);\r
+       return (TRUE);\r
+}\r
+\r
+BOOL CResModule::ReplaceDialog(UINT nID, WORD wLanguage)\r
+{\r
+       const WORD*     lpDlg;\r
+       HRSRC           hrsrc;\r
+       HGLOBAL         hGlblDlgTemplate;\r
+\r
+       hrsrc = FindResourceEx(m_hResDll, RT_DIALOG, MAKEINTRESOURCE(nID), wLanguage);\r
+\r
+       if (hrsrc == NULL)\r
+               MYERROR;\r
+\r
+       hGlblDlgTemplate = LoadResource(m_hResDll, hrsrc);\r
+\r
+       if (hGlblDlgTemplate == NULL)\r
+               MYERROR;\r
+\r
+       lpDlg = (WORD *) LockResource(hGlblDlgTemplate);\r
+\r
+       if (lpDlg == NULL)\r
+               MYERROR;\r
+\r
+       size_t nMem = 0;\r
+       const WORD * p = lpDlg;\r
+       if (!CountMemReplaceDialogResource(p, &nMem, NULL))\r
+               goto DONE_ERROR;\r
+       WORD * newDialog = new WORD[nMem + (nMem % 2)];\r
+       SecureZeroMemory(newDialog, (nMem + (nMem % 2))*2);\r
+\r
+       size_t index = 0;\r
+       if (!CountMemReplaceDialogResource(lpDlg, &index, newDialog))\r
+       {\r
+               delete [] newDialog;\r
+               goto DONE_ERROR;\r
+       }\r
+       \r
+       if (!UpdateResource(m_hUpdateRes, RT_DIALOG, MAKEINTRESOURCE(nID), (m_wTargetLang ? m_wTargetLang : wLanguage), newDialog, (DWORD)(nMem + (nMem % 2))*2))\r
+       {\r
+               delete [] newDialog;\r
+               goto DONE_ERROR;\r
+       }\r
+       \r
+       if ((m_wTargetLang)&&(!UpdateResource(m_hUpdateRes, RT_DIALOG, MAKEINTRESOURCE(nID), wLanguage, NULL, 0)))\r
+       {\r
+               delete [] newDialog;\r
+               goto DONE_ERROR;\r
+       }\r
+\r
+       delete [] newDialog;\r
+       UnlockResource(hGlblDlgTemplate);\r
+       FreeResource(hGlblDlgTemplate);\r
+       return TRUE;\r
+\r
+DONE_ERROR:\r
+       UnlockResource(hGlblDlgTemplate);\r
+       FreeResource(hGlblDlgTemplate);\r
+       MYERROR;\r
+}\r
+\r
+const WORD* CResModule::GetDialogInfo(const WORD * pTemplate, LPDIALOGINFO lpDlgInfo)\r
+{\r
+       const WORD* p = (const WORD *)pTemplate;\r
+\r
+       lpDlgInfo->style = GET_DWORD(p);\r
+       p += 2;\r
+\r
+       if (lpDlgInfo->style == 0xffff0001)     // DIALOGEX resource\r
+       {\r
+               lpDlgInfo->dialogEx = TRUE;\r
+               lpDlgInfo->helpId   = GET_DWORD(p);\r
+               p += 2;\r
+               lpDlgInfo->exStyle  = GET_DWORD(p);\r
+               p += 2;\r
+               lpDlgInfo->style    = GET_DWORD(p);\r
+               p += 2;\r
+       }\r
+       else\r
+       {\r
+               lpDlgInfo->dialogEx = FALSE;\r
+               lpDlgInfo->helpId   = 0;\r
+               lpDlgInfo->exStyle  = GET_DWORD(p);\r
+               p += 2;\r
+       }\r
+\r
+       lpDlgInfo->nbItems = GET_WORD(p);\r
+       p++;\r
+\r
+       lpDlgInfo->x = GET_WORD(p);\r
+       p++;\r
+\r
+       lpDlgInfo->y = GET_WORD(p);\r
+       p++;\r
+\r
+       lpDlgInfo->cx = GET_WORD(p);\r
+       p++;\r
+\r
+       lpDlgInfo->cy = GET_WORD(p);\r
+       p++;\r
+\r
+       // Get the menu name\r
+\r
+       switch (GET_WORD(p))\r
+       {\r
+       case 0x0000:\r
+               lpDlgInfo->menuName = NULL;\r
+               p++;\r
+               break;\r
+       case 0xffff:\r
+               lpDlgInfo->menuName = (LPCTSTR) (WORD) GET_WORD(p + 1);\r
+               p += 2;\r
+               break;\r
+       default:\r
+               lpDlgInfo->menuName = (LPCTSTR) p;\r
+               p += wcslen((LPCWSTR) p) + 1;\r
+               break;\r
+       }\r
+\r
+       // Get the class name\r
+\r
+       switch (GET_WORD(p))\r
+       {\r
+       case 0x0000:\r
+               lpDlgInfo->className = (LPCTSTR)MAKEINTATOM(32770);\r
+               p++;\r
+               break;\r
+       case 0xffff:\r
+               lpDlgInfo->className = (LPCTSTR) (WORD) GET_WORD(p + 1);\r
+               p += 2;\r
+               break;\r
+       default:\r
+               lpDlgInfo->className = (LPCTSTR) p;\r
+               p += wcslen((LPCTSTR)p) + 1;\r
+               break;\r
+       }\r
+\r
+       // Get the window caption\r
+\r
+       lpDlgInfo->caption = (LPCTSTR)p;\r
+       p += wcslen((LPCWSTR) p) + 1;\r
+\r
+       // Get the font name\r
+\r
+       if (lpDlgInfo->style & DS_SETFONT)\r
+       {\r
+               lpDlgInfo->pointSize = GET_WORD(p);\r
+               p++;\r
+\r
+               if (lpDlgInfo->dialogEx)\r
+               {\r
+                       lpDlgInfo->weight = GET_WORD(p);\r
+                       p++;\r
+                       lpDlgInfo->italic = LOBYTE(GET_WORD(p));\r
+                       p++;\r
+               }\r
+               else\r
+               {\r
+                       lpDlgInfo->weight = FW_DONTCARE;\r
+                       lpDlgInfo->italic = FALSE;\r
+               }\r
+\r
+               lpDlgInfo->faceName = (LPCTSTR)p;\r
+               p += wcslen((LPCWSTR) p) + 1;\r
+       }\r
+       // First control is on DWORD boundary\r
+       return (const WORD *) ((((long)p) + 3) & ~3);\r
+}\r
+\r
+const WORD* CResModule::GetControlInfo(const WORD* p, LPDLGITEMINFO lpDlgItemInfo, BOOL dialogEx, LPBOOL bIsID)\r
+{\r
+       if (dialogEx)\r
+       {\r
+               lpDlgItemInfo->helpId = GET_DWORD(p);\r
+               p += 2;\r
+               lpDlgItemInfo->exStyle = GET_DWORD(p);\r
+               p += 2;\r
+               lpDlgItemInfo->style = GET_DWORD(p);\r
+               p += 2;\r
+       }\r
+       else\r
+       {\r
+               lpDlgItemInfo->helpId = 0;\r
+               lpDlgItemInfo->style = GET_DWORD(p);\r
+               p += 2;\r
+               lpDlgItemInfo->exStyle = GET_DWORD(p);\r
+               p += 2;\r
+       }\r
+\r
+       lpDlgItemInfo->x = GET_WORD(p);\r
+       p++;\r
+\r
+       lpDlgItemInfo->y = GET_WORD(p);\r
+       p++;\r
+\r
+       lpDlgItemInfo->cx = GET_WORD(p);\r
+       p++;\r
+\r
+       lpDlgItemInfo->cy = GET_WORD(p);\r
+       p++;\r
+\r
+       if (dialogEx)\r
+       {\r
+               // ID is a DWORD for DIALOGEX\r
+               lpDlgItemInfo->id = (WORD) GET_DWORD(p);\r
+               p += 2;\r
+       }\r
+       else\r
+       {\r
+               lpDlgItemInfo->id = GET_WORD(p);\r
+               p++;\r
+       }\r
+\r
+       if (GET_WORD(p) == 0xffff)\r
+       {\r
+               GET_WORD(p + 1);\r
+\r
+               p += 2;\r
+       }\r
+       else\r
+       {\r
+               lpDlgItemInfo->className = (LPCTSTR) p;\r
+               p += wcslen((LPCWSTR) p) + 1;\r
+       }\r
+\r
+       if (GET_WORD(p) == 0xffff)      // an integer ID?\r
+       {\r
+               *bIsID = TRUE;\r
+               lpDlgItemInfo->windowName = (LPCTSTR) (DWORD) GET_WORD(p + 1);\r
+               p += 2;\r
+       }\r
+       else\r
+       {\r
+               *bIsID = FALSE;\r
+               lpDlgItemInfo->windowName = (LPCTSTR) p;\r
+               p += wcslen((LPCWSTR) p) + 1;\r
+       }\r
+\r
+       if (GET_WORD(p))\r
+       {\r
+               lpDlgItemInfo->data = (LPVOID) (p + 1);\r
+               p += GET_WORD(p) / sizeof(WORD);\r
+       }\r
+       else\r
+               lpDlgItemInfo->data = NULL;\r
+\r
+       p++;\r
+       // Next control is on DWORD boundary\r
+       return (const WORD *)((((long)p) + 3) & ~3);\r
+}\r
+\r
+const WORD * CResModule::CountMemReplaceDialogResource(const WORD * res, size_t * wordcount, WORD * newDialog)\r
+{\r
+       BOOL bEx = FALSE;\r
+       DWORD style = GET_DWORD(res);\r
+       if (newDialog)\r
+       {\r
+               newDialog[(*wordcount)++] = GET_WORD(res++);\r
+               newDialog[(*wordcount)++] = GET_WORD(res++);\r
+       }\r
+       else\r
+       {\r
+               res += 2;\r
+               (*wordcount) += 2;\r
+       }\r
+\r
+       if (style == 0xffff0001)        // DIALOGEX resource\r
+       {\r
+               bEx = TRUE;\r
+               if (newDialog)\r
+               {\r
+                       newDialog[(*wordcount)++] = GET_WORD(res++);    //help id\r
+                       newDialog[(*wordcount)++] = GET_WORD(res++);    //help id\r
+                       newDialog[(*wordcount)++] = GET_WORD(res++);    //exStyle\r
+                       newDialog[(*wordcount)++] = GET_WORD(res++);    //exStyle\r
+                       style = GET_DWORD(res);\r
+                       newDialog[(*wordcount)++] = GET_WORD(res++);    //style\r
+                       newDialog[(*wordcount)++] = GET_WORD(res++);    //style\r
+               }\r
+               else\r
+               {\r
+                       res += 4;\r
+                       style = GET_DWORD(res);\r
+                       res += 2;\r
+                       (*wordcount) += 6;\r
+               }\r
+       }\r
+       else\r
+       {\r
+               bEx = FALSE;\r
+               if (newDialog)\r
+               {\r
+                       newDialog[(*wordcount)++] = GET_WORD(res++);    //exStyle\r
+                       newDialog[(*wordcount)++] = GET_WORD(res++);    //exStyle\r
+                       //style = GET_DWORD(res);\r
+                       //newDialog[(*wordcount)++] = GET_WORD(res++);  //style\r
+                       //newDialog[(*wordcount)++] = GET_WORD(res++);  //style\r
+               }\r
+               else\r
+               {\r
+                       res += 2;\r
+                       (*wordcount) += 2;\r
+               }\r
+       }\r
+\r
+       if (newDialog)\r
+               newDialog[(*wordcount)] = GET_WORD(res);\r
+       WORD nbItems = GET_WORD(res);\r
+       (*wordcount)++;\r
+       res++;\r
+\r
+       if (newDialog)\r
+               newDialog[(*wordcount)] = GET_WORD(res); //x\r
+       (*wordcount)++;\r
+       res++;\r
+\r
+       if (newDialog)\r
+               newDialog[(*wordcount)] = GET_WORD(res); //y\r
+       (*wordcount)++;\r
+       res++;\r
+\r
+       if (newDialog)\r
+               newDialog[(*wordcount)] = GET_WORD(res); //cx\r
+       (*wordcount)++;\r
+       res++;\r
+\r
+       if (newDialog)\r
+               newDialog[(*wordcount)] = GET_WORD(res); //cy\r
+       (*wordcount)++;\r
+       res++;\r
+\r
+       // Get the menu name\r
+\r
+       switch (GET_WORD(res))\r
+       {\r
+       case 0x0000:\r
+               if (newDialog)\r
+                       newDialog[(*wordcount)] = GET_WORD(res);\r
+               (*wordcount)++;\r
+               res++;\r
+               break;\r
+       case 0xffff:\r
+               if (newDialog)\r
+               {\r
+                       newDialog[(*wordcount)++] = GET_WORD(res++);\r
+                       newDialog[(*wordcount)++] = GET_WORD(res++);\r
+               }\r
+               else\r
+               {\r
+                       (*wordcount) += 2;\r
+                       res += 2;\r
+               }\r
+               break;\r
+       default:\r
+               if (newDialog)\r
+               {\r
+                       wcscpy((LPWSTR)&newDialog[(*wordcount)], (LPCWSTR)res);\r
+               }\r
+               (*wordcount) += wcslen((LPCWSTR) res) + 1;\r
+               res += wcslen((LPCWSTR) res) + 1;\r
+               break;\r
+       }\r
+\r
+       // Get the class name\r
+\r
+       switch (GET_WORD(res))\r
+       {\r
+       case 0x0000:\r
+               if (newDialog)\r
+                       newDialog[(*wordcount)] = GET_WORD(res);\r
+               (*wordcount)++;\r
+               res++;\r
+               break;\r
+       case 0xffff:\r
+               if (newDialog)\r
+               {\r
+                       newDialog[(*wordcount)++] = GET_WORD(res++);\r
+                       newDialog[(*wordcount)++] = GET_WORD(res++);\r
+               }\r
+               else\r
+               {\r
+                       (*wordcount) += 2;\r
+                       res += 2;\r
+               }\r
+               break;\r
+       default:\r
+               if (newDialog)\r
+               {\r
+                       wcscpy((LPWSTR)&newDialog[(*wordcount)], (LPCWSTR)res);\r
+               }\r
+               (*wordcount) += wcslen((LPCWSTR) res) + 1;\r
+               res += wcslen((LPCWSTR) res) + 1;\r
+               break;\r
+       }\r
+\r
+       // Get the window caption\r
+\r
+       ReplaceStr((LPCWSTR)res, newDialog, wordcount, &m_bTranslatedDialogStrings, &m_bDefaultDialogStrings);\r
+       res += wcslen((LPCWSTR)res) + 1;\r
+\r
+       // Get the font name\r
+\r
+       if (style & DS_SETFONT)\r
+       {\r
+               if (newDialog)\r
+                       newDialog[(*wordcount)] = GET_WORD(res);\r
+               res++;\r
+               (*wordcount)++;\r
+\r
+               if (bEx)\r
+               {\r
+                       if (newDialog)\r
+                       {\r
+                               newDialog[(*wordcount)++] = GET_WORD(res++);\r
+                               newDialog[(*wordcount)++] = GET_WORD(res++);\r
+                       }\r
+                       else\r
+                       {\r
+                               res += 2;\r
+                               (*wordcount) += 2;\r
+                       }\r
+               }\r
+\r
+               if (newDialog)\r
+                       wcscpy((LPWSTR)&newDialog[(*wordcount)], (LPCWSTR)res);\r
+               (*wordcount) += wcslen((LPCWSTR)res) + 1;\r
+               res += wcslen((LPCWSTR)res) + 1;\r
+       }\r
+       // First control is on DWORD boundary\r
+       while ((*wordcount)%2)\r
+               (*wordcount)++;\r
+       while ((ULONG)res % 4)\r
+               res++;\r
+\r
+       while (nbItems--)\r
+       {\r
+               res = ReplaceControlInfo(res, wordcount, newDialog, bEx);\r
+       }\r
+       return res;\r
+}\r
+\r
+const WORD* CResModule::ReplaceControlInfo(const WORD * res, size_t * wordcount, WORD * newDialog, BOOL bEx)\r
+{\r
+       if (bEx)\r
+       {\r
+               if (newDialog)\r
+               {\r
+                       newDialog[(*wordcount)++] = GET_WORD(res++);    //helpid\r
+                       newDialog[(*wordcount)++] = GET_WORD(res++);    //helpid\r
+               }\r
+               else\r
+               {\r
+                       res += 2;\r
+                       (*wordcount) += 2;\r
+               }\r
+       }\r
+       if (newDialog)\r
+       {\r
+               LONG * exStyle = (LONG*)&newDialog[(*wordcount)];\r
+               newDialog[(*wordcount)++] = GET_WORD(res++);    //exStyle\r
+               newDialog[(*wordcount)++] = GET_WORD(res++);    //exStyle\r
+               if (m_bRTL)\r
+                       *exStyle |= WS_EX_RTLREADING;\r
+       }\r
+       else\r
+       {\r
+               res += 2;\r
+               (*wordcount) += 2;\r
+       }\r
+\r
+       if (newDialog)\r
+       {\r
+               newDialog[(*wordcount)++] = GET_WORD(res++);    //style\r
+               newDialog[(*wordcount)++] = GET_WORD(res++);    //style\r
+       }\r
+       else\r
+       {\r
+               res += 2;\r
+               (*wordcount) += 2;\r
+       }\r
+\r
+       if (newDialog)\r
+               newDialog[(*wordcount)] = GET_WORD(res);        //x\r
+       res++;\r
+       (*wordcount)++;\r
+\r
+       if (newDialog)\r
+               newDialog[(*wordcount)] = GET_WORD(res);        //y\r
+       res++;\r
+       (*wordcount)++;\r
+\r
+       if (newDialog)\r
+               newDialog[(*wordcount)] = GET_WORD(res);        //cx\r
+       res++;\r
+       (*wordcount)++;\r
+\r
+       if (newDialog)\r
+               newDialog[(*wordcount)] = GET_WORD(res);        //cy\r
+       res++;\r
+       (*wordcount)++;\r
+\r
+       if (bEx)\r
+       {\r
+               // ID is a DWORD for DIALOGEX\r
+               if (newDialog)\r
+               {\r
+                       newDialog[(*wordcount)++] = GET_WORD(res++);\r
+                       newDialog[(*wordcount)++] = GET_WORD(res++);\r
+               }\r
+               else\r
+               {\r
+                       res += 2;\r
+                       (*wordcount) += 2;\r
+               }\r
+       }\r
+       else\r
+       {\r
+               if (newDialog)\r
+                       newDialog[(*wordcount)] = GET_WORD(res);\r
+               res++;\r
+               (*wordcount)++;\r
+       }\r
+\r
+       if (GET_WORD(res) == 0xffff)    //classID\r
+       {\r
+               if (newDialog)\r
+               {\r
+                       newDialog[(*wordcount)++] = GET_WORD(res++);\r
+                       newDialog[(*wordcount)++] = GET_WORD(res++);\r
+               }\r
+               else\r
+               {\r
+                       res += 2;\r
+                       (*wordcount) += 2;\r
+               }\r
+       }\r
+       else\r
+       {\r
+               if (newDialog)\r
+                       wcscpy((LPWSTR)&newDialog[(*wordcount)], (LPCWSTR)res);\r
+               (*wordcount) += wcslen((LPCWSTR) res) + 1;\r
+               res += wcslen((LPCWSTR) res) + 1;\r
+       }\r
+\r
+       if (GET_WORD(res) == 0xffff)    // an integer ID?\r
+       {\r
+               if (newDialog)\r
+               {\r
+                       newDialog[(*wordcount)++] = GET_WORD(res++);\r
+                       newDialog[(*wordcount)++] = GET_WORD(res++);\r
+               }\r
+               else\r
+               {\r
+                       res += 2;\r
+                       (*wordcount) += 2;\r
+               }\r
+       }\r
+       else\r
+       {\r
+               ReplaceStr((LPCWSTR)res, newDialog, wordcount, &m_bTranslatedDialogStrings, &m_bDefaultDialogStrings);\r
+               res += wcslen((LPCWSTR)res) + 1;\r
+       }\r
+\r
+       if (newDialog)\r
+               memcpy(&newDialog[(*wordcount)], res, (GET_WORD(res)+1)*sizeof(WORD));\r
+       (*wordcount) += (GET_WORD(res)+1);\r
+       res += (GET_WORD(res)+1);\r
+       // Next control is on DWORD boundary\r
+       while ((*wordcount) % 2)\r
+               (*wordcount)++;\r
+       return (const WORD *)((((long)res) + 3) & ~3);\r
+}\r
+\r
+BOOL CALLBACK CResModule::EnumResNameCallback(HMODULE /*hModule*/, LPCTSTR lpszType, LPTSTR lpszName, LONG_PTR lParam)\r
+{\r
+       CResModule* lpResModule = (CResModule*)lParam;\r
+\r
+       if (lpszType == RT_STRING)\r
+       {\r
+               if (IS_INTRESOURCE(lpszName))\r
+               {\r
+                       if (!lpResModule->ExtractString(LOWORD(lpszName)))\r
+                               return FALSE;\r
+               }\r
+       } \r
+       else if (lpszType == RT_MENU)\r
+       {\r
+               if (IS_INTRESOURCE(lpszName))\r
+               {\r
+                       if (!lpResModule->ExtractMenu(LOWORD(lpszName)))\r
+                               return FALSE;\r
+               }\r
+       }\r
+       else if (lpszType == RT_DIALOG)\r
+       {\r
+               if (IS_INTRESOURCE(lpszName))\r
+               {\r
+                       if (!lpResModule->ExtractDialog(LOWORD(lpszName)))\r
+                               return FALSE;\r
+               }\r
+       }\r
+       else if (lpszType == RT_ACCELERATOR)\r
+       {\r
+               if (IS_INTRESOURCE(lpszName))\r
+               {\r
+                       if (!lpResModule->ExtractAccelerator(LOWORD(lpszName)))\r
+                               return FALSE;\r
+               }\r
+       }\r
+\r
+       return TRUE;\r
+}\r
+\r
+#pragma warning(push)\r
+#pragma warning(disable: 4189)\r
+BOOL CALLBACK CResModule::EnumResNameWriteCallback(HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG_PTR lParam)\r
+{\r
+       CResModule* lpResModule = (CResModule*)lParam;\r
+       return EnumResourceLanguages(hModule, lpszType, lpszName, (ENUMRESLANGPROC)&lpResModule->EnumResWriteLangCallback, lParam);\r
+}\r
+#pragma warning(pop)\r
+\r
+BOOL CALLBACK CResModule::EnumResWriteLangCallback(HMODULE /*hModule*/, LPCTSTR lpszType, LPTSTR lpszName, WORD wLanguage, LONG_PTR lParam)\r
+{\r
+       BOOL bRes = FALSE;\r
+       CResModule* lpResModule = (CResModule*)lParam;\r
+\r
+\r
+       int count = 0;\r
+       do \r
+       {\r
+               lpResModule->m_hUpdateRes = BeginUpdateResource(lpResModule->sDestFile.c_str(), FALSE);\r
+               if (lpResModule->m_hUpdateRes == NULL)\r
+                       Sleep(100);\r
+               count++;\r
+       } while ((lpResModule->m_hUpdateRes == NULL)&&(count < 5));\r
+\r
+       if (lpszType == RT_STRING)\r
+       {\r
+               if (IS_INTRESOURCE(lpszName))\r
+               {\r
+                       bRes = lpResModule->ReplaceString(LOWORD(lpszName), wLanguage);\r
+               }\r
+       } \r
+       else if (lpszType == RT_MENU)\r
+       {\r
+               if (IS_INTRESOURCE(lpszName))\r
+               {\r
+                       bRes = lpResModule->ReplaceMenu(LOWORD(lpszName), wLanguage);\r
+               }\r
+       }\r
+       else if (lpszType == RT_DIALOG)\r
+       {\r
+               if (IS_INTRESOURCE(lpszName))\r
+               {\r
+                       bRes = lpResModule->ReplaceDialog(LOWORD(lpszName), wLanguage);\r
+               }\r
+       }\r
+       else if (lpszType == RT_ACCELERATOR)\r
+       {\r
+               if (IS_INTRESOURCE(lpszName))\r
+               {\r
+                       bRes = lpResModule->ReplaceAccelerator(LOWORD(lpszName), wLanguage);\r
+               }\r
+       }\r
+\r
+       if (!EndUpdateResource(lpResModule->m_hUpdateRes, !bRes))\r
+               MYERROR;\r
+       return bRes;\r
+\r
+}\r
+\r
+void CResModule::ReplaceStr(LPCWSTR src, WORD * dest, size_t * count, int * translated, int * def)\r
+{\r
+       TCHAR * pBuf = new TCHAR[MAX_STRING_LENGTH];\r
+       SecureZeroMemory(pBuf, MAX_STRING_LENGTH * sizeof(TCHAR));\r
+       wcscpy(pBuf, src);\r
+       CUtils::StringExtend(pBuf);\r
+\r
+       std::wstring wstr = std::wstring(pBuf);\r
+       RESOURCEENTRY entry = m_StringEntries[wstr];\r
+       if (entry.msgstr.size())\r
+       {\r
+               wcscpy(pBuf, entry.msgstr.c_str());\r
+               CUtils::StringCollapse(pBuf);\r
+               if (dest)\r
+                       wcscpy((wchar_t *)&dest[(*count)], pBuf);\r
+               (*count) += wcslen(pBuf)+1;\r
+               (*translated)++;\r
+       }\r
+       else\r
+       {\r
+               if (dest)\r
+                       wcscpy((wchar_t *)&dest[(*count)], src);\r
+               (*count) += wcslen(src) + 1;\r
+               if (wcslen(src))\r
+                       (*def)++;\r
+       }\r
+       delete [] pBuf;\r
+}\r
diff --git a/src/ResText/ResModule.h b/src/ResText/ResModule.h
new file mode 100644 (file)
index 0000000..918475f
--- /dev/null
@@ -0,0 +1,137 @@
+// TortoiseSVN - a Windows shell extension for easy version control\r
+\r
+// Copyright (C) 2003-2007 - TortoiseSVN\r
+\r
+// This program is free software; you can redistribute it and/or\r
+// modify it under the terms of the GNU General Public License\r
+// as published by the Free Software Foundation; either version 2\r
+// of the License, or (at your option) any later version.\r
+\r
+// This program is distributed in the hope that it will be useful,\r
+// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+// GNU General Public License for more details.\r
+\r
+// You should have received a copy of the GNU General Public License\r
+// along with this program; if not, write to the Free Software Foundation,\r
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
+#pragma once\r
+#include <vector>\r
+#include <string>\r
+#include <map>\r
+#include "POFile.h"\r
+\r
+#define GET_WORD(ptr)        (*(WORD  *)(ptr))\r
+#define GET_DWORD(ptr)       (*(DWORD *)(ptr))\r
+#define ALIGN_DWORD(type, p) ((type)(((DWORD)p + 3) & ~3))\r
+\r
+#define MAX_STRING_LENGTH      (32*1024)\r
+\r
+// DIALOG CONTROL INFORMATION\r
+typedef struct tagDlgItemInfo\r
+{\r
+       DWORD   style;\r
+       DWORD   exStyle;\r
+       DWORD   helpId;\r
+       short   x;\r
+       short   y;\r
+       short   cx;\r
+       short   cy;\r
+       WORD    id;\r
+       LPCTSTR className;\r
+       LPCTSTR windowName;\r
+       LPVOID  data;\r
+} DLGITEMINFO, * LPDLGITEMINFO;\r
+\r
+// DIALOG TEMPLATE\r
+typedef struct tagDialogInfo\r
+{\r
+       DWORD   style;\r
+       DWORD   exStyle;\r
+       DWORD   helpId;\r
+       WORD    nbItems;\r
+       short   x;\r
+       short   y;\r
+       short   cx;\r
+       short   cy;\r
+       LPCTSTR menuName;\r
+       LPCTSTR className;\r
+       LPCTSTR caption;\r
+       WORD    pointSize;\r
+       WORD    weight;\r
+       BOOL    italic;\r
+       LPCTSTR faceName;\r
+       BOOL    dialogEx;\r
+} DIALOGINFO, * LPDIALOGINFO;\r
+// MENU resource\r
+typedef struct tagMenuEntry\r
+{\r
+       WORD            wID;\r
+       std::wstring    reference;\r
+       std::wstring    msgstr;\r
+} MENUENTRY, * LPMENUENTRY;\r
+\r
+/**\r
+ * \ingroup ResText\r
+ * Class to handle a resource module (*.exe or *.dll file).\r
+ *\r
+ * Provides methods to extract and apply resource strings.\r
+ */\r
+class CResModule\r
+{\r
+public:\r
+       CResModule(void);\r
+       ~CResModule(void);\r
+\r
+       BOOL    ExtractResources(LPCTSTR lpszSrcLangDllPath, LPCTSTR lpszPOFilePath, BOOL bNoUpdate);\r
+       BOOL    ExtractResources(std::vector<std::wstring> filelist, LPCTSTR lpszPOFilePath, BOOL bNoUpdate);\r
+       BOOL    CreateTranslatedResources(LPCTSTR lpszSrcLangDllPath, LPCTSTR lpszDestLangDllPath, LPCTSTR lpszPOFilePath);\r
+       void    SetQuiet(BOOL bQuiet = TRUE) {m_bQuiet = bQuiet; m_StringEntries.SetQuiet(bQuiet);}\r
+       void    SetLanguage(WORD wLangID) {m_wTargetLang = wLangID;}\r
+       void    SetRTL(bool bRTL = true) {m_bRTL = bRTL;}\r
+\r
+private:\r
+       static  BOOL CALLBACK EnumResNameCallback(HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG_PTR lParam);\r
+       static  BOOL CALLBACK EnumResNameWriteCallback(HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG_PTR lParam);\r
+       static  BOOL CALLBACK EnumResWriteLangCallback(HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, WORD wLanguage, LONG_PTR lParam);\r
+       BOOL    ExtractString(UINT nID);\r
+       BOOL    ExtractDialog(UINT nID);\r
+       BOOL    ExtractMenu(UINT nID);\r
+       BOOL    ReplaceString(UINT nID, WORD wLanguage);\r
+       BOOL    ReplaceDialog(UINT nID, WORD wLanguage);\r
+       BOOL    ReplaceMenu(UINT nID, WORD wLanguage);\r
+       BOOL    ExtractAccelerator(UINT nID);\r
+       BOOL    ReplaceAccelerator(UINT nID, WORD wLanguage);\r
+\r
+       const WORD*     ParseMenuResource(const WORD * res);\r
+       const WORD*     CountMemReplaceMenuResource(const WORD * res, size_t * wordcount, WORD * newMenu);\r
+       const WORD*     ParseMenuExResource(const WORD * res);\r
+       const WORD*     CountMemReplaceMenuExResource(const WORD * res, size_t * wordcount, WORD * newMenu);\r
+       const WORD* GetControlInfo(const WORD* p, LPDLGITEMINFO lpDlgItemInfo, BOOL dialogEx, LPBOOL bIsID);\r
+       const WORD*     GetDialogInfo(const WORD * pTemplate, LPDIALOGINFO lpDlgInfo);\r
+       const WORD*     CountMemReplaceDialogResource(const WORD * res, size_t * wordcount, WORD * newMenu);\r
+       const WORD* ReplaceControlInfo(const WORD * res, size_t * wordcount, WORD * newDialog, BOOL bEx);\r
+\r
+       void    ReplaceStr(LPCWSTR src, WORD * dest, size_t * count, int * translated, int * def);\r
+\r
+       HMODULE                 m_hResDll;\r
+       HANDLE                  m_hUpdateRes;\r
+       CPOFile                 m_StringEntries;\r
+       std::map<WORD, MENUENTRY> m_MenuEntries;\r
+       std::map<WORD, MENUENTRY>::iterator pME_iter;\r
+       std::wstring    sDestFile;\r
+       BOOL                    m_bQuiet;\r
+\r
+       bool                    m_bRTL;\r
+\r
+       int                             m_bTranslatedStrings;\r
+       int                             m_bDefaultStrings;\r
+       int                             m_bTranslatedDialogStrings;\r
+       int                             m_bDefaultDialogStrings;\r
+       int                             m_bTranslatedMenuStrings;\r
+       int                             m_bDefaultMenuStrings;\r
+       int                             m_bTranslatedAcceleratorStrings;\r
+       int                             m_bDefaultAcceleratorStrings;\r
+\r
+       WORD                    m_wTargetLang;\r
+};\r
diff --git a/src/ResText/ResText.cpp b/src/ResText/ResText.cpp
new file mode 100644 (file)
index 0000000..b1ebb93
--- /dev/null
@@ -0,0 +1,145 @@
+// TortoiseSVN - a Windows shell extension for easy version control\r
+\r
+// Copyright (C) 2003-2006 - Stefan Kueng\r
+\r
+// This program is free software; you can redistribute it and/or\r
+// modify it under the terms of the GNU General Public License\r
+// as published by the Free Software Foundation; either version 2\r
+// of the License, or (at your option) any later version.\r
+\r
+// This program is distributed in the hope that it will be useful,\r
+// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+// GNU General Public License for more details.\r
+\r
+// You should have received a copy of the GNU General Public License\r
+// along with this program; if not, write to the Free Software Foundation,\r
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
+#include "stdafx.h"\r
+#include "ResModule.h"\r
+\r
+#include <string>\r
+#include <vector>\r
+#include "shlwapi.h"\r
+#pragma comment(lib, "shlwapi.lib")\r
+\r
+typedef std::basic_string<wchar_t> wstring;\r
+#ifdef UNICODE\r
+#      define stdstring wstring\r
+#else\r
+#      define stdstring std::string\r
+#endif\r
+\r
+int _tmain(int argc, _TCHAR* argv[])\r
+{\r
+       bool bShowHelp = true;\r
+       bool bQuiet = false;\r
+       bool bNoUpdate = false;\r
+       bool bRTL = false;\r
+       //parse the command line\r
+       std::vector<stdstring> arguments;\r
+       std::vector<stdstring> switches;\r
+       for (int i=1; i<argc; ++i)\r
+       {\r
+               if ((argv[i][0] == '-')||(argv[i][0] == '/'))\r
+               {\r
+                       stdstring str = stdstring(&argv[i][1]);\r
+                       switches.push_back(str);\r
+               }\r
+               else\r
+               {\r
+                       stdstring str = stdstring(&argv[i][0]);\r
+                       arguments.push_back(str);\r
+               }\r
+       }\r
+\r
+       for (std::vector<stdstring>::iterator I = switches.begin(); I != switches.end(); ++I)\r
+       {\r
+               if (_tcscmp(I->c_str(), _T("?"))==0)\r
+                       bShowHelp = true;\r
+               if (_tcscmp(I->c_str(), _T("help"))==0)\r
+                       bShowHelp = true;\r
+               if (_tcscmp(I->c_str(), _T("quiet"))==0)\r
+                       bQuiet = true;\r
+               if (_tcscmp(I->c_str(), _T("noupdate"))==0)\r
+                       bNoUpdate = true;\r
+               if (_tcscmp(I->c_str(), _T("rtl"))==0)\r
+                       bRTL = true;\r
+       }\r
+       std::vector<stdstring>::iterator arg = arguments.begin();\r
+\r
+       if (arg != arguments.end())\r
+       {\r
+               if (_tcscmp(arg->c_str(), _T("extract"))==0)\r
+               {\r
+                       stdstring sDllFile;\r
+                       stdstring sPoFile;\r
+                       ++arg;\r
+                       \r
+                       std::vector<std::wstring> filelist = arguments;\r
+                       filelist.erase(filelist.begin());\r
+                       sPoFile = stdstring((--filelist.end())->c_str());\r
+                       filelist.erase(--filelist.end());\r
+                       \r
+                       CResModule module;\r
+                       module.SetQuiet(bQuiet);\r
+                       if (!module.ExtractResources(filelist, sPoFile.c_str(), bNoUpdate))\r
+                               return -1;\r
+                       bShowHelp = false;\r
+               }\r
+               else if (_tcscmp(arg->c_str(), _T("apply"))==0)\r
+               {\r
+                       stdstring sSrcDllFile;\r
+                       stdstring sDstDllFile;\r
+                       stdstring sPoFile;\r
+                       WORD wLang = 0;\r
+                       ++arg;\r
+                       if (!PathFileExists(arg->c_str()))\r
+                       {\r
+                               _ftprintf(stderr, _T("the resource dll <%s> does not exist!\n"), arg->c_str());\r
+                               return -1;\r
+                       }\r
+                       sSrcDllFile = stdstring(arg->c_str());\r
+                       ++arg;\r
+                       sDstDllFile = stdstring(arg->c_str());\r
+                       ++arg;\r
+                       if (!PathFileExists(arg->c_str()))\r
+                       {\r
+                               _ftprintf(stderr, _T("the po-file <%s> does not exist!\n"), arg->c_str());\r
+                               return -1;\r
+                       }\r
+                       sPoFile = stdstring(arg->c_str());\r
+                       ++arg;\r
+                       if (arg != arguments.end())\r
+                       {\r
+                               wLang = (WORD)_ttoi(arg->c_str());\r
+                       }\r
+                       CResModule module;\r
+                       module.SetQuiet(bQuiet);\r
+                       module.SetLanguage(wLang);\r
+                       module.SetRTL(bRTL);\r
+                       if (!module.CreateTranslatedResources(sSrcDllFile.c_str(), sDstDllFile.c_str(), sPoFile.c_str()))\r
+                               return -1;\r
+                       bShowHelp = false;\r
+               }\r
+       }\r
+\r
+       if (bShowHelp)\r
+       {\r
+               _ftprintf(stdout, _T("usage:\n"));\r
+               _ftprintf(stdout, _T("\n"));\r
+               _ftprintf(stdout, _T("ResText extract <resource.dll> [<resource.dll> ...] <po-file> [-quiet] [-noupdate]\n"));\r
+               _ftprintf(stdout, _T("Extracts all strings from the resource dll and writes them to the po-file\n"));\r
+               _ftprintf(stdout, _T("-quiet: don't print progress messages\n"));\r
+               _ftprintf(stdout, _T("-noupdate: overwrite the po-file\n"));\r
+               _ftprintf(stdout, _T("\n"));\r
+               _ftprintf(stdout, _T("ResText apply <src resource.dll> <dst resource.dll> <po-file> [langID] [-quiet][-rtl]\n"));\r
+               _ftprintf(stdout, _T("Replaces all strings in the dst resource.dll with the po-file translations\n"));\r
+               _ftprintf(stdout, _T("-quiet: don't print progress messages\n"));\r
+               _ftprintf(stdout, _T("-rtl  : change the controls to RTL reading\n"));\r
+               _ftprintf(stdout, _T("\n"));\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
diff --git a/src/ResText/ResText.vcproj b/src/ResText/ResText.vcproj
new file mode 100644 (file)
index 0000000..50c8b55
--- /dev/null
@@ -0,0 +1,871 @@
+<?xml version="1.0" encoding="Windows-1252"?>\r
+<VisualStudioProject\r
+       ProjectType="Visual C++"\r
+       Version="9.00"\r
+       Name="ResText"\r
+       ProjectGUID="{72EFB681-1397-4193-BBF9-CA05AC52B75D}"\r
+       RootNamespace="ResText"\r
+       Keyword="Win32Proj"\r
+       TargetFrameworkVersion="131072"\r
+       >\r
+       <Platforms>\r
+               <Platform\r
+                       Name="Win32"\r
+               />\r
+               <Platform\r
+                       Name="x64"\r
+               />\r
+       </Platforms>\r
+       <ToolFiles>\r
+       </ToolFiles>\r
+       <Configurations>\r
+               <Configuration\r
+                       Name="Debug|Win32"\r
+                       OutputDirectory="..\..\bin\Debug\bin"\r
+                       IntermediateDirectory="..\..\obj\ResText\Debug"\r
+                       ConfigurationType="1"\r
+                       CharacterSet="1"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
+                               PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;_CRT_NON_CONFORMING_SWPRINTFS"\r
+                               MinimalRebuild="true"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="1"\r
+                               TreatWChar_tAsBuiltInType="true"\r
+                               ForceConformanceInForLoopScope="true"\r
+                               UsePrecompiledHeader="2"\r
+                               WarningLevel="4"\r
+                               DebugInformationFormat="4"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalDependencies="shlwapi.lib"\r
+                               OutputFile="$(OutDir)/ResText.exe"\r
+                               LinkIncremental="2"\r
+                               GenerateDebugInformation="true"\r
+                               ProgramDatabaseFile="$(OutDir)/ResText.pdb"\r
+                               SubSystem="1"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
+                               TargetMachine="1"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Debug|x64"\r
+                       OutputDirectory="..\..\bin\Debug64\bin"\r
+                       IntermediateDirectory="..\..\obj\ResText\Debug64"\r
+                       ConfigurationType="1"\r
+                       CharacterSet="1"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               TargetEnvironment="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
+                               PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;_CRT_NON_CONFORMING_SWPRINTFS"\r
+                               MinimalRebuild="true"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="1"\r
+                               TreatWChar_tAsBuiltInType="true"\r
+                               ForceConformanceInForLoopScope="true"\r
+                               UsePrecompiledHeader="2"\r
+                               WarningLevel="4"\r
+                               DebugInformationFormat="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalDependencies="shlwapi.lib"\r
+                               OutputFile="$(OutDir)/ResText.exe"\r
+                               LinkIncremental="2"\r
+                               GenerateDebugInformation="true"\r
+                               ProgramDatabaseFile="$(OutDir)/ResText.pdb"\r
+                               SubSystem="1"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
+                               TargetMachine="17"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|Win32"\r
+                       OutputDirectory="..\..\bin\Release\bin"\r
+                       IntermediateDirectory="..\..\obj\ResText\Release"\r
+                       ConfigurationType="1"\r
+                       CharacterSet="1"\r
+                       WholeProgramOptimization="1"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="1"\r
+                               FavorSizeOrSpeed="2"\r
+                               PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;_CRT_NON_CONFORMING_SWPRINTFS"\r
+                               StringPooling="true"\r
+                               RuntimeLibrary="0"\r
+                               BufferSecurityCheck="false"\r
+                               TreatWChar_tAsBuiltInType="true"\r
+                               ForceConformanceInForLoopScope="true"\r
+                               UsePrecompiledHeader="2"\r
+                               WarningLevel="4"\r
+                               DebugInformationFormat="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalDependencies="shlwapi.lib"\r
+                               OutputFile="$(OutDir)/ResText.exe"\r
+                               LinkIncremental="1"\r
+                               GenerateDebugInformation="true"\r
+                               SubSystem="1"\r
+                               OptimizeReferences="2"\r
+                               EnableCOMDATFolding="2"\r
+                               OptimizeForWindows98="0"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
+                               TargetMachine="1"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|x64"\r
+                       OutputDirectory="..\..\bin\Release64\bin"\r
+                       IntermediateDirectory="..\..\obj\ResText\Release64"\r
+                       ConfigurationType="1"\r
+                       CharacterSet="1"\r
+                       WholeProgramOptimization="1"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               TargetEnvironment="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="1"\r
+                               FavorSizeOrSpeed="2"\r
+                               PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;_CRT_NON_CONFORMING_SWPRINTFS"\r
+                               StringPooling="true"\r
+                               RuntimeLibrary="2"\r
+                               BufferSecurityCheck="false"\r
+                               TreatWChar_tAsBuiltInType="true"\r
+                               ForceConformanceInForLoopScope="true"\r
+                               UsePrecompiledHeader="2"\r
+                               WarningLevel="4"\r
+                               DebugInformationFormat="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalDependencies="shlwapi.lib"\r
+                               OutputFile="$(OutDir)/ResText.exe"\r
+                               LinkIncremental="1"\r
+                               GenerateDebugInformation="true"\r
+                               SubSystem="1"\r
+                               OptimizeReferences="2"\r
+                               EnableCOMDATFolding="2"\r
+                               OptimizeForWindows98="1"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
+                               TargetMachine="17"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="release_static|Win32"\r
+                       OutputDirectory="..\..\bin\ReleaseStatic\bin"\r
+                       IntermediateDirectory="..\..\obj\ResText\ReleaseStatic"\r
+                       ConfigurationType="1"\r
+                       CharacterSet="1"\r
+                       WholeProgramOptimization="1"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="1"\r
+                               FavorSizeOrSpeed="2"\r
+                               PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;_CRT_NON_CONFORMING_SWPRINTFS"\r
+                               StringPooling="true"\r
+                               RuntimeLibrary="0"\r
+                               BufferSecurityCheck="false"\r
+                               TreatWChar_tAsBuiltInType="true"\r
+                               ForceConformanceInForLoopScope="true"\r
+                               UsePrecompiledHeader="2"\r
+                               WarningLevel="4"\r
+                               DebugInformationFormat="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalDependencies="shlwapi.lib"\r
+                               OutputFile="$(OutDir)/ResText.exe"\r
+                               LinkIncremental="1"\r
+                               GenerateDebugInformation="true"\r
+                               SubSystem="1"\r
+                               OptimizeReferences="2"\r
+                               EnableCOMDATFolding="2"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
+                               TargetMachine="1"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="release_static|x64"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       ConfigurationType="1"\r
+                       CharacterSet="1"\r
+                       WholeProgramOptimization="1"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               TargetEnvironment="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="1"\r
+                               FavorSizeOrSpeed="2"\r
+                               PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;_CRT_NON_CONFORMING_SWPRINTFS"\r
+                               StringPooling="true"\r
+                               RuntimeLibrary="0"\r
+                               BufferSecurityCheck="false"\r
+                               TreatWChar_tAsBuiltInType="true"\r
+                               ForceConformanceInForLoopScope="true"\r
+                               UsePrecompiledHeader="2"\r
+                               WarningLevel="4"\r
+                               DebugInformationFormat="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalDependencies="shlwapi.lib"\r
+                               OutputFile="$(OutDir)/ResText.exe"\r
+                               LinkIncremental="1"\r
+                               GenerateDebugInformation="true"\r
+                               SubSystem="1"\r
+                               OptimizeReferences="2"\r
+                               EnableCOMDATFolding="2"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
+                               TargetMachine="17"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="debug_static|Win32"\r
+                       OutputDirectory="$(ConfigurationName)"\r
+                       IntermediateDirectory="$(ConfigurationName)"\r
+                       ConfigurationType="1"\r
+                       CharacterSet="1"\r
+                       WholeProgramOptimization="1"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="1"\r
+                               FavorSizeOrSpeed="2"\r
+                               PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;_CRT_NON_CONFORMING_SWPRINTFS"\r
+                               StringPooling="true"\r
+                               RuntimeLibrary="0"\r
+                               BufferSecurityCheck="false"\r
+                               TreatWChar_tAsBuiltInType="true"\r
+                               ForceConformanceInForLoopScope="true"\r
+                               UsePrecompiledHeader="2"\r
+                               WarningLevel="4"\r
+                               DebugInformationFormat="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalDependencies="shlwapi.lib"\r
+                               OutputFile="$(OutDir)/ResText.exe"\r
+                               LinkIncremental="1"\r
+                               GenerateDebugInformation="true"\r
+                               SubSystem="1"\r
+                               OptimizeReferences="2"\r
+                               EnableCOMDATFolding="2"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
+                               TargetMachine="1"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="debug_static|x64"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       ConfigurationType="1"\r
+                       CharacterSet="1"\r
+                       WholeProgramOptimization="1"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               TargetEnvironment="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="1"\r
+                               FavorSizeOrSpeed="2"\r
+                               PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;_CRT_NON_CONFORMING_SWPRINTFS"\r
+                               StringPooling="true"\r
+                               RuntimeLibrary="0"\r
+                               BufferSecurityCheck="false"\r
+                               TreatWChar_tAsBuiltInType="true"\r
+                               ForceConformanceInForLoopScope="true"\r
+                               UsePrecompiledHeader="2"\r
+                               WarningLevel="4"\r
+                               DebugInformationFormat="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalDependencies="shlwapi.lib"\r
+                               OutputFile="$(OutDir)/ResText.exe"\r
+                               LinkIncremental="1"\r
+                               GenerateDebugInformation="true"\r
+                               SubSystem="1"\r
+                               OptimizeReferences="2"\r
+                               EnableCOMDATFolding="2"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
+                               TargetMachine="17"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+       </Configurations>\r
+       <References>\r
+       </References>\r
+       <Files>\r
+               <Filter\r
+                       Name="Source Files"\r
+                       Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"\r
+                       UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"\r
+                       >\r
+                       <File\r
+                               RelativePath=".\codecvt.cpp"\r
+                               >\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               UsePrecompiledHeader="0"\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Debug|x64"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               UsePrecompiledHeader="0"\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               UsePrecompiledHeader="0"\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|x64"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               UsePrecompiledHeader="0"\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="release_static|Win32"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               UsePrecompiledHeader="0"\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="release_static|x64"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               UsePrecompiledHeader="0"\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="debug_static|Win32"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               UsePrecompiledHeader="0"\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="debug_static|x64"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               UsePrecompiledHeader="0"\r
+                                       />\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\POFile.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\ResModule.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\ResText.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\stdafx.cpp"\r
+                               >\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               UsePrecompiledHeader="1"\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Debug|x64"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               UsePrecompiledHeader="1"\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               UsePrecompiledHeader="1"\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|x64"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               UsePrecompiledHeader="1"\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="release_static|Win32"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               UsePrecompiledHeader="1"\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="release_static|x64"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               UsePrecompiledHeader="1"\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="debug_static|Win32"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               UsePrecompiledHeader="1"\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="debug_static|x64"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               UsePrecompiledHeader="1"\r
+                                       />\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\Utils.cpp"\r
+                               >\r
+                       </File>\r
+               </Filter>\r
+               <Filter\r
+                       Name="Header Files"\r
+                       Filter="h;hpp;hxx;hm;inl;inc;xsd"\r
+                       UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"\r
+                       >\r
+                       <File\r
+                               RelativePath=".\codecvt.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\POFile.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\ResModule.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\stdafx.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\Utils.h"\r
+                               >\r
+                       </File>\r
+               </Filter>\r
+               <Filter\r
+                       Name="Resource Files"\r
+                       Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"\r
+                       UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"\r
+                       >\r
+               </Filter>\r
+       </Files>\r
+       <Globals>\r
+               <Global\r
+                       Name="DevPartner_IsInstrumented"\r
+                       Value="0"\r
+               />\r
+       </Globals>\r
+</VisualStudioProject>\r
diff --git a/src/ResText/Utils.cpp b/src/ResText/Utils.cpp
new file mode 100644 (file)
index 0000000..5d27a40
--- /dev/null
@@ -0,0 +1,152 @@
+// TortoiseSVN - a Windows shell extension for easy version control\r
+\r
+// Copyright (C) 2003-2006 - Stefan Kueng\r
+\r
+// This program is free software; you can redistribute it and/or\r
+// modify it under the terms of the GNU General Public License\r
+// as published by the Free Software Foundation; either version 2\r
+// of the License, or (at your option) any later version.\r
+\r
+// This program is distributed in the hope that it will be useful,\r
+// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+// GNU General Public License for more details.\r
+\r
+// You should have received a copy of the GNU General Public License\r
+// along with this program; if not, write to the Free Software Foundation,\r
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
+#include "StdAfx.h"\r
+#include ".\utils.h"\r
+\r
+CUtils::CUtils(void)\r
+{\r
+}\r
+\r
+CUtils::~CUtils(void)\r
+{\r
+}\r
+\r
+void CUtils::StringExtend(LPTSTR str)\r
+{\r
+       TCHAR * cPos = str;\r
+       do\r
+       {\r
+               cPos = _tcschr(cPos, '\\');\r
+               if (cPos)\r
+               {\r
+                       memmove(cPos+1, cPos, _tcslen(cPos)*sizeof(TCHAR));\r
+                       *cPos = '\\';\r
+                       *(cPos+1) = '\\';\r
+                       cPos++;\r
+                       cPos++;\r
+               }\r
+       } while (cPos != NULL);\r
+       cPos = str;\r
+       do\r
+       {\r
+               cPos = _tcschr(cPos, '\n');\r
+               if (cPos)\r
+               {\r
+                       memmove(cPos+1, cPos, _tcslen(cPos)*sizeof(TCHAR));\r
+                       *cPos = '\\';\r
+                       *(cPos+1) = 'n';\r
+               }\r
+       } while (cPos != NULL);\r
+       cPos = str;\r
+       do\r
+       {\r
+               cPos = _tcschr(cPos, '\r');\r
+               if (cPos)\r
+               {\r
+                       memmove(cPos+1, cPos, _tcslen(cPos)*sizeof(TCHAR));\r
+                       *cPos = '\\';\r
+                       *(cPos+1) = 'r';\r
+               }\r
+       } while (cPos != NULL);\r
+       cPos = str;\r
+       do\r
+       {\r
+               cPos = _tcschr(cPos, '\t');\r
+               if (cPos)\r
+               {\r
+                       memmove(cPos+1, cPos, _tcslen(cPos)*sizeof(TCHAR));\r
+                       *cPos = '\\';\r
+                       *(cPos+1) = 't';\r
+               }\r
+       } while (cPos != NULL);\r
+       cPos = str;\r
+       do\r
+       {\r
+               cPos = _tcschr(cPos, '"');\r
+               if (cPos)\r
+               {\r
+                       memmove(cPos+1, cPos, _tcslen(cPos)*sizeof(TCHAR));\r
+                       *cPos = '\\';\r
+                       *(cPos+1) = '"';\r
+                       cPos++;\r
+                       cPos++;\r
+               }\r
+       } while (cPos != NULL);\r
+}\r
+\r
+void CUtils::StringCollapse(LPTSTR str)\r
+{\r
+       TCHAR * cPos = str;\r
+       do\r
+       {\r
+               cPos = _tcschr(cPos, '\\');\r
+               if (cPos)\r
+               {\r
+                       if (*(cPos+1) == 'n')\r
+                       {\r
+                               *cPos = '\n';\r
+                               memmove(cPos+1, cPos+2, (_tcslen(cPos+2)+1)*sizeof(TCHAR));\r
+                       }\r
+                       else if (*(cPos+1) == 'r')\r
+                       {\r
+                               *cPos = '\r';\r
+                               memmove(cPos+1, cPos+2, (_tcslen(cPos+2)+1)*sizeof(TCHAR));\r
+                       }\r
+                       else if (*(cPos+1) == 't')\r
+                       {\r
+                               *cPos = '\t';\r
+                               memmove(cPos+1, cPos+2, (_tcslen(cPos+2)+1)*sizeof(TCHAR));\r
+                       }\r
+                       else if (*(cPos+1) == '"')\r
+                       {\r
+                               *cPos = '"';\r
+                               memmove(cPos+1, cPos+2, (_tcslen(cPos+2)+1)*sizeof(TCHAR));\r
+                       }\r
+                       else if (*(cPos+1) == '\\')\r
+                       {\r
+                               *cPos = '\\';\r
+                               memmove(cPos+1, cPos+2, (_tcslen(cPos+2)+1)*sizeof(TCHAR));\r
+                       }\r
+                       cPos++;\r
+               }\r
+       } while (cPos != NULL);\r
+}\r
+\r
+void CUtils::Error()\r
+{\r
+       LPVOID lpMsgBuf;\r
+       if (!FormatMessage( \r
+               FORMAT_MESSAGE_ALLOCATE_BUFFER | \r
+               FORMAT_MESSAGE_FROM_SYSTEM | \r
+               FORMAT_MESSAGE_IGNORE_INSERTS,\r
+               NULL,\r
+               GetLastError(),\r
+               MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language\r
+               (LPTSTR) &lpMsgBuf,\r
+               0,\r
+               NULL ))\r
+       {\r
+               return;\r
+       }\r
+\r
+       // Display the string.\r
+       _ftprintf(stderr, _T("%s\n"), (LPCTSTR)lpMsgBuf);\r
+\r
+       // Free the buffer.\r
+       LocalFree( lpMsgBuf );\r
+}
\ No newline at end of file
diff --git a/src/ResText/Utils.h b/src/ResText/Utils.h
new file mode 100644 (file)
index 0000000..f1a456b
--- /dev/null
@@ -0,0 +1,32 @@
+// TortoiseSVN - a Windows shell extension for easy version control\r
+\r
+// Copyright (C) 2003-2007 - TortoiseSVN\r
+\r
+// This program is free software; you can redistribute it and/or\r
+// modify it under the terms of the GNU General Public License\r
+// as published by the Free Software Foundation; either version 2\r
+// of the License, or (at your option) any later version.\r
+\r
+// This program is distributed in the hope that it will be useful,\r
+// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+// GNU General Public License for more details.\r
+\r
+// You should have received a copy of the GNU General Public License\r
+// along with this program; if not, write to the Free Software Foundation,\r
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
+#pragma once\r
+\r
+/**\r
+ * \ingroup ResText\r
+ * static helper methods for ResText.\r
+ */\r
+class CUtils\r
+{\r
+public:\r
+       CUtils(void);\r
+       ~CUtils(void);\r
+       static void StringExtend(LPTSTR str);\r
+       static void StringCollapse(LPTSTR str);\r
+       static void Error();\r
+};\r
diff --git a/src/ResText/codecvt.cpp b/src/ResText/codecvt.cpp
new file mode 100644 (file)
index 0000000..a87f93b
--- /dev/null
@@ -0,0 +1,137 @@
+#include "codecvt.h"\r
+\r
+using namespace std;\r
+\r
+ucs2_conversion::result\r
+ucs2_conversion::do_in(mbstate_t&,\r
+                                          const char*  from, const char* from_end, const char*& from_next,\r
+                                          wchar_t* to, wchar_t* to_limit, wchar_t*& to_next) const\r
+{\r
+       size_t max_input = (from_end - from) & ~1;\r
+       size_t max_output = (to_limit - to);\r
+       size_t count = min(max_input/2, max_output);\r
+\r
+       result res = ok;\r
+\r
+       from_next = from;\r
+       to_next = to;\r
+       for (;count--; from_next += 2, ++to_next) {\r
+               unsigned char c1 = *from_next, c2 = *(from_next + 1);\r
+               *to_next = c1 | c2 << 8;\r
+       }\r
+       if (to_next == to && from_next == from_end - 1) res = partial;\r
+       return res; \r
+}\r
+\r
+ucs2_conversion::result\r
+ucs2_conversion::do_out(mbstate_t&,\r
+                                 const wchar_t* from, const wchar_t* from_end, const wchar_t*& from_next,\r
+                                 char* to, char* to_limit, char*& to_next) const\r
+{\r
+       size_t max_input = (from_end - from);\r
+       size_t max_output = (to_limit - to) & ~1;\r
+       size_t count = min(max_input, max_output/2);\r
+\r
+       from_next = from;\r
+       to_next = to;\r
+       for (;count--; ++from_next, to_next += 2) {\r
+               *(to_next + 0) = (char)(*from_next & 0xFF);\r
+               *(to_next + 1) = (char)(*from_next >> 8 & 0xFF);\r
+       }\r
+       return ok;\r
+}\r
+\r
+typedef unsigned char uchar;\r
+\r
+inline unsigned char \r
+take_6_bits(unsigned value, size_t right_position)\r
+{\r
+       return uchar((value >> right_position) & 63);\r
+}\r
+\r
+\r
+\r
+inline size_t\r
+most_signifant_bit_position(unsigned value)\r
+{\r
+       size_t result(0);\r
+\r
+       size_t half = 16;\r
+       for(; half > 0; half >>= 1) {\r
+               if (1u << (result + half) <= value ) result += half;\r
+       }       \r
+       return result + 1;\r
+       //return *lower_bound(range(0u, 31u), \x -> (1 << x <= value));\r
+}\r
+\r
+\r
+\r
+utf8_conversion::result\r
+utf8_conversion::do_in(mbstate_t&,\r
+                                          const char*  from, const char* from_end, const char*& from_next,\r
+                                          wchar_t* to, wchar_t* to_limit, wchar_t*& to_next) const\r
+{\r
+       from_next = from;\r
+       to_next = to;\r
+\r
+       for(; to_next < to_limit && from_next < from_end; ++to_next) {\r
+\r
+               if (uchar(*from_next) < 0x80) *to_next = uchar(*from_next++);\r
+               else {\r
+\r
+                       // 111zxxxx : z = 0 xxxx are data bits\r
+                       size_t zero_bit_pos = most_signifant_bit_position(~*from_next);\r
+                       size_t extra_bytes  = 7 - zero_bit_pos;\r
+\r
+                       if (size_t(from_end - from_next) < extra_bytes + 1) \r
+                               return partial;\r
+\r
+                       *to_next = uchar(*from_next++) & (wchar_t)((1 << (zero_bit_pos - 1)) - 1);\r
+\r
+                       for (;extra_bytes--; ++from_next) {\r
+                               *to_next = *to_next << 6  |  uchar(*from_next) & 63;\r
+                       }\r
+               }\r
+       }       \r
+\r
+       return ok;\r
+}\r
+\r
+\r
+utf8_conversion::result\r
+utf8_conversion::do_out(mbstate_t&,\r
+                                 const wchar_t* from, const wchar_t* from_end, const wchar_t*& from_next,\r
+                                 char* to, char* to_limit, char*& to_next) const\r
+{\r
+               from_next = from;\r
+               to_next = to;\r
+\r
+               for (;from_next < from_end; ++from_next) {\r
+\r
+                       unsigned symbol = *from_next;\r
+\r
+                       if (symbol < 0x7F) {\r
+                               if (to_next < to_limit)\r
+                                       *to_next++ = (unsigned char)symbol;\r
+                               else\r
+                                       return ok;\r
+                       } else {\r
+\r
+                               size_t msb_pos = most_signifant_bit_position(symbol);\r
+                               size_t extra_bytes = msb_pos / 6;\r
+\r
+                               if (size_t(to_limit - to_next) >= extra_bytes + 1) {\r
+\r
+                                       *to_next = uchar(0xFF80 >> extra_bytes);\r
+                                       *to_next++ |= take_6_bits(symbol, extra_bytes*6);\r
+\r
+                                       for(;extra_bytes--;)\r
+                                               *to_next++ = 0x80 | take_6_bits(symbol, extra_bytes*6);\r
+                               }\r
+                               else\r
+                                       return ok;\r
+                       }\r
+               }\r
+               return ok;\r
+}\r
+\r
diff --git a/src/ResText/codecvt.h b/src/ResText/codecvt.h
new file mode 100644 (file)
index 0000000..f190806
--- /dev/null
@@ -0,0 +1,64 @@
+\r
+/**    Several code conversions facets.\r
+\r
+       E.g. this is how to convert UCS-2 to UTF-8\r
+\r
+       @code\r
+       wifstream ifs("input", ios_base::binary);\r
+       wofstream ofs("output", ios_base::binary);\r
+\r
+       ifs.rdbuf()->pubimbue(locale(locale(), new ucs2_conversion()));\r
+       ofs.rbbuf()->pubimbue(locale(locale(), new utf8_conversion()));\r
+       ofs << ifs.rdbuf();\r
+       @endcode\r
+\r
+       @author Vladimir Prus <ghost@cs.msu.su>\r
+\r
+       @file\r
+*/\r
+\r
+#include <locale>\r
+#pragma warning(push)\r
+#pragma warning(disable: 4511)\r
+#pragma warning(disable: 4512)\r
+\r
+/**    Conversion facet that allows to use Unicode files in UCS-2 encoding */\r
+class ucs2_conversion\r
+: public std::codecvt<wchar_t, char, std::mbstate_t>\r
+{\r
+protected:\r
+\r
+       result do_in(std::mbstate_t& state,\r
+                                const char* from, const char* from_end, const char*& from_next,\r
+                                wchar_t* to, wchar_t* to_limit, wchar_t*& to_next) const;\r
+\r
+       result do_out(std::mbstate_t& state,\r
+                                 const wchar_t* from, const wchar_t* from_end, const wchar_t*& from_next,\r
+                                 char* to, char* to_limit, char*& to_next) const;\r
+\r
+    bool do_always_noconv() const throw() { return false; }\r
+    int  do_encoding() const throw() { return 2; }\r
+};\r
+\r
+\r
+/**    Conversion facet that allows to read Unicode files in UTF-8 encoding */\r
+class utf8_conversion\r
+: public std::codecvt<wchar_t, char, std::mbstate_t>\r
+{\r
+protected:\r
+\r
+       result do_in(std::mbstate_t& state,\r
+                                const char* from, const char* from_end, const char*& from_next,\r
+                                wchar_t* to, wchar_t* to_limit, wchar_t*& to_next) const;\r
+\r
+       result do_out(std::mbstate_t& state,\r
+                                 const wchar_t* from, const wchar_t* from_end, const wchar_t*& from_next,\r
+                                 char* to, char* to_limit, char*& to_next) const;\r
+\r
+    bool do_always_noconv() const throw() { return false; }\r
+    int  do_encoding() const throw() { return 2; }\r
+};\r
+#pragma warning(pop)\r
+\r
+\r
+\r
diff --git a/src/ResText/stdafx.cpp b/src/ResText/stdafx.cpp
new file mode 100644 (file)
index 0000000..b48f861
--- /dev/null
@@ -0,0 +1,5 @@
+// stdafx.cpp : source file that includes just the standard includes\r
+// ResText.pch will be the pre-compiled header\r
+// stdafx.obj will contain the pre-compiled type information\r
+\r
+#include "stdafx.h"\r
diff --git a/src/ResText/stdafx.h b/src/ResText/stdafx.h
new file mode 100644 (file)
index 0000000..78c9065
--- /dev/null
@@ -0,0 +1,13 @@
+// stdafx.h : include file for standard system include files,\r
+// or project specific include files that are used frequently, but\r
+// are changed infrequently\r
+//\r
+\r
+#pragma once\r
+\r
+#pragma warning(push)\r
+#pragma warning(disable: 4702) // Unreachable code warnings in xtree\r
+#include <iostream>\r
+#include <tchar.h>\r
+#include <windows.h>\r
+#pragma warning(pop)\r