Index: src/libictranslate/ResourceManager.cpp =================================================================== diff -u -rd0d46e0ace97519c52eefcd66e1cab5b586dcac1 -ra347fac4097d0504825a93fec5233adade6345a3 --- src/libictranslate/ResourceManager.cpp (.../ResourceManager.cpp) (revision d0d46e0ace97519c52eefcd66e1cab5b586dcac1) +++ src/libictranslate/ResourceManager.cpp (.../ResourceManager.cpp) (revision a347fac4097d0504825a93fec5233adade6345a3) @@ -80,6 +80,7 @@ delete [] (*it).second; } m_mStrings.clear(); + m_mChecksums.clear(); } CLangData::CLangData(const CLangData& ld) : @@ -103,6 +104,25 @@ SetVersion(ld.GetVersion()); } +CLangData& CLangData::operator=(const CLangData& rSrc) +{ + if(this != &rSrc) + { + SetFilename(rSrc.GetFilename(true)); + SetLangName(rSrc.GetLangName()); + SetLangCode(rSrc.GetLangCode()); + SetFontFace(rSrc.GetFontFace()); + SetCharset(rSrc.GetCharset()); + SetPointSize(rSrc.GetPointSize()); + SetDirection(rSrc.GetDirection()); + SetHelpName(rSrc.GetHelpName()); + SetAuthor(rSrc.GetAuthor()); + SetVersion(rSrc.GetVersion()); + } + + return *this; +} + bool CLangData::ReadInfo(PCTSTR pszFile) { try @@ -192,22 +212,59 @@ } else { - uint_t uiVal = _ttoi(pszName); + // parse the pszName to get both the string id and checksum + const tchar_t* pszChecksum = _tcschr(pszName, _T('[')); + if(pszChecksum == NULL) + { + TRACE(_T("Warning! Old-style translation string %s; skipping.\n"), pszName); + return; // old-style translation; assume incompatibility + } + + UINT uiID = 0; + UINT uiChecksum = 0; + int iCount = _stscanf(pszName, UIFMT _T("[0x%lx]"), &uiID, &uiChecksum); + if(iCount != 2) + { + TRACE(_T("Warning! Problem retrieving checksum from string '%s'\n"), pszName); + return; + } + + uint_t uiKey = pLangData->m_uiSectionID << 16 | uiID; if(pLangData->m_bUpdating) { + // check if the checksum exists and matches + checksum_map::const_iterator itChecksum = pLangData->m_mChecksums.find(uiKey); + if(itChecksum == pLangData->m_mChecksums.end()) + { + TRACE(_T("Warning! Superfluous entry %lu in processed language file\n"), uiKey); + return; // entry not found - probably superfluous entry in the language file + } + + if((*itChecksum).second != uiChecksum) + { + TRACE(_T("Warning! Invalid checksum for string ID %lu in processed language file\n"), uiKey); + return; // entry has invalid checksum (older version of translation) + } + // check if the entry already exists - strings_map::iterator it = pLangData->m_mStrings.find(pLangData->m_uiSectionID << 16 | uiVal); + strings_map::iterator it = pLangData->m_mStrings.find(uiKey); if(it != pLangData->m_mStrings.end()) - return; + { + delete [] (*it).second; + pLangData->m_mStrings.erase(it); + } } + size_t stLen = _tcslen(pszValue); tchar_t* pszStr = new tchar_t[stLen + 1]; _tcscpy(pszStr, pszValue); // convert escape strings into escape sequences CLangData::UnescapeString(pszStr); - pLangData->m_mStrings.insert(strings_map::value_type(pLangData->m_uiSectionID << 16 | uiVal, pszStr)); + pLangData->m_mStrings.insert(strings_map::value_type(uiKey, pszStr)); + if(!pLangData->m_bUpdating) + pLangData->m_mChecksums.insert(checksum_map::value_type(uiKey, uiChecksum)); } } @@ -241,12 +298,24 @@ } -bool CLangData::ReadTranslation(PCTSTR pszFile, bool bUpdate) +bool CLangData::ReadTranslation(PCTSTR pszFile, bool bReadBase) { try { - if(!bUpdate) + // first read the standard language - hard-code english one + const tchar_t* pszBaseName = _t("english.lng"); + if(!bReadBase && _tcsstr(pszFile, pszBaseName) == NULL) + { Clear(); + TCHAR szData[512]; + const TCHAR* pszName=_tcsrchr(pszFile, _T('\\')); + if(pszName) + { + _tcsncpy(szData, pszFile, pszName-pszFile+1); + _tcscpy(szData+(pszName-pszFile+1), pszBaseName); + ReadTranslation(szData, true); + } + } // load data from file icpf::config cfg(icpf::config::eIni); @@ -262,56 +331,52 @@ const uint_t uiVersion = cfg.register_string(_T("Info/Version"), _T("")); cfg.read(pszFile); - TCHAR szData[512]; - if(!bUpdate) - { - const tchar_t* psz = cfg.get_string(uiLangName); - if(!psz || psz[0] == _t('\0')) - return false; - SetLangName(psz); + const tchar_t* psz = cfg.get_string(uiLangName); + if(!psz || psz[0] == _t('\0')) + return false; + SetLangName(psz); - ll_t ll = cfg.get_signed_num(uiLangCode); - if(ll == 0) - return false; - SetLangCode((WORD)ll); + ll_t ll = cfg.get_signed_num(uiLangCode); + if(ll == 0) + return false; + SetLangCode((WORD)ll); - psz = cfg.get_string(uiBaseLanguage); - SetBaseFile(psz); + psz = cfg.get_string(uiBaseLanguage); + SetBaseFile(psz); - psz = cfg.get_string(uiFontFace); - if(!psz || psz[0] == _t('\0')) - return false; - SetFontFace(psz); + psz = cfg.get_string(uiFontFace); + if(!psz || psz[0] == _t('\0')) + return false; + SetFontFace(psz); - ll = cfg.get_signed_num(uiCharset); - if(ll == 0) - return false; - SetCharset((BYTE)ll); + ll = cfg.get_signed_num(uiCharset); + if(ll == 0) + return false; + SetCharset((BYTE)ll); - ll = cfg.get_signed_num(uiSize); - if(ll == 0) - return false; - SetPointSize((WORD)ll); + ll = cfg.get_signed_num(uiSize); + if(ll == 0) + return false; + SetPointSize((WORD)ll); - SetDirection(cfg.get_bool(uiRTL)); + SetDirection(cfg.get_bool(uiRTL)); - psz = cfg.get_string(uiHelpName); - if(!psz || psz[0] == _t('\0')) - return false; - SetHelpName(psz); + psz = cfg.get_string(uiHelpName); + if(!psz || psz[0] == _t('\0')) + return false; + SetHelpName(psz); - psz = cfg.get_string(uiAuthor); - if(!psz || psz[0] == _t('\0')) - return false; - SetAuthor(psz); + psz = cfg.get_string(uiAuthor); + if(!psz || psz[0] == _t('\0')) + return false; + SetAuthor(psz); - psz = cfg.get_string(uiVersion); - if(!psz || psz[0] == _t('\0')) - return false; - SetVersion(psz); - } + psz = cfg.get_string(uiVersion); + if(!psz || psz[0] == _t('\0')) + return false; + SetVersion(psz); - m_bUpdating = bUpdate; + m_bUpdating = !bReadBase; m_uiSectionID = 0; if(!cfg.enum_properties(_t("*"), EnumAttributesCallback, this)) { @@ -320,25 +385,9 @@ } m_bUpdating = false; - if(!bUpdate) - { - // remember the filename + if(!m_bUpdating) SetFilename(pszFile); - // establish path to the base file - if (_tcslen(GetBaseFile()) != 0) - { - const TCHAR* pszName=_tcsrchr(pszFile, _T('\\')); - if (pszName) - { - _tcsncpy(szData, pszFile, pszName-pszFile+1); - _tcscpy(szData+(pszName-pszFile+1), GetBaseFile()); - TRACE(_t("Base (update) path=%s\n"), szData); - ReadTranslation(szData, true); - } - } - } - return true; } catch(...) @@ -380,6 +429,48 @@ } } +void CLangData::SetLangName(PCTSTR psz) +{ + if (m_pszLngName) + delete [] m_pszLngName; + m_pszLngName=new TCHAR[_tcslen(psz)+1]; + _tcscpy(m_pszLngName, psz); +} + +void CLangData::SetBaseFile(PCTSTR psz) +{ + SetFnameData(&m_pszBaseFile, psz); +} + +void CLangData::SetFontFace(PCTSTR psz) +{ + if (m_pszFontFace) + delete [] m_pszFontFace; + m_pszFontFace=new TCHAR[_tcslen(psz)+1]; + _tcscpy(m_pszFontFace, psz); +} + +void CLangData::SetHelpName(PCTSTR psz) +{ + SetFnameData(&m_pszHelpName, psz); +} + +void CLangData::SetAuthor(PCTSTR psz) +{ + if (m_pszAuthor) + delete [] m_pszAuthor; + m_pszAuthor=new TCHAR[_tcslen(psz)+1]; + _tcscpy(m_pszAuthor, psz); +} + +void CLangData::SetVersion(PCTSTR psz) +{ + if (m_pszVersion) + delete [] m_pszVersion; + m_pszVersion=new TCHAR[_tcslen(psz)+1]; + _tcscpy(m_pszVersion, psz); +} + void CLangData::SetFnameData(PTSTR *ppszDst, PCTSTR pszSrc) { if (*ppszDst) Index: src/libictranslate/ResourceManager.h =================================================================== diff -u -rd0d46e0ace97519c52eefcd66e1cab5b586dcac1 -ra347fac4097d0504825a93fec5233adade6345a3 --- src/libictranslate/ResourceManager.h (.../ResourceManager.h) (revision d0d46e0ace97519c52eefcd66e1cab5b586dcac1) +++ src/libictranslate/ResourceManager.h (.../ResourceManager.h) (revision a347fac4097d0504825a93fec5233adade6345a3) @@ -41,7 +41,8 @@ /////////////////////////////////////////////////////////// // language description structure -typedef map strings_map; +typedef std::map strings_map; +typedef std::map checksum_map; class LIBICTRANSLATE_API CLangData { @@ -51,27 +52,29 @@ ~CLangData(); CLangData(const CLangData& ld); + CLangData& operator=(const CLangData& rSrc); + void Clear(); // operations bool ReadInfo(PCTSTR pszFile); - bool ReadTranslation(PCTSTR pszFile, bool bUpdate=false); + bool ReadTranslation(PCTSTR pszFile, bool bReadBase = false); PCTSTR GetString(WORD wHiID, WORD wLoID); // attributes void SetFilename(PCTSTR psz); PCTSTR GetFilename(bool bFullPath) const; - void SetLangName(PCTSTR psz) { if (m_pszLngName) delete [] m_pszLngName; m_pszLngName=new TCHAR[_tcslen(psz)+1]; _tcscpy(m_pszLngName, psz); }; + void SetLangName(PCTSTR psz); PCTSTR GetLangName() const { return m_pszLngName; }; - void SetBaseFile(PCTSTR psz) { SetFnameData(&m_pszBaseFile, psz); }; + void SetBaseFile(PCTSTR psz); PCTSTR GetBaseFile() const { return m_pszBaseFile; }; void SetLangCode(WORD wLang) { m_wLangCode=wLang; }; WORD GetLangCode() const { return m_wLangCode; }; - void SetFontFace(PCTSTR psz) { if (m_pszFontFace) delete [] m_pszFontFace; m_pszFontFace=new TCHAR[_tcslen(psz)+1]; _tcscpy(m_pszFontFace, psz); }; + void SetFontFace(PCTSTR psz); PCTSTR GetFontFace() const { return m_pszFontFace; }; void SetCharset(BYTE byChar) { m_byCharset=byChar; }; @@ -83,17 +86,15 @@ void SetDirection(bool brtl) { m_bRTL=brtl; }; bool GetDirection() const { return m_bRTL; }; - void SetHelpName(PCTSTR psz) { SetFnameData(&m_pszHelpName, psz); }; + void SetHelpName(PCTSTR psz); PCTSTR GetHelpName() const { return m_pszHelpName; }; - void SetAuthor(PCTSTR psz) { if (m_pszAuthor) delete [] m_pszAuthor; m_pszAuthor=new TCHAR[_tcslen(psz)+1]; _tcscpy(m_pszAuthor, psz); }; + void SetAuthor(PCTSTR psz); PCTSTR GetAuthor() const { return m_pszAuthor; }; - void SetVersion(PCTSTR psz) { if (m_pszVersion) delete [] m_pszVersion; m_pszVersion=new TCHAR[_tcslen(psz)+1]; _tcscpy(m_pszVersion, psz); }; + void SetVersion(PCTSTR psz); PCTSTR GetVersion() const { return m_pszVersion; }; -// void SetStringData(PCTSTR psz, size_t tCnt) { tCount=tCnt; if (pszStrings) delete [] pszStrings; if (tCount > 0) { pszStrings=new TCHAR[tCnt]; memcpy(pszStrings, psz, tCnt*sizeof(TCHAR)); } }; - protected: void SetFnameData(PTSTR *ppszDst, PCTSTR pszSrc); static void EnumAttributesCallback(bool bGroup, const tchar_t* pszName, const tchar_t* pszValue, ptr_t pData); @@ -113,7 +114,8 @@ bool m_bRTL; // does the language require right-to-left reading order ? // strings (for controls in dialog boxes the ID contains hi:dlg ID, lo:ctrl ID, for strings hi part is 0) - strings_map m_mStrings; // maps string ID to the offset in pszStrings + strings_map m_mStrings; // maps string ID to the offset in pszStrings + checksum_map m_mChecksums; // checksums of strings private: uint_t m_uiSectionID; ///< ID of the currently processed section