diff --git a/INSTALL b/INSTALL index e3a762b4..fa372388 100644 --- a/INSTALL +++ b/INSTALL @@ -25,6 +25,11 @@ This is a trimmed version of Appendix "Building NSIS" of the documentation. set ZLIB_W32=C:\Dev\zlib-1.2.4 + - For Unicode version of NSIS + + * type: + scons UNICODE=yes + - Installing * type: diff --git a/Source/build.cpp b/Source/build.cpp index ce709aa7..6f85d7fc 100644 --- a/Source/build.cpp +++ b/Source/build.cpp @@ -95,6 +95,7 @@ CEXEBuild::CEXEBuild() : linecnt = 0; fp = 0; curfilename = 0; + curfile_unicode = FALSE; display_info=1; display_script=1; diff --git a/Source/build.h b/Source/build.h index 2263ab5b..c3282792 100644 --- a/Source/build.h +++ b/Source/build.h @@ -107,7 +107,7 @@ class CEXEBuild { // process a script (you can process as many scripts as you want, // it is as if they are concatenated) - int process_script(FILE *fp, const TCHAR *curfilename); + int process_script(FILE *filepointer, const TCHAR *filename, BOOL unicode); int process_oneline(TCHAR *line, const TCHAR *curfilename, int lineptr); // you only get to call write_output once, so use it wisely. @@ -125,6 +125,7 @@ class CEXEBuild { int linecnt; const TCHAR *curfilename; + BOOL curfile_unicode; FILE *fp; HWND notify_hwnd; @@ -166,7 +167,7 @@ class CEXEBuild { int parseScript(); int includeScript(TCHAR *f); int MacroExists(const TCHAR *macroname); - int LoadLicenseFile(TCHAR *file, TCHAR** pdata, LineParser &line); + int LoadLicenseFile(TCHAR *file, TCHAR** pdata, LineParser &line, BOOL* unicode); #ifdef NSIS_FIX_DEFINES_IN_STRINGS void ps_addtoline(const TCHAR *str, GrowBuf &linedata, StringList &hist, bool bIgnoreDefines = false); #else @@ -319,7 +320,7 @@ class CEXEBuild { * return aPS_ERROR. If this function call is overwriting a set user string, * this will return a PS_WARNING. */ - int SetLangString(TCHAR *name, LANGID lang, TCHAR *str); + int SetLangString(TCHAR *name, LANGID lang, TCHAR *str, BOOL unicode); /** * Sets the user string to the specific NLF_STRINGS id. diff --git a/Source/lang.cpp b/Source/lang.cpp index 273bd134..a76fe6e5 100644 --- a/Source/lang.cpp +++ b/Source/lang.cpp @@ -478,7 +478,7 @@ int CEXEBuild::DefineInnerLangString(int id, int process/*=-1*/) { // @return If the language id, the variable name or string is invalid, it will // return a PS_ERROR. If this function call is overwriting a set user string, // this will return a PS_WARNING. -int CEXEBuild::SetLangString(TCHAR *name, LANGID lang, TCHAR *str) { +int CEXEBuild::SetLangString(TCHAR *name, LANGID lang, TCHAR *str, BOOL unicode) { if (!str || !name) return PS_ERROR; LanguageTable *table = GetLangTable(lang); @@ -490,7 +490,7 @@ int CEXEBuild::SetLangString(TCHAR *name, LANGID lang, TCHAR *str) { if (pos < 0) pos = build_langstrings.add(name, &sn); - if (table->lang_strings->set(sn, str)) + if (table->lang_strings->set(sn, unicode ? str : CtoTString2(TtoCString(str),table->nlf.m_uCodePage))) return PS_WARNING; return PS_OK; @@ -912,7 +912,8 @@ TCHAR SkipComments(FILE *f) { // NSIS Language File parser LanguageTable * CEXEBuild::LoadLangFile(TCHAR *filename) { - FILE *f = FOPENTEXT(filename, "r"); + BOOL unicode; + FILE *f = FOPENTEXT2(filename, "r", &unicode); if (!f) { ERROR_MSG(_T("Error: Can't open language file - \"%s\"!\n"),filename); return 0; @@ -1014,6 +1015,15 @@ LanguageTable * CEXEBuild::LoadLangFile(TCHAR *filename) { nlf->m_uCodePage = CP_ACP; } +#ifdef _UNICODE + if (!unicode) // convert font name from ANSI to Unicode now that we know the language codepage + { + TCHAR* str = nlf->m_szFont; + nlf->m_szFont = _tcsdup(CtoTString2(TtoCString(str),table->nlf.m_uCodePage)); + free(str); + } +#endif + // Get RTL setting nlf->m_szStrings[NLF_RTL] = (TCHAR *)malloc(2*sizeof(TCHAR)); nlf->m_bRTL = false; @@ -1121,6 +1131,14 @@ LanguageTable * CEXEBuild::LoadLangFile(TCHAR *filename) { else *out = *in; } *out = 0; +#ifdef _UNICODE + if (!unicode) + { + TCHAR* str = nlf->m_szStrings[i]; + nlf->m_szStrings[i] = _tcsdup(CtoTString2(TtoCString(str),table->nlf.m_uCodePage)); + free(str); + } +#endif } fclose(f); diff --git a/Source/makenssi.cpp b/Source/makenssi.cpp index 90b3fda3..f0decb8b 100644 --- a/Source/makenssi.cpp +++ b/Source/makenssi.cpp @@ -197,7 +197,8 @@ static tstring get_home() static int process_config(CEXEBuild& build, tstring& conf) { - FILE *cfg=FOPENTEXT(conf.c_str(),"rt"); + BOOL unicode; + FILE *cfg=FOPENTEXT2(conf.c_str(),"rt",&unicode); if (cfg) { if (build.display_script) @@ -205,7 +206,7 @@ static int process_config(CEXEBuild& build, tstring& conf) _ftprintf(g_output,_T("Processing config: \n")); fflush(g_output); } - int ret=build.process_script(cfg,(TCHAR*)conf.c_str()); + int ret=build.process_script(cfg,(TCHAR*)conf.c_str(),unicode); fclose(cfg); if (ret != PS_OK && ret != PS_EOF) { @@ -484,6 +485,7 @@ int _tmain(int argc, TCHAR **argv) { TCHAR sfile[1024]; + BOOL unicode=FALSE; if (!_tcscmp(argv[argpos],_T("-")) && !in_files) { fp=stdin; @@ -492,11 +494,11 @@ int _tmain(int argc, TCHAR **argv) else { _tcscpy(sfile,argv[argpos]); - fp=FOPENTEXT(sfile,"rt"); + fp=FOPENTEXT2(sfile,"rt",&unicode); if (!fp) { _stprintf(sfile,_T("%s.nsi"),argv[argpos]); - fp=FOPENTEXT(sfile,"rt"); + fp=FOPENTEXT2(sfile,"rt",&unicode); if (!fp) { if (build.display_errors) @@ -522,7 +524,7 @@ int _tmain(int argc, TCHAR **argv) _ftprintf(g_output,_T("Processing script file: \"%s\"\n"),sfile); fflush(g_output); } - int ret=build.process_script(fp,sfile); + int ret=build.process_script(fp,sfile,unicode); if (fp != stdin) fclose(fp); if (ret != PS_EOF && ret != PS_OK) diff --git a/Source/script.cpp b/Source/script.cpp index 995c2ab2..81039fe0 100644 --- a/Source/script.cpp +++ b/Source/script.cpp @@ -202,11 +202,12 @@ void CEXEBuild::del_date_time_predefines() } #endif -int CEXEBuild::process_script(FILE *filepointer, const TCHAR *filename) +int CEXEBuild::process_script(FILE *filepointer, const TCHAR *filename, BOOL unicode) { linecnt = 0; fp = filepointer; curfilename = filename; + curfile_unicode = unicode; if (has_called_write_output) { @@ -232,6 +233,7 @@ int CEXEBuild::process_script(FILE *filepointer, const TCHAR *filename) fp = 0; curfilename = 0; + curfile_unicode = FALSE; if (m_linebuild.getlen()) { @@ -745,7 +747,8 @@ int CEXEBuild::parseScript() int CEXEBuild::includeScript(TCHAR *f) { SCRIPT_MSG(_T("!include: \"%s\"\n"),f); - FILE *incfp=FOPENTEXT(f,"rt"); + BOOL unicode; + FILE *incfp=FOPENTEXT2(f,"rt",&unicode); if (!incfp) { ERROR_MSG(_T("!include: could not open file: \"%s\"\n"),f); @@ -765,7 +768,9 @@ int CEXEBuild::includeScript(TCHAR *f) int last_linecnt=linecnt; linecnt=0; const TCHAR *last_filename=curfilename; + BOOL last_unicode=curfile_unicode; curfilename=f; + curfile_unicode=unicode; FILE *last_fp=fp; fp=incfp; @@ -787,6 +792,7 @@ int CEXEBuild::includeScript(TCHAR *f) linecnt=last_linecnt; curfilename=last_filename; + curfile_unicode=last_unicode; fp=last_fp; build_include_depth--; @@ -825,9 +831,9 @@ int CEXEBuild::MacroExists(const TCHAR *macroname) return 0; } -int CEXEBuild::LoadLicenseFile(TCHAR *file, TCHAR** pdata, LineParser &line) // caller must free *pdata, even on error result +int CEXEBuild::LoadLicenseFile(TCHAR *file, TCHAR** pdata, LineParser &line, BOOL* unicode) // caller must free *pdata, even on error result { - FILE *fp=FOPENTEXT(file,"rt"); + FILE *fp=FOPENTEXT2(file,"rt",unicode); if (!fp) { ERROR_MSG(_T("%s: open failed \"%s\"\n"),line.gettoken_str(0),file); @@ -1593,7 +1599,7 @@ int CEXEBuild::doCommand(int which_token, LineParser &line) TCHAR *name = line.gettoken_str(1); LANGID lang = line.gettoken_int(2); TCHAR *str = line.gettoken_str(3); - int ret = SetLangString(name, lang, str); + int ret = SetLangString(name, lang, str, curfile_unicode); if (ret == PS_WARNING) warning_fl(_T("LangString \"%s\" set multiple times for %d, wasting space"), name, lang); else if (ret == PS_ERROR) { @@ -1620,12 +1626,13 @@ int CEXEBuild::doCommand(int which_token, LineParser &line) TCHAR *data = NULL; MANAGE_WITH(data, free); + BOOL unicode; - int ret = LoadLicenseFile(file, &data, line); + int ret = LoadLicenseFile(file, &data, line, &unicode); if (ret != PS_OK) return ret; - ret = SetLangString(name, lang, data); + ret = SetLangString(name, lang, data, unicode); if (ret == PS_WARNING) warning_fl(_T("LicenseLangString \"%s\" set multiple times for %d, wasting space"), name, lang); else if (ret == PS_ERROR) @@ -1895,7 +1902,8 @@ int CEXEBuild::doCommand(int which_token, LineParser &line) if (!idx) { - int ret = LoadLicenseFile(file, &filedata, line); + BOOL unicode; + int ret = LoadLicenseFile(file, &filedata, line, &unicode); if (ret != PS_OK) return ret; data = filedata; diff --git a/Source/tstring.cpp b/Source/tstring.cpp index 7a70d97c..f1b93cf5 100644 --- a/Source/tstring.cpp +++ b/Source/tstring.cpp @@ -19,10 +19,11 @@ #include "util.h" #include -FILE* FileOpenUnicodeText(const TCHAR* file, const TCHAR* mode) +FILE* FileOpenUnicodeText(const TCHAR* file, const TCHAR* mode, BOOL* unicode) { extern FILE *g_output; CValidateUnicode::FILE_TYPE ftype = CValidateUnicode::UTF_8; // default file format is UTF-8 + if (unicode) *unicode = TRUE; // If we are reading an existing file, check to see what type of file it // is first. @@ -92,7 +93,7 @@ FILE* FileOpenUnicodeText(const TCHAR* file, const TCHAR* mode) break; default: // Looks like fopen() doesn't support other encodings of Unicode. - strMode.append(_T(", ccs=UNICODE")); + if (unicode) *unicode = FALSE; break; } diff --git a/Source/tstring.h b/Source/tstring.h index 066ee961..bea3a5d2 100644 --- a/Source/tstring.h +++ b/Source/tstring.h @@ -29,20 +29,24 @@ typedef std::wstring tstring; typedef std::wofstream tofstream; typedef std::wifstream tifstream; // Use the following macros to open text files. -FILE* FileOpenUnicodeText(const TCHAR* file, const TCHAR* mode); -#define FOPENTEXT(file, mode) FileOpenUnicodeText(file, _T(mode)) +FILE* FileOpenUnicodeText(const TCHAR* file, const TCHAR* mode, BOOL* unicode); +#define FOPENTEXT(file, mode) FileOpenUnicodeText(file, _T(mode), NULL) +#define FOPENTEXT2(file, mode, unicode) FileOpenUnicodeText(file, _T(mode), unicode) #else typedef std::string tstring; typedef std::ofstream tofstream; typedef std::ifstream tifstream; // Use the following macros to open text files. -#define FOPENTEXT(file, mode) fopen(file, mode) +#define FOPENTEXT(file, mode) fopen(file, mode) +#define FOPENTEXT2(file, mode, unicode) *unicode=FALSE, fopen(file, mode) #endif #ifndef _UNICODE #define CtoTString(str) (str) +#define CtoTString2(str,cp) (str) #define TtoCString(str) (str) #else +#define CtoTString2(str,cp) CtoTString(str,cp) // This is a helpful little function for converting exceptions or // other system type things that come back ANSI and must be @@ -56,6 +60,12 @@ public: m_wStr = (wchar_t*) GlobalAlloc(GPTR, len*sizeof(wchar_t)); MultiByteToWideChar(CP_ACP, 0, str, -1, m_wStr, len); } + CtoTString(const char* str, UINT cp) + { + int len = MultiByteToWideChar(cp, 0, str, -1, NULL, 0); + m_wStr = (wchar_t*) GlobalAlloc(GPTR, len*sizeof(wchar_t)); + MultiByteToWideChar(cp, 0, str, -1, m_wStr, len); + } CtoTString(const std::string& str) { int len = MultiByteToWideChar(CP_ACP, 0, str.c_str(), str.length()+1, NULL, 0);