From f496cc464f1966f07c74c833b55d081a966f91df Mon Sep 17 00:00:00 2001 From: kichik Date: Sat, 17 Feb 2007 15:11:12 +0000 Subject: [PATCH] fixed bug #1662190 - dialog template unicode conversion is lossy git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@4937 212acab6-be3b-0410-9dea-997c60f758d6 --- Source/DialogTemplate.cpp | 32 +++++++++----------- Source/DialogTemplate.h | 12 ++++---- Source/script.cpp | 64 +++++++++++++++++++++++---------------- 3 files changed, 59 insertions(+), 49 deletions(-) diff --git a/Source/DialogTemplate.cpp b/Source/DialogTemplate.cpp index ddab96b2..8db46713 100644 --- a/Source/DialogTemplate.cpp +++ b/Source/DialogTemplate.cpp @@ -46,7 +46,7 @@ static inline short ConvertEndianness(short s) { #define ALIGN(dwToAlign, dwAlignOn) dwToAlign = (dwToAlign%dwAlignOn == 0) ? dwToAlign : dwToAlign - (dwToAlign%dwAlignOn) + dwAlignOn // Reads a variant length array from seeker into readInto and advances seeker -void ReadVarLenArr(LPBYTE &seeker, char* &readInto, unsigned int uCodePage) { +void ReadVarLenArr(LPBYTE &seeker, WCHAR* &readInto, unsigned int uCodePage) { WORD* arr = (WORD*)seeker; switch (ConvertEndianness(arr[0])) { case 0x0000: @@ -54,12 +54,12 @@ void ReadVarLenArr(LPBYTE &seeker, char* &readInto, unsigned int uCodePage) { seeker += sizeof(WORD); break; case 0xFFFF: - readInto = MAKEINTRESOURCE(ConvertEndianness(arr[1])); + readInto = MAKEINTRESOURCEW(ConvertEndianness(arr[1])); seeker += 2*sizeof(WORD); break; default: { - readInto = winchar_toansi((WCHAR *) arr, uCodePage); + readInto = winchar_strdup((WCHAR *) arr); PWCHAR wseeker = PWCHAR(seeker); while (*wseeker++); seeker = LPBYTE(wseeker); @@ -78,17 +78,14 @@ void ReadVarLenArr(LPBYTE &seeker, char* &readInto, unsigned int uCodePage) { seeker += sizeof(WORD); \ } \ else { \ - int us = MultiByteToWideChar(m_uCodePage, 0, x, -1, (WCHAR*)seeker, dwSize - DWORD(seeker - pbDlg)); \ - if (!us) { \ - throw runtime_error("WriteStringOrId - Unicode conversion failed."); \ - } \ - seeker += us*sizeof(WCHAR); \ + winchar_strcpy((WCHAR *) seeker, x); \ + seeker += winchar_strlen((WCHAR *) seeker) * sizeof(WCHAR) + sizeof(WCHAR); \ } \ else \ seeker += sizeof(WORD); // A macro that adds the size of x (which can be a string a number, or nothing) to dwSize -#define AddStringOrIdSize(x) dwSize += x ? (IS_INTRESOURCE(x) ? sizeof(DWORD) : MultiByteToWideChar(m_uCodePage, 0, x, -1, 0, 0) * sizeof(WCHAR)) : sizeof(WORD) +#define AddStringOrIdSize(x) dwSize += x ? (IS_INTRESOURCE(x) ? sizeof(DWORD) : (winchar_strlen(x) + 1) * sizeof(WCHAR)) : sizeof(WORD) ////////////////////////////////////////////////////////////////////// // Construction/Destruction @@ -295,8 +292,7 @@ void CDialogTemplate::SetFont(char* szFaceName, WORD wFontSize) { m_bCharset = DEFAULT_CHARSET; m_dwStyle |= DS_SETFONT; if (m_szFont) delete [] m_szFont; - m_szFont = new char[strlen(szFaceName)+1]; - strcpy(m_szFont, szFaceName); + m_szFont = winchar_fromansi(szFaceName); m_sFontSize = wFontSize; } @@ -306,12 +302,10 @@ void CDialogTemplate::AddItem(DialogItemTemplate item) { CopyMemory(newItem, &item, sizeof(DialogItemTemplate)); if (item.szClass && !IS_INTRESOURCE(item.szClass)) { - newItem->szClass = new char[strlen(item.szClass)+1]; - strcpy(newItem->szClass, item.szClass); + newItem->szClass = winchar_strdup(item.szClass); } if (item.szTitle && !IS_INTRESOURCE(item.szTitle)) { - newItem->szTitle = new char[strlen(item.szTitle)+1]; - strcpy(newItem->szTitle, item.szTitle); + newItem->szTitle = winchar_strdup(item.szTitle); } if (item.wCreateDataSize) { newItem->szCreationData = new char[item.wCreateDataSize]; @@ -442,6 +436,8 @@ void CDialogTemplate::ConvertToRTL() { for (unsigned int i = 0; i < m_vItems.size(); i++) { bool addExStyle = false; + char *szClass = winchar_toansi(m_vItems[i]->szClass); + // Button if (long(m_vItems[i]->szClass) == 0x80) { m_vItems[i]->dwStyle ^= BS_LEFTTEXT; @@ -473,12 +469,12 @@ void CDialogTemplate::ConvertToRTL() { m_vItems[i]->dwStyle |= SS_CENTERIMAGE; } } - else if (!IS_INTRESOURCE(m_vItems[i]->szClass) && !stricmp(m_vItems[i]->szClass, "RichEdit20A")) { + else if (!IS_INTRESOURCE(m_vItems[i]->szClass) && !stricmp(szClass, "RichEdit20A")) { if ((m_vItems[i]->dwStyle & ES_CENTER) == 0) { m_vItems[i]->dwStyle ^= ES_RIGHT; } } - else if (!IS_INTRESOURCE(m_vItems[i]->szClass) && !stricmp(m_vItems[i]->szClass, "SysTreeView32")) { + else if (!IS_INTRESOURCE(m_vItems[i]->szClass) && !stricmp(szClass, "SysTreeView32")) { m_vItems[i]->dwStyle |= TVS_RTLREADING; addExStyle = true; } @@ -490,6 +486,8 @@ void CDialogTemplate::ConvertToRTL() { m_vItems[i]->dwExtStyle |= WS_EX_RTLREADING | WS_EX_LEFTSCROLLBAR; m_vItems[i]->sX = m_sWidth - m_vItems[i]->sWidth - m_vItems[i]->sX; + + delete [] szClass; } m_dwExtStyle |= WS_EX_RIGHT | WS_EX_RTLREADING | WS_EX_LEFTSCROLLBAR; } diff --git a/Source/DialogTemplate.h b/Source/DialogTemplate.h index 327ba2ae..918ca23c 100644 --- a/Source/DialogTemplate.h +++ b/Source/DialogTemplate.h @@ -43,8 +43,8 @@ struct DialogItemTemplate { DWORD dwStyle; WORD wId; - char *szClass; - char *szTitle; + WCHAR *szClass; + WCHAR *szTitle; char *szCreationData; WORD wCreateDataSize; @@ -144,16 +144,16 @@ private: DWORD m_dwExtStyle; DWORD m_dwStyle; - char* m_szMenu; - char* m_szClass; - char* m_szTitle; + WCHAR *m_szMenu; + WCHAR *m_szClass; + WCHAR *m_szTitle; // Only if DS_FONT style is set short m_sFontSize; short m_sFontWeight; // Extended only BYTE m_bItalic; // Extended only BYTE m_bCharset; // Extended only - char* m_szFont; + WCHAR *m_szFont; // For (en/de)coding Unicode unsigned int m_uCodePage; diff --git a/Source/script.cpp b/Source/script.cpp index daef81e7..6728d148 100644 --- a/Source/script.cpp +++ b/Source/script.cpp @@ -20,6 +20,7 @@ #include "tokens.h" #include "build.h" #include "util.h" +#include "winchar.h" #include "ResourceEditor.h" #include "DialogTemplate.h" #include "lang.h" @@ -2441,8 +2442,19 @@ int CEXEBuild::doCommand(int which_token, LineParser &line) branding_image_found = false; DialogItemTemplate* dlgItem = 0; for (int i = 0; (dlgItem = UIDlg.GetItemByIdx(i)); i++) { - if ((IS_INTRESOURCE(dlgItem->szClass) && dlgItem->szClass == MAKEINTRESOURCE(0x0082)) - || (!IS_INTRESOURCE(dlgItem->szClass) && !strcmp(dlgItem->szClass, "Static"))) { + bool check = false; + + if (IS_INTRESOURCE(dlgItem->szClass)) { + if (dlgItem->szClass == MAKEINTRESOURCEW(0x0082)) { + check = true; + } + } else { + char *szClass = winchar_toansi(dlgItem->szClass); + check = strcmp(szClass, "Static") == 0; + delete [] szClass; + } + + if (check) { if ((dlgItem->dwStyle & SS_BITMAP) == SS_BITMAP) { branding_image_found = true; branding_image_id = dlgItem->wId; @@ -2520,8 +2532,8 @@ int CEXEBuild::doCommand(int which_token, LineParser &line) brandingCtl.dwStyle = SS_BITMAP | WS_CHILD | WS_VISIBLE; brandingCtl.sX = padding; brandingCtl.sY = padding; - brandingCtl.szClass = MAKEINTRESOURCE(0x0082); - brandingCtl.szTitle = ""; + brandingCtl.szClass = MAKEINTRESOURCEW(0x0082); + brandingCtl.szTitle = NULL; brandingCtl.wId = IDC_BRANDIMAGE; brandingCtl.sHeight = wh; @@ -2892,17 +2904,17 @@ int CEXEBuild::doCommand(int which_token, LineParser &line) bool required = true; char *f = line.gettoken_str(1); - + if(!stricmp(f,"/nonfatal")) { if (line.getnumtokens()!=3) PRINTHELP(); - + f = line.gettoken_str(2); - required = false; + required = false; } else if (line.getnumtokens()!=2) { PRINTHELP(); } - + #ifdef _WIN32 char *fc = f; #else @@ -2924,27 +2936,27 @@ int CEXEBuild::doCommand(int which_token, LineParser &line) #endif // search working directory - boost::scoped_ptr dr( new_dir_reader() ); - dr->read(dir); + boost::scoped_ptr dr( new_dir_reader() ); + dr->read(dir); - for (dir_reader::iterator files_itr = dr->files().begin(); - files_itr != dr->files().end(); - files_itr++) - { - if (!dir_reader::matches(*files_itr, spec)) - continue; + for (dir_reader::iterator files_itr = dr->files().begin(); + files_itr != dr->files().end(); + files_itr++) + { + if (!dir_reader::matches(*files_itr, spec)) + continue; - string incfile = basedir + *files_itr; + string incfile = basedir + *files_itr; - if (includeScript((char *) incfile.c_str()) != PS_OK) { - return PS_ERROR; - } + if (includeScript((char *) incfile.c_str()) != PS_OK) { + return PS_ERROR; + } included++; } if (included) - return PS_OK; + return PS_OK; // search include dirs char *incdir = include_dirs.get(); @@ -2981,13 +2993,13 @@ int CEXEBuild::doCommand(int which_token, LineParser &line) if (!included) { if(required) { - ERROR_MSG("!include: could not find: \"%s\"\n",f); - return PS_ERROR; - } else { - warning_fl("!include: could not find: \"%s\"",f); - } + ERROR_MSG("!include: could not find: \"%s\"\n",f); + return PS_ERROR; + } else { + warning_fl("!include: could not find: \"%s\"",f); } } + } return PS_OK; case TOK_P_CD: if (!line.gettoken_str(1)[0] || chdir(line.gettoken_str(1)))