From 1b5e8adbb8dacf0610d3dc97081b7b6716ad0881 Mon Sep 17 00:00:00 2001 From: wizou Date: Tue, 4 May 2010 08:21:49 +0000 Subject: [PATCH] Unicode port: Support for Unicode license files git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@6080 212acab6-be3b-0410-9dea-997c60f758d6 --- Source/Platform.h | 3 +++ Source/exehead/Ui.c | 22 +++++++++++++++++++--- Source/script.cpp | 23 ++++++++++++++--------- 3 files changed, 36 insertions(+), 12 deletions(-) diff --git a/Source/Platform.h b/Source/Platform.h index c1454ebf..a3080fcf 100644 --- a/Source/Platform.h +++ b/Source/Platform.h @@ -269,6 +269,9 @@ typedef DWORDLONG ULONGLONG,*PULONGLONG; # ifndef SF_RTF # define SF_RTF 0x0002 # endif +# ifndef SF_UNICODE +# define SF_UNICODE 0x0010 +# endif #endif #ifdef __GNUC__ diff --git a/Source/exehead/Ui.c b/Source/exehead/Ui.c index f5b20e7f..b04892f4 100644 --- a/Source/exehead/Ui.c +++ b/Source/exehead/Ui.c @@ -716,11 +716,23 @@ skipPage: static DWORD dwRead; DWORD CALLBACK StreamLicense(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb) { - lstrcpynA(pbBuff,(char*)dwCookie+dwRead,cb); - *pcb=lstrlenA(pbBuff); + lstrcpyn((LPTSTR)pbBuff,(LPTSTR)(dwCookie+dwRead),cb/sizeof(TCHAR)); + *pcb=lstrlen((LPTSTR)pbBuff)*sizeof(TCHAR); dwRead+=*pcb; return 0; } +#ifdef _UNICODE +// on-the-fly conversion of Unicode to ANSI (because Windows don't recognize Unicode RTF data) +DWORD CALLBACK StreamLicenseRTF(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb) +{ + LONG len = lstrlen(((LPWSTR) dwCookie)+dwRead); + len = min(len, cb/sizeof(WCHAR)); + *pcb=WideCharToMultiByte(CP_ACP,0,((LPWSTR) dwCookie)+dwRead,len,pbBuff,cb,NULL,NULL); + // RTF uses only ASCII characters, so we can assume "number of output bytes" = "number of source WChar consumed" + dwRead+=*pcb; + return 0; +} +#endif static BOOL CALLBACK LicenseProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { @@ -733,9 +745,13 @@ static BOOL CALLBACK LicenseProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM TCHAR *l = (TCHAR *)GetNSISStringNP(GetNSISTab(this_page->parms[1])); int lt = *l; EDITSTREAM es = { - (DWORD)(++l), + (DWORD_PTR)(++l), 0, +#ifdef _UNICODE + lt==SF_RTF?StreamLicenseRTF:StreamLicense +#else StreamLicense +#endif }; int selected = (this_page->flags & PF_LICENSE_SELECTED) | !(this_page->flags & PF_LICENSE_FORCE_SELECTION); diff --git a/Source/script.cpp b/Source/script.cpp index a326ef78..f0ae2ff3 100644 --- a/Source/script.cpp +++ b/Source/script.cpp @@ -825,40 +825,45 @@ int CEXEBuild::MacroExists(const TCHAR *macroname) int CEXEBuild::LoadLicenseFile(TCHAR *file, TCHAR** pdata, LineParser &line) // caller must free *pdata, even on error result { - unsigned int datalen; - FILE *fp=FOPEN(file,_T("rb")); + FILE *fp=FOPENTEXT(file,"rt"); if (!fp) { ERROR_MSG(_T("%s: open failed \"%s\"\n"),line.gettoken_str(0),file); PRINTHELP() } MANAGE_WITH(fp, fclose); + unsigned int beginning=ftell(fp); // (we might be positionned after a BOM) fseek(fp,0,SEEK_END); - datalen=ftell(fp); + unsigned int datalen=ftell(fp)-beginning; // size of file in bytes! not a number of character if (!datalen) { ERROR_MSG(_T("%s: empty license file \"%s\"\n"),line.gettoken_str(0),file); return PS_ERROR; } - rewind(fp); - TCHAR *data=(TCHAR*)malloc(datalen+2); //TODO: review this for Unicode support + fseek(fp,beginning,SEEK_SET); + TCHAR *data=(TCHAR*)malloc((datalen+2)*sizeof(TCHAR)); // alloc enough for worst-case scenario (ANSI/UTF8 characters read in WCHARs) if (!data) { - ERROR_MSG(_T("Internal compiler error #12345: %s malloc(%d) failed.\n"),line.gettoken_str(0),datalen+2); + ERROR_MSG(_T("Internal compiler error #12345: %s malloc(%d) failed.\n"),line.gettoken_str(0),(datalen+2)*sizeof(TCHAR)); return PS_ERROR; } *pdata = data; // memory will be released by caller TCHAR *ldata=data+1; - if (fread((void*)ldata,1,datalen,fp) != datalen) + while (_fgetts(ldata, data+datalen+2-ldata, fp)) // _fgetts translate ANSI/UTF8 characters to TCHAR + ldata += _tcslen(ldata); + if (ferror(fp)) { ERROR_MSG(_T("%s: can't read file.\n"),line.gettoken_str(0)); return PS_ERROR; } - ldata[datalen]='\0'; - if (!memcmp(ldata,"{\\rtf",5)) + if (!memcmp(data+1,_T("{\\rtf"),5*sizeof(TCHAR))) *data = SF_RTF; else +#ifdef _UNICODE + *data = SF_TEXT|SF_UNICODE; +#else *data = SF_TEXT; +#endif return PS_OK; }