Unicode port: Unicode version of NSIS can now generate both ANSI & Unicode installers (using new instruction UnicodeInstaller on/off).
Stubs & Plugins differentiation is done automatically using a 'W' suffix. SConscripts need to be reviewed to generate both variants of Plugins & pluginapi.lib under Unicode compilation. git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@6100 212acab6-be3b-0410-9dea-997c60f758d6
This commit is contained in:
parent
fbc7cb8fd0
commit
57f7ff8a1c
24 changed files with 376 additions and 112 deletions
|
@ -24,19 +24,27 @@ example = Split("""
|
|||
extdll.inc
|
||||
""")
|
||||
|
||||
Import('env plugin_env')
|
||||
Import('env plugin_env plugin_uenv')
|
||||
|
||||
# build library
|
||||
|
||||
api_env = env.Clone()
|
||||
api_env.Append(CPPPATH = ['#Source/exehead'])
|
||||
lib = api_env.Library(lib_target, lib_files)
|
||||
# in Unicode compilation, we should really build both variants but I can't get it to work [Wizou]
|
||||
if env['UNICODE']:
|
||||
api_uenv = plugin_uenv.Clone()
|
||||
api_uenv.Append(CPPPATH = ['#Source/exehead'])
|
||||
libW = api_uenv.Library(lib_target+'W', lib_files)
|
||||
lib = libW
|
||||
else:
|
||||
api_env = plugin_env.Clone()
|
||||
api_env.Append(CPPPATH = ['#Source/exehead'])
|
||||
lib = api_env.Library(lib_target, lib_files)
|
||||
|
||||
# distribute library, files and examples
|
||||
|
||||
env.DistributeExamples(api_files, path='Plugin/nsis')
|
||||
|
||||
if env['PLATFORM'] == 'win32':
|
||||
if env['UNICODE']:
|
||||
env.DistributeExamples(libW, lib_target+".lib", path='Plugin/nsis')
|
||||
env.DistributeExamples(lib, path='Plugin/nsis')
|
||||
|
||||
else:
|
||||
|
@ -57,3 +65,6 @@ env.Install('#$BUILD_PREFIX/api/nsis', api_files + lib)
|
|||
plugin_env.Append(CPPPATH = ['#$BUILD_PREFIX/api'])
|
||||
plugin_env.Append(LIBPATH = ['#$BUILD_PREFIX/api/nsis'])
|
||||
plugin_env.Append(LIBS = [lib_target])
|
||||
plugin_uenv.Append(CPPPATH = ['#$BUILD_PREFIX/api'])
|
||||
plugin_uenv.Append(LIBPATH = ['#$BUILD_PREFIX/api/nsis'])
|
||||
plugin_uenv.Append(LIBS = [lib_target+'W'])
|
||||
|
|
|
@ -126,7 +126,7 @@ Macros and conversion functions for InstallOptions
|
|||
InitPluginsDir
|
||||
File "/oname=$PLUGINSDIR\${FILE}" "${FILE}"
|
||||
!ifdef NSIS_UNICODE
|
||||
InstallOptions::make_unicode "$PLUGINSDIR\${FILE}"
|
||||
InstallOptionsW::make_unicode "$PLUGINSDIR\${FILE}"
|
||||
!endif
|
||||
!insertmacro INSTALLOPTIONS_WRITE "${FILE}" "Settings" "RTL" "$(^RTL)"
|
||||
|
||||
|
@ -139,7 +139,7 @@ Macros and conversion functions for InstallOptions
|
|||
InitPluginsDir
|
||||
File "/oname=$PLUGINSDIR\${FILENAME}" "${FILE}"
|
||||
!ifdef NSIS_UNICODE
|
||||
InstallOptions::make_unicode "$PLUGINSDIR\${FILENAME}"
|
||||
InstallOptionsW::make_unicode "$PLUGINSDIR\${FILENAME}"
|
||||
!endif
|
||||
!insertmacro INSTALLOPTIONS_WRITE "${FILENAME}" "Settings" "RTL" "$(^RTL)"
|
||||
|
||||
|
|
|
@ -706,7 +706,9 @@ BOOL CALLBACK DialogProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) {
|
|||
}
|
||||
|
||||
DWORD WINAPI MakeNSISProc(LPVOID p) {
|
||||
#ifdef _UNICODE
|
||||
TCHAR buf[1024];
|
||||
#endif
|
||||
char iobuf[1024]; //i/o buffer
|
||||
STARTUPINFO si={sizeof(si),};
|
||||
SECURITY_ATTRIBUTES sa={sizeof(sa),};
|
||||
|
|
|
@ -53,4 +53,4 @@ test_env.Append(CPPPATH = ['#$BUILD_CONFIG'])
|
|||
|
||||
# return
|
||||
|
||||
Return('stub_env makensis_env plugin_env util_env cp_util_env test_env')
|
||||
Return('stub_env makensis_env plugin_env util_env cp_util_env test_env stub_env plugin_env')
|
||||
|
|
|
@ -309,4 +309,4 @@ if makensis_env['PLATFORM'] == 'hpux':
|
|||
|
||||
### return
|
||||
|
||||
Return('stub_env makensis_env plugin_env util_env cp_util_env test_env')
|
||||
Return('stub_env makensis_env plugin_env util_env cp_util_env test_env stub_env plugin_env')
|
||||
|
|
|
@ -125,4 +125,4 @@ test_env.Append(CPPPATH = ['#$BUILD_CONFIG'])
|
|||
|
||||
# return
|
||||
|
||||
Return('stub_env makensis_env plugin_env util_env cp_util_env test_env')
|
||||
Return('stub_env makensis_env plugin_env util_env cp_util_env test_env stub_env plugin_env')
|
||||
|
|
|
@ -41,8 +41,9 @@ if defenv['DEBUG']:
|
|||
defenv.Append(LINKFLAGS = ['/debug'])
|
||||
|
||||
### unicode
|
||||
if defenv['UNICODE']:
|
||||
defenv.Append(CPPDEFINES = ['_UNICODE', 'UNICODE'])
|
||||
tdefenv = defenv.Clone()
|
||||
if tdefenv['UNICODE']:
|
||||
tdefenv.Append(CPPDEFINES = ['_UNICODE', 'UNICODE'])
|
||||
|
||||
### workarounds
|
||||
|
||||
|
@ -101,19 +102,19 @@ stub_env.Append(CCFLAGS = ['/W3']) # level 3 warnings
|
|||
|
||||
stub_env.Append(LINKFLAGS = ['/opt:nowin98']) # 512 bytes align
|
||||
|
||||
if defenv['UNICODE']:
|
||||
stub_env.Append(LINKFLAGS = ['/entry:wWinMain']) # Unicode entry point
|
||||
else:
|
||||
stub_env.Append(LINKFLAGS = ['/entry:WinMain']) # ANSI entry point
|
||||
|
||||
stub_env.Append(LINKFLAGS = ['$NODEFLIBS_FLAG']) # no default libraries
|
||||
stub_env.Append(LINKFLAGS = ['$MAP_FLAG']) # generate map file
|
||||
stub_env.Append(CCFLAGS = ['/FAcs']) # full listing files
|
||||
stub_env.Append(CCFLAGS = ['/Fa${TARGET}.lst']) # listing file name
|
||||
|
||||
stub_uenv = stub_env.Clone()
|
||||
stub_uenv.Append(LINKFLAGS = ['/entry:wWinMain']) # Unicode entry point
|
||||
stub_uenv.Append(CPPDEFINES = ['_UNICODE', 'UNICODE'])
|
||||
stub_env.Append(LINKFLAGS = ['/entry:WinMain']) # ANSI entry point
|
||||
|
||||
### makensis environment
|
||||
|
||||
makensis_env = defenv.Clone()
|
||||
makensis_env = tdefenv.Clone()
|
||||
|
||||
makensis_env.Append(CPPPATH = ['#$BUILD_CONFIG'])
|
||||
|
||||
|
@ -140,9 +141,12 @@ plugin_env.Append(CCFLAGS = ['/W3']) # level 3 warnings
|
|||
plugin_env.Append(LINKFLAGS = ['/opt:nowin98']) # 512 bytes align
|
||||
plugin_env.Append(LINKFLAGS = ['$MAP_FLAG']) # generate map file
|
||||
|
||||
plugin_uenv = plugin_env.Clone()
|
||||
plugin_uenv.Append(CPPDEFINES = ['_UNICODE', 'UNICODE'])
|
||||
|
||||
### util environment
|
||||
|
||||
util_env = defenv.Clone()
|
||||
util_env = tdefenv.Clone()
|
||||
|
||||
if not defenv['DEBUG']:
|
||||
util_env.Append(CCFLAGS = ['/O1']) # optimize for speed
|
||||
|
@ -209,8 +213,10 @@ def add_file_to_emitter(env, emitter_name, file):
|
|||
def add_file(file):
|
||||
file = File(file)
|
||||
add_file_to_emitter(stub_env, 'PROGEMITTER', file)
|
||||
add_file_to_emitter(stub_uenv, 'PROGEMITTER', file)
|
||||
add_file_to_emitter(util_env, 'PROGEMITTER', file)
|
||||
add_file_to_emitter(plugin_env, 'SHLIBEMITTER', file)
|
||||
add_file_to_emitter(plugin_uenv, 'SHLIBEMITTER', file)
|
||||
|
||||
#
|
||||
# MSVC 6 SP6 doesn't like direct shifting of 64-bit integers.
|
||||
|
@ -240,6 +246,7 @@ else:
|
|||
|
||||
if not conf.TryLink(int64test, '.c'):
|
||||
stub_env.Append(CPPDEFINES = ['_NSIS_NO_INT64_SHR'])
|
||||
stub_uenv.Append(CPPDEFINES = ['_NSIS_NO_INT64_SHR'])
|
||||
|
||||
conf.Finish()
|
||||
|
||||
|
@ -256,4 +263,4 @@ conf.Finish()
|
|||
|
||||
### return
|
||||
|
||||
Return('stub_env makensis_env plugin_env util_env cp_util_env test_env')
|
||||
Return('stub_env makensis_env plugin_env util_env cp_util_env test_env stub_uenv plugin_uenv')
|
||||
|
|
48
SConstruct
48
SConstruct
|
@ -420,8 +420,10 @@ plugin_env = envs[2]
|
|||
util_env = envs[3]
|
||||
cp_util_env = envs[4]
|
||||
test_env = envs[5]
|
||||
stub_uenv = envs[6]
|
||||
plugin_uenv = envs[7]
|
||||
|
||||
Export('stub_env makensis_env plugin_env util_env cp_util_env test_env')
|
||||
Export('stub_env makensis_env plugin_env plugin_uenv util_env cp_util_env test_env')
|
||||
|
||||
######################################################################
|
||||
####### Distribution ###
|
||||
|
@ -484,12 +486,17 @@ defenv.DistributeConf('nsisconf.nsh')
|
|||
####### Stubs ###
|
||||
######################################################################
|
||||
|
||||
def BuildStub(compression, solid):
|
||||
env = stub_env.Clone()
|
||||
def BuildStub(compression, solid, unicode):
|
||||
|
||||
suffix = ''
|
||||
if solid:
|
||||
suffix = '_solid'
|
||||
if unicode:
|
||||
suffix += 'W'
|
||||
env = stub_uenv.Clone()
|
||||
else:
|
||||
env = stub_env.Clone()
|
||||
|
||||
|
||||
build_dir = '$BUILD_PREFIX/stub_%s%s' % (compression, suffix)
|
||||
|
||||
|
@ -507,8 +514,12 @@ for stub in stubs:
|
|||
if stub in defenv['SKIPSTUBS']:
|
||||
continue
|
||||
|
||||
BuildStub(stub, False)
|
||||
BuildStub(stub, True)
|
||||
if defenv['UNICODE']:
|
||||
BuildStub(stub, False, True)
|
||||
BuildStub(stub, True, True)
|
||||
|
||||
BuildStub(stub, False, False)
|
||||
BuildStub(stub, True, False)
|
||||
|
||||
defenv.DistributeStubs('Source/exehead/uninst.ico',names='uninst')
|
||||
|
||||
|
@ -569,11 +580,25 @@ def DistributeExtras(env, target, examples, docs):
|
|||
####### Plug-ins ###
|
||||
######################################################################
|
||||
|
||||
def BuildPlugin(target, source, libs, examples = None, docs = None,
|
||||
def BuildPluginBoth(target, source, libs, examples = None, docs = None,
|
||||
entry = 'DllMain', res = None, resources = None,
|
||||
defines = None, flags = None, nodeflib = True,
|
||||
cppused = False):
|
||||
env = plugin_env.Clone()
|
||||
# this function should build the ANSI & Unicode variant of the DLL, but I can't get it to work... help!!! [Wizou]
|
||||
if defenv['UNICODE']:
|
||||
#VariantDir('$BUILD_PREFIX/' + plugin + 'W', path)
|
||||
BuildPlugin(target, source, libs, examples, docs, entry, res, resources, defines, flags, nodeflib, cppused, True)
|
||||
else:
|
||||
BuildPlugin(target, source, libs, examples, docs, entry, res, resources, defines, flags, nodeflib, cppused, False)
|
||||
|
||||
def BuildPlugin(target, source, libs, examples = None, docs = None,
|
||||
entry = 'DllMain', res = None, resources = None,
|
||||
defines = None, flags = None, nodeflib = True,
|
||||
cppused = False, unicode = False):
|
||||
if unicode:
|
||||
env = plugin_uenv.Clone()
|
||||
else:
|
||||
env = plugin_env.Clone()
|
||||
|
||||
if cppused and env['CPP_REQUIRES_STDLIB']:
|
||||
nodeflib = False
|
||||
|
@ -595,7 +620,10 @@ def BuildPlugin(target, source, libs, examples = None, docs = None,
|
|||
plugin = i
|
||||
break
|
||||
env.DistributePlugin(plugin)
|
||||
if unicode:
|
||||
env.DistributePlugin(plugin, str(plugin)[:-4]+"W.dll") # tweak to generate both plugin.dll & pluginW.dll (until we get to build really both variant)
|
||||
|
||||
#if not unicode: # distribute extras only for ANSI builds
|
||||
DistributeExtras(env, target, examples, docs)
|
||||
|
||||
for plugin in plugin_libs + plugins:
|
||||
|
@ -604,8 +632,10 @@ for plugin in plugin_libs + plugins:
|
|||
|
||||
path = 'Contrib/' + plugin
|
||||
build_dir = '$BUILD_PREFIX/' + plugin
|
||||
exports = {'BuildPlugin' : BuildPlugin, 'env' : plugin_env.Clone()}
|
||||
|
||||
if defenv['UNICODE']:
|
||||
exports = {'BuildPlugin' : BuildPluginBoth, 'env' : plugin_uenv.Clone()}
|
||||
else:
|
||||
exports = {'BuildPlugin' : BuildPlugin, 'env' : plugin_env.Clone()}
|
||||
defenv.SConscript(dirs = path, build_dir = build_dir, duplicate = False, exports = exports)
|
||||
|
||||
######################################################################
|
||||
|
|
|
@ -91,8 +91,9 @@ void ReadVarLenArr(LPBYTE &seeker, WCHAR* &readInto, unsigned int uCodePage) {
|
|||
// Construction/Destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
CDialogTemplate::CDialogTemplate(BYTE* pbData, unsigned int uCodePage) {
|
||||
CDialogTemplate::CDialogTemplate(BYTE* pbData, bool build_unicode, unsigned int uCodePage) {
|
||||
m_uCodePage = uCodePage;
|
||||
m_build_unicode = build_unicode;
|
||||
|
||||
m_dwHelpId = 0;
|
||||
m_szClass = 0;
|
||||
|
@ -598,7 +599,7 @@ BYTE* CDialogTemplate::Save(DWORD& dwSize) {
|
|||
// Write class variant length array
|
||||
WCHAR *szClass = m_vItems[i]->szClass;
|
||||
#ifdef _UNICODE
|
||||
if (!IS_INTRESOURCE(szClass) && !_wcsicmp(szClass, L"RichEdit20A"))
|
||||
if (!IS_INTRESOURCE(szClass) && m_build_unicode && !_wcsicmp(szClass, L"RichEdit20A"))
|
||||
szClass = L"RichEdit20W"; // transmute ANSI RichEdit control into Unicode RichEdit
|
||||
#endif
|
||||
WriteStringOrId(szClass);
|
||||
|
|
|
@ -107,7 +107,7 @@ typedef struct {
|
|||
|
||||
class CDialogTemplate {
|
||||
public:
|
||||
CDialogTemplate(BYTE* pbData, unsigned int uCodePage=CP_ACP);
|
||||
CDialogTemplate(BYTE* pbData, bool build_unicode, unsigned int uCodePage=CP_ACP);
|
||||
virtual ~CDialogTemplate();
|
||||
|
||||
short GetWidth();
|
||||
|
@ -136,6 +136,7 @@ public:
|
|||
|
||||
private:
|
||||
bool m_bExtended;
|
||||
bool m_build_unicode;
|
||||
|
||||
DWORD m_dwHelpId; // Extended only
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ void Plugins::FindCommands(const tstring &path, bool displayInfo)
|
|||
|
||||
for (dir_reader::iterator files_itr = dr->files().begin();
|
||||
files_itr != dr->files().end();
|
||||
files_itr++)
|
||||
files_itr++) // note: files are listed alphabetically, so plugin.dll will be listed before pluginW.dll
|
||||
{
|
||||
if (!dir_reader::matches(*files_itr, _T("*.dll")))
|
||||
continue;
|
||||
|
@ -109,7 +109,10 @@ void Plugins::GetExports(const tstring &pathToDll, bool displayInfo)
|
|||
return;
|
||||
}
|
||||
|
||||
const tstring dllName = remove_file_extension(get_file_name(pathToDll));
|
||||
tstring dllName = remove_file_extension(get_file_name(pathToDll));
|
||||
#ifdef _UNICODE
|
||||
bool unicodeDll = dllName[dllName.size()-1] == 'W';
|
||||
#endif
|
||||
|
||||
FIX_ENDIAN_INT16_INPLACE(NTHeaders->FileHeader.Characteristics);
|
||||
if (NTHeaders->FileHeader.Characteristics & IMAGE_FILE_DLL)
|
||||
|
@ -143,6 +146,12 @@ void Plugins::GetExports(const tstring &pathToDll, bool displayInfo)
|
|||
const tstring lcsig = lowercase(signature);
|
||||
m_command_to_path[lcsig] = pathToDll;
|
||||
m_command_lowercase_to_command[lcsig] = signature;
|
||||
#ifdef _UNICODE
|
||||
const tstring lcsigA = lowercase(dllName.substr(0,dllName.size()-1) + _T("::") + tstring(CtoTString(name)));
|
||||
if (unicodeDll && m_command_to_path.find(lcsigA) != m_command_to_path.end())
|
||||
m_unicode_variant[lcsigA] = signature;
|
||||
else
|
||||
#endif
|
||||
if (displayInfo)
|
||||
_ftprintf(g_output, _T(" - %s\n"), signature.c_str());
|
||||
}
|
||||
|
@ -180,6 +189,10 @@ tstring Plugins::NormalizedCommand(const tstring& command) const {
|
|||
return get_value(m_command_lowercase_to_command, lowercase(command));
|
||||
}
|
||||
|
||||
tstring Plugins::UseUnicodeVariant(const tstring& command) const {
|
||||
return get_value(m_unicode_variant, lowercase(command), command);
|
||||
}
|
||||
|
||||
int Plugins::GetPluginHandle(bool uninst, const tstring& command) const {
|
||||
if (uninst) {
|
||||
return get_value(m_command_to_uninstall_data_handle, command, -1);
|
||||
|
|
|
@ -30,6 +30,7 @@ class Plugins
|
|||
tstring NormalizedCommand(const tstring& command) const;
|
||||
int GetPluginHandle(bool uninst, const tstring& command) const;
|
||||
tstring GetPluginPath(const tstring& command) const;
|
||||
tstring UseUnicodeVariant(const tstring& lcsig) const;
|
||||
void SetDllDataHandle(bool uninst, const tstring& command, int dataHandle);
|
||||
|
||||
private: // methods
|
||||
|
@ -38,6 +39,7 @@ class Plugins
|
|||
private: // data members
|
||||
std::map<tstring, tstring> m_command_lowercase_to_command;
|
||||
std::map<tstring, tstring> m_command_to_path;
|
||||
std::map<tstring, tstring> m_unicode_variant;
|
||||
std::map<tstring, int> m_command_to_data_handle;
|
||||
std::map<tstring, int> m_command_to_uninstall_data_handle;
|
||||
};
|
||||
|
|
107
Source/build.cpp
107
Source/build.cpp
|
@ -116,12 +116,8 @@ CEXEBuild::CEXEBuild() :
|
|||
|
||||
definedlist.add(_T("NSIS_VERSION"), NSIS_VERSION);
|
||||
|
||||
#ifdef _UNICODE
|
||||
definedlist.add(_T("NSIS_UNICODE"));
|
||||
definedlist.add(_T("NSIS_CHAR_SIZE"), _T("2"));
|
||||
#else
|
||||
definedlist.add(_T("NSIS_CHAR_SIZE"), _T("1"));
|
||||
#endif
|
||||
build_unicode=false;
|
||||
definedlist.add(_T("NSIS_CHAR_SIZE"), _T("1")); // this can change after a UnicodeInstaller instruction is found
|
||||
|
||||
// automatically generated header file containing all defines
|
||||
#include <nsis-defines.h>
|
||||
|
@ -230,8 +226,8 @@ CEXEBuild::CEXEBuild() :
|
|||
|
||||
uninstaller_writes_used=0;
|
||||
|
||||
build_strlist.add(_T(""),0);
|
||||
ubuild_strlist.add(_T(""),0);
|
||||
build_strlist.add(_T(""), CP_ACP, false, build_unicode);
|
||||
ubuild_strlist.add(_T(""), CP_ACP, false, build_unicode);
|
||||
|
||||
build_langstring_num=0;
|
||||
ubuild_langstring_num=0;
|
||||
|
@ -469,11 +465,11 @@ int CEXEBuild::add_string(const TCHAR *string, int process/*=1*/, WORD codepage/
|
|||
if (idx < 0) return idx;
|
||||
}
|
||||
|
||||
if (!process) return cur_strlist->add(string,2);
|
||||
if (!process) return cur_strlist->add(string, codepage, false, build_unicode);
|
||||
|
||||
TCHAR buf[NSIS_MAX_STRLEN*4];
|
||||
preprocess_string(buf,string,codepage);
|
||||
return cur_strlist->add(buf,2);
|
||||
return cur_strlist->add(buf,codepage, true, build_unicode);
|
||||
}
|
||||
|
||||
int CEXEBuild::add_intstring(const int i) // returns offset in stringblock
|
||||
|
@ -483,6 +479,35 @@ int CEXEBuild::add_intstring(const int i) // returns offset in stringblock
|
|||
return add_string(i_str);
|
||||
}
|
||||
|
||||
#ifdef _UNICODE
|
||||
char* convert_processed_string_to_ansi(char *out, const TCHAR *in, WORD codepage)
|
||||
{
|
||||
const TCHAR *p=in;
|
||||
for (;;)
|
||||
{
|
||||
_TUCHAR i = (_TUCHAR)*p++;
|
||||
if (NS_IS_CODE(i)) // Note: this include '\0'
|
||||
{
|
||||
// convert all character up to, and including this code
|
||||
int cb = WideCharToMultiByte(codepage, 0, in, p-in, out, (p-in)*2, NULL, NULL);
|
||||
out += cb;
|
||||
if (i == _T('\0'))
|
||||
break;
|
||||
else if (i == NS_SKIP_CODE)
|
||||
*out++ = (char) *in++; // simply copy escaped code (01..04)
|
||||
else
|
||||
{
|
||||
WORD w = *p++; // special NSIS code is following by a WORD we need to output unchanged
|
||||
*out++ = LOBYTE(w);
|
||||
*out++ = HIBYTE(w);
|
||||
}
|
||||
in = p;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
#endif
|
||||
|
||||
// based on Dave Laundon's code
|
||||
int CEXEBuild::preprocess_string(TCHAR *out, const TCHAR *in, WORD codepage/*=CP_ACP*/)
|
||||
{
|
||||
|
@ -1498,7 +1523,7 @@ int CEXEBuild::resolve_coderefs(const TCHAR *str)
|
|||
else
|
||||
{
|
||||
// normal string
|
||||
section_name = cur_strlist->get() + x;
|
||||
section_name = cur_strlist->getTchar() + x;
|
||||
}
|
||||
if (x) wsprintf(fname,_T("%s section \"%s\" (%d)"),str,section_name,cnt);
|
||||
else wsprintf(fname,_T("unnamed %s section (%d)"),str,cnt);
|
||||
|
@ -2080,7 +2105,7 @@ again:
|
|||
#define REMOVE_ICON(id) if (disable_window_icon) { \
|
||||
BYTE* dlg = res_editor->GetResource(RT_DIALOG, id, NSIS_DEFAULT_LANG); \
|
||||
if (dlg) { \
|
||||
CDialogTemplate dt(dlg,uDefCodePage); \
|
||||
CDialogTemplate dt(dlg,build_unicode,uDefCodePage); \
|
||||
res_editor->FreeResource(dlg); \
|
||||
if (dt.RemoveItem(IDC_ULICON)) { \
|
||||
DialogItemTemplate* text = dt.GetItem(IDC_INTROTEXT); \
|
||||
|
@ -2210,7 +2235,7 @@ void CEXEBuild::AddStandardStrings()
|
|||
void CEXEBuild::PrepareHeaders(IGrowBuf *hdrbuf)
|
||||
{
|
||||
GrowBuf blocks_buf;
|
||||
growbuf_writer_sink sink(&blocks_buf);
|
||||
growbuf_writer_sink sink(&blocks_buf, build_unicode);
|
||||
|
||||
#ifdef NSIS_CONFIG_VISIBLE_SUPPORT
|
||||
cur_header->blocks[NB_PAGES].offset = sizeof(header) + blocks_buf.getlen();
|
||||
|
@ -2224,7 +2249,12 @@ void CEXEBuild::PrepareHeaders(IGrowBuf *hdrbuf)
|
|||
entry_writer::write_block(cur_entries, &sink);
|
||||
|
||||
cur_header->blocks[NB_STRINGS].offset = sizeof(header) + blocks_buf.getlen();
|
||||
blocks_buf.add(cur_strlist->get(), cur_strlist->getcount()*sizeof(TCHAR));
|
||||
#ifdef _UNICODE
|
||||
if (!build_unicode)
|
||||
blocks_buf.add(cur_strlist->getAnsi(), cur_strlist->getcount());
|
||||
else
|
||||
#endif
|
||||
blocks_buf.add(cur_strlist->getTchar(), cur_strlist->getcount()*sizeof(TCHAR));
|
||||
|
||||
cur_header->blocks[NB_LANGTABLES].offset = sizeof(header) + blocks_buf.getlen();
|
||||
lang_table_writer::write_block(cur_langtables, &sink, cur_header->langtable_size);
|
||||
|
@ -2244,7 +2274,7 @@ void CEXEBuild::PrepareHeaders(IGrowBuf *hdrbuf)
|
|||
}
|
||||
#endif
|
||||
|
||||
growbuf_writer_sink sink2(hdrbuf);
|
||||
growbuf_writer_sink sink2(hdrbuf, build_unicode);
|
||||
header_writer header(&sink2);
|
||||
header.write(cur_header);
|
||||
|
||||
|
@ -2259,7 +2289,8 @@ int CEXEBuild::SetVarsSection()
|
|||
VerifyDeclaredUserVarRefs(&m_UserVarNames);
|
||||
int MaxUserVars = m_UserVarNames.getnum();
|
||||
// -1 because the default size is 1
|
||||
if (!res_editor->AddExtraVirtualSize2PESection(NSIS_VARS_SECTION, (MaxUserVars - 1) * sizeof(NSIS_STRING)))
|
||||
int stringSize = NSIS_MAX_STRLEN*(build_unicode?sizeof(TCHAR):sizeof(char));
|
||||
if (!res_editor->AddExtraVirtualSize2PESection(NSIS_VARS_SECTION, (MaxUserVars - 1) * stringSize))
|
||||
{
|
||||
ERROR_MSG(_T("Internal compiler error #12346: invalid exehead cannot find section \"%s\"!\n"), _T(NSIS_VARS_SECTION));
|
||||
return PS_ERROR;
|
||||
|
@ -2658,7 +2689,7 @@ int CEXEBuild::write_output(void)
|
|||
int ne=build_header.blocks[NB_ENTRIES].num;
|
||||
INFO_MSG(_T("%d instruction%s (%d bytes), "),ne,ne==1?_T(""):_T("s"),ne*sizeof(entry));
|
||||
int ns=build_strlist.getnum();
|
||||
INFO_MSG(_T("%d string%s (%d bytes), "),ns,ns==1?_T(""):_T("s"),build_strlist.getcount()*sizeof(TCHAR));
|
||||
INFO_MSG(_T("%d string%s (%d bytes), "),ns,ns==1?_T(""):_T("s"),build_strlist.getcount()*(build_unicode ? sizeof(CHAR) : sizeof(TCHAR)));
|
||||
int nlt=build_header.blocks[NB_LANGTABLES].num;
|
||||
INFO_MSG(_T("%d language table%s (%d bytes).\n"),nlt,nlt==1?_T(""):_T("s"),build_langtables.getlen());
|
||||
if (ubuild_entries.getlen())
|
||||
|
@ -2687,7 +2718,7 @@ int CEXEBuild::write_output(void)
|
|||
ne=build_uninst.blocks[NB_ENTRIES].num;
|
||||
INFO_MSG(_T("%d instruction%s (%d bytes), "),ne,ne==1?_T(""):_T("s"),ubuild_entries.getlen());
|
||||
ns=ubuild_strlist.getnum();
|
||||
INFO_MSG(_T("%d string%s (%d bytes), "),ns,ns==1?_T(""):_T("s"),ubuild_strlist.getcount()*sizeof(TCHAR));
|
||||
INFO_MSG(_T("%d string%s (%d bytes), "),ns,ns==1?_T(""):_T("s"),ubuild_strlist.getcount()*(build_unicode ? sizeof(CHAR) : sizeof(TCHAR)));
|
||||
nlt=build_uninst.blocks[NB_LANGTABLES].num;
|
||||
INFO_MSG(_T("%d language table%s (%d bytes).\n"),nlt,nlt==1?_T(""):_T("s"),ubuild_langtables.getlen());
|
||||
}
|
||||
|
@ -3014,7 +3045,7 @@ int CEXEBuild::uninstall_generate()
|
|||
MMapBuf udata;
|
||||
|
||||
{
|
||||
growbuf_writer_sink sink(&udata);
|
||||
growbuf_writer_sink sink(&udata, build_unicode);
|
||||
firstheader_writer w(&sink);
|
||||
w.write(&fh);
|
||||
}
|
||||
|
@ -3532,12 +3563,40 @@ void CEXEBuild::VerifyDeclaredUserVarRefs(UserVarsStringList *pVarsStringList)
|
|||
}
|
||||
}
|
||||
|
||||
int CEXEBuild::set_compressor(const tstring& compressor, const bool solid) {
|
||||
tstring stub = stubs_dir + PLATFORM_PATH_SEPARATOR_STR + compressor;
|
||||
if (solid)
|
||||
stub += _T("_solid");
|
||||
#ifdef _UNICODE
|
||||
int CEXEBuild::set_build_unicode(bool unicode_installer)
|
||||
{
|
||||
build_unicode = unicode_installer;
|
||||
definedlist.del(_T("NSIS_UNICODE"));
|
||||
definedlist.del(_T("NSIS_CHAR_SIZE"));
|
||||
if (unicode_installer) // update defines depending on target installer type
|
||||
{
|
||||
definedlist.add(_T("NSIS_UNICODE"));
|
||||
definedlist.add(_T("NSIS_CHAR_SIZE"), _T("2"));
|
||||
}
|
||||
else
|
||||
{
|
||||
definedlist.add(_T("NSIS_CHAR_SIZE"), _T("1"));
|
||||
}
|
||||
return load_stub();
|
||||
}
|
||||
#endif
|
||||
|
||||
return update_exehead(stub, &m_exehead_original_size);
|
||||
int CEXEBuild::set_compressor(const tstring& compressor, const bool solid) {
|
||||
stub_filename = stubs_dir + PLATFORM_PATH_SEPARATOR_STR + compressor;
|
||||
if (solid)
|
||||
stub_filename += _T("_solid");
|
||||
return load_stub();
|
||||
}
|
||||
|
||||
int CEXEBuild::load_stub()
|
||||
{
|
||||
#ifdef _UNICODE
|
||||
if (build_unicode)
|
||||
return update_exehead(stub_filename+_T('W'), &m_exehead_original_size);
|
||||
else
|
||||
#endif
|
||||
return update_exehead(stub_filename, &m_exehead_original_size);
|
||||
}
|
||||
|
||||
int CEXEBuild::update_exehead(const tstring& file, size_t *size/*=NULL*/) {
|
||||
|
|
|
@ -136,7 +136,9 @@ class CEXEBuild {
|
|||
int prepare_uninstaller();
|
||||
int pack_exe_header();
|
||||
|
||||
int set_build_unicode(bool unicode_installer);
|
||||
int set_compressor(const tstring& compressor, const bool solid);
|
||||
int load_stub();
|
||||
int update_exehead(const tstring& file, size_t *size=NULL);
|
||||
void update_exehead(const unsigned char *new_exehead, size_t new_size);
|
||||
|
||||
|
@ -377,6 +379,7 @@ class CEXEBuild {
|
|||
// a whole bunch O data.
|
||||
|
||||
tstring stubs_dir;
|
||||
tstring stub_filename;
|
||||
|
||||
#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT
|
||||
ICompressor *compressor;
|
||||
|
@ -392,6 +395,7 @@ class CEXEBuild {
|
|||
int build_compress_dict_size;
|
||||
|
||||
bool no_space_texts;
|
||||
bool build_unicode;
|
||||
|
||||
bool has_called_write_output;
|
||||
|
||||
|
@ -442,7 +446,7 @@ class CEXEBuild {
|
|||
GrowBuf build_instruction_entry_map,ubuild_instruction_entry_map, *cur_instruction_entry_map;
|
||||
TinyGrowBuf build_functions, ubuild_functions, *cur_functions;
|
||||
TinyGrowBuf build_labels, ubuild_labels, *cur_labels;
|
||||
StringList build_strlist, ubuild_strlist, *cur_strlist;
|
||||
MLStringList build_strlist, ubuild_strlist, *cur_strlist;
|
||||
GrowBuf build_langtables, ubuild_langtables, *cur_langtables;
|
||||
TinyGrowBuf build_pages, ubuild_pages, *cur_pages;
|
||||
TinyGrowBuf build_ctlcolors, ubuild_ctlcolors, *cur_ctlcolors;
|
||||
|
|
|
@ -722,7 +722,7 @@ DWORD CALLBACK StreamLicense(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)
|
|||
return 0;
|
||||
}
|
||||
#ifdef _UNICODE
|
||||
// on-the-fly conversion of Unicode to ANSI (because Windows don't recognize Unicode RTF data)
|
||||
// on-the-fly conversion of Unicode to ANSI (because Windows doesn't recognize Unicode RTF data)
|
||||
DWORD CALLBACK StreamLicenseRTF(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)
|
||||
{
|
||||
size_t len = lstrlen(((LPWSTR) dwCookie)+dwRead);
|
||||
|
|
|
@ -489,17 +489,10 @@ typedef struct {
|
|||
|
||||
// We are doing this to store an integer value into a char string and we
|
||||
// don't want false end of string values
|
||||
#if _UNICODE
|
||||
#define CODE_SHORT(x) ((WORD)x + 1)
|
||||
#define MAX_CODED 0xFFFE
|
||||
// This macro takes a pointer to WCHAR
|
||||
#define DECODE_SHORT(c) (c[0]-1)
|
||||
#else
|
||||
#define CODE_SHORT(x) (WORD)((((WORD)(x) & 0x7F) | (((WORD)(x) & 0x3F80) << 1) | 0x8080))
|
||||
#define MAX_CODED 0x3FFF
|
||||
// This macro takes a pointer to CHAR
|
||||
#define DECODE_SHORT(c) (((c[1] & 0x7F) << 7) | (c[0] & 0x7F))
|
||||
#endif
|
||||
#define DECODE_SHORT(c) (((((char*)c)[1] & 0x7F) << 7) | (((char*)c)[0] & 0x7F))
|
||||
|
||||
#define NSIS_INSTDIR_INVALID 1
|
||||
#define NSIS_INSTDIR_NOT_ENOUGH_SPACE 2
|
||||
|
|
|
@ -381,15 +381,10 @@ const TCHAR *CEXEBuild::GetLangNameAndCP(LANGID lang, unsigned int *codepage/*=N
|
|||
return table->nlf.m_szName;
|
||||
}
|
||||
else {
|
||||
// If the language table does not exist, then we default to Unicode in the
|
||||
// Unicode version and English in the ANSI version.
|
||||
#ifdef _UNICODE
|
||||
// If the language table does not exist, then we default to Unicode or ANSI
|
||||
// depending on the target installer type
|
||||
if (codepage)
|
||||
*codepage = 1200; // Unicode
|
||||
#else
|
||||
if (codepage)
|
||||
*codepage = 1252; // ANSI CP1252
|
||||
#endif
|
||||
*codepage = build_unicode ? 1200 : 1252; // Unicode or CP1252
|
||||
|
||||
if (lang == 1033)
|
||||
return _T("English");
|
||||
|
@ -703,7 +698,7 @@ int CEXEBuild::GenerateLangTables() {
|
|||
#define ADD_FONT(id) { \
|
||||
BYTE* dlg = res_editor->GetResource(RT_DIALOG, id, NSIS_DEFAULT_LANG); \
|
||||
if (dlg) { \
|
||||
CDialogTemplate td(dlg); \
|
||||
CDialogTemplate td(dlg,build_unicode); \
|
||||
res_editor->FreeResource(dlg); \
|
||||
td.SetFont(build_font, (WORD) build_font_size); \
|
||||
DWORD dwSize; \
|
||||
|
@ -758,7 +753,7 @@ int CEXEBuild::GenerateLangTables() {
|
|||
#define ADD_FONT(id) { \
|
||||
BYTE* dlg = res_editor->GetResource(RT_DIALOG, id, NSIS_DEFAULT_LANG); \
|
||||
if (dlg) { \
|
||||
CDialogTemplate td(dlg,lt[i].nlf.m_uCodePage); \
|
||||
CDialogTemplate td(dlg,build_unicode,lt[i].nlf.m_uCodePage); \
|
||||
res_editor->FreeResource(dlg); \
|
||||
if (font) td.SetFont(font, (WORD) lt[i].nlf.m_iFontSize); \
|
||||
if (lt[i].nlf.m_bRTL) { \
|
||||
|
|
|
@ -867,12 +867,10 @@ int CEXEBuild::LoadLicenseFile(TCHAR *file, TCHAR** pdata, LineParser &line, BOO
|
|||
}
|
||||
if (!memcmp(data+1,_T("{\\rtf"),5*sizeof(TCHAR)))
|
||||
*data = SF_RTF;
|
||||
else
|
||||
#ifdef _UNICODE
|
||||
else if (unicode)
|
||||
*data = SF_TEXT|SF_UNICODE;
|
||||
#else
|
||||
else
|
||||
*data = SF_TEXT;
|
||||
#endif
|
||||
return PS_OK;
|
||||
}
|
||||
|
||||
|
@ -2155,7 +2153,7 @@ int CEXEBuild::doCommand(int which_token, LineParser &line)
|
|||
|
||||
BYTE* dlg = res_editor->GetResource(RT_DIALOG, IDD_INSTFILES, NSIS_DEFAULT_LANG);
|
||||
if (!dlg) throw runtime_error("IDD_INSTFILES doesn't exist!");
|
||||
CDialogTemplate dt(dlg,uDefCodePage);
|
||||
CDialogTemplate dt(dlg,build_unicode,uDefCodePage);
|
||||
free(dlg);
|
||||
DialogItemTemplate* progress = dt.GetItem(IDC_PROGRESS);
|
||||
if (!progress) {
|
||||
|
@ -2448,7 +2446,7 @@ int CEXEBuild::doCommand(int which_token, LineParser &line)
|
|||
init_res_editor();
|
||||
|
||||
// Search for required items
|
||||
#define GET(x) dlg = uire->GetResource(RT_DIALOG, x, 0); if (!dlg) return PS_ERROR; CDialogTemplate UIDlg(dlg, uDefCodePage);
|
||||
#define GET(x) dlg = uire->GetResource(RT_DIALOG, x, 0); if (!dlg) return PS_ERROR; CDialogTemplate UIDlg(dlg, build_unicode, uDefCodePage);
|
||||
#define SEARCH(x) if (!UIDlg.GetItem(x)) {ERROR_MSG(_T("Error: Can't find %s (%u) in the custom UI!\n"), _T(#x), x);delete [] dlg;delete uire;return PS_ERROR;}
|
||||
#define SAVE(x) dwSize = UIDlg.GetSize(); res_editor->UpdateResource(RT_DIALOG, x, NSIS_DEFAULT_LANG, dlg, dwSize); delete [] dlg;
|
||||
|
||||
|
@ -2568,7 +2566,7 @@ int CEXEBuild::doCommand(int which_token, LineParser &line)
|
|||
init_res_editor();
|
||||
BYTE* dlg = res_editor->GetResource(RT_DIALOG, IDD_INST, NSIS_DEFAULT_LANG);
|
||||
|
||||
CDialogTemplate dt(dlg, uDefCodePage);
|
||||
CDialogTemplate dt(dlg, build_unicode, uDefCodePage);
|
||||
|
||||
res_editor->FreeResource(dlg);
|
||||
|
||||
|
@ -2687,6 +2685,25 @@ int CEXEBuild::doCommand(int which_token, LineParser &line)
|
|||
}
|
||||
return PS_OK;
|
||||
|
||||
#ifdef _UNICODE
|
||||
case TOK_UNICODEINSTALLER:
|
||||
{
|
||||
if (build_compressor_set) {
|
||||
ERROR_MSG(_T("Error: can't change type of installer after data already got compressed or header already changed!\n"));
|
||||
return PS_ERROR;
|
||||
}
|
||||
int param=line.gettoken_enum(1,_T("off\0on\0"));
|
||||
if (param==-1) PRINTHELP()
|
||||
SCRIPT_MSG(_T("UnicodeInstaller: %s\n"),line.gettoken_str(1));
|
||||
if (set_build_unicode(param != 0) != PS_OK)
|
||||
{
|
||||
ERROR_MSG(_T("Error: error while setting type of installer! (stub not found?)\n"));
|
||||
return PS_ERROR;
|
||||
}
|
||||
}
|
||||
return PS_OK;
|
||||
#endif
|
||||
|
||||
// Ability to change compression methods from within the script
|
||||
case TOK_SETCOMPRESSOR:
|
||||
#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT
|
||||
|
@ -3681,7 +3698,7 @@ int CEXEBuild::doCommand(int which_token, LineParser &line)
|
|||
init_res_editor();
|
||||
|
||||
BYTE* dlg = res_editor->GetResource(RT_DIALOG, IDD_INST, NSIS_DEFAULT_LANG);
|
||||
CDialogTemplate td(dlg,uDefCodePage);
|
||||
CDialogTemplate td(dlg,build_unicode,uDefCodePage);
|
||||
free(dlg);
|
||||
|
||||
if (trim) {
|
||||
|
@ -5913,8 +5930,13 @@ int CEXEBuild::doCommand(int which_token, LineParser &line)
|
|||
{
|
||||
int ret;
|
||||
|
||||
const tstring command = m_plugins.NormalizedCommand(line.gettoken_str(0));
|
||||
const tstring dllPath = m_plugins.GetPluginPath(command);
|
||||
tstring command = m_plugins.NormalizedCommand(line.gettoken_str(0));
|
||||
#ifdef _UNICODE
|
||||
if (build_unicode)
|
||||
command = m_plugins.UseUnicodeVariant(command);
|
||||
#endif
|
||||
tstring dllPath = m_plugins.GetPluginPath(command);
|
||||
tstring dllName = get_file_name(dllPath);
|
||||
int data_handle = m_plugins.GetPluginHandle(uninstall_mode?true:false, command);
|
||||
|
||||
if (uninstall_mode) uninst_plugin_used = true;
|
||||
|
@ -5930,7 +5952,6 @@ int CEXEBuild::doCommand(int which_token, LineParser &line)
|
|||
|
||||
// DLL name on the user machine
|
||||
TCHAR tempDLL[NSIS_MAX_STRLEN];
|
||||
tstring dllName = get_file_name(dllPath);
|
||||
wsprintf(tempDLL, _T("$PLUGINSDIR\\%s"), dllName.c_str());
|
||||
|
||||
// Add the DLL to the installer
|
||||
|
|
|
@ -18,6 +18,97 @@
|
|||
|
||||
#include "strlist.h"
|
||||
|
||||
MLStringList::MLStringList()
|
||||
{
|
||||
m_gr.set_zeroing(1);
|
||||
#ifdef _UNICODE
|
||||
m_grAnsi.set_zeroing(1);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef _UNICODE
|
||||
char* convert_processed_string_to_ansi(char *out, const TCHAR *in, WORD codepage); // defined in build.cpp
|
||||
|
||||
// use 2 for case sensitive end-of-string matches too
|
||||
int MLStringList::findAnsi(const char *str, int case_sensitive) const // returns -1 if not found
|
||||
{
|
||||
const char *s=(const char*) m_grAnsi.get();
|
||||
int ml=getcount();
|
||||
int offs=0;
|
||||
|
||||
size_t str_slen = strlen(str);
|
||||
size_t offs_slen;
|
||||
|
||||
while (offs < ml)
|
||||
{
|
||||
// Check if the whole string matches str.
|
||||
if ((case_sensitive && !strcmp(s+offs,str)) ||
|
||||
(!case_sensitive && !stricmp(s+offs,str)))
|
||||
{
|
||||
return offs;
|
||||
}
|
||||
|
||||
offs_slen = strlen(s+offs);
|
||||
|
||||
// Check if just the end of the string matches str.
|
||||
if (case_sensitive==2 &&
|
||||
str_slen < offs_slen && // check for end of string
|
||||
!strcmp(s + offs + offs_slen - str_slen,str))
|
||||
{
|
||||
return offs + offs_slen - str_slen;
|
||||
}
|
||||
offs += offs_slen + 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
int MLStringList::add(const TCHAR *str, WORD codepage /*= CP_ACP*/, bool processed, bool build_unicode)
|
||||
{
|
||||
#ifndef _UNICODE
|
||||
int a=find(str,2);
|
||||
if (a >= 0)
|
||||
return a;
|
||||
int len = _tcslen(str)+1;
|
||||
return m_gr.add(str,len*sizeof(TCHAR))/sizeof(TCHAR);
|
||||
#else
|
||||
if (build_unicode)
|
||||
{
|
||||
int a=find(str,2);
|
||||
if (a >= 0)
|
||||
return a;
|
||||
}
|
||||
// convert to ANSI
|
||||
int len = _tcslen(str)+1;
|
||||
char* ansiBuf = new char[len*2];
|
||||
int cbMultiByte;
|
||||
if (processed)
|
||||
cbMultiByte = convert_processed_string_to_ansi(ansiBuf, str, codepage)-ansiBuf;
|
||||
else
|
||||
cbMultiByte = WideCharToMultiByte(codepage, 0, str, len, ansiBuf, len*2, NULL, NULL);
|
||||
if (!build_unicode)
|
||||
{
|
||||
int a=findAnsi(ansiBuf,2);
|
||||
if (a >= 0)
|
||||
{
|
||||
delete[] ansiBuf;
|
||||
return a;
|
||||
}
|
||||
}
|
||||
// string not found, add it
|
||||
int a=m_gr.add(str,len*sizeof(TCHAR))/sizeof(TCHAR);
|
||||
m_grAnsi.add(ansiBuf,cbMultiByte);
|
||||
delete[] ansiBuf;
|
||||
if (len != cbMultiByte)
|
||||
{ // resize buffers to align future strings on same offsets
|
||||
len = a+max(len,cbMultiByte);
|
||||
m_gr.resize(len*sizeof(TCHAR));
|
||||
m_grAnsi.resize(len);
|
||||
}
|
||||
return a;
|
||||
#endif
|
||||
}
|
||||
|
||||
int StringList::add(const TCHAR *str, int case_sensitive)
|
||||
{
|
||||
int a=find(str,case_sensitive);
|
||||
|
@ -103,15 +194,6 @@ int StringList::getnum() const
|
|||
return idx;
|
||||
}
|
||||
|
||||
const TCHAR *StringList::get() const
|
||||
{
|
||||
return (const TCHAR*) m_gr.get();
|
||||
}
|
||||
|
||||
int StringList::getcount() const
|
||||
{
|
||||
return m_gr.getlen() / sizeof(TCHAR);
|
||||
}
|
||||
|
||||
// ==========
|
||||
// DefineList
|
||||
|
|
|
@ -104,18 +104,43 @@ public:
|
|||
* Get the buffer straight as a const TCHAR pointer. Very unwise to use.
|
||||
* @return m_gr.m_s cast as a TCHAR*.
|
||||
*/
|
||||
const TCHAR *get() const;
|
||||
const TCHAR *get() const { return (const TCHAR*) m_gr.get(); }
|
||||
|
||||
/**
|
||||
* Get the buffer size (number of TCHARs).
|
||||
* @return The buffer size (number of TCHARs).
|
||||
*/
|
||||
int getcount() const;
|
||||
int getcount() const { return m_gr.getlen() / sizeof(TCHAR); }
|
||||
|
||||
private:
|
||||
protected:
|
||||
GrowBuf m_gr;
|
||||
};
|
||||
|
||||
/**
|
||||
* Similar to StringList with case_sensitive=2, but stores strings as both Unicode AND ANSI (codepaged)
|
||||
*/
|
||||
class MLStringList : private StringList
|
||||
{
|
||||
private: // don't copy instances
|
||||
MLStringList(const MLStringList&);
|
||||
void operator=(const MLStringList&);
|
||||
|
||||
public:
|
||||
MLStringList();
|
||||
~MLStringList() {}
|
||||
|
||||
int add(const TCHAR *str, WORD codepage, bool processed, bool build_unicode);
|
||||
int getnum() const { return StringList::getnum(); }
|
||||
int getcount() const { return StringList::getcount(); }
|
||||
const TCHAR *getTchar() const { return (const TCHAR*) m_gr.get(); }
|
||||
#ifdef _UNICODE
|
||||
const char *getAnsi() const { return (const char*) m_grAnsi.get(); }
|
||||
int findAnsi(const char *str, int case_sensitive) const;
|
||||
private:
|
||||
GrowBuf m_grAnsi;
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* This class maintains a list of T types in a GrowBuf sorted by T.name which
|
||||
* is assumed to be a string (TCHAR*). So it's really sort of a
|
||||
|
|
|
@ -216,6 +216,9 @@ static tokenType tokenlist[TOK__LAST] =
|
|||
{TOK_STRCPY,_T("StrCpy"),2,2,_T("$(user_var: output) str [maxlen] [startoffset]"),TP_CODE},
|
||||
{TOK_STRLEN,_T("StrLen"),2,0,_T("$(user_var: length output) str"),TP_CODE},
|
||||
{TOK_SUBCAPTION,_T("SubCaption"),2,0,_T("page_number(0-4) new_subcaption"),TP_GLOBAL},
|
||||
#ifdef _UNICODE
|
||||
{TOK_UNICODEINSTALLER,_T("UnicodeInstaller"),1,0,_T("(on|off)"),TP_GLOBAL},
|
||||
#endif
|
||||
{TOK_UNINSTALLEXENAME,_T("UninstallExeName"),0,0,_T("no longer supported, use WriteUninstaller from section."),TP_ALL},
|
||||
{TOK_UNINSTCAPTION,_T("UninstallCaption"),1,0,_T("uninstaller_caption"),TP_GLOBAL},
|
||||
{TOK_UNINSTICON,_T("UninstallIcon"),1,0,_T("icon_on_local_system.ico"),TP_GLOBAL},
|
||||
|
|
|
@ -70,6 +70,9 @@ enum
|
|||
TOK_DEFVAR,
|
||||
TOK_VI_ADDKEY,
|
||||
TOK_VI_SETPRODUCTVERSION,
|
||||
#ifdef _UNICODE
|
||||
TOK_UNICODEINSTALLER,
|
||||
#endif
|
||||
|
||||
TOK_MISCBUTTONTEXT,
|
||||
TOK_DETAILSBUTTONTEXT,
|
||||
|
|
|
@ -54,18 +54,29 @@ void writer_sink::write_int_array(const int i[], const size_t len)
|
|||
void writer_sink::write_string(const TCHAR *s, size_t size)
|
||||
{
|
||||
#ifdef _UNICODE
|
||||
bool strEnd = false;
|
||||
TCHAR ch;
|
||||
for (; size ; size--)
|
||||
if (m_build_unicode)
|
||||
{
|
||||
if (!strEnd)
|
||||
bool strEnd = false;
|
||||
TCHAR ch;
|
||||
for (; size ; size--)
|
||||
{
|
||||
ch = *s++;
|
||||
if (ch == _T('\0'))
|
||||
strEnd = true;
|
||||
if (!strEnd)
|
||||
{
|
||||
ch = *s++;
|
||||
if (ch == _T('\0'))
|
||||
strEnd = true;
|
||||
}
|
||||
write_short(ch);
|
||||
}
|
||||
write_short(ch);
|
||||
}
|
||||
else
|
||||
{
|
||||
char *wb = new char[size];
|
||||
memset(wb, 0, size);
|
||||
WideCharToMultiByte(CP_ACP, 0, s, -1, wb, size, NULL, NULL);
|
||||
write_data(wb, size);
|
||||
delete [] wb;
|
||||
}
|
||||
#else
|
||||
char *wb = new char[size];
|
||||
memset(wb, 0, size);
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
|
||||
class writer_sink {
|
||||
public:
|
||||
writer_sink() {}
|
||||
writer_sink() : m_build_unicode(false) {}
|
||||
virtual ~writer_sink() {}
|
||||
|
||||
virtual void write_byte(const unsigned char b);
|
||||
|
@ -38,7 +38,8 @@ public:
|
|||
virtual void write_growbuf(const IGrowBuf *b);
|
||||
|
||||
virtual void write_data(const void *data, const size_t size) = 0;
|
||||
|
||||
protected:
|
||||
bool m_build_unicode;
|
||||
};
|
||||
|
||||
class writer {
|
||||
|
@ -53,7 +54,7 @@ protected:
|
|||
|
||||
class growbuf_writer_sink : public writer_sink {
|
||||
public:
|
||||
growbuf_writer_sink(IGrowBuf *buf) : m_buf(buf) {}
|
||||
growbuf_writer_sink(IGrowBuf *buf, bool build_unicode) : m_buf(buf) { m_build_unicode=build_unicode; }
|
||||
|
||||
virtual void write_data(const void *data, const size_t size);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue