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
This commit is contained in:
kichik 2007-02-17 15:11:12 +00:00
parent 0b19a3fa29
commit f496cc464f
3 changed files with 59 additions and 49 deletions

View file

@ -46,7 +46,7 @@ static inline short ConvertEndianness(short s) {
#define ALIGN(dwToAlign, dwAlignOn) dwToAlign = (dwToAlign%dwAlignOn == 0) ? dwToAlign : dwToAlign - (dwToAlign%dwAlignOn) + dwAlignOn #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 // 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; WORD* arr = (WORD*)seeker;
switch (ConvertEndianness(arr[0])) { switch (ConvertEndianness(arr[0])) {
case 0x0000: case 0x0000:
@ -54,12 +54,12 @@ void ReadVarLenArr(LPBYTE &seeker, char* &readInto, unsigned int uCodePage) {
seeker += sizeof(WORD); seeker += sizeof(WORD);
break; break;
case 0xFFFF: case 0xFFFF:
readInto = MAKEINTRESOURCE(ConvertEndianness(arr[1])); readInto = MAKEINTRESOURCEW(ConvertEndianness(arr[1]));
seeker += 2*sizeof(WORD); seeker += 2*sizeof(WORD);
break; break;
default: default:
{ {
readInto = winchar_toansi((WCHAR *) arr, uCodePage); readInto = winchar_strdup((WCHAR *) arr);
PWCHAR wseeker = PWCHAR(seeker); PWCHAR wseeker = PWCHAR(seeker);
while (*wseeker++); while (*wseeker++);
seeker = LPBYTE(wseeker); seeker = LPBYTE(wseeker);
@ -78,17 +78,14 @@ void ReadVarLenArr(LPBYTE &seeker, char* &readInto, unsigned int uCodePage) {
seeker += sizeof(WORD); \ seeker += sizeof(WORD); \
} \ } \
else { \ else { \
int us = MultiByteToWideChar(m_uCodePage, 0, x, -1, (WCHAR*)seeker, dwSize - DWORD(seeker - pbDlg)); \ winchar_strcpy((WCHAR *) seeker, x); \
if (!us) { \ seeker += winchar_strlen((WCHAR *) seeker) * sizeof(WCHAR) + sizeof(WCHAR); \
throw runtime_error("WriteStringOrId - Unicode conversion failed."); \
} \
seeker += us*sizeof(WCHAR); \
} \ } \
else \ else \
seeker += sizeof(WORD); seeker += sizeof(WORD);
// A macro that adds the size of x (which can be a string a number, or nothing) to dwSize // 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 // Construction/Destruction
@ -295,8 +292,7 @@ void CDialogTemplate::SetFont(char* szFaceName, WORD wFontSize) {
m_bCharset = DEFAULT_CHARSET; m_bCharset = DEFAULT_CHARSET;
m_dwStyle |= DS_SETFONT; m_dwStyle |= DS_SETFONT;
if (m_szFont) delete [] m_szFont; if (m_szFont) delete [] m_szFont;
m_szFont = new char[strlen(szFaceName)+1]; m_szFont = winchar_fromansi(szFaceName);
strcpy(m_szFont, szFaceName);
m_sFontSize = wFontSize; m_sFontSize = wFontSize;
} }
@ -306,12 +302,10 @@ void CDialogTemplate::AddItem(DialogItemTemplate item) {
CopyMemory(newItem, &item, sizeof(DialogItemTemplate)); CopyMemory(newItem, &item, sizeof(DialogItemTemplate));
if (item.szClass && !IS_INTRESOURCE(item.szClass)) { if (item.szClass && !IS_INTRESOURCE(item.szClass)) {
newItem->szClass = new char[strlen(item.szClass)+1]; newItem->szClass = winchar_strdup(item.szClass);
strcpy(newItem->szClass, item.szClass);
} }
if (item.szTitle && !IS_INTRESOURCE(item.szTitle)) { if (item.szTitle && !IS_INTRESOURCE(item.szTitle)) {
newItem->szTitle = new char[strlen(item.szTitle)+1]; newItem->szTitle = winchar_strdup(item.szTitle);
strcpy(newItem->szTitle, item.szTitle);
} }
if (item.wCreateDataSize) { if (item.wCreateDataSize) {
newItem->szCreationData = new char[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++) { for (unsigned int i = 0; i < m_vItems.size(); i++) {
bool addExStyle = false; bool addExStyle = false;
char *szClass = winchar_toansi(m_vItems[i]->szClass);
// Button // Button
if (long(m_vItems[i]->szClass) == 0x80) { if (long(m_vItems[i]->szClass) == 0x80) {
m_vItems[i]->dwStyle ^= BS_LEFTTEXT; m_vItems[i]->dwStyle ^= BS_LEFTTEXT;
@ -473,12 +469,12 @@ void CDialogTemplate::ConvertToRTL() {
m_vItems[i]->dwStyle |= SS_CENTERIMAGE; 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) { if ((m_vItems[i]->dwStyle & ES_CENTER) == 0) {
m_vItems[i]->dwStyle ^= ES_RIGHT; 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; m_vItems[i]->dwStyle |= TVS_RTLREADING;
addExStyle = true; addExStyle = true;
} }
@ -490,6 +486,8 @@ void CDialogTemplate::ConvertToRTL() {
m_vItems[i]->dwExtStyle |= WS_EX_RTLREADING | WS_EX_LEFTSCROLLBAR; m_vItems[i]->dwExtStyle |= WS_EX_RTLREADING | WS_EX_LEFTSCROLLBAR;
m_vItems[i]->sX = m_sWidth - m_vItems[i]->sWidth - m_vItems[i]->sX; 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; m_dwExtStyle |= WS_EX_RIGHT | WS_EX_RTLREADING | WS_EX_LEFTSCROLLBAR;
} }

View file

@ -43,8 +43,8 @@ struct DialogItemTemplate {
DWORD dwStyle; DWORD dwStyle;
WORD wId; WORD wId;
char *szClass; WCHAR *szClass;
char *szTitle; WCHAR *szTitle;
char *szCreationData; char *szCreationData;
WORD wCreateDataSize; WORD wCreateDataSize;
@ -144,16 +144,16 @@ private:
DWORD m_dwExtStyle; DWORD m_dwExtStyle;
DWORD m_dwStyle; DWORD m_dwStyle;
char* m_szMenu; WCHAR *m_szMenu;
char* m_szClass; WCHAR *m_szClass;
char* m_szTitle; WCHAR *m_szTitle;
// Only if DS_FONT style is set // Only if DS_FONT style is set
short m_sFontSize; short m_sFontSize;
short m_sFontWeight; // Extended only short m_sFontWeight; // Extended only
BYTE m_bItalic; // Extended only BYTE m_bItalic; // Extended only
BYTE m_bCharset; // Extended only BYTE m_bCharset; // Extended only
char* m_szFont; WCHAR *m_szFont;
// For (en/de)coding Unicode // For (en/de)coding Unicode
unsigned int m_uCodePage; unsigned int m_uCodePage;

View file

@ -20,6 +20,7 @@
#include "tokens.h" #include "tokens.h"
#include "build.h" #include "build.h"
#include "util.h" #include "util.h"
#include "winchar.h"
#include "ResourceEditor.h" #include "ResourceEditor.h"
#include "DialogTemplate.h" #include "DialogTemplate.h"
#include "lang.h" #include "lang.h"
@ -2441,8 +2442,19 @@ int CEXEBuild::doCommand(int which_token, LineParser &line)
branding_image_found = false; branding_image_found = false;
DialogItemTemplate* dlgItem = 0; DialogItemTemplate* dlgItem = 0;
for (int i = 0; (dlgItem = UIDlg.GetItemByIdx(i)); i++) { for (int i = 0; (dlgItem = UIDlg.GetItemByIdx(i)); i++) {
if ((IS_INTRESOURCE(dlgItem->szClass) && dlgItem->szClass == MAKEINTRESOURCE(0x0082)) bool check = false;
|| (!IS_INTRESOURCE(dlgItem->szClass) && !strcmp(dlgItem->szClass, "Static"))) {
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) { if ((dlgItem->dwStyle & SS_BITMAP) == SS_BITMAP) {
branding_image_found = true; branding_image_found = true;
branding_image_id = dlgItem->wId; 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.dwStyle = SS_BITMAP | WS_CHILD | WS_VISIBLE;
brandingCtl.sX = padding; brandingCtl.sX = padding;
brandingCtl.sY = padding; brandingCtl.sY = padding;
brandingCtl.szClass = MAKEINTRESOURCE(0x0082); brandingCtl.szClass = MAKEINTRESOURCEW(0x0082);
brandingCtl.szTitle = ""; brandingCtl.szTitle = NULL;
brandingCtl.wId = IDC_BRANDIMAGE; brandingCtl.wId = IDC_BRANDIMAGE;
brandingCtl.sHeight = wh; brandingCtl.sHeight = wh;
@ -2892,17 +2904,17 @@ int CEXEBuild::doCommand(int which_token, LineParser &line)
bool required = true; bool required = true;
char *f = line.gettoken_str(1); char *f = line.gettoken_str(1);
if(!stricmp(f,"/nonfatal")) { if(!stricmp(f,"/nonfatal")) {
if (line.getnumtokens()!=3) if (line.getnumtokens()!=3)
PRINTHELP(); PRINTHELP();
f = line.gettoken_str(2); f = line.gettoken_str(2);
required = false; required = false;
} else if (line.getnumtokens()!=2) { } else if (line.getnumtokens()!=2) {
PRINTHELP(); PRINTHELP();
} }
#ifdef _WIN32 #ifdef _WIN32
char *fc = f; char *fc = f;
#else #else
@ -2924,27 +2936,27 @@ int CEXEBuild::doCommand(int which_token, LineParser &line)
#endif #endif
// search working directory // search working directory
boost::scoped_ptr<dir_reader> dr( new_dir_reader() ); boost::scoped_ptr<dir_reader> dr( new_dir_reader() );
dr->read(dir); dr->read(dir);
for (dir_reader::iterator files_itr = dr->files().begin(); for (dir_reader::iterator files_itr = dr->files().begin();
files_itr != dr->files().end(); files_itr != dr->files().end();
files_itr++) files_itr++)
{ {
if (!dir_reader::matches(*files_itr, spec)) if (!dir_reader::matches(*files_itr, spec))
continue; continue;
string incfile = basedir + *files_itr; string incfile = basedir + *files_itr;
if (includeScript((char *) incfile.c_str()) != PS_OK) { if (includeScript((char *) incfile.c_str()) != PS_OK) {
return PS_ERROR; return PS_ERROR;
} }
included++; included++;
} }
if (included) if (included)
return PS_OK; return PS_OK;
// search include dirs // search include dirs
char *incdir = include_dirs.get(); char *incdir = include_dirs.get();
@ -2981,13 +2993,13 @@ int CEXEBuild::doCommand(int which_token, LineParser &line)
if (!included) if (!included)
{ {
if(required) { if(required) {
ERROR_MSG("!include: could not find: \"%s\"\n",f); ERROR_MSG("!include: could not find: \"%s\"\n",f);
return PS_ERROR; return PS_ERROR;
} else { } else {
warning_fl("!include: could not find: \"%s\"",f); warning_fl("!include: could not find: \"%s\"",f);
}
} }
} }
}
return PS_OK; return PS_OK;
case TOK_P_CD: case TOK_P_CD:
if (!line.gettoken_str(1)[0] || chdir(line.gettoken_str(1))) if (!line.gettoken_str(1)[0] || chdir(line.gettoken_str(1)))